From: Daniel Vetter Date: Thu, 11 Sep 2014 12:46:53 +0000 (+0200) Subject: Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework X-Git-Tag: v3.18-rc1~44^2~39^2 X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=336879b1da97fffc097f77c6d6f818660f2826f0;p=cascardo%2Flinux.git Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework 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 --- 336879b1da97fffc097f77c6d6f818660f2826f0 diff --cc drivers/gpu/drm/drm_irq.c index 79836594030c,5708c056fa1b..034297640b48 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@@ -827,9 -720,9 +817,11 @@@ drm_get_last_vbltimestamp(struct drm_de */ u32 drm_vblank_count(struct drm_device *dev, int crtc) { + struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + + if (WARN_ON(crtc >= dev->num_crtcs)) + return 0; - return atomic_read(&dev->vblank[crtc].count); + return atomic_read(&vblank->count); } EXPORT_SYMBOL(drm_vblank_count); @@@ -849,9 -742,11 +841,12 @@@ 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; + if (WARN_ON(crtc >= dev->num_crtcs)) + return; + - spin_lock_irqsave(&dev->vbl_lock, irqflags); + 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. diff --cc drivers/gpu/drm/i915/intel_display.c index de40a44e0ca0,ca8592e73644..0b327ebb2d9e --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@@ -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); diff --cc drivers/gpu/drm/nouveau/nouveau_display.c index 37a6ab8a97f8,a9ec525c0994..6d0a3cdc752b --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@@ -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; } diff --cc include/drm/drmP.h index 7b87fccff183,be1160fa5ebc..e748b42e4186 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@@ -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