Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iopoll: Introduce read_poll_timeout_atomic macro

Like read_poll_timeout, an atomic variant for multiple parameter read
function can be useful.

Will be used by a later patch.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200424184918.30360-1-kai.heng.feng@canonical.com

authored by

Kai-Heng Feng and committed by
Kalle Valo
57a29df3 ea1b3bc6

+43 -19
+43 -19
include/linux/iopoll.h
··· 58 58 }) 59 59 60 60 /** 61 + * read_poll_timeout_atomic - Periodically poll an address until a condition is 62 + * met or a timeout occurs 63 + * @op: accessor function (takes @addr as its only argument) 64 + * @addr: Address to poll 65 + * @val: Variable to read the value into 66 + * @cond: Break condition (usually involving @val) 67 + * @delay_us: Time to udelay between reads in us (0 tight-loops). Should 68 + * be less than ~10us since udelay is used (see 69 + * Documentation/timers/timers-howto.rst). 70 + * @timeout_us: Timeout in us, 0 means never timeout 71 + * @delay_before_read: if it is true, delay @delay_us before read. 72 + * 73 + * Returns 0 on success and -ETIMEDOUT upon a timeout. In either 74 + * case, the last read value at @args is stored in @val. 75 + * 76 + * When available, you'll probably want to use one of the specialized 77 + * macros defined below rather than this macro directly. 78 + */ 79 + #define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \ 80 + delay_before_read, args...) \ 81 + ({ \ 82 + u64 __timeout_us = (timeout_us); \ 83 + unsigned long __delay_us = (delay_us); \ 84 + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ 85 + if (delay_before_read && __delay_us) \ 86 + udelay(__delay_us); \ 87 + for (;;) { \ 88 + (val) = op(args); \ 89 + if (cond) \ 90 + break; \ 91 + if (__timeout_us && \ 92 + ktime_compare(ktime_get(), __timeout) > 0) { \ 93 + (val) = op(args); \ 94 + break; \ 95 + } \ 96 + if (__delay_us) \ 97 + udelay(__delay_us); \ 98 + } \ 99 + (cond) ? 0 : -ETIMEDOUT; \ 100 + }) 101 + 102 + /** 61 103 * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs 62 104 * @op: accessor function (takes @addr as its only argument) 63 105 * @addr: Address to poll ··· 138 96 * macros defined below rather than this macro directly. 139 97 */ 140 98 #define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \ 141 - ({ \ 142 - u64 __timeout_us = (timeout_us); \ 143 - unsigned long __delay_us = (delay_us); \ 144 - ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ 145 - for (;;) { \ 146 - (val) = op(addr); \ 147 - if (cond) \ 148 - break; \ 149 - if (__timeout_us && \ 150 - ktime_compare(ktime_get(), __timeout) > 0) { \ 151 - (val) = op(addr); \ 152 - break; \ 153 - } \ 154 - if (__delay_us) \ 155 - udelay(__delay_us); \ 156 - } \ 157 - (cond) ? 0 : -ETIMEDOUT; \ 158 - }) 159 - 99 + read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, false, addr) 160 100 161 101 #define readb_poll_timeout(addr, val, cond, delay_us, timeout_us) \ 162 102 readx_poll_timeout(readb, addr, val, cond, delay_us, timeout_us)