Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 11 Sep 2014 12:46:53 +0000 (14:46 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 11 Sep 2014 12:46:53 +0000 (14:46 +0200)
Dave asked me to do the backmerge before sending him the revised pull
request, so here we go. Nothing fancy in the conflicts, just a few
things changed right next to each another.

Conflicts:
drivers/gpu/drm/drm_irq.c

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
1  2 
Documentation/DocBook/drm.tmpl
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_pm.c
include/drm/drmP.h

Simple merge
Simple merge
@@@ -827,9 -720,9 +817,11 @@@ drm_get_last_vbltimestamp(struct drm_de
   */
  u32 drm_vblank_count(struct drm_device *dev, int crtc)
  {
 -      return atomic_read(&dev->vblank[crtc].count);
 +      struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
 +
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return 0;
 +      return atomic_read(&vblank->count);
  }
  EXPORT_SYMBOL(drm_vblank_count);
  
  u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
                              struct timeval *vblanktime)
  {
 +      struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
        u32 cur_vblank;
  
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return 0;
        /* Read timestamp from slot of _vblank_time ringbuffer
         * that corresponds to current vblank count. Retry if
         * count has incremented during readout. This works like
@@@ -965,13 -922,16 +960,16 @@@ int drm_vblank_get(struct drm_device *d
        unsigned long irqflags;
        int ret = 0;
  
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return -EINVAL;
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        /* Going from 0->1 means we have to enable interrupts again */
 -      if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
 +      if (atomic_add_return(1, &vblank->refcount) == 1) {
                ret = drm_vblank_enable(dev, crtc);
        } else {
 -              if (!dev->vblank[crtc].enabled) {
 -                      atomic_dec(&dev->vblank[crtc].refcount);
 +              if (!vblank->enabled) {
 +                      atomic_dec(&vblank->refcount);
                        ret = -EINVAL;
                }
        }
@@@ -1011,20 -971,16 +1009,23 @@@ EXPORT_SYMBOL(drm_crtc_vblank_get)
   */
  void drm_vblank_put(struct drm_device *dev, int crtc)
  {
 -      BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
 +      struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
 +
 +      BUG_ON(atomic_read(&vblank->refcount) == 0);
  
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return;
        /* Last user schedules interrupt disable */
 -      if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
 -          (drm_vblank_offdelay > 0))
 -              mod_timer(&dev->vblank[crtc].disable_timer,
 -                        jiffies + ((drm_vblank_offdelay * HZ)/1000));
 +      if (atomic_dec_and_test(&vblank->refcount)) {
 +              if (drm_vblank_offdelay == 0)
 +                      return;
 +              else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0)
 +                      vblank_disable_fn((unsigned long)vblank);
 +              else
 +                      mod_timer(&vblank->disable_timer,
 +                                jiffies + ((drm_vblank_offdelay * HZ)/1000));
 +      }
  }
  EXPORT_SYMBOL(drm_vblank_put);
  
@@@ -1065,21 -1064,12 +1110,24 @@@ void drm_vblank_off(struct drm_device *
        unsigned long irqflags;
        unsigned int seq;
  
 -      spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return;
 +      spin_lock_irqsave(&dev->event_lock, irqflags);
 +
 +      spin_lock(&dev->vbl_lock);
        vblank_disable_and_save(dev, crtc);
 -      wake_up(&dev->vblank[crtc].queue);
 +      wake_up(&vblank->queue);
 +
 +      /*
 +       * Prevent subsequent drm_vblank_get() from re-enabling
 +       * the vblank interrupt by bumping the refcount.
 +       */
 +      if (!vblank->inmodeset) {
 +              atomic_inc(&vblank->refcount);
 +              vblank->inmodeset = 1;
 +      }
 +      spin_unlock(&dev->vbl_lock);
  
        /* Send any queued vblank events, lest the natives grow disquiet */
        seq = drm_vblank_count_and_time(dev, crtc, &now);
@@@ -1131,32 -1124,14 +1179,35 @@@ EXPORT_SYMBOL(drm_crtc_vblank_off)
   */
  void drm_vblank_on(struct drm_device *dev, int crtc)
  {
 +      struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
        unsigned long irqflags;
  
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return;
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
 -      /* re-enable interrupts if there's are users left */
 -      if (atomic_read(&dev->vblank[crtc].refcount) != 0)
 +      /* Drop our private "prevent drm_vblank_get" refcount */
 +      if (vblank->inmodeset) {
 +              atomic_dec(&vblank->refcount);
 +              vblank->inmodeset = 0;
 +      }
 +
 +      /*
 +       * sample the current counter to avoid random jumps
 +       * when drm_vblank_enable() applies the diff
 +       *
 +       * -1 to make sure user will never see the same
 +       * vblank counter value before and after a modeset
 +       */
 +      vblank->last =
 +              (dev->driver->get_vblank_counter(dev, crtc) - 1) &
 +              dev->max_vblank_count;
 +      /*
 +       * re-enable interrupts if there are users left, or the
 +       * user wishes vblank interrupts to be enabled all the time.
 +       */
 +      if (atomic_read(&vblank->refcount) != 0 ||
 +          (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
                WARN_ON(drm_vblank_enable(dev, crtc));
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
  }
@@@ -1532,8 -1494,9 +1587,11 @@@ bool drm_handle_vblank(struct drm_devic
        if (!dev->num_crtcs)
                return false;
  
+       if (WARN_ON(crtc >= dev->num_crtcs))
+               return false;
 +      spin_lock_irqsave(&dev->event_lock, irqflags);
 +
        /* Need timestamp lock to prevent concurrent execution with
         * vblank enable/disable, as this would cause inconsistent
         * or corrupted timestamps and vblank counts.
Simple merge
@@@ -3906,16 -3888,12 +3894,14 @@@ static void intel_crtc_dpms_overlay(str
  static void intel_crtc_enable_planes(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
  
 +      assert_vblank_disabled(crtc);
 +
        drm_vblank_on(dev, pipe);
  
-       intel_enable_primary_hw_plane(dev_priv, plane, pipe);
+       intel_enable_primary_hw_plane(crtc->primary, crtc);
        intel_enable_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
        intel_crtc_dpms_overlay(intel_crtc, true);
@@@ -105,13 -119,14 +119,14 @@@ nouveau_display_scanoutpos_head(struct 
                if (retry) ndelay(crtc->linedur_ns);
        } while (retry--);
  
-       *hpos = args.hline;
-       *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
-       if (stime) *stime = ns_to_ktime(args.time[0]);
-       if (etime) *etime = ns_to_ktime(args.time[1]);
+       *hpos = args.scan.hline;
+       *vpos = calc(args.scan.vblanks, args.scan.vblanke,
+                    args.scan.vtotal, args.scan.vline);
+       if (stime) *stime = ns_to_ktime(args.scan.time[0]);
+       if (etime) *etime = ns_to_ktime(args.scan.time[1]);
  
        if (*vpos < 0)
 -              ret |= DRM_SCANOUTPOS_INVBL;
 +              ret |= DRM_SCANOUTPOS_IN_VBLANK;
        return ret;
  }
  
Simple merge
@@@ -678,13 -602,9 +602,9 @@@ struct drm_master 
  
  /* get_scanout_position() return flags */
  #define DRM_SCANOUTPOS_VALID        (1 << 0)
 -#define DRM_SCANOUTPOS_INVBL        (1 << 1)
 +#define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
  #define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
  
- struct drm_bus {
-       int (*set_busid)(struct drm_device *dev, struct drm_master *master);
- };
  /**
   * DRM driver structure. This structure represent the common code for
   * a family of cards. There will one drm_device for each card present