830bc1125e4e4b191d1ad1da9e7446b6b40e9e18
[openwrt/staging/linusw.git] /
1 From 12b60ef71cc005ee7290f692169d46a7e78df01a Mon Sep 17 00:00:00 2001
2 From: Yukimasa Sugizaki <4298265+Terminus-IMRC@users.noreply.github.com>
3 Date: Fri, 20 Mar 2020 19:01:23 +0900
4 Subject: [PATCH] drm/v3d: Replace wait_for macros to remove use of
5 msleep (#3510)
6
7 commit 9daee6141cc9c75b09659b02b1cb9eeb2f5e16cc upstream.
8
9 The wait_for macro's for Broadcom V3D driver used msleep, which is
10 inappropriate due to its inaccuracy at low values (minimum wait time
11 is about 30ms on the Raspberry Pi). This sleep was triggering in
12 v3d_clean_caches(), causing us to only be able to dispatch ~33 compute
13 jobs per second.
14
15 This patch replaces the macro with the one from the Intel i915 version
16 which uses usleep_range to provide more accurate waits.
17
18 v2: Split from the vc4 patch so that we can confidently apply to
19 stable (by anholt)
20
21 Signed-off-by: James Hughes <james.hughes@raspberrypi.com>
22 Signed-off-by: Eric Anholt <eric@anholt.net>
23 Link: https://patchwork.freedesktop.org/patch/msgid/20200217153145.13780-1-james.hughes@raspberrypi.com
24 Link: https://github.com/raspberrypi/linux/issues/3460
25 Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+")
26
27 Co-authored-by: James Hughes <james.hughes@raspberrypi.com>
28 ---
29 drivers/gpu/drm/v3d/v3d_drv.h | 41 ++++++++++++++++++++++++-----------
30 1 file changed, 28 insertions(+), 13 deletions(-)
31
32 --- a/drivers/gpu/drm/v3d/v3d_drv.h
33 +++ b/drivers/gpu/drm/v3d/v3d_drv.h
34 @@ -260,27 +260,42 @@ struct v3d_csd_job {
35 };
36
37 /**
38 - * _wait_for - magic (register) wait macro
39 + * __wait_for - magic wait macro
40 *
41 - * Does the right thing for modeset paths when run under kdgb or similar atomic
42 - * contexts. Note that it's important that we check the condition again after
43 - * having timed out, since the timeout could be due to preemption or similar and
44 - * we've never had a chance to check the condition before the timeout.
45 + * Macro to help avoid open coding check/wait/timeout patterns. Note that it's
46 + * important that we check the condition again after having timed out, since the
47 + * timeout could be due to preemption or similar and we've never had a chance to
48 + * check the condition before the timeout.
49 */
50 -#define wait_for(COND, MS) ({ \
51 - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
52 - int ret__ = 0; \
53 - while (!(COND)) { \
54 - if (time_after(jiffies, timeout__)) { \
55 - if (!(COND)) \
56 - ret__ = -ETIMEDOUT; \
57 +#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \
58 + const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \
59 + long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \
60 + int ret__; \
61 + might_sleep(); \
62 + for (;;) { \
63 + const bool expired__ = ktime_after(ktime_get_raw(), end__); \
64 + OP; \
65 + /* Guarantee COND check prior to timeout */ \
66 + barrier(); \
67 + if (COND) { \
68 + ret__ = 0; \
69 break; \
70 } \
71 - msleep(1); \
72 + if (expired__) { \
73 + ret__ = -ETIMEDOUT; \
74 + break; \
75 + } \
76 + usleep_range(wait__, wait__ * 2); \
77 + if (wait__ < (Wmax)) \
78 + wait__ <<= 1; \
79 } \
80 ret__; \
81 })
82
83 +#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \
84 + (Wmax))
85 +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
86 +
87 static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
88 {
89 /* nsecs_to_jiffies64() does not guard against overflow */