diff mbox series

[net-next,v3,4/4] net: fec: add phy_reset_after_clk_enable() support

Message ID 20171205132600.13796-5-dev@g0hl1n.net
State Changes Requested, archived
Delegated to: David Miller
Headers show
Series net: fec: fix refclk enable for SMSC LAN8710/20 | expand

Commit Message

Richard Leitner Dec. 5, 2017, 1:26 p.m. UTC
From: Richard Leitner <richard.leitner@skidata.com>

Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
the refclk on and off again during operation (according to their
datasheet). Nonetheless exactly this behaviour was introduced for power
saving reasons by commit e8fcfcd5684a ("net: fec: optimize the clock management to save power").
Therefore add support for the phy_reset_after_clk_enable function from
phylib to mitigate this issue.

Generally speaking this issue is only relevant if the ref clk for the
PHY is generated by the SoC and therefore the PHY is configured to
"REF_CLK In Mode". In our specific case (PCB) this problem does occur at
about every 10th to 50th POR of an LAN8710 connected to an i.MX6SOLO
SoC. The typical symptom of this problem is a "swinging" ethernet link.
Similar issues were reported by users of the NXP forum:
	https://community.nxp.com/thread/389902
	https://community.nxp.com/message/309354
With this patch applied the issue didn't occur for at least a few
hundret PORs of our board.

Fixes: e8fcfcd5684a ("net: fec: optimize the clock management to save power")
Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 7 +++++++
 1 file changed, 7 insertions(+)

Comments

