X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fi915%2Fi915_irq.c;h=188b497e50768d56a3a93f2422000c03a0bcaddf;hp=8a9e08bf1cf74d3a9ba9060a8523e394593a09bd;hb=4697995b98417;hpb=1f0090a1eaa1b750a2fc5c99c91b790d5322a1fd diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a9e08bf1cf7..d967e1754cf2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -85,21 +85,11 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) } } -static inline u32 -i915_pipestat(int pipe) -{ - if (pipe == 0) - return PIPEASTAT; - if (pipe == 1) - return PIPEBSTAT; - BUG(); -} - void i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != mask) { - u32 reg = i915_pipestat(pipe); + u32 reg = PIPESTAT(pipe); dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ @@ -112,7 +102,7 @@ void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != 0) { - u32 reg = i915_pipestat(pipe); + u32 reg = PIPESTAT(pipe); dev_priv->pipestat[pipe] &= ~mask; I915_WRITE(reg, dev_priv->pipestat[pipe]); @@ -171,12 +161,12 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) if (!i915_pipe_enabled(dev, pipe)) { DRM_DEBUG_DRIVER("trying to get vblank count for disabled " - "pipe %d\n", pipe); + "pipe %c\n", pipe_name(pipe)); return 0; } - high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; - low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + high_frame = PIPEFRAME(pipe); + low_frame = PIPEFRAMEPIXEL(pipe); /* * High & low register fields aren't synchronized, so make sure @@ -197,11 +187,11 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; + int reg = PIPE_FRMCOUNT_GM45(pipe); if (!i915_pipe_enabled(dev, pipe)) { DRM_DEBUG_DRIVER("trying to get vblank count for disabled " - "pipe %d\n", pipe); + "pipe %c\n", pipe_name(pipe)); return 0; } @@ -219,7 +209,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, if (!i915_pipe_enabled(dev, pipe)) { DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " - "pipe %d\n", pipe); + "pipe %c\n", pipe_name(pipe)); return 0; } @@ -367,7 +357,7 @@ static void notify_ring(struct drm_device *dev, return; seqno = ring->get_seqno(ring); - trace_i915_gem_request_complete(dev, seqno); + trace_i915_gem_request_complete(ring, seqno); ring->irq_seqno = seqno; wake_up_all(&ring->irq_queue); @@ -377,22 +367,30 @@ static void notify_ring(struct drm_device *dev, jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); } -static void gen6_pm_irq_handler(struct drm_device *dev) +static void gen6_pm_rps_work(struct work_struct *work) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, + rps_work); u8 new_delay = dev_priv->cur_delay; - u32 pm_iir; + u32 pm_iir, pm_imr; + + spin_lock_irq(&dev_priv->rps_lock); + pm_iir = dev_priv->pm_iir; + dev_priv->pm_iir = 0; + pm_imr = I915_READ(GEN6_PMIMR); + spin_unlock_irq(&dev_priv->rps_lock); - pm_iir = I915_READ(GEN6_PMIIR); if (!pm_iir) return; + mutex_lock(&dev_priv->dev->struct_mutex); if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { if (dev_priv->cur_delay != dev_priv->max_delay) new_delay = dev_priv->cur_delay + 1; if (new_delay > dev_priv->max_delay) new_delay = dev_priv->max_delay; } else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) { + gen6_gt_force_wake_get(dev_priv); if (dev_priv->cur_delay != dev_priv->min_delay) new_delay = dev_priv->cur_delay - 1; if (new_delay < dev_priv->min_delay) { @@ -406,19 +404,26 @@ static void gen6_pm_irq_handler(struct drm_device *dev) I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000); } - + gen6_gt_force_wake_put(dev_priv); } - gen6_set_rps(dev, new_delay); + gen6_set_rps(dev_priv->dev, new_delay); dev_priv->cur_delay = new_delay; - I915_WRITE(GEN6_PMIIR, pm_iir); + /* + * rps_lock not held here because clearing is non-destructive. There is + * an *extremely* unlikely race with gen6_rps_enable() that is prevented + * by holding struct_mutex for the duration of the write. + */ + I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir); + mutex_unlock(&dev_priv->dev->struct_mutex); } static void pch_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 pch_iir; + int pipe; pch_iir = I915_READ(SDEIIR); @@ -439,13 +444,11 @@ static void pch_irq_handler(struct drm_device *dev) if (pch_iir & SDE_POISON) DRM_ERROR("PCH poison interrupt\n"); - if (pch_iir & SDE_FDI_MASK) { - u32 fdia, fdib; - - fdia = I915_READ(FDI_RXA_IIR); - fdib = I915_READ(FDI_RXB_IIR); - DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib); - } + if (pch_iir & SDE_FDI_MASK) + for_each_pipe(pipe) + DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", + pipe_name(pipe), + I915_READ(FDI_RX_IIR(pipe))); if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); @@ -459,8 +462,9 @@ static void pch_irq_handler(struct drm_device *dev) DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); } -static irqreturn_t ironlake_irq_handler(struct drm_device *dev) +irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) { + struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; @@ -468,6 +472,8 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) struct drm_i915_master_private *master_priv; u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; + atomic_inc(&dev_priv->irq_received); + if (IS_GEN6(dev)) bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; @@ -537,13 +543,30 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) i915_handle_rps_change(dev); } - if (IS_GEN6(dev)) - gen6_pm_irq_handler(dev); + if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) { + /* + * IIR bits should never already be set because IMR should + * prevent an interrupt from being shown in IIR. The warning + * displays a case where we've unsafely cleared + * dev_priv->pm_iir. Although missing an interrupt of the same + * type is not a problem, it displays a problem in the logic. + * + * The mask bit in IMR is cleared by rps_work. + */ + unsigned long flags; + spin_lock_irqsave(&dev_priv->rps_lock, flags); + WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); + I915_WRITE(GEN6_PMIMR, pm_iir); + dev_priv->pm_iir |= pm_iir; + spin_unlock_irqrestore(&dev_priv->rps_lock, flags); + queue_work(dev_priv->wq, &dev_priv->rps_work); + } /* should clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); I915_WRITE(GTIIR, gt_iir); I915_WRITE(DEIIR, de_iir); + I915_WRITE(GEN6_PMIIR, pm_iir); done: I915_WRITE(DEIER, de_ier); @@ -650,9 +673,14 @@ static void i915_error_state_free(struct drm_device *dev, struct drm_i915_error_state *error) { - i915_error_object_free(error->batchbuffer[0]); - i915_error_object_free(error->batchbuffer[1]); - i915_error_object_free(error->ringbuffer); + int i; + + for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) + i915_error_object_free(error->batchbuffer[i]); + + for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) + i915_error_object_free(error->ringbuffer[i]); + kfree(error->active_bo); kfree(error->overlay); kfree(error); @@ -682,7 +710,7 @@ static u32 capture_bo_list(struct drm_i915_error_buffer *err, err->dirty = obj->dirty; err->purgeable = obj->madv != I915_MADV_WILLNEED; err->ring = obj->ring ? obj->ring->id : 0; - err->agp_type = obj->agp_type == AGP_USER_CACHED_MEMORY; + err->cache_level = obj->cache_level; if (++i == count) break; @@ -767,7 +795,7 @@ static void i915_capture_error_state(struct drm_device *dev) struct drm_i915_gem_object *obj; struct drm_i915_error_state *error; unsigned long flags; - int i; + int i, pipe; spin_lock_irqsave(&dev_priv->error_lock, flags); error = dev_priv->first_error; @@ -775,19 +803,21 @@ static void i915_capture_error_state(struct drm_device *dev) if (error) return; + /* Account for pipe specific data like PIPE*STAT */ error = kmalloc(sizeof(*error), GFP_ATOMIC); if (!error) { DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); return; } - DRM_DEBUG_DRIVER("generating error event\n"); + DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", + dev->primary->index); error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); - error->pipeastat = I915_READ(PIPEASTAT); - error->pipebstat = I915_READ(PIPEBSTAT); + for_each_pipe(pipe) + error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); error->instpm = I915_READ(INSTPM); error->error = 0; if (INTEL_INFO(dev)->gen >= 6) { @@ -826,15 +856,16 @@ static void i915_capture_error_state(struct drm_device *dev) } i915_gem_record_fences(dev, error); - /* Record the active batchbuffers */ - for (i = 0; i < I915_NUM_RINGS; i++) + /* Record the active batch and ring buffers */ + for (i = 0; i < I915_NUM_RINGS; i++) { error->batchbuffer[i] = i915_error_first_batchbuffer(dev_priv, &dev_priv->ring[i]); - /* Record the ringbuffer */ - error->ringbuffer = i915_error_object_create(dev_priv, - dev_priv->ring[RCS].obj); + error->ringbuffer[i] = + i915_error_object_create(dev_priv, + dev_priv->ring[i].obj); + } /* Record buffers on the active and pinned lists. */ error->active_bo = NULL; @@ -907,6 +938,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 eir = I915_READ(EIR); + int pipe; if (!eir) return; @@ -955,14 +987,10 @@ static void i915_report_and_clear_eir(struct drm_device *dev) } if (eir & I915_ERROR_MEMORY_REFRESH) { - u32 pipea_stats = I915_READ(PIPEASTAT); - u32 pipeb_stats = I915_READ(PIPEBSTAT); - - printk(KERN_ERR "memory refresh error\n"); - printk(KERN_ERR "PIPEASTAT: 0x%08x\n", - pipea_stats); - printk(KERN_ERR "PIPEBSTAT: 0x%08x\n", - pipeb_stats); + printk(KERN_ERR "memory refresh error:\n"); + for_each_pipe(pipe) + printk(KERN_ERR "pipe %c stat: 0x%08x\n", + pipe_name(pipe), I915_READ(PIPESTAT(pipe))); /* pipestat has already been acked */ } if (eir & I915_ERROR_INSTRUCTION) { @@ -1076,10 +1104,10 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ obj = work->pending_flip_obj; if (INTEL_INFO(dev)->gen >= 4) { - int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; + int dspsurf = DSPSURF(intel_crtc->plane); stall_detected = I915_READ(dspsurf) == obj->gtt_offset; } else { - int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR; + int dspaddr = DSPADDR(intel_crtc->plane); stall_detected = I915_READ(dspaddr) == (obj->gtt_offset + crtc->y * crtc->fb->pitch + crtc->x * crtc->fb->bits_per_pixel/8); @@ -1099,18 +1127,16 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; struct drm_i915_master_private *master_priv; u32 iir, new_iir; - u32 pipea_stats, pipeb_stats; + u32 pipe_stats[I915_MAX_PIPES]; u32 vblank_status; int vblank = 0; unsigned long irqflags; int irq_received; - int ret = IRQ_NONE; + int ret = IRQ_NONE, pipe; + bool blc_event = false; atomic_inc(&dev_priv->irq_received); - if (HAS_PCH_SPLIT(dev)) - return ironlake_irq_handler(dev); - iir = I915_READ(IIR); if (INTEL_INFO(dev)->gen >= 4) @@ -1127,27 +1153,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) * interrupts (for non-MSI). */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - pipea_stats = I915_READ(PIPEASTAT); - pipeb_stats = I915_READ(PIPEBSTAT); - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) i915_handle_error(dev, false); - /* - * Clear the PIPE(A|B)STAT regs before the IIR - */ - if (pipea_stats & 0x8000ffff) { - if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) - DRM_DEBUG_DRIVER("pipe a underrun\n"); - I915_WRITE(PIPEASTAT, pipea_stats); - irq_received = 1; - } - - if (pipeb_stats & 0x8000ffff) { - if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) - DRM_DEBUG_DRIVER("pipe b underrun\n"); - I915_WRITE(PIPEBSTAT, pipeb_stats); - irq_received = 1; + for_each_pipe(pipe) { + int reg = PIPESTAT(pipe); + pipe_stats[pipe] = I915_READ(reg); + + /* + * Clear the PIPE*STAT regs before the IIR + */ + if (pipe_stats[pipe] & 0x8000ffff) { + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + DRM_DEBUG_DRIVER("pipe %c underrun\n", + pipe_name(pipe)); + I915_WRITE(reg, pipe_stats[pipe]); + irq_received = 1; + } } spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); @@ -1198,27 +1220,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (pipea_stats & vblank_status && - drm_handle_vblank(dev, 0)) { - vblank++; - if (!dev_priv->flip_pending_is_done) { - i915_pageflip_stall_check(dev, 0); - intel_finish_page_flip(dev, 0); + for_each_pipe(pipe) { + if (pipe_stats[pipe] & vblank_status && + drm_handle_vblank(dev, pipe)) { + vblank++; + if (!dev_priv->flip_pending_is_done) { + i915_pageflip_stall_check(dev, pipe); + intel_finish_page_flip(dev, pipe); + } } - } - if (pipeb_stats & vblank_status && - drm_handle_vblank(dev, 1)) { - vblank++; - if (!dev_priv->flip_pending_is_done) { - i915_pageflip_stall_check(dev, 1); - intel_finish_page_flip(dev, 1); - } + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) + blc_event = true; } - if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || - (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || - (iir & I915_ASLE_INTERRUPT)) + + if (blc_event || (iir & I915_ASLE_INTERRUPT)) intel_opregion_asle_intr(dev); /* With MSI, interrupts are only generated when iir @@ -1268,16 +1285,6 @@ static int i915_emit_irq(struct drm_device * dev) return dev_priv->counter; } -void i915_trace_irq_get(struct drm_device *dev, u32 seqno) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - struct intel_ring_buffer *ring = LP_RING(dev_priv); - - if (dev_priv->trace_irq_seqno == 0 && - ring->irq_get(ring)) - dev_priv->trace_irq_seqno = seqno; -} - static int i915_wait_irq(struct drm_device * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1377,7 +1384,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) else i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); + + /* maintain vblank delivery even in deep C-states */ + if (dev_priv->info->gen == 3) + I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + return 0; } @@ -1390,6 +1402,10 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) unsigned long irqflags; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + if (dev_priv->info->gen == 3) + I915_WRITE(INSTPM, + INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); + if (HAS_PCH_SPLIT(dev)) ironlake_disable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); @@ -1400,16 +1416,6 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -void i915_enable_interrupt (struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_PCH_SPLIT(dev)) - intel_opregion_enable_asle(dev); - dev_priv->irq_enabled = 1; -} - - /* Set the vblank monitor pipe */ int i915_vblank_pipe_set(struct drm_device *dev, void *data, @@ -1587,10 +1593,15 @@ repeat: /* drm_dma.h hooks */ -static void ironlake_irq_preinstall(struct drm_device *dev) +void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + atomic_set(&dev_priv->irq_received, 0); + + INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); + INIT_WORK(&dev_priv->error_work, i915_error_work_func); + I915_WRITE(HWSTAM, 0xeffe); /* XXX hotplug from PCH */ @@ -1610,7 +1621,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) POSTING_READ(SDEIER); } -static int ironlake_irq_postinstall(struct drm_device *dev) +int ironlake_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ @@ -1619,6 +1630,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev) u32 render_irqs; u32 hotplug_mask; + DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); + if (HAS_BSD(dev)) + DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); + if (HAS_BLT(dev)) + DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); + + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; dev_priv->irq_mask = ~display_mask; /* should always can generate irq */ @@ -1646,12 +1664,16 @@ static int ironlake_irq_postinstall(struct drm_device *dev) POSTING_READ(GTIER); if (HAS_PCH_CPT(dev)) { - hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT | - SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ; + hotplug_mask = (SDE_CRT_HOTPLUG_CPT | + SDE_PORTB_HOTPLUG_CPT | + SDE_PORTC_HOTPLUG_CPT | + SDE_PORTD_HOTPLUG_CPT); } else { - hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | - SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; - hotplug_mask |= SDE_AUX_MASK; + hotplug_mask = (SDE_CRT_HOTPLUG | + SDE_PORTB_HOTPLUG | + SDE_PORTC_HOTPLUG | + SDE_PORTD_HOTPLUG | + SDE_AUX_MASK); } dev_priv->pch_irq_mask = ~hotplug_mask; @@ -1674,16 +1696,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev) void i915_driver_irq_preinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe; atomic_set(&dev_priv->irq_received, 0); INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); - - if (HAS_PCH_SPLIT(dev)) { - ironlake_irq_preinstall(dev); - return; - } + INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); if (I915_HAS_HOTPLUG(dev)) { I915_WRITE(PORT_HOTPLUG_EN, 0); @@ -1691,8 +1710,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) } I915_WRITE(HWSTAM, 0xeffe); - I915_WRITE(PIPEASTAT, 0); - I915_WRITE(PIPEBSTAT, 0); + for_each_pipe(pipe) + I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); POSTING_READ(IER); @@ -1708,17 +1727,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev) u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; u32 error_mask; - DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); - if (HAS_BSD(dev)) - DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); - if (HAS_BLT(dev)) - DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; - if (HAS_PCH_SPLIT(dev)) - return ironlake_irq_postinstall(dev); - /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX; @@ -1787,9 +1797,15 @@ int i915_driver_irq_postinstall(struct drm_device *dev) return 0; } -static void ironlake_irq_uninstall(struct drm_device *dev) +void ironlake_irq_uninstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (!dev_priv) + return; + + dev_priv->vblank_pipe = 0; + I915_WRITE(HWSTAM, 0xffffffff); I915_WRITE(DEIMR, 0xffffffff); @@ -1804,29 +1820,26 @@ static void ironlake_irq_uninstall(struct drm_device *dev) void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int pipe; if (!dev_priv) return; dev_priv->vblank_pipe = 0; - if (HAS_PCH_SPLIT(dev)) { - ironlake_irq_uninstall(dev); - return; - } - if (I915_HAS_HOTPLUG(dev)) { I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } I915_WRITE(HWSTAM, 0xffffffff); - I915_WRITE(PIPEASTAT, 0); - I915_WRITE(PIPEBSTAT, 0); + for_each_pipe(pipe) + I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); - I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); + for_each_pipe(pipe) + I915_WRITE(PIPESTAT(pipe), + I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); }