diff mbox series

[1/3] net: macb: fix for fixed-link mode

Message ID 1575890061-24250-1-git-send-email-mparab@cadence.com
State Changes Requested
Delegated to: David Miller
Headers show
Series net: macb: fix for fixed link, support for c45 mdio and 10G | expand

Commit Message

Milind Parab Dec. 9, 2019, 11:14 a.m. UTC
This patch fix the issue with fixed link. With fixed-link
device opening fails due to macb_phylink_connect not
handling fixed-link mode, in which case no MAC-PHY connection
is needed and phylink_connect return success (0), however
in current driver attempt is made to search and connect to
PHY even for fixed-link.

Signed-off-by: Milind Parab <mparab@cadence.com>
---
 drivers/net/ethernet/cadence/macb_main.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

Comments

Russell King (Oracle) Dec. 9, 2019, 11:26 a.m. UTC | #1
On Mon, Dec 09, 2019 at 11:14:21AM +0000, Milind Parab wrote:
> This patch fix the issue with fixed link. With fixed-link
> device opening fails due to macb_phylink_connect not
> handling fixed-link mode, in which case no MAC-PHY connection
> is needed and phylink_connect return success (0), however
> in current driver attempt is made to search and connect to
> PHY even for fixed-link.
> 
> Signed-off-by: Milind Parab <mparab@cadence.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 17 ++++++++---------
>  1 file changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index 9c767ee252ac..6b68ef34ab19 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -615,17 +615,13 @@ static int macb_phylink_connect(struct macb *bp)
>  {
>  	struct net_device *dev = bp->dev;
>  	struct phy_device *phydev;
> +	struct device_node *dn = bp->pdev->dev.of_node;
>  	int ret;
>  
> -	if (bp->pdev->dev.of_node &&
> -	    of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) {
> -		ret = phylink_of_phy_connect(bp->phylink, bp->pdev->dev.of_node,
> -					     0);
> -		if (ret) {
> -			netdev_err(dev, "Could not attach PHY (%d)\n", ret);
> -			return ret;
> -		}
> -	} else {
> +	if (dn)
> +		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
> +
> +	if (!dn || (ret && !of_parse_phandle(dn, "phy-handle", 0))) {

Hi,

If of_parse_phandle() returns non-null, the device_node it returns will
have its reference count increased by one.  That reference needs to be
put.

I assume you're trying to determine whether phylink_of_phy_connect()
failed because of a missing phy-handle rather than of_phy_attach()
failing?  Maybe those two failures ought to be distinguished by errno
return value?

of_phy_attach() may fail due to of_phy_find_device() failing to find
the PHY, or phy_attach_direct() failing.  We could switch from using
of_phy_attach(), to using of_phy_find_device() directly so we can then
propagate phy_attach_direct()'s error code back, rather than losing it.
That would then leave the case of of_phy_find_device() failure to be
considered in terms of errno return value.

>  		phydev = phy_find_first(bp->mii_bus);
>  		if (!phydev) {
>  			netdev_err(dev, "no PHY found\n");
> @@ -638,6 +634,9 @@ static int macb_phylink_connect(struct macb *bp)
>  			netdev_err(dev, "Could not attach to PHY (%d)\n", ret);
>  			return ret;
>  		}
> +	} else if (ret) {
> +		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
> +		return ret;
>  	}
>  
>  	phylink_start(bp->phylink);
> -- 
> 2.17.1
> 
>
Milind Parab Dec. 10, 2019, 9:14 a.m. UTC | #2
>> This patch fix the issue with fixed link. With fixed-link
>> device opening fails due to macb_phylink_connect not
>> handling fixed-link mode, in which case no MAC-PHY connection
>> is needed and phylink_connect return success (0), however
>> in current driver attempt is made to search and connect to
>> PHY even for fixed-link.
>>
>> Signed-off-by: Milind Parab <mparab@cadence.com>
>> ---
>>  drivers/net/ethernet/cadence/macb_main.c | 17 ++++++++---------
>>  1 file changed, 8 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
>> index 9c767ee252ac..6b68ef34ab19 100644
>> --- a/drivers/net/ethernet/cadence/macb_main.c
>> +++ b/drivers/net/ethernet/cadence/macb_main.c
>> @@ -615,17 +615,13 @@ static int macb_phylink_connect(struct macb *bp)
>>  {
>>  	struct net_device *dev = bp->dev;
>>  	struct phy_device *phydev;
>> +	struct device_node *dn = bp->pdev->dev.of_node;
>>  	int ret;
>>
>> -	if (bp->pdev->dev.of_node &&
>> -	    of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) {
>> -		ret = phylink_of_phy_connect(bp->phylink, bp->pdev-
>>dev.of_node,
>> -					     0);
>> -		if (ret) {
>> -			netdev_err(dev, "Could not attach PHY (%d)\n", ret);
>> -			return ret;
>> -		}
>> -	} else {
>> +	if (dn)
>> +		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
>> +
>> +	if (!dn || (ret && !of_parse_phandle(dn, "phy-handle", 0))) {
>
>Hi,
>If of_parse_phandle() returns non-null, the device_node it returns will
>have its reference count increased by one.  That reference needs to be
>put.
>

Okay, as per your suggestion below addition will be okay to store the "phy_node" and then of_node_put(phy_node) on error

phy_node = of_parse_phandle(dn, "phy-handle", 0);
        if (!dn || (ret && !phy_node)) {
                phydev = phy_find_first(bp->mii_bus);
                if (!phydev) {
                        netdev_err(dev, "no PHY found\n");
                        ret = -ENXIO;
                        goto phylink_connect_err;
                }

                /* attach the mac to the phy */
                ret = phylink_connect_phy(bp->phylink, phydev);
                if (ret) {
                        netdev_err(dev, "Could not attach to PHY (%d)\n", ret);
                        goto phylink_connect_err;
                }
        } else if (ret) {
                netdev_err(dev, "Could not attach PHY (%d)\n", ret);
                goto phylink_connect_err;
        }

        phylink_start(bp->phylink);

phylink_connect_err:
        if (phy_node)
                of_node_put(phy_node);

        return ret;

>I assume you're trying to determine whether phylink_of_phy_connect()
>failed because of a missing phy-handle rather than of_phy_attach()
>failing?  Maybe those two failures ought to be distinguished by errno
>return value?

Yes, PHY will be scanned only if phylink_of_phy_connect() returns error due to missing "phy-handle". 
Currently, phylink_of_phy_connect() returns same error for missing "phy-handle" and of_phy_attach() failure.

>of_phy_attach() may fail due to of_phy_find_device() failing to find
>the PHY, or phy_attach_direct() failing.  We could switch from using
>of_phy_attach(), to using of_phy_find_device() directly so we can then
>propagate phy_attach_direct()'s error code back, rather than losing it.
>That would then leave the case of of_phy_find_device() failure to be
>considered in terms of errno return value.

>>  		phydev = phy_find_first(bp->mii_bus);
>>  		if (!phydev) {
>>  			netdev_err(dev, "no PHY found\n");
>> @@ -638,6 +634,9 @@ static int macb_phylink_connect(struct macb *bp)
>>  			netdev_err(dev, "Could not attach to PHY (%d)\n",ret);
>>  			return ret;
>>  		}
>> +	} else if (ret) {
>> +		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
>> +		return ret;
>>  	}
>>
>>  	phylink_start(bp->phylink);
>> --
>> 2.17.1
>>
>>
>--RMK's Patch system: https://urldefense.proofpoint.com/v2/url?u=https-
>3A__www.armlinux.org.uk_developer_patches_&d=DwIBAg&c=aUq983L2pue
>2FqKFoP6PGHMJQyoJ7kl3s3GZ-
>_haXqY&r=BDdk1JtITE_JJ0519WwqU7IKF80Cw1i55lZOGqv2su8&m=blnuaRbic
>V2uF6XaoVuWN0U5yR5cFOzUSAs3ZPlxioU&s=rhp71ilc6R4_pmDsY07-
>kLPGbhyoyixXoHF0hMGu4Go&e=
>
>FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps
>up
>
>According to speedtest.net: 11.9Mbps down 500kbps up
Russell King (Oracle) Dec. 10, 2019, 11:38 a.m. UTC | #3
On Tue, Dec 10, 2019 at 09:14:13AM +0000, Milind Parab wrote:
> >> This patch fix the issue with fixed link. With fixed-link
> >> device opening fails due to macb_phylink_connect not
> >> handling fixed-link mode, in which case no MAC-PHY connection
> >> is needed and phylink_connect return success (0), however
> >> in current driver attempt is made to search and connect to
> >> PHY even for fixed-link.
> >>
> >> Signed-off-by: Milind Parab <mparab@cadence.com>
> >> ---
> >>  drivers/net/ethernet/cadence/macb_main.c | 17 ++++++++---------
> >>  1 file changed, 8 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> >> index 9c767ee252ac..6b68ef34ab19 100644
> >> --- a/drivers/net/ethernet/cadence/macb_main.c
> >> +++ b/drivers/net/ethernet/cadence/macb_main.c
> >> @@ -615,17 +615,13 @@ static int macb_phylink_connect(struct macb *bp)
> >>  {
> >>  	struct net_device *dev = bp->dev;
> >>  	struct phy_device *phydev;
> >> +	struct device_node *dn = bp->pdev->dev.of_node;
> >>  	int ret;
> >>
> >> -	if (bp->pdev->dev.of_node &&
> >> -	    of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) {
> >> -		ret = phylink_of_phy_connect(bp->phylink, bp->pdev-
> >>dev.of_node,
> >> -					     0);
> >> -		if (ret) {
> >> -			netdev_err(dev, "Could not attach PHY (%d)\n", ret);
> >> -			return ret;
> >> -		}
> >> -	} else {
> >> +	if (dn)
> >> +		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
> >> +
> >> +	if (!dn || (ret && !of_parse_phandle(dn, "phy-handle", 0))) {
> >
> >Hi,
> >If of_parse_phandle() returns non-null, the device_node it returns will
> >have its reference count increased by one.  That reference needs to be
> >put.
> >
> 
> Okay, as per your suggestion below addition will be okay to store the "phy_node" and then of_node_put(phy_node) on error
> 
> phy_node = of_parse_phandle(dn, "phy-handle", 0);
>         if (!dn || (ret && !phy_node)) {
>                 phydev = phy_find_first(bp->mii_bus);
...
>         if (phy_node)
>                 of_node_put(phy_node);

As you're only interested in whether phy-handle exists or not, you
could do this instead:

	phy_node = of_parse_phandle(dn, "phy-handle", 0);
	of_node_put(phy_node);
	if (!dn || (ret && !phy_node)) {
		...

Yes, it looks a bit weird, but the only thing you're interested in
here is whether of_parse_phandle() returned NULL or non-NULL. You're
not interested in dereferencing the pointer.

Some may raise some eye-brows at that, so it may be better to have
this as a helper:

static bool macb_phy_handle_exists(struct device_node *dn)
{
	dn = of_parse_phandle(dn, "phy-handle", 0);
	of_node_put(dn);
	return dn != NULL;
}

and use it as:

	if (!dn || (ret && !macb_phy_handle_exists(dn))) {

which is more obvious what is going on.

> 
>         return ret;
> 
> >I assume you're trying to determine whether phylink_of_phy_connect()
> >failed because of a missing phy-handle rather than of_phy_attach()
> >failing?  Maybe those two failures ought to be distinguished by errno
> >return value?
> 
> Yes, PHY will be scanned only if phylink_of_phy_connect() returns error due to missing "phy-handle". 
> Currently, phylink_of_phy_connect() returns same error for missing "phy-handle" and of_phy_attach() failure.
> 
> >of_phy_attach() may fail due to of_phy_find_device() failing to find
> >the PHY, or phy_attach_direct() failing.  We could switch from using
> >of_phy_attach(), to using of_phy_find_device() directly so we can then
> >propagate phy_attach_direct()'s error code back, rather than losing it.
> >That would then leave the case of of_phy_find_device() failure to be
> >considered in terms of errno return value.

Here's a patch I quickly knocked up that does this - may not apply to
the kernel you're using as there's a whole bunch of work I have
outstanding, but gives the outline idea.  Does this help?

8<===
From: Russell King <rmk+kernel@armlinux.org.uk>
Subject: [PATCH] net: phylink: avoid of_phy_attach()

of_phy_attach() hides the return value of phy_attach_direct(), forcing
us to return a "generic" ENODEV error code that is indistinguishable
from the lack-of-phy-property case.

Switch to using of_phy_find_device() to find the PHY device, and then
propagating any phy_attach_direct() error back to the caller.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index e9036b72114c..5a5109428d9e 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -887,14 +887,17 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
 		return 0;
 	}
 
-	phy_dev = of_phy_attach(pl->netdev, phy_node, flags,
-				pl->link_interface);
+	phy_dev = of_phy_find_device(phy_node);
 	/* We're done with the phy_node handle */
 	of_node_put(phy_node);
-
 	if (!phy_dev)
 		return -ENODEV;
 
+	ret = phy_attach_direct(pl->netdev, phy_dev, flags,
+				pl->link_interface);
+	if (ret)
+		return ret;
+
 	ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
 	if (ret)
 		phy_detach(phy_dev);
Milind Parab Dec. 11, 2019, 8:21 a.m. UTC | #4
>> >> +		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
>> >> +
>> >> +	if (!dn || (ret && !of_parse_phandle(dn, "phy-handle", 0))) {
>> >
>> >Hi,
>> >If of_parse_phandle() returns non-null, the device_node it returns will
>> >have its reference count increased by one.  That reference needs to be
>> >put.
>> >
>>
>> Okay, as per your suggestion below addition will be okay to store the
>"phy_node" and then of_node_put(phy_node) on error
>>
>> phy_node = of_parse_phandle(dn, "phy-handle", 0);
>>         if (!dn || (ret && !phy_node)) {
>>                 phydev = phy_find_first(bp->mii_bus);
>...
>>         if (phy_node)
>>                 of_node_put(phy_node);
>
>As you're only interested in whether phy-handle exists or not, you
>could do this instead:
>
>	phy_node = of_parse_phandle(dn, "phy-handle", 0);
>	of_node_put(phy_node);
>	if (!dn || (ret && !phy_node)) {
>		...
>
>Yes, it looks a bit weird, but the only thing you're interested in
>here is whether of_parse_phandle() returned NULL or non-NULL. You're
>not interested in dereferencing the pointer.
>
>Some may raise some eye-brows at that, so it may be better to have
>this as a helper:
>
>static bool macb_phy_handle_exists(struct device_node *dn)
>{
>	dn = of_parse_phandle(dn, "phy-handle", 0);
>	of_node_put(dn);
>	return dn != NULL;
>}
>
>and use it as:
>
>	if (!dn || (ret && !macb_phy_handle_exists(dn))) {
>
>which is more obvious what is going on.
>

This is good. I will put this in the revised patch.

>
>>
>>         return ret;
>>
>> >I assume you're trying to determine whether phylink_of_phy_connect()
>> >failed because of a missing phy-handle rather than of_phy_attach()
>> >failing?  Maybe those two failures ought to be distinguished by errno
>> >return value?
>>
>> Yes, PHY will be scanned only if phylink_of_phy_connect() returns error due to missing "phy-handle".
>> Currently, phylink_of_phy_connect() returns same error for missing "phy-handle" and of_phy_attach() failure.
>>
>> >of_phy_attach() may fail due to of_phy_find_device() failing to find
>> >the PHY, or phy_attach_direct() failing.  We could switch from using
>> >of_phy_attach(), to using of_phy_find_device() directly so we can then
>> >propagate phy_attach_direct()'s error code back, rather than losing it.
>> >That would then leave the case of of_phy_find_device() failure to be
>> >considered in terms of errno return value.
>
>Here's a patch I quickly knocked up that does this - may not apply to
>the kernel you're using as there's a whole bunch of work I have
>outstanding, but gives the outline idea.  Does this help?
>
>

Yes, this will help. Once available, we will adopt this change.

>8<===
>From: Russell King <rmk+kernel@armlinux.org.uk>
>Subject: [PATCH] net: phylink: avoid of_phy_attach()
>
>of_phy_attach() hides the return value of phy_attach_direct(), forcing
>us to return a "generic" ENODEV error code that is indistinguishable
>from the lack-of-phy-property case.
>Switch to using of_phy_find_device() to find the PHY device, and then
>propagating any phy_attach_direct() error back to the caller.
>
>
>Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>---
>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 9c767ee252ac..6b68ef34ab19 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -615,17 +615,13 @@  static int macb_phylink_connect(struct macb *bp)
 {
 	struct net_device *dev = bp->dev;
 	struct phy_device *phydev;
+	struct device_node *dn = bp->pdev->dev.of_node;
 	int ret;
 
-	if (bp->pdev->dev.of_node &&
-	    of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) {
-		ret = phylink_of_phy_connect(bp->phylink, bp->pdev->dev.of_node,
-					     0);
-		if (ret) {
-			netdev_err(dev, "Could not attach PHY (%d)\n", ret);
-			return ret;
-		}
-	} else {
+	if (dn)
+		ret = phylink_of_phy_connect(bp->phylink, dn, 0);
+
+	if (!dn || (ret && !of_parse_phandle(dn, "phy-handle", 0))) {
 		phydev = phy_find_first(bp->mii_bus);
 		if (!phydev) {
 			netdev_err(dev, "no PHY found\n");
@@ -638,6 +634,9 @@  static int macb_phylink_connect(struct macb *bp)
 			netdev_err(dev, "Could not attach to PHY (%d)\n", ret);
 			return ret;
 		}
+	} else if (ret) {
+		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
+		return ret;
 	}
 
 	phylink_start(bp->phylink);