2020-03-22 02:50:21

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 0/7] 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.

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 <[email protected]>, 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.



Dejin Zheng (7):
iopoll: introduce read_poll_timeout macro
iopoll: redefined readx_poll_timeout macro to simplify the code
net: phy: introduce phy_read_mmd_poll_timeout macro
net: phy: bcm84881: use phy_read_mmd_poll_timeout() to simplify the
code
net: phy: aquantia: use phy_read_mmd_poll_timeout() to simplify the
code
net: phy: introduce phy_read_poll_timeout macro
net: phy: use phy_read_poll_timeout() to simplify the code

drivers/net/phy/aquantia_main.c | 13 ++++--------
drivers/net/phy/bcm84881.c | 27 ++++---------------------
drivers/net/phy/phy_device.c | 16 ++++-----------
include/linux/iopoll.h | 36 ++++++++++++++++++++++++++-------
include/linux/phy.h | 27 +++++++++++++++++++++++++
5 files changed, 68 insertions(+), 51 deletions(-)

--
2.25.0


2020-03-22 02:50:25

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 4/7] net: phy: bcm84881: use phy_read_mmd_poll_timeout() to simplify the code

use phy_read_mmd_poll_timeout() to replace the poll codes for
simplify the code in bcm84881_wait_init() function.

Signed-off-by: Dejin Zheng <[email protected]>
---
v2 -> v3:
- adapt to it after modifying the parameter order of the
newly added function
v1 -> v2:
- remove the handle of phy_read_mmd's return error.

drivers/net/phy/bcm84881.c | 27 ++++-----------------------
1 file changed, 4 insertions(+), 23 deletions(-)

diff --git a/drivers/net/phy/bcm84881.c b/drivers/net/phy/bcm84881.c
index 14d55a77eb28..b70be775909c 100644
--- a/drivers/net/phy/bcm84881.c
+++ b/drivers/net/phy/bcm84881.c
@@ -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);
}

static int bcm84881_config_init(struct phy_device *phydev)
--
2.25.0

2020-03-22 02:50:25

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 3/7] net: phy: introduce phy_read_mmd_poll_timeout macro

it is sometimes necessary to poll a phy register by phy_read_mmd()
function until its value satisfies some condition. introduce
phy_read_mmd_poll_timeout() macros that do this.

Suggested-by: Andrew Lunn <[email protected]>
Signed-off-by: Dejin Zheng <[email protected]>
---
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)
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. Andrew Lunn <[email protected]>, Thanks very much for
your help!
- handle phy_read_mmd return an error(the return value < 0) in
phy_read_mmd_poll_timeout(). Thanks Andrew again.


include/linux/phy.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 36d9dea04016..29718865242d 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -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>

@@ -784,6 +785,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) \
+({ \
+ int ret = 0; \
+ ret = read_poll_timeout(phy_read_mmd, val, cond || val < 0, sleep_us, \
+ timeout_us, 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.
--
2.25.0

2020-03-22 02:51:41

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 6/7] net: phy: introduce phy_read_poll_timeout macro

it is sometimes necessary to poll a phy register by phy_read()
function until its value satisfies some condition. introduce
phy_read_poll_timeout() macros that do this.

Suggested-by: Andrew Lunn <[email protected]>
Signed-off-by: Dejin Zheng <[email protected]>
---
v2 -> v3:
- modify the parameter order of newly added functions.
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:
- pass a phydev and a regnum to replace args... parameter in
the phy_read_poll_timeout(), and also handle the
phy_read() function's return error.

include/linux/phy.h | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 29718865242d..a23d6caf5c2c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -714,6 +714,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) \
+({ \
+ int ret = 0; \
+ ret = read_poll_timeout(phy_read, val, cond || val < 0, sleep_us, \
+ timeout_us, 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
--
2.25.0

2020-03-22 02:51:52

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 7/7] net: phy: use phy_read_poll_timeout() to simplify the code

use phy_read_poll_timeout() to replace the poll codes for
simplify the code in phy_poll_reset() function.

Signed-off-by: Dejin Zheng <[email protected]>
---
v2 -> v3:
- adapt to it after modifying the parameter order of the
newly added function
v1 -> v2:
- remove the handle of phy_read()'s return error.

drivers/net/phy/phy_device.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a585faf8b844..cfe7aae35084 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1059,23 +1059,15 @@ 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);
/* Some chips (smsc911x) may still need up to another 1ms after the
* BMCR_RESET bit is cleared before they are usable.
*/
msleep(1);
- return 0;
+ return ret;
}

int phy_init_hw(struct phy_device *phydev)
--
2.25.0

2020-03-22 02:51:54

by Dejin Zheng

[permalink] [raw]
Subject: [PATCH net-next v3 5/7] net: phy: aquantia: use phy_read_mmd_poll_timeout() to simplify the code

use phy_read_mmd_poll_timeout() to replace the poll codes for
simplify the code in aqr107_wait_reset_complete() function.

Signed-off-by: Dejin Zheng <[email protected]>
---
v2 -> v3:
- adapt to it after modifying the parameter order of the
newly added function
v1 -> v2:
- remove the handle of phy_read_mmd's return error.

drivers/net/phy/aquantia_main.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
index 31927b2c7d5a..db3e20938729 100644
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -451,16 +451,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);
}

