[Intel-gfx] [PATCH 4/9] drm/i915: handle interrupt on new chipset

Eric Anholt eric at anholt.net
Fri Jun 5 13:27:16 CEST 2009


On Fri, 2009-06-05 at 15:38 +0800, Zhenyu Wang wrote:
> Update interrupt handling methods for IGDNG with new registers
> for display and graphics interrupt functions.
> 
> Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c |    2 +-
>  drivers/gpu/drm/i915/i915_drv.h |    5 +
>  drivers/gpu/drm/i915/i915_gem.c |    5 +-
>  drivers/gpu/drm/i915/i915_irq.c |  228 +++++++++++++++++++++++++++++++++++++--
>  4 files changed, 228 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 53d5445..e89560c 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1161,7 +1161,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  #endif
>  
>  	dev->driver->get_vblank_counter = i915_get_vblank_counter;
> -	if (IS_GM45(dev))
> +	if (IS_GM45(dev) || IS_IGDNG(dev))
>  		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
>  
>  	i915_gem_load(dev);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 96f5279..97f9771 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -158,6 +158,11 @@ typedef struct drm_i915_private {
>  	/** Cached value of IMR to avoid reads in updating the bitfield */
>  	u32 irq_mask_reg;
>  	u32 pipestat[2];
> +	/** splitted irq regs for graphics and display engine on IGDNG,
> +	    irq_mask_reg is still used for display irq. */
> +	u32 gt_irq_mask_reg;
> +	u32 gt_irq_enable_reg;
> +	u32 de_irq_enable_reg;
>  
>  	u32 hotplug_supported_mask;
>  	struct work_struct hotplug_work;
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 670d128..cfc27aa 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1702,7 +1702,10 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
>  	BUG_ON(seqno == 0);
>  
>  	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
> -		ier = I915_READ(IER);
> +		if (IS_IGDNG(dev))
> +			ier = I915_READ(DEIER) | I915_READ(GTIER);
> +		else
> +			ier = I915_READ(IER);
>  		if (!ier) {
>  			DRM_ERROR("something (likely vbetool) disabled "
>  				  "interrupts, re-enabling\n");
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 98bb4c8..2314784 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -58,6 +58,34 @@
>  					 DRM_I915_VBLANK_PIPE_B)
>  
>  void
> +igdng_enable_irq(drm_i915_private_t *dev_priv, u32 mask, int gfx_irq)
> +{
> +	if (gfx_irq && ((dev_priv->gt_irq_mask_reg & mask) != 0)) {
> +		dev_priv->gt_irq_mask_reg &= ~mask;
> +		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
> +		(void) I915_READ(GTIMR);
> +	} else if ((dev_priv->irq_mask_reg & mask) != 0) {
> +		dev_priv->irq_mask_reg &= ~mask;
> +		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
> +		(void) I915_READ(DEIMR);
> +	}
> +}

It seems like this should just be two separate functions,
igdng_enable_graphics_irq and igdng_enable_display_irq(), and similarly
below.

> +
> +static inline void
> +igdng_disable_irq(drm_i915_private_t *dev_priv, u32 mask, int gfx_irq)
> +{
> +	if (gfx_irq && ((dev_priv->gt_irq_mask_reg & mask) != mask)) {
> +		dev_priv->gt_irq_mask_reg |= mask;
> +		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
> +		(void) I915_READ(GTIMR);
> +	} else if ((dev_priv->irq_mask_reg & mask) != mask) {
> +		dev_priv->irq_mask_reg |= mask;
> +		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
> +		(void) I915_READ(DEIMR);
> +	}
> +}
> +
> +void
>  i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
>  {
>  	if ((dev_priv->irq_mask_reg & mask) != 0) {
> @@ -196,6 +224,58 @@ static void i915_hotplug_work_func(struct work_struct *work)
>  	drm_sysfs_hotplug_event(dev);
>  }
>  
> +irqreturn_t igdng_irq_handler(struct drm_device *dev)
> +{
> +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> +	int ret = IRQ_NONE;
> +	u32 de_iir, gt_iir;
> +	u32 new_de_iir, new_gt_iir;
> +	int vblank = 0;
> +	struct drm_i915_master_private *master_priv;
> +
> +	de_iir = I915_READ(DEIIR);
> +	gt_iir = I915_READ(GTIIR);
> +
> +	for (;;) {
> +		if (de_iir == 0 && gt_iir == 0)
> +			break;
> +
> +		ret = IRQ_HANDLED;
> +
> +		I915_WRITE(DEIIR, de_iir);
> +		new_de_iir = I915_READ(DEIIR);
> +		I915_WRITE(GTIIR, gt_iir);
> +		new_gt_iir = I915_READ(GTIIR);
> +
> +		if (dev->primary->master) {
> +			master_priv = dev->primary->master->driver_priv;
> +			if (master_priv->sarea_priv)
> +				master_priv->sarea_priv->last_dispatch =
> +					READ_BREADCRUMB(dev_priv);
> +		}
> +
> +		if (gt_iir & GT_USER_INTERRUPT) {
> +			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
> +			DRM_WAKEUP(&dev_priv->irq_queue);
> +		}
> +
> +		if (de_iir & DE_PIPEA_VBLANK) {
> +			vblank++;
> +			drm_handle_vblank(dev, 0);
> +		}
> +
> +		if (de_iir & DE_PIPEB_VBLANK) {
> +			vblank++;
> +			drm_handle_vblank(dev, 1);
> +		}
> +
> +		de_iir = new_de_iir;
> +		gt_iir = new_gt_iir;
> +	}
> +
> +	return ret;
> +}
> +
>  irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
>  {
>  	struct drm_device *dev = (struct drm_device *) arg;
> @@ -212,6 +292,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
>  
>  	atomic_inc(&dev_priv->irq_received);
>  
> +	if (IS_IGDNG(dev))
> +		return igdng_irq_handler(dev);
> +
>  	iir = I915_READ(IIR);
>  
>  	if (IS_I965G(dev)) {
> @@ -349,8 +432,12 @@ void i915_user_irq_get(struct drm_device *dev)
>  	unsigned long irqflags;
>  
>  	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
> -	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
> -		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
> +	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
> +		if (IS_IGDNG(dev))
> +			igdng_enable_irq(dev_priv, GT_USER_INTERRUPT, 1);
> +		else
> +			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
> +	}
>  	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
>  }
>  
> @@ -361,8 +448,12 @@ void i915_user_irq_put(struct drm_device *dev)
>  
>  	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
>  	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
> -	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
> -		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
> +	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
> +		if (IS_IGDNG(dev))
> +			igdng_disable_irq(dev_priv, GT_USER_INTERRUPT, 1);
> +		else
> +			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
> +	}
>  	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
>  }
>  
> @@ -441,6 +532,43 @@ int i915_irq_wait(struct drm_device *dev, void *data,
>  	return i915_wait_irq(dev, irqwait->irq_seq);
>  }
>  
> +static void igdng_enable_vblank(struct drm_device *dev, int pipe)
> +{
> +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> +	u32 vblank;
> +
> +	if (pipe == 0)
> +		vblank = DE_PIPEA_VBLANK;
> +	else
> +		vblank = DE_PIPEB_VBLANK;
> +
> +	if ((dev_priv->de_irq_enable_reg & vblank) == 0) {
> +		igdng_enable_irq(dev_priv, vblank, 0);
> +		dev_priv->de_irq_enable_reg |= vblank;
> +		I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
> +		(void) I915_READ(DEIER);
> +	}
> +}
> +
> +static void igdng_disable_vblank(struct drm_device *dev, int pipe)
> +{
> +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> +	u32 vblank;
> +
> +	if (pipe == 0)
> +		vblank = DE_PIPEA_VBLANK;
> +	else
> +		vblank = DE_PIPEB_VBLANK;
> +
> +	if ((dev_priv->de_irq_enable_reg & vblank) != 0) {
> +		igdng_disable_irq(dev_priv, vblank, 0);
> +		dev_priv->de_irq_enable_reg &= ~vblank;
> +		I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
> +		(void) I915_READ(DEIER);
> +	}
> +}

Do we really want to support the old vblank irq functions on this new
hardware?  I don't know -- we're not using vblank irq-based syncing in
the DRI2 world, and we I don't think we have any plans to.

-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090605/bbaac4f3/attachment.sig>


More information about the Intel-gfx mailing list