diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_irq.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 47 | 
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 9fe9827ee499..9498a5e33c12 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -1,6 +1,6 @@  /**************************************************************************   * - * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA + * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA   * All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a @@ -56,6 +56,9 @@ irqreturn_t vmw_irq_handler(int irq, void *arg)  	if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS)  		wake_up_all(&dev_priv->fifo_queue); +	if (masked_status & (SVGA_IRQFLAG_COMMAND_BUFFER | +			     SVGA_IRQFLAG_ERROR)) +		vmw_cmdbuf_tasklet_schedule(dev_priv->cman);  	return IRQ_HANDLED;  } @@ -69,7 +72,7 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)  void vmw_update_seqno(struct vmw_private *dev_priv,  			 struct vmw_fifo_state *fifo_state)  { -	__le32 __iomem *fifo_mem = dev_priv->mmio_virt; +	u32 __iomem *fifo_mem = dev_priv->mmio_virt;  	uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);  	if (dev_priv->last_read_seqno != seqno) { @@ -131,8 +134,16 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,  	 * Block command submission while waiting for idle.  	 */ -	if (fifo_idle) +	if (fifo_idle) {  		down_read(&fifo_state->rwsem); +		if (dev_priv->cman) { +			ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible, +					      10*HZ); +			if (ret) +				goto out_err; +		} +	} +  	signal_seq = atomic_read(&dev_priv->marker_seq);  	ret = 0; @@ -167,10 +178,11 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,  	}  	finish_wait(&dev_priv->fence_queue, &__wait);  	if (ret == 0 && fifo_idle) { -		__le32 __iomem *fifo_mem = dev_priv->mmio_virt; +		u32 __iomem *fifo_mem = dev_priv->mmio_virt;  		iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE);  	}  	wake_up_all(&dev_priv->fence_queue); +out_err:  	if (fifo_idle)  		up_read(&fifo_state->rwsem); @@ -315,3 +327,30 @@ 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); +}  |