|
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