netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] Add Xilinx GMII2RGMII loopback support
@ 2021-08-18 12:27 Gerhard Engleder
  2021-08-18 12:27 ` [PATCH net-next 1/2] net: phy: Support set_loopback override Gerhard Engleder
  2021-08-18 12:27 ` [PATCH net-next 2/2] net: phy: gmii2rgmii: Support PHY loopback Gerhard Engleder
  0 siblings, 2 replies; 6+ messages in thread
From: Gerhard Engleder @ 2021-08-18 12:27 UTC (permalink / raw)
  To: andrew; +Cc: netdev, Gerhard Engleder

The Xilinx GMII2RGMII driver overrides PHY driver functions in order to
configure the device according to the link speed of the PHY attached to it.
This is implemented for a normal link but not for loopback.

Andrew told me to use phy_loopback and this changes make phy_loopback work
in combination with Xilinx GMII2RGMII.

Gerhard Engleder (2):
  net: phy: Support set_loopback override
  net: phy: gmii2rgmii: Support PHY loopback

 drivers/net/phy/phy_device.c        |  9 +++---
 drivers/net/phy/xilinx_gmii2rgmii.c | 46 ++++++++++++++++++++++-------
 2 files changed, 39 insertions(+), 16 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next 1/2] net: phy: Support set_loopback override
  2021-08-18 12:27 [PATCH net-next 0/2] Add Xilinx GMII2RGMII loopback support Gerhard Engleder
@ 2021-08-18 12:27 ` Gerhard Engleder
  2021-08-18 15:03   ` Andrew Lunn
  2021-08-18 12:27 ` [PATCH net-next 2/2] net: phy: gmii2rgmii: Support PHY loopback Gerhard Engleder
  1 sibling, 1 reply; 6+ messages in thread
From: Gerhard Engleder @ 2021-08-18 12:27 UTC (permalink / raw)
  To: andrew; +Cc: netdev, Gerhard Engleder

phy_read_status and various other PHY functions support PHY specific
overriding of driver functions by using a PHY specific pointer to the
PHY driver. Add support of PHY specific override to phy_loopback too.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/phy/phy_device.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 107aa6d7bc6b..ba5ad86ec826 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1821,11 +1821,10 @@ EXPORT_SYMBOL(phy_resume);
 
 int phy_loopback(struct phy_device *phydev, bool enable)
 {
-	struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
 	int ret = 0;
 
-	if (!phydrv)
-		return -ENODEV;
+	if (!phydev->drv)
+		return -EIO;
 
 	mutex_lock(&phydev->lock);
 
@@ -1839,8 +1838,8 @@ int phy_loopback(struct phy_device *phydev, bool enable)
 		goto out;
 	}
 
-	if (phydrv->set_loopback)
-		ret = phydrv->set_loopback(phydev, enable);
+	if (phydev->drv->set_loopback)
+		ret = phydev->drv->set_loopback(phydev, enable);
 	else
 		ret = genphy_loopback(phydev, enable);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 2/2] net: phy: gmii2rgmii: Support PHY loopback
  2021-08-18 12:27 [PATCH net-next 0/2] Add Xilinx GMII2RGMII loopback support Gerhard Engleder
  2021-08-18 12:27 ` [PATCH net-next 1/2] net: phy: Support set_loopback override Gerhard Engleder
