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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
629cb91942
|
@ -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;
|
||||
int val;
|
||||
|
||||
do {
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID);
|
||||
if (val < 0)
|
||||
return val;
|
||||
msleep(20);
|
||||
} while (!val && --retries);
|
||||
|
||||
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;
|
||||
int 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);
|
||||
|
||||
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;
|
||||
int val;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -13,6 +13,50 @@
|
|||
#include <linux/errno.h>
|
||||
#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)
|
||||
|
@ -32,25 +76,7 @@
|
|||
* macros defined below rather than this macro directly.
|
||||
*/
|
||||
#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \
|
||||
({ \
|
||||
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); \
|
||||
for (;;) { \
|
||||
(val) = op(addr); \
|
||||
if (cond) \
|
||||
break; \
|
||||
if (__timeout_us && \
|
||||
ktime_compare(ktime_get(), __timeout) > 0) { \
|
||||
(val) = op(addr); \
|
||||
break; \
|
||||
} \
|
||||
if (__sleep_us) \
|
||||
usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
|
||||
} \
|
||||
(cond) ? 0 : -ETIMEDOUT; \
|
||||
})
|
||||
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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue