diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1e15c21257ea5d69299eaf1973dfea2b0abd76c1..f5c91b01194f7f8035731064fc05625f3d4eff22 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -634,6 +634,13 @@ enum forcewake_domains { FORCEWAKE_MEDIA) }; +#define FW_REG_READ (1) +#define FW_REG_WRITE (2) + +enum forcewake_domains +intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, + i915_reg_t reg, unsigned int op); + 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 0d6dc5ec4a46332259a79f8ae5ab658eb5808241..e6e69c2f238630f3785105af593e9a7187e6eb45 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; 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); 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); spin_lock(&engine->execlist_lock); @@ -2089,7 +2090,9 @@ 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; + enum forcewake_domains fw_domains; int ret; /* Intentionally left blank. */ @@ -2111,6 +2114,20 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine) logical_ring_init_platform_invariants(engine); + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, + RING_ELSP(engine), + FW_REG_WRITE); + + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + RING_CONTEXT_STATUS_PTR(engine), + FW_REG_READ | FW_REG_WRITE); + + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + RING_CONTEXT_STATUS_BUF_BASE(engine), + FW_REG_READ); + + engine->fw_domains = fw_domains; + ret = i915_cmd_parser_init_ring(engine); if (ret) goto error; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 0b0853eee91e1325d2f86167a17b4ab63217a09f..8de1ea536ad400f660af16d9b5ec2791f748e0a6 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -34,6 +34,7 @@ #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0) #define CTX_CTRL_RS_CTX_ENABLE (1 << 1) +#define RING_CONTEXT_STATUS_BUF_BASE(ring) _MMIO((ring)->mmio_base + 0x370) #define RING_CONTEXT_STATUS_BUF_LO(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8) #define RING_CONTEXT_STATUS_BUF_HI(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8 + 4) #define RING_CONTEXT_STATUS_PTR(ring) _MMIO((ring)->mmio_base + 0x3a0) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 78dc46864a1021d95567a496b45f5dfd5a0a6fd6..2ade194bbea92d9208674ce52763a8f71a5d0b7f 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; 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 41dd30f6ddbb57c24af81feef7d324c65252a77e..24b0a9ae3df3bfc36d597002104c236f965acb6b 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1772,3 +1772,111 @@ intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) return false; } + +static enum forcewake_domains +intel_uncore_forcewake_for_read(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; +} + +static enum forcewake_domains +intel_uncore_forcewake_for_write(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; + case 7: + case 6: + fw_domains = FORCEWAKE_RENDER; + break; + default: + MISSING_CASE(INTEL_INFO(dev_priv)->gen); + case 5: + case 4: + case 3: + case 2: + return 0; + } + + WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); + + return fw_domains; +} + +/** + * intel_uncore_forcewake_for_reg - which forcewake domains are needed to access + * a register + * @dev_priv: pointer to struct drm_i915_private + * @reg: register in question + * @op: operation bitmask of FW_REG_READ and/or FW_REG_WRITE + * + * Returns a set of forcewake domains required to be taken with for example + * intel_uncore_forcewake_get for the specified register to be accessible in the + * specified mode (read, write or read/write) with raw mmio accessors. + * + * NOTE: On Gen6 and Gen7 write forcewake domain (FORCEWAKE_RENDER) requires the + * callers to do FIFO management on their own or risk losing writes. + */ +enum forcewake_domains +intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, + i915_reg_t reg, unsigned int op) +{ + enum forcewake_domains fw_domains = 0; + + WARN_ON(!op); + + if (op & FW_REG_READ) + fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg); + + if (op & FW_REG_WRITE) + fw_domains |= intel_uncore_forcewake_for_write(dev_priv, reg); + + return fw_domains; +}