@ 2021-08-18 12:27 ` Gerhard Engleder
  1 sibling, 0 replies; 6+ messages in thread
From: Gerhard Engleder @ 2021-08-18 12:27 UTC (permalink / raw)
  To: andrew; +Cc: netdev, Gerhard Engleder

Configure speed if loopback is used. read_status is not called for
loopback.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/phy/xilinx_gmii2rgmii.c | 46 ++++++++++++++++++++++-------
 1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 151c2a3f0b3a..8dcb49ed1f3d 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -27,12 +27,28 @@ struct gmii2rgmii {
 	struct mdio_device *mdio;
 };
 
-static int xgmiitorgmii_read_status(struct phy_device *phydev)
+static void xgmiitorgmii_configure(struct gmii2rgmii *priv, int speed)
 {
-	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
 	struct mii_bus *bus = priv->mdio->bus;
 	int addr = priv->mdio->addr;
-	u16 val = 0;
+	u16 val;
+
+	val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
+	val &= ~XILINX_GMII2RGMII_SPEED_MASK;
+
+	if (speed == SPEED_1000)
+		val |= BMCR_SPEED1000;
+	else if (speed == SPEED_100)
+		val |= BMCR_SPEED100;
+	else
+		val |= BMCR_SPEED10;
+
+	mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
+}
+
+static int xgmiitorgmii_read_status(struct phy_device *phydev)
+{
+	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
 	int err;
 
 	if (priv->phy_drv->read_status)
@@ -42,17 +58,24 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
 	if (err < 0)
 		return err;
 
-	val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
-	val &= ~XILINX_GMII2RGMII_SPEED_MASK;
+	xgmiitorgmii_configure(priv, phydev->speed);
 
-	if (phydev->speed == SPEED_1000)
-		val |= BMCR_SPEED1000;
-	else if (phydev->speed == SPEED_100)
-		val |= BMCR_SPEED100;
+	return 0;
+}
+
+static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable)
+{
+	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
+	int err;
+
+	if (priv->phy_drv->set_loopback)
+		err = priv->phy_drv->set_loopback(phydev, enable);
 	else
-		val |= BMCR_SPEED10;
+		err = genphy_loopback(phydev, enable);
+	if (err < 0)
+		return err;
 
-	mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
+	xgmiitorgmii_configure(priv, phydev->speed);
 
 	return 0;
 }
@@ -90,6 +113,7 @@ static int xgmiitorgmii_probe(struct mdio_device *mdiodev)
 	memcpy(&priv->conv_phy_drv, priv->phy_dev->drv,
 	       sizeof(struct phy_driver));
 	priv->conv_phy_drv.read_status = xgmiitorgmii_read_status;
+	priv->conv_phy_drv.set_loopback = xgmiitorgmii_set_loopback;
 	mdiodev_set_drvdata(&priv->phy_dev->mdio, priv);
 	priv->phy_dev->drv = &priv->conv_phy_drv;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 1/2] net: phy: Support set_loopback override
  2021-08-18 12:27 ` [PATCH net-next 1/2] net: phy: Support set_loopback override Gerhard Engleder
@ 2021-08-18 15:03   ` Andrew Lunn
  2021-08-18 20:11     ` Gerhard Engleder
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2021-08-18 15:03 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: netdev

