Commit 9daee614 authored by James Hughes's avatar James Hughes Committed by Eric Anholt

drm/v3d: Replace wait_for macros to remove use of msleep

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: default avatarJames Hughes <james.hughes@raspberrypi.com>
Signed-off-by: default avatarEric 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: 57692c94 ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
parent 7f2a09ec
...@@ -254,27 +254,42 @@ struct v3d_csd_job { ...@@ -254,27 +254,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 * Macro to help avoid open coding check/wait/timeout patterns. Note that it's
* contexts. Note that it's important that we check the condition again after * important that we check the condition again after having timed out, since the
* having timed out, since the timeout could be due to preemption or similar and * timeout could be due to preemption or similar and we've never had a chance to
* we've never had a chance to check the condition before the timeout. * check the condition before the timeout.
*/ */
#define wait_for(COND, MS) ({ \ #define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
int ret__ = 0; \ long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
while (!(COND)) { \ int ret__; \
if (time_after(jiffies, timeout__)) { \ might_sleep(); \
if (!(COND)) \ for (;;) { \
ret__ = -ETIMEDOUT; \ const bool expired__ = ktime_after(ktime_get_raw(), end__); \
OP; \
/* Guarantee COND check prior to timeout */ \
barrier(); \
if (COND) { \
ret__ = 0; \
break; \ break; \
} \ } \
msleep(1); \ if (expired__) { \
ret__ = -ETIMEDOUT; \
break; \
} \
usleep_range(wait__, wait__ * 2); \
if (wait__ < (Wmax)) \
wait__ <<= 1; \
} \ } \
ret__; \ 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) static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
{ {
/* nsecs_to_jiffies64() does not guard against overflow */ /* nsecs_to_jiffies64() does not guard against overflow */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment