mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
90 lines
3.4 KiB
Diff
90 lines
3.4 KiB
Diff
|
From 12b60ef71cc005ee7290f692169d46a7e78df01a Mon Sep 17 00:00:00 2001
|
||
|
From: Yukimasa Sugizaki <4298265+Terminus-IMRC@users.noreply.github.com>
|
||
|
Date: Fri, 20 Mar 2020 19:01:23 +0900
|
||
|
Subject: [PATCH] drm/v3d: Replace wait_for macros to remove use of
|
||
|
msleep (#3510)
|
||
|
|
||
|
commit 9daee6141cc9c75b09659b02b1cb9eeb2f5e16cc upstream.
|
||
|
|
||
|
The wait_for macro's for Broadcom V3D driver used msleep, which is
|
||
|
inappropriate due to its inaccuracy at low values (minimum wait time
|
||
|
is about 30ms on the Raspberry Pi). This sleep was triggering in
|
||
|
v3d_clean_caches(), causing us to only be able to dispatch ~33 compute
|
||
|
jobs per second.
|
||
|
|
||
|
This patch replaces the macro with the one from the Intel i915 version
|
||
|
which uses usleep_range to provide more accurate waits.
|
||
|
|
||
|
v2: Split from the vc4 patch so that we can confidently apply to
|
||
|
stable (by anholt)
|
||
|
|
||
|
Signed-off-by: James Hughes <james.hughes@raspberrypi.com>
|
||
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||
|
Link: https://patchwork.freedesktop.org/patch/msgid/20200217153145.13780-1-james.hughes@raspberrypi.com
|
||
|
Link: https://github.com/raspberrypi/linux/issues/3460
|
||
|
Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
|
||
|
|
||
|
Co-authored-by: James Hughes <james.hughes@raspberrypi.com>
|
||
|
---
|
||
|
drivers/gpu/drm/v3d/v3d_drv.h | 41 ++++++++++++++++++++++++-----------
|
||
|
1 file changed, 28 insertions(+), 13 deletions(-)
|
||
|
|
||
|
--- a/drivers/gpu/drm/v3d/v3d_drv.h
|
||
|
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
|
||
|
@@ -260,27 +260,42 @@ struct v3d_csd_job {
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
- * _wait_for - magic (register) wait macro
|
||
|
+ * __wait_for - magic wait macro
|
||
|
*
|
||
|
- * Does the right thing for modeset paths when run under kdgb or similar atomic
|
||
|
- * contexts. Note that it's important that we check the condition again after
|
||
|
- * having timed out, since the timeout could be due to preemption or similar and
|
||
|
- * we've never had a chance to check the condition before the timeout.
|
||
|
+ * Macro to help avoid open coding check/wait/timeout patterns. Note that it's
|
||
|
+ * important that we check the condition again after having timed out, since the
|
||
|
+ * timeout could be due to preemption or similar and we've never had a chance to
|
||
|
+ * check the condition before the timeout.
|
||
|
*/
|
||
|
-#define wait_for(COND, MS) ({ \
|
||
|
- unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
|
||
|
- int ret__ = 0; \
|
||
|
- while (!(COND)) { \
|
||
|
- if (time_after(jiffies, timeout__)) { \
|
||
|
- if (!(COND)) \
|
||
|
- ret__ = -ETIMEDOUT; \
|
||
|
+#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
|
||
|
+ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
|
||
|
+ long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
|
||
|
+ int ret__; \
|
||
|
+ might_sleep(); \
|
||
|
+ for (;;) { \
|
||
|
+ const bool expired__ = ktime_after(ktime_get_raw(), end__); \
|
||
|
+ OP; \
|
||
|
+ /* Guarantee COND check prior to timeout */ \
|
||
|
+ barrier(); \
|
||
|
+ if (COND) { \
|
||
|
+ ret__ = 0; \
|
||
|
break; \
|
||
|
} \
|
||
|
- msleep(1); \
|
||
|
+ if (expired__) { \
|
||
|
+ ret__ = -ETIMEDOUT; \
|
||
|
+ break; \
|
||
|
+ } \
|
||
|
+ usleep_range(wait__, wait__ * 2); \
|
||
|
+ if (wait__ < (Wmax)) \
|
||
|
+ wait__ <<= 1; \
|
||
|
} \
|
||
|
ret__; \
|
||
|
})
|
||
|
|
||
|
+#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \
|
||
|
+ (Wmax))
|
||
|
+#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
|
||
|
+
|
||
|
static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
|
||
|
{
|
||
|
/* nsecs_to_jiffies64() does not guard against overflow */
|