[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