Andy Duan Dec. 6, 2017, 1:50 a.m. UTC | #1
From: Richard Leitner <dev@g0hl1n.net> Sent: Tuesday, December 05, 2017 9:26 PM
>Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
>the refclk on and off again during operation (according to their datasheet).
>Nonetheless exactly this behaviour was introduced for power saving reasons
>by commit e8fcfcd5684a ("net: fec: optimize the clock management to save
>power").
>Therefore add support for the phy_reset_after_clk_enable function from
>phylib to mitigate this issue.
>
>Generally speaking this issue is only relevant if the ref clk for the PHY is
>generated by the SoC and therefore the PHY is configured to "REF_CLK In
>Mode". In our specific case (PCB) this problem does occur at about every 10th
>to 50th POR of an LAN8710 connected to an i.MX6SOLO SoC. The typical
>symptom of this problem is a "swinging" ethernet link.
>Similar issues were reported by users of the NXP forum:
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Fcommunity.nxp.com%2Fthread%2F389902&data=02%7C01%7Cfugang.du
>an%40nxp.com%7C7f9fee272fc44662c2a108d53be3d1ee%7C686ea1d3bc2b4c6
>fa92cd99c5c301635%7C0%7C0%7C636480772022331090&sdata=7RdUsoWVWu
>o1nM5zKwLt7%2F6U3dxgDJtBDGlQCUWC6IM%3D&reserved=0
>	https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F
>%2Fcommunity.nxp.com%2Fmessage%2F309354&data=02%7C01%7Cfugang.d
>uan%40nxp.com%7C7f9fee272fc44662c2a108d53be3d1ee%7C686ea1d3bc2b4
>c6fa92cd99c5c301635%7C0%7C0%7C636480772022331090&sdata=D56KilGWD3
>kLABxc0yOI%2B44Y%2FhLfrGtdAvupCEyvI%2BI%3D&reserved=0
>With this patch applied the issue didn't occur for at least a few hundret PORs
>of our board.
>
>Fixes: e8fcfcd5684a ("net: fec: optimize the clock management to save
>power")
>Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
>---
> drivers/net/ethernet/freescale/fec_main.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
>diff --git a/drivers/net/ethernet/freescale/fec_main.c
>b/drivers/net/ethernet/freescale/fec_main.c
>index 610573855213..8c3d0fb7db20 100644
>--- a/drivers/net/ethernet/freescale/fec_main.c
>+++ b/drivers/net/ethernet/freescale/fec_main.c
>@@ -1862,6 +1862,8 @@ static int fec_enet_clk_enable(struct net_device
>*ndev, bool enable)
> 		ret = clk_prepare_enable(fep->clk_ref);
> 		if (ret)
> 			goto failed_clk_ref;
>+
>+		phy_reset_after_clk_enable(ndev->phydev);
> 	} else {
> 		clk_disable_unprepare(fep->clk_ahb);
> 		clk_disable_unprepare(fep->clk_enet_out);
>@@ -2860,6 +2862,11 @@ fec_enet_open(struct net_device *ndev)
> 	if (ret)
> 		goto err_enet_mii_probe;
>
>+	/* reset phy if needed here, due to the fact this is the first time we
>+	 * have the net_device to phy_driver link
>+	 */
>+	phy_reset_after_clk_enable(ndev->phydev);
>+

The patch series look better.
But why does it need to reset phy here since phy already is hard reset after clock enable.


> 	if (fep->quirks & FEC_QUIRK_ERR006687)
> 		imx6q_cpuidle_fec_irqs_used();
>
>--
>2.11.0
Richard Leitner Dec. 6, 2017, 8:12 a.m. UTC | #2
Hi Andy,

On 12/06/2017 02:50 AM, Andy Duan wrote:
> From: Richard Leitner <dev@g0hl1n.net> Sent: Tuesday, December 05, 2017 9:26 PM
>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow turning
>> the refclk on and off again during operation (according to their datasheet).
>> Nonetheless exactly this behaviour was introduced for power saving reasons
>> by commit e8fcfcd5684a ("net: fec: optimize the clock management to save
>> power").
>> Therefore add support for the phy_reset_after_clk_enable function from
>> phylib to mitigate this issue.

...

>> diff --git a/drivers/net/ethernet/freescale/fec_main.c
>> b/drivers/net/ethernet/freescale/fec_main.c
>> index 610573855213..8c3d0fb7db20 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -1862,6 +1862,8 @@ static int fec_enet_clk_enable(struct net_device
>> *ndev, bool enable)
>> 		ret = clk_prepare_enable(fep->clk_ref);
>> 		if (ret)
>> 			goto failed_clk_ref;
>> +
>> +		phy_reset_after_clk_enable(ndev->phydev);
>> 	} else {
>> 		clk_disable_unprepare(fep->clk_ahb);
>> 		clk_disable_unprepare(fep->clk_enet_out);
>> @@ -2860,6 +2862,11 @@ fec_enet_open(struct net_device *ndev)
>> 	if (ret)
>> 		goto err_enet_mii_probe;
>>
>> +	/* reset phy if needed here, due to the fact this is the first time we
>> +	 * have the net_device to phy_driver link
>> +	 */
>> +	phy_reset_after_clk_enable(ndev->phydev);
>> +
> 
> The patch series look better.
> But why does it need to reset phy here since phy already is hard reset after clock enable.

The problem here is that in fec_enet_open() the fec_enet_clk_enable()
call is done before the phy is probed. Therefore (as mentioned in the
comment) there's no link from the net_device (ndev) to the phy_driver
(which holds the flags).

Any suggestions for a better solution are highly appreciated here! Thanks!

regards;Richard.L
Andy Duan Dec. 6, 2017, 8:41 a.m. UTC | #3
From: Richard Leitner <richard.leitner@skidata.com> Sent: Wednesday, December 06, 2017 4:12 PM

>To: Andy Duan <fugang.duan@nxp.com>; Richard Leitner <dev@g0hl1n.net>;

>robh+dt@kernel.org; mark.rutland@arm.com; andrew@lunn.ch;

>f.fainelli@gmail.com; frowand.list@gmail.com

>Cc: davem@davemloft.net; geert+renesas@glider.be;

>sergei.shtylyov@cogentembedded.com; baruch@tkos.co.il; david.wu@rock-

>chips.com; lukma@denx.de; netdev@vger.kernel.org;

>devicetree@vger.kernel.org; linux-kernel@vger.kernel.org

>Subject: Re: [PATCH net-next v3 4/4] net: fec: add

>phy_reset_after_clk_enable() support

>

>Hi Andy,

>

>On 12/06/2017 02:50 AM, Andy Duan wrote:

>> From: Richard Leitner <dev@g0hl1n.net> Sent: Tuesday, December 05,

>> 2017 9:26 PM

>>> Some PHYs (for example the SMSC LAN8710/LAN8720) doesn't allow

>>> turning the refclk on and off again during operation (according to their

>datasheet).

>>> Nonetheless exactly this behaviour was introduced for power saving

>>> reasons by commit e8fcfcd5684a ("net: fec: optimize the clock

>>> management to save power").

>>> Therefore add support for the phy_reset_after_clk_enable function

>>> from phylib to mitigate this issue.

>

>...

>

>>> diff --git a/drivers/net/ethernet/freescale/fec_main.c

>>> b/drivers/net/ethernet/freescale/fec_main.c

>>> index 610573855213..8c3d0fb7db20 100644

>>> --- a/drivers/net/ethernet/freescale/fec_main.c

>>> +++ b/drivers/net/ethernet/freescale/fec_main.c

>>> @@ -1862,6 +1862,8 @@ static int fec_enet_clk_enable(struct

>>> net_device *ndev, bool enable)

>>> 		ret = clk_prepare_enable(fep->clk_ref);

>>> 		if (ret)

>>> 			goto failed_clk_ref;

>>> +

>>> +		phy_reset_after_clk_enable(ndev->phydev);

>>> 	} else {

>>> 		clk_disable_unprepare(fep->clk_ahb);

>>> 		clk_disable_unprepare(fep->clk_enet_out);

>>> @@ -2860,6 +2862,11 @@ fec_enet_open(struct net_device *ndev)

>>> 	if (ret)

>>> 		goto err_enet_mii_probe;

>>>

>>> +	/* reset phy if needed here, due to the fact this is the first time we

>>> +	 * have the net_device to phy_driver link

>>> +	 */

>>> +	phy_reset_after_clk_enable(ndev->phydev);

>>> +

>>

>> The patch series look better.

>> But why does it need to reset phy here since phy already is hard reset after

>clock enable.

>

>The problem here is that in fec_enet_open() the fec_enet_clk_enable() call is

>done before the phy is probed. Therefore (as mentioned in the

>comment) there's no link from the net_device (ndev) to the phy_driver

>(which holds the flags).

>

>Any suggestions for a better solution are highly appreciated here! Thanks!

>

>regards;Richard.L


Okay, I see.

For the patch: Acked-by: Fugang Duan <fugang.duan@nxp.com>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 610573855213..8c3d0fb7db20 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1862,6 +1862,8 @@  static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
 		ret = clk_prepare_enable(fep->clk_ref);
 		if (ret)
 			goto failed_clk_ref;
+
+		phy_reset_after_clk_enable(ndev->phydev);
 	} else {
 		clk_disable_unprepare(fep->clk_ahb);
 		clk_disable_unprepare(fep->clk_enet_out);
@@ -2860,6 +2862,11 @@  fec_enet_open(struct net_device *ndev)
 	if (ret)
 		goto err_enet_mii_probe;
 
+	/* reset phy if needed here, due to the fact this is the first time we
+	 * have the net_device to phy_driver link
+	 */
+	phy_reset_after_clk_enable(ndev->phydev);
+
 	if (fep->quirks & FEC_QUIRK_ERR006687)
 		imx6q_cpuidle_fec_irqs_used();