aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_drv.h
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-11-01 05:26:26 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-21 11:45:06 -0500
commitb4a98e57fc27854b5938fc8b08b68e5e68b91e1f (patch)
tree61db63ff4f2e3d7beabef9ef1a50079038e2467e /drivers/gpu/drm/i915/intel_drv.h
parenta726915cef1daab57aad4c5b5e4773822f0a4bf8 (diff)
drm/i915: Flush outstanding unpin tasks before pageflipping
If we accumulate unpin tasks because we are pageflipping faster than the system can schedule its workers, we can effectively create a pin-leak. The solution taken here is to limit the number of unpin tasks we have per-crtc and to flush those outstanding tasks if we accumulate too many. This should prevent any jitter in the normal case, and also prevent the hang if we should run too fast. Note: It is important that we switch from the system workqueue to our own dev_priv->wq since all work items on that queue are guaranteed to only need the dev->struct_mutex and not any modeset resources. For otherwise if we have a work item ahead in the queue which needs the modeset lock (like the output detect work used by both polling or hpd), this work and so the unpin work will never execute since the pageflip code already holds that lock. Unfortunately there's no lockdep support for this scenario in the workqueue code. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46991 Reported-and-tested-by: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> [danvet: Added note about workqueu deadlock.] Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56337 Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_drv.h')
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bcc52412810..522061ca068 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -211,6 +211,8 @@ struct intel_crtc {
211 struct intel_unpin_work *unpin_work; 211 struct intel_unpin_work *unpin_work;
212 int fdi_lanes; 212 int fdi_lanes;
213 213
214 atomic_t unpin_work_count;
215
214 /* Display surface base address adjustement for pageflips. Note that on 216 /* Display surface base address adjustement for pageflips. Note that on
215 * gen4+ this only adjusts up to a tile, offsets within a tile are 217 * gen4+ this only adjusts up to a tile, offsets within a tile are
216 * handled in the hw itself (with the TILEOFF register). */ 218 * handled in the hw itself (with the TILEOFF register). */
@@ -395,7 +397,7 @@ intel_get_crtc_for_plane(struct drm_device *dev, int plane)
395 397
396struct intel_unpin_work { 398struct intel_unpin_work {
397 struct work_struct work; 399 struct work_struct work;
398 struct drm_device *dev; 400 struct drm_crtc *crtc;
399 struct drm_i915_gem_object *old_fb_obj; 401 struct drm_i915_gem_object *old_fb_obj;
400 struct drm_i915_gem_object *pending_flip_obj; 402 struct drm_i915_gem_object *pending_flip_obj;
401 struct drm_pending_vblank_event *event; 403 struct drm_pending_vblank_event *event;