diff options
author | Eric Anholt <eric@anholt.net> | 2008-09-01 16:45:29 -0700 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-10-18 07:10:51 +1000 |
commit | 546b0974c39657017407c86fe79811100b60700d (patch) | |
tree | 42ae164d23ecaa1cb78ad87ad9603e0bdd29740d /drivers/gpu/drm/i915/i915_irq.c | |
parent | ed4c9c4acf948b42b138747fcb8843ecb1a24ce4 (diff) |
i915: Use struct_mutex to protect ring in GEM mode.
In the conversion for GEM, we had stopped using the hardware lock to protect
ring usage, since it was all internal to the DRM now. However, some paths
weren't converted to using struct_mutex to prevent multiple threads from
concurrently working on the ring, in particular between the vblank swap handler
and ioctls.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f295bdf16e2..d04c526410a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -349,6 +349,21 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) return count; } +void +i915_gem_vblank_work_handler(struct work_struct *work) +{ + drm_i915_private_t *dev_priv; + struct drm_device *dev; + + dev_priv = container_of(work, drm_i915_private_t, + mm.vblank_work); + dev = dev_priv->dev; + + mutex_lock(&dev->struct_mutex); + i915_vblank_tasklet(dev); + mutex_unlock(&dev->struct_mutex); +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -422,8 +437,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (iir & I915_ASLE_INTERRUPT) opregion_asle_intr(dev); - if (vblank && dev_priv->swaps_pending > 0) - drm_locked_tasklet(dev, i915_vblank_tasklet); + if (vblank && dev_priv->swaps_pending > 0) { + if (dev_priv->ring.ring_obj == NULL) + drm_locked_tasklet(dev, i915_vblank_tasklet); + else + schedule_work(&dev_priv->mm.vblank_work); + } return IRQ_HANDLED; } @@ -514,14 +533,15 @@ int i915_irq_emit(struct drm_device *dev, void *data, drm_i915_irq_emit_t *emit = data; int result; - LOCK_TEST_WITH_RETURN(dev, file_priv); + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } - + mutex_lock(&dev->struct_mutex); result = i915_emit_irq(dev); + mutex_unlock(&dev->struct_mutex); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); |