On Wed, Aug 18, 2021 at 02:27:35PM +0200, Gerhard Engleder wrote:
> phy_read_status and various other PHY functions support PHY specific
> overriding of driver functions by using a PHY specific pointer to the
> PHY driver. Add support of PHY specific override to phy_loopback too.
> 
> Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
> ---
>  drivers/net/phy/phy_device.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 107aa6d7bc6b..ba5ad86ec826 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -1821,11 +1821,10 @@ EXPORT_SYMBOL(phy_resume);
>  
>  int phy_loopback(struct phy_device *phydev, bool enable)
>  {
> -	struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
>  	int ret = 0;
>  
> -	if (!phydrv)
> -		return -ENODEV;
> +	if (!phydev->drv)
> +		return -EIO;

Humm, we need to take a closer look at what uses to_phy_driver() and
what uses phydev->drv. Do they need to be different? Can we make it
uniform?

	Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 1/2] net: phy: Support set_loopback override
  2021-08-18 15:03   ` Andrew Lunn
@ 2021-08-18 20:11     ` Gerhard Engleder
  2021-08-18 21:20       ` Andrew Lunn
  0 siblings, 1 reply; 6+ messages in thread
From: Gerhard Engleder @ 2021-08-18 20:11 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: netdev

On Wed, Aug 18, 2021 at 5:03 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Wed, Aug 18, 2021 at 02:27:35PM +0200, Gerhard Engleder wrote:
> > phy_read_status and various other PHY functions support PHY specific
> > overriding of driver functions by using a PHY specific pointer to the
> > PHY driver. Add support of PHY specific override to phy_loopback too.
> >
> > Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
> > ---
> >  drivers/net/phy/phy_device.c | 9 ++++-----
> >  1 file changed, 4 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> > index 107aa6d7bc6b..ba5ad86ec826 100644
> > --- a/drivers/net/phy/phy_device.c
> > +++ b/drivers/net/phy/phy_device.c
> > @@ -1821,11 +1821,10 @@ EXPORT_SYMBOL(phy_resume);
> >
> >  int phy_loopback(struct phy_device *phydev, bool enable)
> >  {
> > -     struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
> >       int ret = 0;
> >
> > -     if (!phydrv)
> > -             return -ENODEV;
> > +     if (!phydev->drv)
> > +             return -EIO;
>
> Humm, we need to take a closer look at what uses to_phy_driver() and
> what uses phydev->drv. Do they need to be different? Can we make it
> uniform?
>
>         Andrew

I saw only 4 references for to_phy_driver():
- phy_loopback() of course
- phy_probe() which uses it to initialize phydev->drv 3 lines later
- mdio_bus_phy_may_suspend() which checks only for valid suspend function
  pointer, but later phy_suspend() uses phydev->drv, so this is at
least inconsistent
- phy_bus_match() which casts from struct device_driver to struct phy_driver

phydev->drv is used much more often and seems to be the right way. I suggest to
also fix mdio_bus_phy_may_suspend(). phy_probe() and phy_bus_match() are
valid uses, because phydev->drv is not available for them.

Do you agree?

Gerhard

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 1/2] net: phy: Support set_loopback override
  2021-08-18 20:11     ` Gerhard Engleder
@ 2021-08-18 21:20       ` Andrew Lunn
  0 siblings, 0 replies; 6+ messages in thread
From: Andrew Lunn @ 2021-08-18 21:20 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: netdev

> I saw only 4 references for to_phy_driver():
> - phy_loopback() of course
> - phy_probe() which uses it to initialize phydev->drv 3 lines later

This is correct. The driver core will set dev.driver to what it thinks
is the correct driver to use, before calling probe.

> - mdio_bus_phy_may_suspend() which checks only for valid suspend function
>   pointer, but later phy_suspend() uses phydev->drv, so this is at
>   least inconsistent

I guess the real question here is, can a device be suspended before it
is probed? It would seem rather odd. So i expect phydev->drv is safe
to use.

> - phy_bus_match() which casts from struct device_driver to struct phy_driver

This is used by the driver core when trying to find a matching
driver. So it is used before phy_probe(). So this is correct.

> 
> phydev->drv is used much more often and seems to be the right way. I suggest to
> also fix mdio_bus_phy_may_suspend(). phy_probe() and phy_bus_match() are
> valid uses, because phydev->drv is not available for them.
> 
> Do you agree?

Agreed. Thanks for spending the time to look at this. I was expecting
there to be more problems than just loopback.

	Andrew

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-08-18 21:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-08-18 12:27 [PATCH net-next 0/2] Add Xilinx GMII2RGMII loopback support Gerhard Engleder
2021-08-18 12:27 ` [PATCH net-next 1/2] net: phy: Support set_loopback override Gerhard Engleder
2021-08-18 15:03   ` Andrew Lunn
2021-08-18 20:11     ` Gerhard Engleder
2021-08-18 21:20       ` Andrew Lunn
2021-08-18 12:27 ` [PATCH net-next 2/2] net: phy: gmii2rgmii: Support PHY loopback Gerhard Engleder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).