From: Jesse B. <jb...@vi...> - 2010-03-26 18:08:08
|
When we call drm_vblank_off() at DPMS off time (to wake any clients so they don't hang) we need to make sure interrupts are actually disabled. If drm_vblank_off() gets called before the vblank usage timer expires, it'll prevent the timer from disabling interrupts since it also clears the vblank_enabled flag for the pipe. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/drm_irq.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b98384d..99ce7dc 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -475,6 +475,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) unsigned long irqflags; spin_lock_irqsave(&dev->vbl_lock, irqflags); + dev->driver->disable_vblank(dev, crtc); DRM_WAKEUP(&dev->vbl_queue[crtc]); dev->vblank_enabled[crtc] = 0; dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:08:09
|
Drivers may use vblank calls now (e.g. drm_vblank_off) in their unload paths, so don't clean up the vblank related structures until after driver unload. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/drm_stub.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index ad73e14..543e79c 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -515,8 +515,6 @@ void drm_put_dev(struct drm_device *dev) } driver = dev->driver; - drm_vblank_cleanup(dev); - drm_lastclose(dev); if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && @@ -536,6 +534,8 @@ void drm_put_dev(struct drm_device *dev) dev->agp = NULL; } + drm_vblank_cleanup(dev); + list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) drm_rmmap(dev, r_list->map); drm_ht_remove(&dev->map_hash); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:08:11
|
Just use the PIPEASTAT definitions, and kill a related, unused variable in i915_irq_handler while we're there. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_irq.c | 23 +++++++++-------------- drivers/gpu/drm/i915/i915_reg.h | 26 -------------------------- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5388354..eca0e5b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -170,7 +170,7 @@ void intel_enable_asle (struct drm_device *dev) ironlake_enable_display_irq(dev_priv, DE_GSE); else i915_enable_pipestat(dev_priv, 1, - I915_LEGACY_BLC_EVENT_ENABLE); + PIPE_LEGACY_BLC_EVENT_ENABLE); } /** @@ -832,9 +832,7 @@ 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 vblank_status; - u32 vblank_enable; + u32 pipea_stats, pipeb_stats, pipe_vblank_mask; int vblank = 0; unsigned long irqflags; int irq_received; @@ -847,13 +845,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) iir = I915_READ(IIR); - if (IS_I965G(dev)) { - vblank_status = I915_START_VBLANK_INTERRUPT_STATUS; - vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE; - } else { - vblank_status = I915_VBLANK_INTERRUPT_STATUS; - vblank_enable = I915_VBLANK_INTERRUPT_ENABLE; - } + if (IS_I965G(dev)) + pipe_vblank_mask = PIPE_START_VBLANK_INTERRUPT_STATUS; + else + pipe_vblank_mask = PIPE_VBLANK_INTERRUPT_STATUS; for (;;) { irq_received = iir != 0; @@ -933,19 +928,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) intel_prepare_page_flip(dev, 1); - if (pipea_stats & vblank_status) { + if (pipea_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 0); intel_finish_page_flip(dev, 0); } - if (pipeb_stats & vblank_status) { + if (pipeb_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 1); intel_finish_page_flip(dev, 1); } - if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || + if ((pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || (iir & I915_ASLE_INTERRUPT)) opregion_asle_intr(dev); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2720bc2..df20187 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -486,32 +486,6 @@ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ -#define I915_FIFO_UNDERRUN_STATUS (1UL<<31) -#define I915_CRC_ERROR_ENABLE (1UL<<29) -#define I915_CRC_DONE_ENABLE (1UL<<28) -#define I915_GMBUS_EVENT_ENABLE (1UL<<27) -#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25) -#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24) -#define I915_DPST_EVENT_ENABLE (1UL<<23) -#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22) -#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21) -#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20) -#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */ -#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) -#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16) -#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13) -#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12) -#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11) -#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9) -#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) -#define I915_DPST_EVENT_STATUS (1UL<<7) -#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6) -#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) -#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4) -#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ -#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1) -#define I915_OVERLAY_UPDATED_STATUS (1UL<<0) - #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 #define SR01 1 -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:08:13
|
Most of the PIPE*STAT status bits will continue to flip even if they're not generating interrupts. So only check for those that can cause interrupts when we reach the i915_irq_handler, since it might be shared and we don't want to process spurious events. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index aba8260..abf2713 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -260,6 +260,7 @@ typedef struct drm_i915_private { /** Cached value of IMR to avoid reads in updating the bitfield */ u32 irq_mask_reg; u32 pipestat[2]; + u32 pipe_mask[2]; /** splitted irq regs for graphics and display engine on Ironlake, irq_mask_reg is still used for display irq. */ u32 gt_irq_mask_reg; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index eca0e5b..9519346 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -141,6 +141,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) u32 reg = i915_pipestat(pipe); dev_priv->pipestat[pipe] |= mask; + dev_priv->pipe_mask[pipe] |= (mask >> 16); /* Enable the interrupt, clear any pending status */ I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16)); (void) I915_READ(reg); @@ -154,6 +155,7 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) u32 reg = i915_pipestat(pipe); dev_priv->pipestat[pipe] &= ~mask; + dev_priv->pipe_mask[pipe] &= ~(mask >> 16); I915_WRITE(reg, dev_priv->pipestat[pipe]); (void) I915_READ(reg); } @@ -868,14 +870,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) /* * Clear the PIPE(A|B)STAT regs before the IIR */ - if (pipea_stats & 0x8000ffff) { + if (pipea_stats & dev_priv->pipe_mask[0]) { 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 & dev_priv->pipe_mask[1]) { if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) DRM_DEBUG_DRIVER("pipe b underrun\n"); I915_WRITE(PIPEBSTAT, pipeb_stats); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:12:57
|
On Fri, 26 Mar 2010 11:07:18 -0700 Jesse Barnes <jb...@vi...> wrote: > Most of the PIPE*STAT status bits will continue to flip even if they're > not generating interrupts. So only check for those that can cause > interrupts when we reach the i915_irq_handler, since it might be shared > and we don't want to process spurious events. > > Signed-off-by: Jesse Barnes <jb...@vi...> > --- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/i915_irq.c | 6 ++++-- > 2 files changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index aba8260..abf2713 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -260,6 +260,7 @@ typedef struct drm_i915_private { > /** Cached value of IMR to avoid reads in updating the bitfield */ > u32 irq_mask_reg; > u32 pipestat[2]; > + u32 pipe_mask[2]; > /** splitted irq regs for graphics and display engine on Ironlake, > irq_mask_reg is still used for display irq. */ > u32 gt_irq_mask_reg; > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index eca0e5b..9519346 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -141,6 +141,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) > u32 reg = i915_pipestat(pipe); > > dev_priv->pipestat[pipe] |= mask; > + dev_priv->pipe_mask[pipe] |= (mask >> 16); > /* Enable the interrupt, clear any pending status */ > I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16)); > (void) I915_READ(reg); > @@ -154,6 +155,7 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) > u32 reg = i915_pipestat(pipe); > > dev_priv->pipestat[pipe] &= ~mask; > + dev_priv->pipe_mask[pipe] &= ~(mask >> 16); > I915_WRITE(reg, dev_priv->pipestat[pipe]); > (void) I915_READ(reg); > } > @@ -868,14 +870,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) > /* > * Clear the PIPE(A|B)STAT regs before the IIR > */ > - if (pipea_stats & 0x8000ffff) { > + if (pipea_stats & dev_priv->pipe_mask[0]) { > 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 & dev_priv->pipe_mask[1]) { > if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) > DRM_DEBUG_DRIVER("pipe b underrun\n"); > I915_WRITE(PIPEBSTAT, pipeb_stats); Still testing 4-6 on GM45 to make sure I haven't broken anything on non-gen3, additional testing would be appreciated too. These core changes always make me nervous. -- Jesse Barnes, Intel Open Source Technology Center |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:09:10
|
On 945, vblank delivery alone seems unreliable. The PIPE*STAT bits get set correctly, but interrupts occur at a low frequency relative to refresh. If we enable VSYNC interrupts as well however (even though we only check for VBLANK interrupts when handling) we get the right frequency. Increases OA performance on my AspireOne by about 300% with the new DRI2 bits, which rely on high frequency vblank events. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_irq.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9519346..b16bb0d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -45,8 +45,8 @@ */ #define I915_INTERRUPT_ENABLE_FIX \ (I915_ASLE_INTERRUPT | \ - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \ + I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \ I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | \ I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | \ I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) @@ -1132,6 +1132,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) PIPE_START_VBLANK_INTERRUPT_ENABLE); else i915_enable_pipestat(dev_priv, pipe, + PIPE_VSYNC_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); return 0; @@ -1151,6 +1152,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); else i915_disable_pipestat(dev_priv, pipe, + PIPE_VSYNC_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE | PIPE_START_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-04-27 17:28:00
|
On Fri, 26 Mar 2010 11:07:19 -0700 Jesse Barnes <jb...@vi...> wrote: > On 945, vblank delivery alone seems unreliable. The PIPE*STAT bits get > set correctly, but interrupts occur at a low frequency relative to > refresh. If we enable VSYNC interrupts as well however (even though we > only check for VBLANK interrupts when handling) we get the right > frequency. Increases OA performance on my AspireOne by about 300% with > the new DRI2 bits, which rely on high frequency vblank events. > > Signed-off-by: Jesse Barnes <jb...@vi...> > --- Ignore this patch; it's still broken. Working on a fix now. -- Jesse Barnes, Intel Open Source Technology Center |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:10:26
|
Gen3 chips have slightly different flip commands, and also contain a bit that indicates whether a "flip pending" interrupt means the flip has been queued or has been completed. So implement support for the gen3 flip command, and make sure we use the flip pending interrupt correctly depending on the value of ECOSKPD bit 0. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 21 +++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 29 ++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 1 + 6 files changed, 51 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a9f8589..193bf16 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1475,6 +1475,10 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + /* IIR "flip pending" bit means done if this bit is set */ + if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE)) + dev_priv->flip_pending_is_done = true; + intel_modeset_init(dev); ret = drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index abf2713..4e41f0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -608,6 +608,7 @@ typedef struct drm_i915_private { struct drm_crtc *plane_to_crtc_mapping[2]; struct drm_crtc *pipe_to_crtc_mapping[2]; wait_queue_head_t pending_flip_queue; + bool flip_pending_is_done; /* Reclocking support */ bool render_reclock_avail; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b16bb0d..d5eeca6 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -924,22 +924,35 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } - if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) + if ((iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) && + !(pipeb_stats & pipe_vblank_mask)) { + DRM_ERROR("flip complete w/o vblank irq?\n"); + } + + if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 0); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 0); + } - if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) + if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 1); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 1); + } if (pipea_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 0); - intel_finish_page_flip(dev, 0); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 0); } if (pipeb_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 1); - intel_finish_page_flip(dev, 1); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 1); } if ((pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index df20187..9179b38 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -178,6 +178,7 @@ #define MI_OVERLAY_OFF (0x2<<21) #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ @@ -357,6 +358,9 @@ #define CM0_RC_OP_FLUSH_DISABLE (1<<0) #define BB_ADDR 0x02140 /* 8 bytes */ #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ +#define ECOSKPD 0x021d0 +#define ECO_GATING_CX_ONLY (1<<3) +#define ECO_FLIP_DONE (1<<0) /* diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 92ca56c..cd6f8b7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4136,10 +4136,10 @@ static void intel_unpin_work_fn(struct work_struct *__work) kfree(work); } -void intel_finish_page_flip(struct drm_device *dev, int pipe) +static void do_intel_finish_page_flip(struct drm_device *dev, + struct drm_crtc *crtc) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; struct drm_i915_gem_object *obj_priv; @@ -4189,6 +4189,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) schedule_work(&work->work); } +void intel_finish_page_flip(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + do_intel_finish_page_flip(dev, crtc); +} + +void intel_finish_page_flip_plane(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; + + do_intel_finish_page_flip(dev, crtc); +} + void intel_prepare_page_flip(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -4270,14 +4286,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->pending_flip_obj = obj; BEGIN_LP_RING(4); - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); if (IS_I965G(dev)) { + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); pipesrc = I915_READ(pipesrc_reg); OUT_RING(pipesrc & 0x0fff0fff); } else { + OUT_RING(MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset); OUT_RING(MI_NOOP); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3a467ca..8323225 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -219,6 +219,7 @@ extern int intel_framebuffer_create(struct drm_device *dev, extern void intel_prepare_page_flip(struct drm_device *dev, int plane); extern void intel_finish_page_flip(struct drm_device *dev, int pipe); +extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); extern void intel_setup_overlay(struct drm_device *dev); extern void intel_cleanup_overlay(struct drm_device *dev); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 18:11:48
|
We'll turn off outputs etc at unload time, so don't unmap the registers before doing it. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 193bf16..91a3c3d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1760,6 +1760,8 @@ int i915_driver_unload(struct drm_device *dev) } if (drm_core_check_feature(dev, DRIVER_MODESET)) { + intel_modeset_cleanup(dev); + /* * free the memory space allocated for the child device * config parsed from VBT @@ -1783,8 +1785,6 @@ int i915_driver_unload(struct drm_device *dev) intel_opregion_free(dev, 0); if (drm_core_check_feature(dev, DRIVER_MODESET)) { - intel_modeset_cleanup(dev); - i915_gem_free_all_phys_object(dev); mutex_lock(&dev->struct_mutex); -- 1.6.1.3 |
From: Jesse B. <jb...@vi...> - 2010-03-26 20:41:55
|
On Fri, 26 Mar 2010 11:07:20 -0700 Jesse Barnes <jb...@vi...> wrote: > - if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) > + if ((iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) && > + !(pipeb_stats & pipe_vblank_mask)) { > + DRM_ERROR("flip complete w/o vblank irq?\n"); > + } Oops, this hunk definitely doesn't belong here. I'll post an update to this one. -- Jesse Barnes, Intel Open Source Technology Center |
From: Jesse B. <jb...@vi...> - 2010-04-05 21:10:03
|
On Fri, 26 Mar 2010 13:41:08 -0700 Jesse Barnes <jb...@vi...> wrote: > On Fri, 26 Mar 2010 11:07:20 -0700 > Jesse Barnes <jb...@vi...> wrote: > > > - if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) > > + if ((iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) && > > + !(pipeb_stats & pipe_vblank_mask)) { > > + DRM_ERROR("flip complete w/o vblank irq?\n"); > > + } > > Oops, this hunk definitely doesn't belong here. I'll post an update to > this one. Updated patch w/o the extra debug statement. --- From 34265649a24f92a9fa004d27ca869cc3dd750fe3 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jb...@vi...> Date: Fri, 26 Mar 2010 10:35:20 -0700 Subject: [PATCH 1/3] drm/i915: fix page flipping on gen3 Gen3 chips have slightly different flip commands, and also contain a bit that indicates whether a "flip pending" interrupt means the flip has been queued or has been completed. So implement support for the gen3 flip command, and make sure we use the flip pending interrupt correctly depending on the value of ECOSKPD bit 0. Signed-off-by: Jesse Barnes <jb...@vi...> --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 16 ++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 29 ++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 1 + 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a9f8589..193bf16 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1475,6 +1475,10 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + /* IIR "flip pending" bit means done if this bit is set */ + if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE)) + dev_priv->flip_pending_is_done = true; + intel_modeset_init(dev); ret = drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index abf2713..4e41f0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -608,6 +608,7 @@ typedef struct drm_i915_private { struct drm_crtc *plane_to_crtc_mapping[2]; struct drm_crtc *pipe_to_crtc_mapping[2]; wait_queue_head_t pending_flip_queue; + bool flip_pending_is_done; /* Reclocking support */ bool render_reclock_avail; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b16bb0d..79cbead 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -924,22 +924,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } - if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) + if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 0); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 0); + } - if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) + if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 1); + if (dev_priv->flip_pending_is_done) + intel_finish_page_flip_plane(dev, 1); + } if (pipea_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 0); - intel_finish_page_flip(dev, 0); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 0); } if (pipeb_stats & pipe_vblank_mask) { vblank++; drm_handle_vblank(dev, 1); - intel_finish_page_flip(dev, 1); + if (!dev_priv->flip_pending_is_done) + intel_finish_page_flip(dev, 1); } if ((pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index df20187..9179b38 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -178,6 +178,7 @@ #define MI_OVERLAY_OFF (0x2<<21) #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ @@ -357,6 +358,9 @@ #define CM0_RC_OP_FLUSH_DISABLE (1<<0) #define BB_ADDR 0x02140 /* 8 bytes */ #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ +#define ECOSKPD 0x021d0 +#define ECO_GATING_CX_ONLY (1<<3) +#define ECO_FLIP_DONE (1<<0) /* diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0e2c5da..6f5e7f5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4136,10 +4136,10 @@ static void intel_unpin_work_fn(struct work_struct *__work) kfree(work); } -void intel_finish_page_flip(struct drm_device *dev, int pipe) +static void do_intel_finish_page_flip(struct drm_device *dev, + struct drm_crtc *crtc) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; struct drm_i915_gem_object *obj_priv; @@ -4189,6 +4189,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) schedule_work(&work->work); } +void intel_finish_page_flip(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + do_intel_finish_page_flip(dev, crtc); +} + +void intel_finish_page_flip_plane(struct drm_device *dev, int plane) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; + + do_intel_finish_page_flip(dev, crtc); +} + void intel_prepare_page_flip(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -4270,14 +4286,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->pending_flip_obj = obj; BEGIN_LP_RING(4); - OUT_RING(MI_DISPLAY_FLIP | - MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch); if (IS_I965G(dev)) { + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); pipesrc = I915_READ(pipesrc_reg); OUT_RING(pipesrc & 0x0fff0fff); } else { + OUT_RING(MI_DISPLAY_FLIP_I915 | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch); OUT_RING(obj_priv->gtt_offset); OUT_RING(MI_NOOP); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3a467ca..8323225 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -219,6 +219,7 @@ extern int intel_framebuffer_create(struct drm_device *dev, extern void intel_prepare_page_flip(struct drm_device *dev, int plane); extern void intel_finish_page_flip(struct drm_device *dev, int pipe); +extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); extern void intel_setup_overlay(struct drm_device *dev); extern void intel_cleanup_overlay(struct drm_device *dev); -- 1.6.6.1 |
From: Kristian H. <kr...@bi...> - 2010-03-28 22:30:24
|
On Fri, Mar 26, 2010 at 7:07 PM, Jesse Barnes <jb...@vi...> wrote: > Drivers may use vblank calls now (e.g. drm_vblank_off) in their unload > paths, so don't clean up the vblank related structures until after > driver unload. I haven't tested this specific patch on a recent DRM, but I made the same patch a while ago, and it fixed module unload for me. I sent it to the list and it fell through the cracks, because "vblank is hard" or something. Reviewed-by: Kristian Høgsberg <kr...@bi...> > Signed-off-by: Jesse Barnes <jb...@vi...> > --- > drivers/gpu/drm/drm_stub.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c > index ad73e14..543e79c 100644 > --- a/drivers/gpu/drm/drm_stub.c > +++ b/drivers/gpu/drm/drm_stub.c > @@ -515,8 +515,6 @@ void drm_put_dev(struct drm_device *dev) > } > driver = dev->driver; > > - drm_vblank_cleanup(dev); > - > drm_lastclose(dev); > > if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && > @@ -536,6 +534,8 @@ void drm_put_dev(struct drm_device *dev) > dev->agp = NULL; > } > > + drm_vblank_cleanup(dev); > + > list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) > drm_rmmap(dev, r_list->map); > drm_ht_remove(&dev->map_hash); > -- > 1.6.1.3 > > _______________________________________________ > Intel-gfx mailing list > Int...@li... > http://lists.freedesktop.org/mailman/listinfo/intel-gfx > |
From: Dave A. <ai...@gm...> - 2010-03-29 00:02:10
|
2010/3/29 Kristian Høgsberg <kr...@bi...>: > On Fri, Mar 26, 2010 at 7:07 PM, Jesse Barnes <jb...@vi...> wrote: >> Drivers may use vblank calls now (e.g. drm_vblank_off) in their unload >> paths, so don't clean up the vblank related structures until after >> driver unload. > > I haven't tested this specific patch on a recent DRM, but I made the > same patch a while ago, and it fixed module unload for me. I sent it > to the list and it fell through the cracks, because "vblank is hard" > or something. > > Reviewed-by: Kristian Høgsberg <kr...@bi...> I didn't apply it because from what I can see non-kms drivers need to free the vbl stuff on lastclose not unload. I'm nearly sure I said that at the time to. This patch seems to suffer from the same problem from what I can see. And really someone should already have cleaned up the insanity that is vbl struct allocations, vblank might not be hard, but it sure has some ugly. Dave. |
From: Dave A. <ai...@gm...> - 2010-03-29 00:09:48
|
2010/3/29 Dave Airlie <ai...@gm...>: > 2010/3/29 Kristian Høgsberg <kr...@bi...>: >> On Fri, Mar 26, 2010 at 7:07 PM, Jesse Barnes <jb...@vi...> wrote: >>> Drivers may use vblank calls now (e.g. drm_vblank_off) in their unload >>> paths, so don't clean up the vblank related structures until after >>> driver unload. >> >> I haven't tested this specific patch on a recent DRM, but I made the >> same patch a while ago, and it fixed module unload for me. I sent it >> to the list and it fell through the cracks, because "vblank is hard" >> or something. >> >> Reviewed-by: Kristian Høgsberg <kr...@bi...> > > I didn't apply it because from what I can see non-kms drivers need > to free the vbl stuff on lastclose not unload. I'm nearly sure I said > that at the > time to. > > This patch seems to suffer from the same problem from what I can see. > > And really someone should already have cleaned up the insanity that is vbl > struct allocations, vblank might not be hard, but it sure has some ugly. Oops on reading it makes more sense, I thought we were moving it from lastclose, my bad, too little sleep. Okay I'll push it in next push. Dave. > > Dave. > |
From: Jesse B. <jb...@vi...> - 2010-03-29 16:06:44
|
On Mon, 29 Mar 2010 10:02:04 +1000 Dave Airlie <ai...@gm...> wrote: > 2010/3/29 Kristian Høgsberg <kr...@bi...>: > > On Fri, Mar 26, 2010 at 7:07 PM, Jesse Barnes <jb...@vi...> wrote: > >> Drivers may use vblank calls now (e.g. drm_vblank_off) in their unload > >> paths, so don't clean up the vblank related structures until after > >> driver unload. > > > > I haven't tested this specific patch on a recent DRM, but I made the > > same patch a while ago, and it fixed module unload for me. I sent it > > to the list and it fell through the cracks, because "vblank is hard" > > or something. > > > > Reviewed-by: Kristian Høgsberg <kr...@bi...> > > I didn't apply it because from what I can see non-kms drivers need > to free the vbl stuff on lastclose not unload. I'm nearly sure I said > that at the > time to. > > This patch seems to suffer from the same problem from what I can see. > > And really someone should already have cleaned up the insanity that is vbl > struct allocations, vblank might not be hard, but it sure has some ugly. Arg, yeah I didn't consider non-kms drivers. And we had a patch to bunch all the vbl info into a single struct, but iirc it came along as we were still adding fields so never got applied. Anyway I'll fix up this patch and re-post. -- Jesse Barnes, Intel Open Source Technology Center |