diff options
author | Dejin Zheng <zhengdejin5@gmail.com> | 2020-03-23 23:05:51 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-23 22:00:02 -0700 |
commit | 5f5323a14cad19323060a8cbf9d96f2280a462dd (patch) | |
tree | 6a777a6822fdb9310a3b8c659d4d176509c4d001 /include/linux/iopoll.h | |
parent | af13b3c338bea6a766b1a0ee4f9c939e8bf38256 (diff) | |
download | lwn-5f5323a14cad19323060a8cbf9d96f2280a462dd.tar.gz lwn-5f5323a14cad19323060a8cbf9d96f2280a462dd.zip |
iopoll: introduce read_poll_timeout macro
this macro is an extension of readx_poll_timeout macro. the accessor
function op just supports only one parameter in the readx_poll_timeout
macro, but this macro can supports multiple variable parameters for
it. so functions like phy_read(struct phy_device *phydev, u32 regnum)
and phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) can
also use this poll timeout core. and also expand it can sleep some time
before read operation.
Signed-off-by: Dejin Zheng <zhengdejin5@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/iopoll.h')
-rw-r--r-- | include/linux/iopoll.h | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h index 35e15dfd4155..70f89b389648 100644 --- a/include/linux/iopoll.h +++ b/include/linux/iopoll.h @@ -14,6 +14,50 @@ #include <linux/io.h> /** + * read_poll_timeout - Periodically poll an address until a condition is + * met or a timeout occurs + * @op: accessor function (takes @args as its arguments) + * @val: Variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * @sleep_before_read: if it is true, sleep @sleep_us before read. + * @args: arguments for @op poll + * + * Returns 0 on success and -ETIMEDOUT upon a timeout. In either + * case, the last read value at @args is stored in @val. Must not + * be called from atomic context if sleep_us or timeout_us are used. + * + * When available, you'll probably want to use one of the specialized + * macros defined below rather than this macro directly. + */ +#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \ + sleep_before_read, args...) \ +({ \ + u64 __timeout_us = (timeout_us); \ + unsigned long __sleep_us = (sleep_us); \ + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ + might_sleep_if((__sleep_us) != 0); \ + if (sleep_before_read && __sleep_us) \ + usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ + for (;;) { \ + (val) = op(args); \ + if (cond) \ + break; \ + if (__timeout_us && \ + ktime_compare(ktime_get(), __timeout) > 0) { \ + (val) = op(args); \ + break; \ + } \ + if (__sleep_us) \ + usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ + } \ + (cond) ? 0 : -ETIMEDOUT; \ +}) + +/** * 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) * @addr: Address to poll |