Commit 629cb919 authored by David S. Miller's avatar David S. Miller

Merge branch 'introduce-read_poll_timeout'

Dejin Zheng says:

====================
introduce read_poll_timeout

This patch sets is introduce read_poll_timeout macro, it 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
use this poll timeout framework.

the first patch introduce read_poll_timeout macro, and the second patch
redefined readx_poll_timeout macro by read_poll_timeout(), and the other
patches are examples using read_poll_timeout macro.

v6 -> v7:
	- add a parameter to supports that it can sleep some time
	  before read operation in read_poll_timeout macro.
	- add prefix with double underscores for some variable to avoid
	  any variable re-declaration or shadowing in patch 3 and patch
	  7.
v5 -> v6:
	- add some check to keep the code more similar in patch 8
v4 -> v5:
	- add some msleep() before call phy_read_mmd_poll_timeout() to
	  keep the code more similar in patch 6 and patch 9.
	- add a patch of drop by v4, it can add msleep before call
	  phy_read_poll_timeout() to keep the code more similar.
v3 -> v4:
	- add 3 examples of using new functions.
	- deal with precedence issues for parameter cond.
	- drop a patch about phy_poll_reset() function.
v2 -> v3:
	- modify the parameter order of newly added functions.
	  phy_read_mmd_poll_timeout(val, cond, sleep_us, timeout_us, \
				     phydev, devaddr, regnum)
				||
				\/
	  phy_read_mmd_poll_timeout(phydev, devaddr regnum, val, cond, \
				    sleep_us, timeout_us)

	  phy_read_poll_timeout(val, cond, sleep_us, timeout_us, \
				phydev, regnum)
				||
				\/
	  phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
				timeout_us)
v1 -> v2:
	- passed a phydev, device address and a reg to replace args...
	  parameter in phy_read_mmd_poll_timeout() by Andrew Lunn 's
	  suggestion in patch 3. Andrew Lunn <andrew@lunn.ch>, Thanks
	  very much for your help!
	- also in patch 3, handle phy_read_mmd return an error(the return
	  value < 0) in phy_read_mmd_poll_timeout(). Thanks Andrew
	  again.
	- in patch 6, pass a phydev and a reg to replace args...
	  parameter in phy_read_poll_timeout(), and also handle the
	  phy_read() function's return error.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents af13b3c3 704f691a