static void aqr107_chip_info(struct phy_device *phydev)
--
2.25.0

2020-03-22 02:58:54

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next v3 7/7] net: phy: use phy_read_poll_timeout() to simplify the code



On 3/21/2020 7:48 PM, Dejin Zheng wrote:
> use phy_read_poll_timeout() to replace the poll codes for
> simplify the code in phy_poll_reset() function.
>
> Signed-off-by: Dejin Zheng <[email protected]>
> ---
> v2 -> v3:
> - adapt to it after modifying the parameter order of the
> newly added function
> v1 -> v2:
> - remove the handle of phy_read()'s return error.
>
> drivers/net/phy/phy_device.c | 16 ++++------------
> 1 file changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index a585faf8b844..cfe7aae35084 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -1059,23 +1059,15 @@ 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);

You are doing some subtle changes here, the sleep used to be *before*
the read of BMCR and now it will be *after*. If there were PHY devices
that required 50ms at least, but would incorrectly return that
BMCR_RESET is cleared *before* 50ms, then we would be breaking those.

I would recommend we drop this patch for now, the rest looks good to me
though.
--
Florian

2020-03-22 06:14:29

by Dejin Zheng

[permalink] [raw]
Subject: Re: [PATCH net-next v3 7/7] net: phy: use phy_read_poll_timeout() to simplify the code

On Sat, Mar 21, 2020 at 07:57:11PM -0700, Florian Fainelli wrote:
>
>
> On 3/21/2020 7:48 PM, Dejin Zheng wrote:
> > use phy_read_poll_timeout() to replace the poll codes for
> > simplify the code in phy_poll_reset() function.
> >
> > Signed-off-by: Dejin Zheng <[email protected]>
> > ---
> > v2 -> v3:
> > - adapt to it after modifying the parameter order of the
> > newly added function
> > v1 -> v2:
> > - remove the handle of phy_read()'s return error.
> >
> > drivers/net/phy/phy_device.c | 16 ++++------------
> > 1 file changed, 4 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> > index a585faf8b844..cfe7aae35084 100644
> > --- a/drivers/net/phy/phy_device.c
> > +++ b/drivers/net/phy/phy_device.c
> > @@ -1059,23 +1059,15 @@ 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);
>
> You are doing some subtle changes here, the sleep used to be *before*
> the read of BMCR and now it will be *after*. If there were PHY devices
> that required 50ms at least, but would incorrectly return that
> BMCR_RESET is cleared *before* 50ms, then we would be breaking those.
>
> I would recommend we drop this patch for now, the rest looks good to me
> though.

Hi Florian��

Thanks very much for your comments, I will drop this patch, and can I get
your ack/reviewed-by for the rest patches? thanks again!

BR,
dejin

> --
> Florian