Since the advent of trying to perform lockless-waits,

commit 3236f57a0162391f84b93f39fc1882c49a8998c7
Author: Chris Wilson <[email protected]>
Date:   Fri Aug 24 09:35:09 2012 +0100

    drm/i915: Use a non-blocking wait for set-to-domain ioctl

we exposed ourselves to a race between the reset-worker and those
waiters. Previously the reset would have been serialized by the
acquisition of the struct_mutex, but now we need to perform an explicit
serialisation between the two.

Signed-off-by: Chris Wilson <[email protected]>
Cc: Daniel Vetter <[email protected]>
---
 drivers/gpu/drm/i915/i915_dma.c      |    2 ++
 drivers/gpu/drm/i915/i915_drv.h      |    2 ++
 drivers/gpu/drm/i915/i915_gem.c      |    2 ++
 drivers/gpu/drm/i915/i915_irq.c      |    2 ++
 drivers/gpu/drm/i915/intel_display.c |    4 ++++
 5 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a35217d..50f5535 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1626,6 +1626,8 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)
        spin_lock_init(&dev_priv->rps.lock);
        spin_lock_init(&dev_priv->dpio_lock);
 
+       init_rwsem(&dev_priv->reset_lock);
+
        mutex_init(&dev_priv->rps.hw_lock);
 
        if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cf407b1..fc5c152 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -42,6 +42,7 @@
 #include <linux/kref.h>
 #include <linux/mmu_notifier.h>
 #include <linux/pm_qos.h>
+#include <linux/rwsem.h>
 
 /* General customization:
  */
@@ -736,6 +737,7 @@ typedef struct drm_i915_private {
 
        unsigned int fsb_freq, mem_freq, is_ddr3;
 
+       struct rw_semaphore reset_lock;
        spinlock_t error_lock;
        /* Protected by dev->error_lock. */
        struct drm_i915_error_state *first_error;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 30501d3..4ef5ba6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1140,6 +1140,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, 
u32 seqno,
 
        /* Record current time in case interrupted by signal, or wedged * */
        getrawmonotonic(&before);
+       down_read(&dev_priv->reset_lock);
 
 #define EXIT_COND \
        (i915_seqno_passed(ring->get_seqno(ring, false), seqno) || \
@@ -1161,6 +1162,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, 
u32 seqno,
                        end = ret;
        } while (end == 0 && wait_forever);
 
+       up_read(&dev_priv->reset_lock);
        getrawmonotonic(&now);
 
        ring->irq_put(ring);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bfb6c51..54f2d92 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -875,6 +875,7 @@ static void i915_error_work_func(struct work_struct *work)
 
        kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
 
+       down_write(&dev_priv->reset_lock);
        if (atomic_read(&dev_priv->mm.wedged)) {
                DRM_DEBUG_DRIVER("resetting chip\n");
                kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, 
reset_event);
@@ -884,6 +885,7 @@ static void i915_error_work_func(struct work_struct *work)
                }
                complete_all(&dev_priv->error_completion);
        }
+       up_write(&dev_priv->reset_lock);
 }
 
 /* NB: please notice the memset */
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 8a9df7d..816ea41 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2313,9 +2313,11 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
        bool was_interruptible = dev_priv->mm.interruptible;
        int ret;
 
+       down_read(&dev_priv->reset_lock);
        wait_event(dev_priv->pending_flip_queue,
                   atomic_read(&dev_priv->mm.wedged) ||
                   atomic_read(&obj->pending_flip) == 0);
+       up_read(&dev_priv->reset_lock);
 
        /* Big Hammer, we also need to ensure that any pending
         * MI_WAIT_FOR_EVENT inside a user batch buffer on the
@@ -3075,8 +3077,10 @@ static void intel_crtc_wait_for_pending_flips(struct 
drm_crtc *crtc)
        if (crtc->fb == NULL)
                return;
 
+       down_read(&dev_priv->reset_lock);
        wait_event(dev_priv->pending_flip_queue,
                   !intel_crtc_has_pending_flip(crtc));
+       up_read(&dev_priv->reset_lock);
 
        mutex_lock(&dev->struct_mutex);
        intel_finish_fb(crtc->fb);
-- 
1.7.10.4

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to