......@@ -434,16 +434,11 @@ static int aqr107_set_tunable(struct phy_device *phydev,
*/
static int aqr107_wait_reset_complete(struct phy_device *phydev)
{
int val, retries = 100;
do {
val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID);
if (val < 0)
return val;
msleep(20);
} while (!val && --retries);
int val;
return val ? 0 : -ETIMEDOUT;
return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
VEND1_GLOBAL_FW_ID, val, val != 0,
20000, 2000000, false);
}
static void aqr107_chip_info(struct phy_device *phydev)
......
......@@ -22,30 +22,11 @@ enum {
static int bcm84881_wait_init(struct phy_device *phydev)
{
unsigned int tries = 20;
int ret, val;
do {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
if (val < 0) {
ret = val;
break;
}
if (!(val & MDIO_CTRL1_RESET)) {
ret = 0;
break;
}
if (!--tries) {
ret = -ETIMEDOUT;
break;
}
msleep(100);
} while (1);
int val;
if (ret)
phydev_err(phydev, "%s failed: %d\n", __func__, ret);
return ret;
return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
val, !(val & MDIO_CTRL1_RESET),
100000, 2000000, false);
}
static int bcm84881_config_init(struct phy_device *phydev)
......
......@@ -241,22 +241,17 @@ static int mv3310_power_up(struct phy_device *phydev)
static int mv3310_reset(struct phy_device *phydev, u32 unit)
{
int retries, val, err;
int val, err;
err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
if (err < 0)
return err;
retries = 20;
do {
msleep(5);
val = phy_read_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1);
if (val < 0)
return val;
} while (val & MDIO_CTRL1_RESET && --retries);
return val & MDIO_CTRL1_RESET ? -ETIMEDOUT : 0;
return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
unit + MDIO_CTRL1, val,
!(val & MDIO_CTRL1_RESET),
5000, 100000, true);
}
static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd)
......
......@@ -72,20 +72,10 @@ static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
{
int i, ret;
for (i = 0; i < 200; i++) {
ret = phy_read(phydev, reg);
if (ret < 0)
return ret;
if ((ret & mask) == set)
return 0;
usleep_range(100, 150);
}
int val;
return -ETIMEDOUT;
return phy_read_poll_timeout(phydev, reg, val, (val & mask) == set,
150, 30000, false);
}
static int phy_modify_check(struct phy_device *phydev, u8 reg,
......
......@@ -1059,18 +1059,12 @@ EXPORT_SYMBOL(phy_disconnect);
static int phy_poll_reset(struct phy_device *phydev)
{
/* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
unsigned int retries = 12;
int ret;
do {
msleep(50);
ret = phy_read(phydev, MII_BMCR);
if (ret < 0)
return ret;
} while (ret & BMCR_RESET && --retries);
if (ret & BMCR_RESET)
return -ETIMEDOUT;
int ret, val;
ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
50000, 600000, true);
if (ret)
return ret;
/* Some chips (smsc911x) may still need up to another 1ms after the
* BMCR_RESET bit is cleared before they are usable.
*/
......
......@@ -112,8 +112,6 @@ static int lan87xx_read_status(struct phy_device *phydev)
int err = genphy_read_status(phydev);
if (!phydev->link && priv->energy_enable) {
int i;
/* Disable EDPD to wake up PHY */
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
......@@ -125,15 +123,11 @@ static int lan87xx_read_status(struct phy_device *phydev)
return rc;
/* Wait max 640 ms to detect energy */
for (i = 0; i < 64; i++) {
/* Sleep to allow link test pulses to be sent */
msleep(10);
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
if (rc < 0)
return rc;
if (rc & MII_LAN83C185_ENERGYON)
break;
}
phy_read_poll_timeout(phydev, MII_LAN83C185_CTRL_STATUS, rc,
rc & MII_LAN83C185_ENERGYON, 10000,
640000, true);
if (rc < 0)
return rc;
/* Re-enable EDPD */
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
......
......@@ -14,36 +14,41 @@
#include <linux/io.h>
/**
* 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
* 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 @addr is stored in @val. Must not
* 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 readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
#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(addr); \
(val) = op(args); \
if (cond) \
break; \
if (__timeout_us && \
ktime_compare(ktime_get(), __timeout) > 0) { \
(val) = op(addr); \
(val) = op(args); \
break; \
} \
if (__sleep_us) \
......@@ -52,6 +57,27 @@
(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
* @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
*
* Returns 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @addr 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 readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
read_poll_timeout(op, val, cond, sleep_us, timeout_us, false, addr)
/**
* readx_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)
......
......@@ -24,6 +24,7 @@
#include <linux/mod_devicetable.h>
#include <linux/u64_stats_sync.h>
#include <linux/irqreturn.h>
#include <linux/iopoll.h>
#include <linux/atomic.h>
......@@ -716,6 +717,19 @@ static inline int phy_read(struct phy_device *phydev, u32 regnum)
return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
}
#define phy_read_poll_timeout(phydev, regnum, val, cond, sleep_us, \
timeout_us, sleep_before_read) \
({ \
int __ret = read_poll_timeout(phy_read, val, (cond) || val < 0, \
sleep_us, timeout_us, sleep_before_read, phydev, regnum); \
if (val < 0) \
__ret = val; \
if (__ret) \
phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
__ret; \
})
/**
* __phy_read - convenience function for reading a given PHY register
* @phydev: the phy_device struct
......@@ -787,6 +801,19 @@ static inline int __phy_modify_changed(struct phy_device *phydev, u32 regnum,
*/
int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
#define phy_read_mmd_poll_timeout(phydev, devaddr, regnum, val, cond, \
sleep_us, timeout_us, sleep_before_read) \
({ \
int __ret = read_poll_timeout(phy_read_mmd, val, (cond) || val < 0, \
sleep_us, timeout_us, sleep_before_read, \
phydev, devaddr, regnum); \
if (val < 0) \
__ret = val; \
if (__ret) \
phydev_err(phydev, "%s failed: %d\n", __func__, __ret); \
__ret; \
})
/**
* __phy_read_mmd - Convenience function for reading a register
* from an MMD on a given PHY.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment