From: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx> Rather than blindly waking up all forcewake domains on command submission, we can teach each engine what is (or are) the correct one to take. On platforms with multiple forcewake domains like VLV, CHV, SKL and BXT, this has the potential of lowering the GPU and CPU power use and submission latency. To implement it we add two new functions named intel_reg_read_fw_domains and intel_reg_write_fw_domains, whose purpose is to query which forcewake domains need to be taken to read or write a specific register with raw mmio accessors. These enables the execlists engine setup to query which forcewake domains are relevant per engine on the currently running platform. v2: * Kerneldoc. * Split from intel_uncore.c macro extraction, WARN_ON, no warns on old platforms. (Chris Wilson) Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.h | 6 +++ drivers/gpu/drm/i915/intel_lrc.c | 18 +++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + drivers/gpu/drm/i915/intel_uncore.c | 91 +++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4ebd3ff02803..55fec504b19f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -633,6 +633,12 @@ enum forcewake_domains { FORCEWAKE_MEDIA) }; +enum forcewake_domains +intel_reg_read_fw_domains(struct drm_i915_private *dev_priv, i915_reg_t reg); + +enum forcewake_domains +intel_reg_write_fw_domains(struct drm_i915_private *dev_priv, i915_reg_t reg); + struct intel_uncore_funcs { void (*force_wake_get)(struct drm_i915_private *dev_priv, enum forcewake_domains domains); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a1db6a02cf23..cac387f38cf6 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -418,6 +418,7 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { struct drm_i915_private *dev_priv = rq0->i915; + unsigned int fw_domains = rq0->engine->fw_domains_elsp; execlists_update_context(rq0); @@ -425,11 +426,11 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0, execlists_update_context(rq1); spin_lock_irq(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); execlists_elsp_write(rq0, rq1); - intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); spin_unlock_irq(&dev_priv->uncore.lock); } @@ -552,7 +553,7 @@ static void intel_lrc_irq_handler(unsigned long data) unsigned int csb_read = 0, i; unsigned int submit_contexts = 0; - intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + intel_uncore_forcewake_get(dev_priv, engine->fw_domains_csb); status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine)); @@ -577,7 +578,7 @@ static void intel_lrc_irq_handler(unsigned long data) _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, engine->next_context_status_buffer << 8)); - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + intel_uncore_forcewake_put(dev_priv, engine->fw_domains_csb); spin_lock(&engine->execlist_lock); @@ -2077,7 +2078,8 @@ logical_ring_default_irqs(struct intel_engine_cs *engine, unsigned shift) static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine) { - struct intel_context *dctx = to_i915(dev)->kernel_context; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_context *dctx = dev_priv->kernel_context; int ret; /* Intentionally left blank. */ @@ -2099,6 +2101,12 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine) logical_ring_init_platform_invariants(engine); + engine->fw_domains_elsp = + intel_reg_write_fw_domains(dev_priv, RING_ELSP(engine)); + engine->fw_domains_csb = + intel_reg_write_fw_domains(dev_priv, + RING_CONTEXT_STATUS_PTR(engine)); + ret = i915_cmd_parser_init_ring(engine); if (ret) goto error; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 18074ab55f61..fd248cde7164 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -270,6 +270,7 @@ struct intel_engine_cs { spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */ struct list_head execlist_queue; struct list_head execlist_retired_req_list; + unsigned int fw_domains_elsp, fw_domains_csb; unsigned int next_context_status_buffer; unsigned int idle_lite_restore_wa; bool disable_lite_restore_wa; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index b77bdf4a47f6..550e480fedd4 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1766,3 +1766,94 @@ intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) return false; } + +/** + * intel_reg_read_fw_domains - which forcewake domains are needed to read a register + * @dev_priv: pointer to struct drm_i915_private + * @reg: register in question + * + * Returns a set of forcewake domains required to be taken with for example + * intel_uncore_forcewake_get for the specified register to be readable with the + * raw mmio accessors. + */ +enum forcewake_domains +intel_reg_read_fw_domains(struct drm_i915_private *dev_priv, i915_reg_t reg) +{ + enum forcewake_domains fw_domains; + + if (intel_vgpu_active(dev_priv->dev)) + return 0; + + switch (INTEL_INFO(dev_priv)->gen) { + case 9: + fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg)); + break; + case 8: + if (IS_CHERRYVIEW(dev_priv)) + fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); + else + fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); + break; + case 7: + case 6: + if (IS_VALLEYVIEW(dev_priv)) + fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); + else + fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); + break; + default: + MISSING_CASE(INTEL_INFO(dev_priv)->gen); + case 5: /* forcewake was introduced with gen6 */ + case 4: + case 3: + case 2: + return 0; + } + + WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); + + return fw_domains; +} + +/** + * intel_reg_write_fw_domains - which forcewake domains are needed to write a register + * @dev_priv: pointer to struct drm_i915_private + * @reg: register in question + * + * Returns a set of forcewake domains required to be taken with for example + * intel_uncore_forcewake_get for the specified register to be writable with the + * raw mmio accessors. + */ +enum forcewake_domains +intel_reg_write_fw_domains(struct drm_i915_private *dev_priv, i915_reg_t reg) +{ + enum forcewake_domains fw_domains; + + if (intel_vgpu_active(dev_priv->dev)) + return 0; + + switch (INTEL_INFO(dev_priv)->gen) { + case 9: + fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg)); + break; + case 8: + if (IS_CHERRYVIEW(dev_priv)) + fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg)); + else + fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg)); + break; + default: + MISSING_CASE(INTEL_INFO(dev_priv)->gen); + case 7: + case 6: + case 5: + case 4: + case 3: + case 2: + return 0; + } + + WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); + + return fw_domains; +} -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx