]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/vc4: Replace wait_for macros to remove use of msleep
authorJames Hughes <james.hughes@raspberrypi.com>
Mon, 17 Feb 2020 15:31:45 +0000 (15:31 +0000)
committerEric Anholt <eric@anholt.net>
Thu, 5 Mar 2020 06:15:27 +0000 (22:15 -0800)
The wait_for macro's for Broadcom VC4 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 v3d patch in case this tickles modesetting bugs (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
drivers/gpu/drm/vc4/vc4_drv.h

index f90c0d08e740b27a242f476683e0efb32cf9c4b2..26d1d5886352955d11068d64e0f9817af312e0f0 100644 (file)
@@ -677,32 +677,41 @@ struct vc4_validated_shader_info {
 };
 
 /**
- * _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, W) ({ \
-       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;                                          \
                }                                                       \
-               if (W && drm_can_sleep())  {                            \
-                       msleep(W);                                      \
-               } else {                                                \
-                       cpu_relax();                                    \
+               if (expired__) {                                        \
+                       ret__ = -ETIMEDOUT;                             \
+                       break;                                          \
                }                                                       \
+               usleep_range(wait__, wait__ * 2);                       \
+               if (wait__ < (Wmax))                                    \
+                       wait__ <<= 1;                                   \
        }                                                               \
        ret__;                                                          \
 })
 
-#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+#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)
 
 /* vc4_bo.c */
 struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size);