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
This commit is contained in:
Kai-Heng Feng 2020-04-25 02:49:14 +08:00 committed by Kalle Valo
parent ea1b3bc6d5
commit 57a29df341

View File

@ -57,6 +57,48 @@
(cond) ? 0 : -ETIMEDOUT; \ (cond) ? 0 : -ETIMEDOUT; \
}) })
/**
* read_poll_timeout_atomic - Periodically poll an address until a condition is
* met or a timeout occurs
* @op: accessor function (takes @addr as its only argument)
* @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
* @delay_us: Time to udelay between reads in us (0 tight-loops). Should
* be less than ~10us since udelay is used (see
* Documentation/timers/timers-howto.rst).
* @timeout_us: Timeout in us, 0 means never timeout
* @delay_before_read: if it is true, delay @delay_us before read.
*
* Returns 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @args is stored in @val.
*
* When available, you'll probably want to use one of the specialized
* macros defined below rather than this macro directly.
*/
#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \
delay_before_read, args...) \
({ \
u64 __timeout_us = (timeout_us); \
unsigned long __delay_us = (delay_us); \
ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
if (delay_before_read && __delay_us) \
udelay(__delay_us); \
for (;;) { \
(val) = op(args); \
if (cond) \
break; \
if (__timeout_us && \
ktime_compare(ktime_get(), __timeout) > 0) { \
(val) = op(args); \
break; \
} \
if (__delay_us) \
udelay(__delay_us); \
} \
(cond) ? 0 : -ETIMEDOUT; \
})
/** /**
* readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
* @op: accessor function (takes @addr as its only argument) * @op: accessor function (takes @addr as its only argument)
@ -96,25 +138,7 @@
* macros defined below rather than this macro directly. * macros defined below rather than this macro directly.
*/ */
#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \ #define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
({ \ read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, false, addr)
u64 __timeout_us = (timeout_us); \
unsigned long __delay_us = (delay_us); \
ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
for (;;) { \
(val) = op(addr); \
if (cond) \
break; \
if (__timeout_us && \
ktime_compare(ktime_get(), __timeout) > 0) { \
(val) = op(addr); \
break; \
} \
if (__delay_us) \
udelay(__delay_us); \
} \
(cond) ? 0 : -ETIMEDOUT; \
})
#define readb_poll_timeout(addr, val, cond, delay_us, timeout_us) \ #define readb_poll_timeout(addr, val, cond, delay_us, timeout_us) \
readx_poll_timeout(readb, addr, val, cond, delay_us, timeout_us) readx_poll_timeout(readb, addr, val, cond, delay_us, timeout_us)