summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Widawsky <ben@bwidawsk.net>2011-06-24 14:31:47 -0700
committerKeith Packard <keithp@keithp.com>2011-06-28 09:44:55 -0700
commit25732821cb965f00475922ca46e84f78e4bada95 (patch)
treee265e7fe4cb531722b2bfe8ddb17e521f6e460b8 /drivers/gpu
parent7c9017e5b77118439952fe8dc22809bae4fae4b6 (diff)
downloadlinux-3.10-25732821cb965f00475922ca46e84f78e4bada95.tar.gz
linux-3.10-25732821cb965f00475922ca46e84f78e4bada95.tar.bz2
linux-3.10-25732821cb965f00475922ca46e84f78e4bada95.zip
drm/i915: forcewake fix after reset
The failure is as follows: 1. Userspace gets forcewake lock, lock count >=1 2. GPU hang/reset occurs (forcewake bit is reset) 3. count is now incorrect The failure can only occur when using the forcewake userspace lock. This has the unfortunate consequence of messing up the driver as well as userspace, unless userspace closes the debugfs file, the kernel will never end up waking the GT since the refcount will be > 1. The solution is to try to recover the correct forcewake state based on the refcount. There is a period of time where userspace reads/writes may occur after the reset, before the GT has been forcewaked. The interface was never designed to be a perfect solution for userspace reads/writes, and the kernel portion is fixed by this patch. Suggested-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Ben Widawsky <ben@bwidawsk.net> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 0defd427059..609358faaa9 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -579,6 +579,9 @@ int i915_reset(struct drm_device *dev, u8 flags)
} else switch (INTEL_INFO(dev)->gen) {
case 6:
ret = gen6_do_reset(dev, flags);
+ /* If reset with a user forcewake, try to restore */
+ if (atomic_read(&dev_priv->forcewake_count))
+ __gen6_gt_force_wake_get(dev_priv);
break;
case 5:
ret = ironlake_do_reset(dev, flags);