* [RFC] drm/i915: Simplify waiting for registers
@ 2017-04-12 10:36 Tvrtko Ursulin
2017-04-12 10:42 ` Tvrtko Ursulin
2017-04-12 10:56 ` ✗ Fi.CI.BAT: warning for " Patchwork
0 siblings, 2 replies; 4+ messages in thread
From: Tvrtko Ursulin @ 2017-04-12 10:36 UTC (permalink / raw)
To: Intel-gfx
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
I was thinking if we could get away with simplifying the API
a bit by getting rid of the _fw variant and only have these
three functions with a common implementation:
intel_wait_for_register
intel_wait_for_register_atomic
__intel_wait_for_register
The fast/busy loop in all cases grabs it's own forcewake and
is done under the uncore lock. The extra overhead for call
sites which already have the forcewake, or do not need it is
there, but not sure that it matters for where wait_for_register
functions are used.
This makes the difference between the normal and atomic API
just in the fact atomic doesn't sleep while the normal can.
I've also put in the change to move the BUILD_BUG_ON from
_wait_for_atomic to wait_for_atomic(_us) macros, as Michal
suggested at one point, which should fix the GCC 4.4 build
issue.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 75 ++++++++++++++-----
drivers/gpu/drm/i915/intel_drv.h | 18 ++++-
drivers/gpu/drm/i915/intel_i2c.c | 4 +-
drivers/gpu/drm/i915/intel_pm.c | 10 ++-
drivers/gpu/drm/i915/intel_ringbuffer.c | 9 ++-
drivers/gpu/drm/i915/intel_uc.c | 10 +--
drivers/gpu/drm/i915/intel_uncore.c | 123 +++++++++-----------------------
7 files changed, 121 insertions(+), 128 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ed079c244b5d..ba95a54b9dfa 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3083,27 +3083,68 @@ u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv);
void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
-int intel_wait_for_register(struct drm_i915_private *dev_priv,
- i915_reg_t reg,
- u32 mask,
- u32 value,
- unsigned int timeout_ms);
-int __intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
- i915_reg_t reg,
- u32 mask,
- u32 value,
- unsigned int fast_timeout_us,
- unsigned int slow_timeout_ms,
- u32 *out_value);
-static inline
-int intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
+int __intel_wait_for_register(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
+ u32 mask,
+ u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_ms,
+ u32 *out_value);
+
+/**
+ * intel_wait_for_register - wait until register matches expected state
+ * @dev_priv: the i915 device
+ * @reg: the register to read
+ * @mask: mask to apply to register value
+ * @value: expected value
+ * @timeout_ms: timeout in millisecond
+ *
+ * This routine waits until the target register @reg contains the expected
+ * @value after applying the @mask, i.e. it waits until ::
+ *
+ * (I915_READ(reg) & mask) == value
+ *
+ * Otherwise, the wait will timeout after @timeout_ms milliseconds.
+ *
+ * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
+ */
+static inline int
+intel_wait_for_register(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
+ u32 mask,
+ u32 value,
+ unsigned int timeout_ms)
+{
+ return __intel_wait_for_register(dev_priv, reg, mask, value,
+ 2, timeout_ms, NULL);
+}
+
+/**
+ * intel_wait_for_register_atomic - wait until register matches expected state
+ * @dev_priv: the i915 device
+ * @reg: the register to read
+ * @mask: mask to apply to register value
+ * @value: expected value
+ * @timeout_us: timeout in microsecond
+ *
+ * This routine waits until the target register @reg contains the expected
+ * @value after applying the @mask, i.e. it waits until ::
+ *
+ * (I915_READ(reg) & mask) == value
+ *
+ * The wait is done with busy-looping.
+ *
+ * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
+ */
+static inline int
+intel_wait_for_register_atomic(struct drm_i915_private *dev_priv,
i915_reg_t reg,
u32 mask,
u32 value,
- unsigned int timeout_ms)
+ unsigned int timeout_us)
{
- return __intel_wait_for_register_fw(dev_priv, reg, mask, value,
- 2, timeout_ms, NULL);
+ return __intel_wait_for_register(dev_priv, reg, mask, value,
+ timeout_us, 0, NULL);
}
static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 43ea74882f9a..d7018d44371c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -88,7 +88,6 @@
int cpu, ret, timeout = (US) * 1000; \
u64 base; \
_WAIT_FOR_ATOMIC_CHECK(ATOMIC); \
- BUILD_BUG_ON((US) > 50000); \
if (!(ATOMIC)) { \
preempt_disable(); \
cpu = smp_processor_id(); \
@@ -130,8 +129,21 @@
ret__; \
})
-#define wait_for_atomic(COND, MS) _wait_for_atomic((COND), (MS) * 1000, 1)
-#define wait_for_atomic_us(COND, US) _wait_for_atomic((COND), (US), 1)
+#define wait_for_atomic(COND, MS) \
+({ \
+ int ret__; \
+ BUILD_BUG_ON((MS) > 50); \
+ ret__ = _wait_for_atomic((COND), (MS) * 1000, 1); \
+ ret__; \
+})
+
+#define wait_for_atomic_us(COND, US) \
+({ \
+ int ret__; \
+ BUILD_BUG_ON((US) > 50000); \
+ ret__ = _wait_for_atomic((COND), (US), 1); \
+ ret__; \
+})
#define KHz(x) (1000 * (x))
#define MHz(x) KHz(1000 * (x))
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index b6401e8f1bd6..ddc615d3d40d 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -297,9 +297,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
add_wait_queue(&dev_priv->gmbus_wait_queue, &wait);
I915_WRITE_FW(GMBUS4, irq_enable);
- ret = intel_wait_for_register_fw(dev_priv,
- GMBUS2, GMBUS_ACTIVE, 0,
- 10);
+ ret = intel_wait_for_register(dev_priv, GMBUS2, GMBUS_ACTIVE, 0, 10);
I915_WRITE_FW(GMBUS4, 0);
remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index cacb65fa2dd5..a93e6427aabf 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -8135,9 +8135,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val
I915_WRITE_FW(GEN6_PCODE_DATA1, 0);
I915_WRITE_FW(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
- if (__intel_wait_for_register_fw(dev_priv,
- GEN6_PCODE_MAILBOX, GEN6_PCODE_READY, 0,
- 500, 0, NULL)) {
+ if (intel_wait_for_register_atomic(dev_priv, GEN6_PCODE_MAILBOX,
+ GEN6_PCODE_READY, 0, 500)) {
DRM_ERROR("timeout waiting for pcode read (%d) to finish\n", mbox);
return -ETIMEDOUT;
}
@@ -8180,9 +8179,8 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv,
I915_WRITE_FW(GEN6_PCODE_DATA1, 0);
I915_WRITE_FW(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
- if (__intel_wait_for_register_fw(dev_priv,
- GEN6_PCODE_MAILBOX, GEN6_PCODE_READY, 0,
- 500, 0, NULL)) {
+ if (intel_wait_for_register_atomic(dev_priv, GEN6_PCODE_MAILBOX,
+ GEN6_PCODE_READY, 0, 500)) {
DRM_ERROR("timeout waiting for pcode write (%d) to finish\n", mbox);
return -ETIMEDOUT;
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 97d5fcca8805..af31d786a517 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1729,11 +1729,10 @@ static void gen6_bsd_submit_request(struct drm_i915_gem_request *request)
I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
/* Wait for the ring not to be idle, i.e. for it to wake up. */
- if (__intel_wait_for_register_fw(dev_priv,
- GEN6_BSD_SLEEP_PSMI_CONTROL,
- GEN6_BSD_SLEEP_INDICATOR,
- 0,
- 1000, 0, NULL))
+ if (intel_wait_for_register_atomic(dev_priv,
+ GEN6_BSD_SLEEP_PSMI_CONTROL,
+ GEN6_BSD_SLEEP_INDICATOR, 0,
+ 1000))
DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
/* Now that the ring is fully powered up, update the tail */
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index 4364b1a9064e..bae60f5c52d6 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -389,11 +389,11 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len)
* No GuC command should ever take longer than 10ms.
* Fast commands should still complete in 10us.
*/
- ret = __intel_wait_for_register_fw(dev_priv,
- SOFT_SCRATCH(0),
- INTEL_GUC_RECV_MASK,
- INTEL_GUC_RECV_MASK,
- 10, 10, &status);
+ ret = __intel_wait_for_register(dev_priv,
+ SOFT_SCRATCH(0),
+ INTEL_GUC_RECV_MASK,
+ INTEL_GUC_RECV_MASK,
+ 10, 10, &status);
if (status != INTEL_GUC_STATUS_SUCCESS) {
/*
* Either the GuC explicitly returned an error (which
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index fb38c7692fc2..215fbed8808c 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1535,9 +1535,8 @@ static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
__raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask);
/* Spin waiting for the device to ack the reset requests */
- return intel_wait_for_register_fw(dev_priv,
- GEN6_GDRST, hw_domain_mask, 0,
- 500);
+ return intel_wait_for_register(dev_priv, GEN6_GDRST, hw_domain_mask, 0,
+ 500);
}
/**
@@ -1585,7 +1584,7 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
}
/**
- * __intel_wait_for_register_fw - wait until register matches expected state
+ * __intel_wait_for_register - wait until register matches expected state
* @dev_priv: the i915 device
* @reg: the register to read
* @mask: mask to apply to register value
@@ -1597,90 +1596,47 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
* This routine waits until the target register @reg contains the expected
* @value after applying the @mask, i.e. it waits until ::
*
- * (I915_READ_FW(reg) & mask) == value
+ * (I915_READ(reg) & mask) == value
*
* Otherwise, the wait will timeout after @slow_timeout_ms milliseconds.
- * For atomic context @slow_timeout_ms must be zero and @fast_timeout_us
- * must be not larger than 20,0000 microseconds.
- *
- * Note that this routine assumes the caller holds forcewake asserted, it is
- * not suitable for very long waits. See intel_wait_for_register() if you
- * wish to wait without holding forcewake for the duration (i.e. you expect
- * the wait to be slow).
*
* Returns 0 if the register matches the desired condition, or -ETIMEOUT.
*/
-int __intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
- i915_reg_t reg,
- u32 mask,
- u32 value,
- unsigned int fast_timeout_us,
- unsigned int slow_timeout_ms,
- u32 *out_value)
-{
+int __intel_wait_for_register(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
+ u32 mask,
+ u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_ms,
+ u32 *out_value)
+{
+ unsigned long flags;
+ unsigned int fw_domains;
u32 reg_value;
-#define done (((reg_value = I915_READ_FW(reg)) & mask) == value)
int ret;
/* Catch any overuse of this function */
might_sleep_if(slow_timeout_ms);
- GEM_BUG_ON(fast_timeout_us > 20000);
-
- ret = -ETIMEDOUT;
- if (fast_timeout_us && fast_timeout_us <= 20000)
- ret = _wait_for_atomic(done, fast_timeout_us, 0);
- if (ret)
- ret = wait_for(done, slow_timeout_ms);
+ GEM_BUG_ON(fast_timeout_us > 1000);
- if (out_value)
- *out_value = reg_value;
+ spin_lock_irqsave(&dev_priv->uncore.lock, flags);
+ fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ);
+ intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
- return ret;
+#define done (((reg_value = I915_READ_FW(reg)) & mask) == value)
+ ret = _wait_for_atomic(done, fast_timeout_us, 1);
#undef done
-}
-/**
- * intel_wait_for_register - wait until register matches expected state
- * @dev_priv: the i915 device
- * @reg: the register to read
- * @mask: mask to apply to register value
- * @value: expected value
- * @timeout_ms: timeout in millisecond
- *
- * This routine waits until the target register @reg contains the expected
- * @value after applying the @mask, i.e. it waits until ::
- *
- * (I915_READ(reg) & mask) == value
- *
- * Otherwise, the wait will timeout after @timeout_ms milliseconds.
- *
- * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
- */
-int intel_wait_for_register(struct drm_i915_private *dev_priv,
- i915_reg_t reg,
- u32 mask,
- u32 value,
- unsigned int timeout_ms)
-{
- unsigned fw =
- intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ);
- int ret;
-
- might_sleep();
-
- spin_lock_irq(&dev_priv->uncore.lock);
- intel_uncore_forcewake_get__locked(dev_priv, fw);
-
- ret = __intel_wait_for_register_fw(dev_priv,
- reg, mask, value,
- 2, 0, NULL);
+ intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
- intel_uncore_forcewake_put__locked(dev_priv, fw);
- spin_unlock_irq(&dev_priv->uncore.lock);
+#define done (((reg_value = I915_READ_NOTRACE(reg)) & mask) == value)
+ if (ret && slow_timeout_ms)
+ ret = wait_for(done, slow_timeout_ms);
+#undef done
- if (ret)
- ret = wait_for((I915_READ_NOTRACE(reg) & mask) == value,
- timeout_ms);
+ if (out_value)
+ *out_value = reg_value;
return ret;
}
@@ -1693,11 +1649,11 @@ static int gen8_request_engine_reset(struct intel_engine_cs *engine)
I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
- ret = intel_wait_for_register_fw(dev_priv,
- RING_RESET_CTL(engine->mmio_base),
- RESET_CTL_READY_TO_RESET,
- RESET_CTL_READY_TO_RESET,
- 700);
+ ret = intel_wait_for_register(dev_priv,
+ RING_RESET_CTL(engine->mmio_base),
+ RESET_CTL_READY_TO_RESET,
+ RESET_CTL_READY_TO_RESET,
+ 700);
if (ret)
DRM_ERROR("%s: reset request timeout\n", engine->name);
@@ -1780,21 +1736,10 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
int intel_guc_reset(struct drm_i915_private *dev_priv)
{
- int ret;
- unsigned long irqflags;
-
if (!HAS_GUC(dev_priv))
return -EINVAL;
- intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
- spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
- ret = gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
-
- spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
- intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-
- return ret;
+ return gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
}
bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv)
--
2.9.3
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [RFC] drm/i915: Simplify waiting for registers
2017-04-12 10:36 [RFC] drm/i915: Simplify waiting for registers Tvrtko Ursulin
@ 2017-04-12 10:42 ` Tvrtko Ursulin
2017-04-12 10:54 ` Chris Wilson
2017-04-12 10:56 ` ✗ Fi.CI.BAT: warning for " Patchwork
1 sibling, 1 reply; 4+ messages in thread
From: Tvrtko Ursulin @ 2017-04-12 10:42 UTC (permalink / raw)
To: Tvrtko Ursulin, Intel-gfx
On 12/04/2017 11:36, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>
> I was thinking if we could get away with simplifying the API
> a bit by getting rid of the _fw variant and only have these
> three functions with a common implementation:
>
> intel_wait_for_register
> intel_wait_for_register_atomic
> __intel_wait_for_register
>
> The fast/busy loop in all cases grabs it's own forcewake and
> is done under the uncore lock. The extra overhead for call
> sites which already have the forcewake, or do not need it is
> there, but not sure that it matters for where wait_for_register
> functions are used.
This is probably quite bad for pcode, since AFAIR those can be quite
slow. So scratch this idea I think..
Regards,
Tvrtko
> This makes the difference between the normal and atomic API
> just in the fact atomic doesn't sleep while the normal can.
>
> I've also put in the change to move the BUILD_BUG_ON from
> _wait_for_atomic to wait_for_atomic(_us) macros, as Michal
> suggested at one point, which should fix the GCC 4.4 build
> issue.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 75 ++++++++++++++-----
> drivers/gpu/drm/i915/intel_drv.h | 18 ++++-
> drivers/gpu/drm/i915/intel_i2c.c | 4 +-
> drivers/gpu/drm/i915/intel_pm.c | 10 ++-
> drivers/gpu/drm/i915/intel_ringbuffer.c | 9 ++-
> drivers/gpu/drm/i915/intel_uc.c | 10 +--
> drivers/gpu/drm/i915/intel_uncore.c | 123 +++++++++-----------------------
> 7 files changed, 121 insertions(+), 128 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index ed079c244b5d..ba95a54b9dfa 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -3083,27 +3083,68 @@ u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv);
>
> void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
>
> -int intel_wait_for_register(struct drm_i915_private *dev_priv,
> - i915_reg_t reg,
> - u32 mask,
> - u32 value,
> - unsigned int timeout_ms);
> -int __intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
> - i915_reg_t reg,
> - u32 mask,
> - u32 value,
> - unsigned int fast_timeout_us,
> - unsigned int slow_timeout_ms,
> - u32 *out_value);
> -static inline
> -int intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
> +int __intel_wait_for_register(struct drm_i915_private *dev_priv,
> + i915_reg_t reg,
> + u32 mask,
> + u32 value,
> + unsigned int fast_timeout_us,
> + unsigned int slow_timeout_ms,
> + u32 *out_value);
> +
> +/**
> + * intel_wait_for_register - wait until register matches expected state
> + * @dev_priv: the i915 device
> + * @reg: the register to read
> + * @mask: mask to apply to register value
> + * @value: expected value
> + * @timeout_ms: timeout in millisecond
> + *
> + * This routine waits until the target register @reg contains the expected
> + * @value after applying the @mask, i.e. it waits until ::
> + *
> + * (I915_READ(reg) & mask) == value
> + *
> + * Otherwise, the wait will timeout after @timeout_ms milliseconds.
> + *
> + * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
> + */
> +static inline int
> +intel_wait_for_register(struct drm_i915_private *dev_priv,
> + i915_reg_t reg,
> + u32 mask,
> + u32 value,
> + unsigned int timeout_ms)
> +{
> + return __intel_wait_for_register(dev_priv, reg, mask, value,
> + 2, timeout_ms, NULL);
> +}
> +
> +/**
> + * intel_wait_for_register_atomic - wait until register matches expected state
> + * @dev_priv: the i915 device
> + * @reg: the register to read
> + * @mask: mask to apply to register value
> + * @value: expected value
> + * @timeout_us: timeout in microsecond
> + *
> + * This routine waits until the target register @reg contains the expected
> + * @value after applying the @mask, i.e. it waits until ::
> + *
> + * (I915_READ(reg) & mask) == value
> + *
> + * The wait is done with busy-looping.
> + *
> + * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
> + */
> +static inline int
> +intel_wait_for_register_atomic(struct drm_i915_private *dev_priv,
> i915_reg_t reg,
> u32 mask,
> u32 value,
> - unsigned int timeout_ms)
> + unsigned int timeout_us)
> {
> - return __intel_wait_for_register_fw(dev_priv, reg, mask, value,
> - 2, timeout_ms, NULL);
> + return __intel_wait_for_register(dev_priv, reg, mask, value,
> + timeout_us, 0, NULL);
> }
>
> static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 43ea74882f9a..d7018d44371c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -88,7 +88,6 @@
> int cpu, ret, timeout = (US) * 1000; \
> u64 base; \
> _WAIT_FOR_ATOMIC_CHECK(ATOMIC); \
> - BUILD_BUG_ON((US) > 50000); \
> if (!(ATOMIC)) { \
> preempt_disable(); \
> cpu = smp_processor_id(); \
> @@ -130,8 +129,21 @@
> ret__; \
> })
>
> -#define wait_for_atomic(COND, MS) _wait_for_atomic((COND), (MS) * 1000, 1)
> -#define wait_for_atomic_us(COND, US) _wait_for_atomic((COND), (US), 1)
> +#define wait_for_atomic(COND, MS) \
> +({ \
> + int ret__; \
> + BUILD_BUG_ON((MS) > 50); \
> + ret__ = _wait_for_atomic((COND), (MS) * 1000, 1); \
> + ret__; \
> +})
> +
> +#define wait_for_atomic_us(COND, US) \
> +({ \
> + int ret__; \
> + BUILD_BUG_ON((US) > 50000); \
> + ret__ = _wait_for_atomic((COND), (US), 1); \
> + ret__; \
> +})
>
> #define KHz(x) (1000 * (x))
> #define MHz(x) KHz(1000 * (x))
> diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
> index b6401e8f1bd6..ddc615d3d40d 100644
> --- a/drivers/gpu/drm/i915/intel_i2c.c
> +++ b/drivers/gpu/drm/i915/intel_i2c.c
> @@ -297,9 +297,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
> add_wait_queue(&dev_priv->gmbus_wait_queue, &wait);
> I915_WRITE_FW(GMBUS4, irq_enable);
>
> - ret = intel_wait_for_register_fw(dev_priv,
> - GMBUS2, GMBUS_ACTIVE, 0,
> - 10);
> + ret = intel_wait_for_register(dev_priv, GMBUS2, GMBUS_ACTIVE, 0, 10);
>
> I915_WRITE_FW(GMBUS4, 0);
> remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index cacb65fa2dd5..a93e6427aabf 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -8135,9 +8135,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val
> I915_WRITE_FW(GEN6_PCODE_DATA1, 0);
> I915_WRITE_FW(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
>
> - if (__intel_wait_for_register_fw(dev_priv,
> - GEN6_PCODE_MAILBOX, GEN6_PCODE_READY, 0,
> - 500, 0, NULL)) {
> + if (intel_wait_for_register_atomic(dev_priv, GEN6_PCODE_MAILBOX,
> + GEN6_PCODE_READY, 0, 500)) {
> DRM_ERROR("timeout waiting for pcode read (%d) to finish\n", mbox);
> return -ETIMEDOUT;
> }
> @@ -8180,9 +8179,8 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv,
> I915_WRITE_FW(GEN6_PCODE_DATA1, 0);
> I915_WRITE_FW(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
>
> - if (__intel_wait_for_register_fw(dev_priv,
> - GEN6_PCODE_MAILBOX, GEN6_PCODE_READY, 0,
> - 500, 0, NULL)) {
> + if (intel_wait_for_register_atomic(dev_priv, GEN6_PCODE_MAILBOX,
> + GEN6_PCODE_READY, 0, 500)) {
> DRM_ERROR("timeout waiting for pcode write (%d) to finish\n", mbox);
> return -ETIMEDOUT;
> }
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index 97d5fcca8805..af31d786a517 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -1729,11 +1729,10 @@ static void gen6_bsd_submit_request(struct drm_i915_gem_request *request)
> I915_WRITE64_FW(GEN6_BSD_RNCID, 0x0);
>
> /* Wait for the ring not to be idle, i.e. for it to wake up. */
> - if (__intel_wait_for_register_fw(dev_priv,
> - GEN6_BSD_SLEEP_PSMI_CONTROL,
> - GEN6_BSD_SLEEP_INDICATOR,
> - 0,
> - 1000, 0, NULL))
> + if (intel_wait_for_register_atomic(dev_priv,
> + GEN6_BSD_SLEEP_PSMI_CONTROL,
> + GEN6_BSD_SLEEP_INDICATOR, 0,
> + 1000))
> DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
>
> /* Now that the ring is fully powered up, update the tail */
> diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
> index 4364b1a9064e..bae60f5c52d6 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -389,11 +389,11 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len)
> * No GuC command should ever take longer than 10ms.
> * Fast commands should still complete in 10us.
> */
> - ret = __intel_wait_for_register_fw(dev_priv,
> - SOFT_SCRATCH(0),
> - INTEL_GUC_RECV_MASK,
> - INTEL_GUC_RECV_MASK,
> - 10, 10, &status);
> + ret = __intel_wait_for_register(dev_priv,
> + SOFT_SCRATCH(0),
> + INTEL_GUC_RECV_MASK,
> + INTEL_GUC_RECV_MASK,
> + 10, 10, &status);
> if (status != INTEL_GUC_STATUS_SUCCESS) {
> /*
> * Either the GuC explicitly returned an error (which
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index fb38c7692fc2..215fbed8808c 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -1535,9 +1535,8 @@ static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
> __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask);
>
> /* Spin waiting for the device to ack the reset requests */
> - return intel_wait_for_register_fw(dev_priv,
> - GEN6_GDRST, hw_domain_mask, 0,
> - 500);
> + return intel_wait_for_register(dev_priv, GEN6_GDRST, hw_domain_mask, 0,
> + 500);
> }
>
> /**
> @@ -1585,7 +1584,7 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
> }
>
> /**
> - * __intel_wait_for_register_fw - wait until register matches expected state
> + * __intel_wait_for_register - wait until register matches expected state
> * @dev_priv: the i915 device
> * @reg: the register to read
> * @mask: mask to apply to register value
> @@ -1597,90 +1596,47 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
> * This routine waits until the target register @reg contains the expected
> * @value after applying the @mask, i.e. it waits until ::
> *
> - * (I915_READ_FW(reg) & mask) == value
> + * (I915_READ(reg) & mask) == value
> *
> * Otherwise, the wait will timeout after @slow_timeout_ms milliseconds.
> - * For atomic context @slow_timeout_ms must be zero and @fast_timeout_us
> - * must be not larger than 20,0000 microseconds.
> - *
> - * Note that this routine assumes the caller holds forcewake asserted, it is
> - * not suitable for very long waits. See intel_wait_for_register() if you
> - * wish to wait without holding forcewake for the duration (i.e. you expect
> - * the wait to be slow).
> *
> * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
> */
> -int __intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
> - i915_reg_t reg,
> - u32 mask,
> - u32 value,
> - unsigned int fast_timeout_us,
> - unsigned int slow_timeout_ms,
> - u32 *out_value)
> -{
> +int __intel_wait_for_register(struct drm_i915_private *dev_priv,
> + i915_reg_t reg,
> + u32 mask,
> + u32 value,
> + unsigned int fast_timeout_us,
> + unsigned int slow_timeout_ms,
> + u32 *out_value)
> +{
> + unsigned long flags;
> + unsigned int fw_domains;
> u32 reg_value;
> -#define done (((reg_value = I915_READ_FW(reg)) & mask) == value)
> int ret;
>
> /* Catch any overuse of this function */
> might_sleep_if(slow_timeout_ms);
> - GEM_BUG_ON(fast_timeout_us > 20000);
> -
> - ret = -ETIMEDOUT;
> - if (fast_timeout_us && fast_timeout_us <= 20000)
> - ret = _wait_for_atomic(done, fast_timeout_us, 0);
> - if (ret)
> - ret = wait_for(done, slow_timeout_ms);
> + GEM_BUG_ON(fast_timeout_us > 1000);
>
> - if (out_value)
> - *out_value = reg_value;
> + spin_lock_irqsave(&dev_priv->uncore.lock, flags);
> + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ);
> + intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
>
> - return ret;
> +#define done (((reg_value = I915_READ_FW(reg)) & mask) == value)
> + ret = _wait_for_atomic(done, fast_timeout_us, 1);
> #undef done
> -}
>
> -/**
> - * intel_wait_for_register - wait until register matches expected state
> - * @dev_priv: the i915 device
> - * @reg: the register to read
> - * @mask: mask to apply to register value
> - * @value: expected value
> - * @timeout_ms: timeout in millisecond
> - *
> - * This routine waits until the target register @reg contains the expected
> - * @value after applying the @mask, i.e. it waits until ::
> - *
> - * (I915_READ(reg) & mask) == value
> - *
> - * Otherwise, the wait will timeout after @timeout_ms milliseconds.
> - *
> - * Returns 0 if the register matches the desired condition, or -ETIMEOUT.
> - */
> -int intel_wait_for_register(struct drm_i915_private *dev_priv,
> - i915_reg_t reg,
> - u32 mask,
> - u32 value,
> - unsigned int timeout_ms)
> -{
> - unsigned fw =
> - intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ);
> - int ret;
> -
> - might_sleep();
> -
> - spin_lock_irq(&dev_priv->uncore.lock);
> - intel_uncore_forcewake_get__locked(dev_priv, fw);
> -
> - ret = __intel_wait_for_register_fw(dev_priv,
> - reg, mask, value,
> - 2, 0, NULL);
> + intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
> + spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
>
> - intel_uncore_forcewake_put__locked(dev_priv, fw);
> - spin_unlock_irq(&dev_priv->uncore.lock);
> +#define done (((reg_value = I915_READ_NOTRACE(reg)) & mask) == value)
> + if (ret && slow_timeout_ms)
> + ret = wait_for(done, slow_timeout_ms);
> +#undef done
>
> - if (ret)
> - ret = wait_for((I915_READ_NOTRACE(reg) & mask) == value,
> - timeout_ms);
> + if (out_value)
> + *out_value = reg_value;
>
> return ret;
> }
> @@ -1693,11 +1649,11 @@ static int gen8_request_engine_reset(struct intel_engine_cs *engine)
> I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
> _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
>
> - ret = intel_wait_for_register_fw(dev_priv,
> - RING_RESET_CTL(engine->mmio_base),
> - RESET_CTL_READY_TO_RESET,
> - RESET_CTL_READY_TO_RESET,
> - 700);
> + ret = intel_wait_for_register(dev_priv,
> + RING_RESET_CTL(engine->mmio_base),
> + RESET_CTL_READY_TO_RESET,
> + RESET_CTL_READY_TO_RESET,
> + 700);
> if (ret)
> DRM_ERROR("%s: reset request timeout\n", engine->name);
>
> @@ -1780,21 +1736,10 @@ bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
>
> int intel_guc_reset(struct drm_i915_private *dev_priv)
> {
> - int ret;
> - unsigned long irqflags;
> -
> if (!HAS_GUC(dev_priv))
> return -EINVAL;
>
> - intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
> - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> - ret = gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
> -
> - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> -
> - return ret;
> + return gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
> }
>
> bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv)
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] drm/i915: Simplify waiting for registers
2017-04-12 10:42 ` Tvrtko Ursulin
@ 2017-04-12 10:54 ` Chris Wilson
0 siblings, 0 replies; 4+ messages in thread
From: Chris Wilson @ 2017-04-12 10:54 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: Intel-gfx
On Wed, Apr 12, 2017 at 11:42:55AM +0100, Tvrtko Ursulin wrote:
>
> On 12/04/2017 11:36, Tvrtko Ursulin wrote:
> >From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> >
> >I was thinking if we could get away with simplifying the API
> >a bit by getting rid of the _fw variant and only have these
> >three functions with a common implementation:
> >
> > intel_wait_for_register
> > intel_wait_for_register_atomic
> > __intel_wait_for_register
> >
> >The fast/busy loop in all cases grabs it's own forcewake and
> >is done under the uncore lock. The extra overhead for call
> >sites which already have the forcewake, or do not need it is
> >there, but not sure that it matters for where wait_for_register
> >functions are used.
>
> This is probably quite bad for pcode, since AFAIR those can be quite
> slow. So scratch this idea I think..
There's definitely some merit here. I'd wait until Ville presents his
gt/de split since that's going to be quite a major paradigm shift for us
and then re-evaluate.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 4+ messages in thread
* ✗ Fi.CI.BAT: warning for drm/i915: Simplify waiting for registers
2017-04-12 10:36 [RFC] drm/i915: Simplify waiting for registers Tvrtko Ursulin
2017-04-12 10:42 ` Tvrtko Ursulin
@ 2017-04-12 10:56 ` Patchwork
1 sibling, 0 replies; 4+ messages in thread
From: Patchwork @ 2017-04-12 10:56 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: Simplify waiting for registers
URL : https://patchwork.freedesktop.org/series/22915/
State : warning
== Summary ==
Series 22915v1 drm/i915: Simplify waiting for registers
https://patchwork.freedesktop.org/api/1.0/series/22915/revisions/1/mbox/
Test gem_exec_suspend:
Subgroup basic-s4-devices:
pass -> DMESG-WARN (fi-kbl-7560u) fdo#100125
Test kms_force_connector_basic:
Subgroup force-connector-state:
pass -> SKIP (fi-ivb-3520m)
Subgroup force-edid:
pass -> SKIP (fi-ivb-3520m)
Subgroup force-load-detect:
pass -> SKIP (fi-ivb-3520m)
Subgroup prune-stale-modes:
pass -> SKIP (fi-ivb-3520m)
fdo#100125 https://bugs.freedesktop.org/show_bug.cgi?id=100125
fi-bdw-5557u total:278 pass:267 dwarn:0 dfail:0 fail:0 skip:11 time:439s
fi-bdw-gvtdvm total:278 pass:256 dwarn:8 dfail:0 fail:0 skip:14 time:429s
fi-bsw-n3050 total:278 pass:242 dwarn:0 dfail:0 fail:0 skip:36 time:578s
fi-bxt-j4205 total:278 pass:259 dwarn:0 dfail:0 fail:0 skip:19 time:503s
fi-bxt-t5700 total:278 pass:258 dwarn:0 dfail:0 fail:0 skip:20 time:556s
fi-byt-j1900 total:278 pass:254 dwarn:0 dfail:0 fail:0 skip:24 time:492s
fi-byt-n2820 total:278 pass:250 dwarn:0 dfail:0 fail:0 skip:28 time:479s
fi-hsw-4770 total:278 pass:262 dwarn:0 dfail:0 fail:0 skip:16 time:408s
fi-hsw-4770r total:278 pass:262 dwarn:0 dfail:0 fail:0 skip:16 time:404s
fi-ilk-650 total:278 pass:228 dwarn:0 dfail:0 fail:0 skip:50 time:423s
fi-ivb-3520m total:278 pass:256 dwarn:0 dfail:0 fail:0 skip:22 time:488s
fi-ivb-3770 total:278 pass:260 dwarn:0 dfail:0 fail:0 skip:18 time:472s
fi-kbl-7500u total:278 pass:260 dwarn:0 dfail:0 fail:0 skip:18 time:453s
fi-kbl-7560u total:278 pass:267 dwarn:1 dfail:0 fail:0 skip:10 time:568s
fi-skl-6260u total:278 pass:268 dwarn:0 dfail:0 fail:0 skip:10 time:454s
fi-skl-6700hq total:278 pass:261 dwarn:0 dfail:0 fail:0 skip:17 time:568s
fi-skl-6700k total:278 pass:256 dwarn:4 dfail:0 fail:0 skip:18 time:463s
fi-skl-6770hq total:278 pass:268 dwarn:0 dfail:0 fail:0 skip:10 time:494s
fi-skl-gvtdvm total:278 pass:265 dwarn:0 dfail:0 fail:0 skip:13 time:435s
fi-snb-2520m total:278 pass:250 dwarn:0 dfail:0 fail:0 skip:28 time:533s
fi-snb-2600 total:278 pass:249 dwarn:0 dfail:0 fail:0 skip:29 time:399s
02b830fd67a6a2681e7f64510c3256b51a85c21a drm-tip: 2017y-04m-12d-09h-19m-10s UTC integration manifest
fed29f9 drm/i915: Simplify waiting for registers
== Logs ==
For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_4488/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-04-12 10:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-12 10:36 [RFC] drm/i915: Simplify waiting for registers Tvrtko Ursulin
2017-04-12 10:42 ` Tvrtko Ursulin
2017-04-12 10:54 ` Chris Wilson
2017-04-12 10:56 ` ✗ Fi.CI.BAT: warning for " Patchwork
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.