summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2015-10-28 19:07:35 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2015-11-06 16:15:40 +0100
commitd2e8851a909c76c6f0b34553f2c9993808bc1d58 (patch)
treed0e85f87deb5a075b260365490d56f261d228857 /drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
parent4e0858a682c008a2a8f5f4fb3aec705500575ae1 (diff)
drm/vmwgfx: Relax irq locking somewhat
Relax locking with the goal of reducing the number of locking cycles and time spent with irqs disabled. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_irq.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c104
1 files changed, 30 insertions, 74 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index ac3eccd9223f..0c7e1723292c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -36,15 +36,13 @@ irqreturn_t vmw_irq_handler(int irq, void *arg)
struct vmw_private *dev_priv = vmw_priv(dev);
uint32_t status, masked_status;
- spin_lock(&dev_priv->irq_lock);
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- masked_status = status & dev_priv->irq_mask;
- spin_unlock(&dev_priv->irq_lock);
+ masked_status = status & READ_ONCE(dev_priv->irq_mask);
if (likely(status))
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- if (!masked_status)
+ if (!status)
return IRQ_NONE;
if (masked_status & (SVGA_IRQFLAG_ANY_FENCE |
@@ -190,65 +188,51 @@ out_err:
return ret;
}
-void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+void vmw_generic_waiter_add(struct vmw_private *dev_priv,
+ u32 flag, int *waiter_count)
{
- spin_lock(&dev_priv->waiter_lock);
- if (dev_priv->fence_queue_waiters++ == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_ANY_FENCE,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE;
+ spin_lock_bh(&dev_priv->waiter_lock);
+ if ((*waiter_count)++ == 0) {
+ outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+ dev_priv->irq_mask |= flag;
vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
- spin_unlock(&dev_priv->waiter_lock);
+ spin_unlock_bh(&dev_priv->waiter_lock);
}
-void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
+ u32 flag, int *waiter_count)
{
- spin_lock(&dev_priv->waiter_lock);
- if (--dev_priv->fence_queue_waiters == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE;
+ spin_lock_bh(&dev_priv->waiter_lock);
+ if (--(*waiter_count) == 0) {
+ dev_priv->irq_mask &= ~flag;
vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
}
- spin_unlock(&dev_priv->waiter_lock);
+ spin_unlock_bh(&dev_priv->waiter_lock);
}
+void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
+{
+ vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
+ &dev_priv->fence_queue_waiters);
+}
+
+void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
+{
+ vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
+ &dev_priv->fence_queue_waiters);
+}
void vmw_goal_waiter_add(struct vmw_private *dev_priv)
{
- spin_lock(&dev_priv->waiter_lock);
- if (dev_priv->goal_queue_waiters++ == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- outl(SVGA_IRQFLAG_FENCE_GOAL,
- dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ &dev_priv->goal_queue_waiters);
}
void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
{
- spin_lock(&dev_priv->waiter_lock);
- if (--dev_priv->goal_queue_waiters == 0) {
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
- }
- spin_unlock(&dev_priv->waiter_lock);
+ vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ &dev_priv->goal_queue_waiters);
}
int vmw_wait_seqno(struct vmw_private *dev_priv,
@@ -305,7 +289,6 @@ void vmw_irq_preinstall(struct drm_device *dev)
if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
return;
- spin_lock_init(&dev_priv->irq_lock);
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
}
@@ -328,30 +311,3 @@ void vmw_irq_uninstall(struct drm_device *dev)
status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
}
-
-void vmw_generic_waiter_add(struct vmw_private *dev_priv,
- u32 flag, int *waiter_count)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- if ((*waiter_count)++ == 0) {
- outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
- dev_priv->irq_mask |= flag;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- }
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-}
-
-void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
- u32 flag, int *waiter_count)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
- if (--(*waiter_count) == 0) {
- dev_priv->irq_mask &= ~flag;
- vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
- }
- spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
-}