Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote: Add runtime PM support for VLV, but leave it disabled. The next patch enables it. The suspend/resume sequence used is based on [1] and [2]. In practice we depend on the GT RC6 mechanism to save the HW context depending on the render and media power wells. By the time we run the runtime suspend callback the display side is also off and the HW context for that is managed by the display power domain framework. Besides the above there are Gunit registers that depend on a system-wide power well. This power well goes off once the device enters any of the S0i[R123] states. To handle this scenario, save/restore these Gunit registers. Note that this is not the complete register set dictated by [2], to remove some overhead, registers that are known not to be used are ignored. Also some registers are fully setup by initialization functions called during resume, these are not saved either. The list of registers can be further reduced, see the TODO note in the code. [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit [2] VLV2_S0IXRegs Signed-off-by: Imre Deak imre.d...@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 327 drivers/gpu/drm/i915/i915_drv.h | 62 2 files changed, 389 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 08e210c..bc206dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv) return 0; } +/* + * Save all Gunit registers that may be lost after a D3 and a subsequent + * S0i[R123] transition. The list of registers needing a save/restore is + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit + * registers in the following way: + * - Driver: saved/restored by the driver + * - Punit : saved/restored by the Punit firmware + * - No, w/o marking: no need to save/restore, since the register is R/O or + *used internally by the HW in a way that doesn't depend + *keeping the content across a suspend/resume. + * - Debug : used for debugging + * + * We save/restore all registers marked with 'Driver', with the following + * exceptions: + * - Registers out of use, including also registers marked with 'Debug'. + * These have no effect on the driver's operation, so we don't save/restore + * them to reduce the overhead. + * - Registers that are fully setup by an initialization function called from + * the resume path. For example many clock gating and RPS/RC6 registers. + * - Registers that provide the right functionality with their reset defaults. + * + * TODO: Except for registers that based on the above 3 criteria can be safely + * ignored, we save/restore all others, practically treating the HW context as + * a black-box for the driver. Further investigation is needed to reduce the + * saved/restored registers even further, by following the same 3 criteria. + */ +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) +{ + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state; + int i; + + /* GAM 0x4000-0x4770 */ + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK); + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL); + s-arb_mode = I915_READ(ARB_MODE); + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0); + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1); + + for (i = 0; i ARRAY_SIZE(s-lra_limits); i++) + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + + s-media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + + s-render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); + s-ecochk = I915_READ(GAM_ECOCHK); + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7); + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7); + + s-tlb_rd_addr = I915_READ(GEN7_TLB_RD_ADDR); + + /* MBC 0x9024-0x91D0, 0x8500 */ + s-g3dctl = I915_READ(GEN7_G3DCTL); + s-gsckgctl = I915_READ(GEN7_GSCKGCTL); + s-mbctl= I915_READ(GEN6_MBCTL); + + /* GCP 0x9400-0x9424, 0x8100-0x810C */ + s-ucgctl1 = I915_READ(GEN6_UCGCTL1); + s-ucgctl3 = I915_READ(GEN7_UCGCTL3); + s-rcgctl1 = I915_READ(GEN7_RCGCTL1); + s-rcgctl2 = I915_READ(GEN7_RCGCTL2); + s-rstctl = I915_READ(GEN7_RSTCTL); + s-misccpctl= I915_READ(GEN7_MISCCPCTL); + + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */ + s-gfxpause = I915_READ(GEN7_GFXPAUSE); + s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC); + s-rpdeuc
Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote: Add runtime PM support for VLV, but leave it disabled. The next patch enables it. The suspend/resume sequence used is based on [1] and [2]. In practice we depend on the GT RC6 mechanism to save the HW context depending on the render and media power wells. By the time we run the runtime suspend callback the display side is also off and the HW context for that is managed by the display power domain framework. Besides the above there are Gunit registers that depend on a system-wide power well. This power well goes off once the device enters any of the S0i[R123] states. To handle this scenario, save/restore these Gunit registers. Note that this is not the complete register set dictated by [2], to remove some overhead, registers that are known not to be used are ignored. Also some registers are fully setup by initialization functions called during resume, these are not saved either. The list of registers can be further reduced, see the TODO note in the code. [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit [2] VLV2_S0IXRegs Signed-off-by: Imre Deak imre.d...@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 327 drivers/gpu/drm/i915/i915_drv.h | 62 2 files changed, 389 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 08e210c..bc206dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv) return 0; } +/* + * Save all Gunit registers that may be lost after a D3 and a subsequent + * S0i[R123] transition. The list of registers needing a save/restore is + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit + * registers in the following way: + * - Driver: saved/restored by the driver + * - Punit : saved/restored by the Punit firmware + * - No, w/o marking: no need to save/restore, since the register is R/O or + *used internally by the HW in a way that doesn't depend + *keeping the content across a suspend/resume. + * - Debug : used for debugging + * + * We save/restore all registers marked with 'Driver', with the following + * exceptions: + * - Registers out of use, including also registers marked with 'Debug'. + * These have no effect on the driver's operation, so we don't save/restore + * them to reduce the overhead. + * - Registers that are fully setup by an initialization function called from + * the resume path. For example many clock gating and RPS/RC6 registers. + * - Registers that provide the right functionality with their reset defaults. + * + * TODO: Except for registers that based on the above 3 criteria can be safely + * ignored, we save/restore all others, practically treating the HW context as + * a black-box for the driver. Further investigation is needed to reduce the + * saved/restored registers even further, by following the same 3 criteria. + */ +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) +{ + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state; + int i; + + /* GAM 0x4000-0x4770 */ + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK); + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL); + s-arb_mode = I915_READ(ARB_MODE); + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0); + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1); + + for (i = 0; i ARRAY_SIZE(s-lra_limits); i++) + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + + s-media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + + s-render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); + s-ecochk = I915_READ(GAM_ECOCHK); + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7); + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7); + + s-tlb_rd_addr = I915_READ(GEN7_TLB_RD_ADDR); + + /* MBC 0x9024-0x91D0, 0x8500 */ + s-g3dctl = I915_READ(GEN7_G3DCTL); + s-gsckgctl = I915_READ(GEN7_GSCKGCTL); + s-mbctl= I915_READ(GEN6_MBCTL); + + /* GCP 0x9400-0x9424, 0x8100-0x810C */ + s-ucgctl1 = I915_READ(GEN6_UCGCTL1); + s-ucgctl3 = I915_READ(GEN7_UCGCTL3); + s-rcgctl1 = I915_READ(GEN7_RCGCTL1); + s-rcgctl2 = I915_READ(GEN7_RCGCTL2); + s-rstctl = I915_READ(GEN7_RSTCTL); + s-misccpctl= I915_READ(GEN7_MISCCPCTL); + + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */ + s-gfxpause = I915_READ(GEN7_GFXPAUSE); + s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC); + s-rpdeuc
Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
On Wed, 2014-04-16 at 16:53 +0200, Daniel Vetter wrote: On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote: Add runtime PM support for VLV, but leave it disabled. The next patch enables it. The suspend/resume sequence used is based on [1] and [2]. In practice we depend on the GT RC6 mechanism to save the HW context depending on the render and media power wells. By the time we run the runtime suspend callback the display side is also off and the HW context for that is managed by the display power domain framework. Besides the above there are Gunit registers that depend on a system-wide power well. This power well goes off once the device enters any of the S0i[R123] states. To handle this scenario, save/restore these Gunit registers. Note that this is not the complete register set dictated by [2], to remove some overhead, registers that are known not to be used are ignored. Also some registers are fully setup by initialization functions called during resume, these are not saved either. The list of registers can be further reduced, see the TODO note in the code. [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit [2] VLV2_S0IXRegs Signed-off-by: Imre Deak imre.d...@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 327 drivers/gpu/drm/i915/i915_drv.h | 62 2 files changed, 389 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 08e210c..bc206dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv) return 0; } +/* + * Save all Gunit registers that may be lost after a D3 and a subsequent + * S0i[R123] transition. The list of registers needing a save/restore is + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit + * registers in the following way: + * - Driver: saved/restored by the driver + * - Punit : saved/restored by the Punit firmware + * - No, w/o marking: no need to save/restore, since the register is R/O or + *used internally by the HW in a way that doesn't depend + *keeping the content across a suspend/resume. + * - Debug : used for debugging + * + * We save/restore all registers marked with 'Driver', with the following + * exceptions: + * - Registers out of use, including also registers marked with 'Debug'. + * These have no effect on the driver's operation, so we don't save/restore + * them to reduce the overhead. + * - Registers that are fully setup by an initialization function called from + * the resume path. For example many clock gating and RPS/RC6 registers. + * - Registers that provide the right functionality with their reset defaults. + * + * TODO: Except for registers that based on the above 3 criteria can be safely + * ignored, we save/restore all others, practically treating the HW context as + * a black-box for the driver. Further investigation is needed to reduce the + * saved/restored registers even further, by following the same 3 criteria. + */ +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) +{ + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state; + int i; + + /* GAM 0x4000-0x4770 */ + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK); + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL); + s-arb_mode = I915_READ(ARB_MODE); + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0); + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1); + + for (i = 0; i ARRAY_SIZE(s-lra_limits); i++) + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + + s-media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + + s-render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); + s-ecochk = I915_READ(GAM_ECOCHK); + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7); + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7); + + s-tlb_rd_addr = I915_READ(GEN7_TLB_RD_ADDR); + + /* MBC 0x9024-0x91D0, 0x8500 */ + s-g3dctl = I915_READ(GEN7_G3DCTL); + s-gsckgctl = I915_READ(GEN7_GSCKGCTL); + s-mbctl= I915_READ(GEN6_MBCTL); + + /* GCP 0x9400-0x9424, 0x8100-0x810C */ + s-ucgctl1 = I915_READ(GEN6_UCGCTL1); + s-ucgctl3 = I915_READ(GEN7_UCGCTL3); + s-rcgctl1 = I915_READ(GEN7_RCGCTL1); + s-rcgctl2 = I915_READ(GEN7_RCGCTL2); + s-rstctl = I915_READ(GEN7_RSTCTL); + s-misccpctl= I915_READ(GEN7_MISCCPCTL); + + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */ + s-gfxpause
[Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support
Add runtime PM support for VLV, but leave it disabled. The next patch enables it. The suspend/resume sequence used is based on [1] and [2]. In practice we depend on the GT RC6 mechanism to save the HW context depending on the render and media power wells. By the time we run the runtime suspend callback the display side is also off and the HW context for that is managed by the display power domain framework. Besides the above there are Gunit registers that depend on a system-wide power well. This power well goes off once the device enters any of the S0i[R123] states. To handle this scenario, save/restore these Gunit registers. Note that this is not the complete register set dictated by [2], to remove some overhead, registers that are known not to be used are ignored. Also some registers are fully setup by initialization functions called during resume, these are not saved either. The list of registers can be further reduced, see the TODO note in the code. [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit [2] VLV2_S0IXRegs Signed-off-by: Imre Deak imre.d...@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 327 drivers/gpu/drm/i915/i915_drv.h | 62 2 files changed, 389 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 08e210c..bc206dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private *dev_priv) return 0; } +/* + * Save all Gunit registers that may be lost after a D3 and a subsequent + * S0i[R123] transition. The list of registers needing a save/restore is + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit + * registers in the following way: + * - Driver: saved/restored by the driver + * - Punit : saved/restored by the Punit firmware + * - No, w/o marking: no need to save/restore, since the register is R/O or + *used internally by the HW in a way that doesn't depend + *keeping the content across a suspend/resume. + * - Debug : used for debugging + * + * We save/restore all registers marked with 'Driver', with the following + * exceptions: + * - Registers out of use, including also registers marked with 'Debug'. + * These have no effect on the driver's operation, so we don't save/restore + * them to reduce the overhead. + * - Registers that are fully setup by an initialization function called from + * the resume path. For example many clock gating and RPS/RC6 registers. + * - Registers that provide the right functionality with their reset defaults. + * + * TODO: Except for registers that based on the above 3 criteria can be safely + * ignored, we save/restore all others, practically treating the HW context as + * a black-box for the driver. Further investigation is needed to reduce the + * saved/restored registers even further, by following the same 3 criteria. + */ +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) +{ + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state; + int i; + + /* GAM 0x4000-0x4770 */ + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK); + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL); + s-arb_mode = I915_READ(ARB_MODE); + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0); + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1); + + for (i = 0; i ARRAY_SIZE(s-lra_limits); i++) + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + + s-media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); + + s-render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); + s-ecochk = I915_READ(GAM_ECOCHK); + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7); + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7); + + s-tlb_rd_addr = I915_READ(GEN7_TLB_RD_ADDR); + + /* MBC 0x9024-0x91D0, 0x8500 */ + s-g3dctl = I915_READ(GEN7_G3DCTL); + s-gsckgctl = I915_READ(GEN7_GSCKGCTL); + s-mbctl= I915_READ(GEN6_MBCTL); + + /* GCP 0x9400-0x9424, 0x8100-0x810C */ + s-ucgctl1 = I915_READ(GEN6_UCGCTL1); + s-ucgctl3 = I915_READ(GEN7_UCGCTL3); + s-rcgctl1 = I915_READ(GEN7_RCGCTL1); + s-rcgctl2 = I915_READ(GEN7_RCGCTL2); + s-rstctl = I915_READ(GEN7_RSTCTL); + s-misccpctl= I915_READ(GEN7_MISCCPCTL); + + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */ + s-gfxpause = I915_READ(GEN7_GFXPAUSE); + s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC); + s-rpdeuc = I915_READ(GEN7_RPDEUC); + s-ecobus = I915_READ(ECOBUS); +