|
53 | 53 | } \
|
54 | 54 | if (__sleep_us) \
|
55 | 55 | usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
|
| 56 | + cpu_relax(); \ |
56 | 57 | } \
|
57 | 58 | (cond) ? 0 : -ETIMEDOUT; \
|
58 | 59 | })
|
|
73 | 74 | * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
|
74 | 75 | * case, the last read value at @args is stored in @val.
|
75 | 76 | *
|
| 77 | + * This macro does not rely on timekeeping. Hence it is safe to call even when |
| 78 | + * timekeeping is suspended, at the expense of an underestimation of wall clock |
| 79 | + * time, which is rather minimal with a non-zero delay_us. |
| 80 | + * |
76 | 81 | * When available, you'll probably want to use one of the specialized
|
77 | 82 | * macros defined below rather than this macro directly.
|
78 | 83 | */
|
79 | 84 | #define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \
|
80 | 85 | delay_before_read, args...) \
|
81 | 86 | ({ \
|
82 | 87 | u64 __timeout_us = (timeout_us); \
|
| 88 | + s64 __left_ns = __timeout_us * NSEC_PER_USEC; \ |
83 | 89 | unsigned long __delay_us = (delay_us); \
|
84 |
| - ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ |
85 |
| - if (delay_before_read && __delay_us) \ |
| 90 | + u64 __delay_ns = __delay_us * NSEC_PER_USEC; \ |
| 91 | + if (delay_before_read && __delay_us) { \ |
86 | 92 | udelay(__delay_us); \
|
| 93 | + if (__timeout_us) \ |
| 94 | + __left_ns -= __delay_ns; \ |
| 95 | + } \ |
87 | 96 | for (;;) { \
|
88 | 97 | (val) = op(args); \
|
89 | 98 | if (cond) \
|
90 | 99 | break; \
|
91 |
| - if (__timeout_us && \ |
92 |
| - ktime_compare(ktime_get(), __timeout) > 0) { \ |
| 100 | + if (__timeout_us && __left_ns < 0) { \ |
93 | 101 | (val) = op(args); \
|
94 | 102 | break; \
|
95 | 103 | } \
|
96 |
| - if (__delay_us) \ |
| 104 | + if (__delay_us) { \ |
97 | 105 | udelay(__delay_us); \
|
| 106 | + if (__timeout_us) \ |
| 107 | + __left_ns -= __delay_ns; \ |
| 108 | + } \ |
| 109 | + cpu_relax(); \ |
| 110 | + if (__timeout_us) \ |
| 111 | + __left_ns--; \ |
98 | 112 | } \
|
99 | 113 | (cond) ? 0 : -ETIMEDOUT; \
|
100 | 114 | })
|
|
0 commit comments