diff mbox series

[stable,4.9,v2] net: dsa: bcm_sf2: force pause link settings

Message ID 20220706192455.56001-1-f.fainelli@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [stable,4.9,v2] net: dsa: bcm_sf2: force pause link settings | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Florian Fainelli July 6, 2022, 7:24 p.m. UTC
From: Doug Berger <opendmb@gmail.com>

commit 7c97bc0128b2eecc703106112679a69d446d1a12 upstream

The pause settings reported by the PHY should also be applied to the
GMII port status override otherwise the switch will not generate pause
frames towards the link partner despite the advertisement saying
otherwise.

Fixes: 246d7f773c13 ("net: dsa: add Broadcom SF2 switch driver")
Signed-off-by: Doug Berger <opendmb@gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20220623030204.1966851-1-f.fainelli@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
Changes in v2:

- use both local and remote advertisement to determine when to apply
  flow control settings

 drivers/net/dsa/bcm_sf2.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

Vladimir Oltean July 6, 2022, 8:31 p.m. UTC | #1
Hi Florian,

On Wed, Jul 06, 2022 at 12:24:54PM -0700, Florian Fainelli wrote:
> From: Doug Berger <opendmb@gmail.com>
> 
> commit 7c97bc0128b2eecc703106112679a69d446d1a12 upstream
> 
> The pause settings reported by the PHY should also be applied to the
> GMII port status override otherwise the switch will not generate pause
> frames towards the link partner despite the advertisement saying
> otherwise.
> 
> Fixes: 246d7f773c13 ("net: dsa: add Broadcom SF2 switch driver")
> Signed-off-by: Doug Berger <opendmb@gmail.com>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> Link: https://lore.kernel.org/r/20220623030204.1966851-1-f.fainelli@gmail.com
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> Changes in v2:
> 
> - use both local and remote advertisement to determine when to apply
>   flow control settings
> 
>  drivers/net/dsa/bcm_sf2.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
> index 40b3adf7ad99..562b5eb23d90 100644
> --- a/drivers/net/dsa/bcm_sf2.c
> +++ b/drivers/net/dsa/bcm_sf2.c
> @@ -600,7 +600,9 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
>  	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
>  	struct ethtool_eee *p = &priv->port_sts[port].eee;
>  	u32 id_mode_dis = 0, port_mode;
> +	u16 lcl_adv = 0, rmt_adv = 0;
>  	const char *str = NULL;
> +	u8 flowctrl = 0;
>  	u32 reg;
>  
>  	switch (phydev->interface) {
> @@ -667,10 +669,24 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
>  		break;
>  	}
>  
> +	if (phydev->pause)
> +		rmt_adv = LPA_PAUSE_CAP;
> +	if (phydev->asym_pause)
> +		rmt_adv |= LPA_PAUSE_ASYM;
> +	if (phydev->advertising & ADVERTISED_Pause)
> +		lcl_adv = ADVERTISE_PAUSE_CAP;
> +	if (phydev->advertising & ADVERTISED_Asym_Pause)
> +		lcl_adv |= ADVERTISE_PAUSE_ASYM;
> +	flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);

IEEE 802.3 says "The PAUSE function shall be enabled according to Table
28B–3 only if the highest common denominator is a full duplex technology."

> +
>  	if (phydev->link)
>  		reg |= LINK_STS;
>  	if (phydev->duplex == DUPLEX_FULL)
>  		reg |= DUPLX_MODE;
> +	if (flowctrl & FLOW_CTRL_TX)
> +		reg |= TXFLOW_CNTL;
> +	if (flowctrl & FLOW_CTRL_RX)
> +		reg |= RXFLOW_CNTL;
>  
>  	core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
>  
> -- 
> 2.25.1
>
Florian Fainelli July 7, 2022, 4:53 p.m. UTC | #2
On 7/6/22 13:31, Vladimir Oltean wrote:
> Hi Florian,
> 
> On Wed, Jul 06, 2022 at 12:24:54PM -0700, Florian Fainelli wrote:
>> From: Doug Berger <opendmb@gmail.com>
>>
>> commit 7c97bc0128b2eecc703106112679a69d446d1a12 upstream
>>
>> The pause settings reported by the PHY should also be applied to the
>> GMII port status override otherwise the switch will not generate pause
>> frames towards the link partner despite the advertisement saying
>> otherwise.
>>
>> Fixes: 246d7f773c13 ("net: dsa: add Broadcom SF2 switch driver")
>> Signed-off-by: Doug Berger <opendmb@gmail.com>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> Link: https://lore.kernel.org/r/20220623030204.1966851-1-f.fainelli@gmail.com
>> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
>> ---
>> Changes in v2:
>>
>> - use both local and remote advertisement to determine when to apply
>>    flow control settings
>>
>>   drivers/net/dsa/bcm_sf2.c | 16 ++++++++++++++++
>>   1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
>> index 40b3adf7ad99..562b5eb23d90 100644
>> --- a/drivers/net/dsa/bcm_sf2.c
>> +++ b/drivers/net/dsa/bcm_sf2.c
>> @@ -600,7 +600,9 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
>>   	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
>>   	struct ethtool_eee *p = &priv->port_sts[port].eee;
>>   	u32 id_mode_dis = 0, port_mode;
>> +	u16 lcl_adv = 0, rmt_adv = 0;
>>   	const char *str = NULL;
>> +	u8 flowctrl = 0;
>>   	u32 reg;
>>   
>>   	switch (phydev->interface) {
>> @@ -667,10 +669,24 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
>>   		break;
>>   	}
>>   
>> +	if (phydev->pause)
>> +		rmt_adv = LPA_PAUSE_CAP;
>> +	if (phydev->asym_pause)
>> +		rmt_adv |= LPA_PAUSE_ASYM;
>> +	if (phydev->advertising & ADVERTISED_Pause)
>> +		lcl_adv = ADVERTISE_PAUSE_CAP;
>> +	if (phydev->advertising & ADVERTISED_Asym_Pause)
>> +		lcl_adv |= ADVERTISE_PAUSE_ASYM;
>> +	flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
> 
> IEEE 802.3 says "The PAUSE function shall be enabled according to Table
> 28B–3 only if the highest common denominator is a full duplex technology."

Indeed, sorry about that, so I suppose the incremental patch would do, 
since we do not support changing pause frame auto-negotiation settings 
in 4.9:

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 562b5eb23d90..f3d61f2bb0f7 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -669,15 +669,18 @@ static void bcm_sf2_sw_adjust_link(struct 
dsa_switch *ds, int port,
                 break;
         }

-       if (phydev->pause)
-               rmt_adv = LPA_PAUSE_CAP;
-       if (phydev->asym_pause)
-               rmt_adv |= LPA_PAUSE_ASYM;
-       if (phydev->advertising & ADVERTISED_Pause)
-               lcl_adv = ADVERTISE_PAUSE_CAP;
-       if (phydev->advertising & ADVERTISED_Asym_Pause)
-               lcl_adv |= ADVERTISE_PAUSE_ASYM;
-       flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+       if (phydev->duplex == DUPLEX_FULL &&
+           phydev->autoneg == AUTONEG_ENABLE) {
+               if (phydev->pause)
+                       rmt_adv = LPA_PAUSE_CAP;
+               if (phydev->asym_pause)
+                       rmt_adv |= LPA_PAUSE_ASYM;
+               if (phydev->advertising & ADVERTISED_Pause)
+                       lcl_adv = ADVERTISE_PAUSE_CAP;
+               if (phydev->advertising & ADVERTISED_Asym_Pause)
+                       lcl_adv |= ADVERTISE_PAUSE_ASYM;
+               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+       }

         if (phydev->link)
                 reg |= LINK_STS;
Vladimir Oltean July 7, 2022, 10:15 p.m. UTC | #3
On Thu, Jul 07, 2022 at 09:53:04AM -0700, Florian Fainelli wrote:
> > IEEE 802.3 says "The PAUSE function shall be enabled according to Table
> > 28B–3 only if the highest common denominator is a full duplex technology."
> 
> Indeed, sorry about that, so I suppose the incremental patch would do, since
> we do not support changing pause frame auto-negotiation settings in 4.9:
> 
> diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
> index 562b5eb23d90..f3d61f2bb0f7 100644
> --- a/drivers/net/dsa/bcm_sf2.c
> +++ b/drivers/net/dsa/bcm_sf2.c
> @@ -669,15 +669,18 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch
> *ds, int port,
>                 break;
>         }
> 
> -       if (phydev->pause)
> -               rmt_adv = LPA_PAUSE_CAP;
> -       if (phydev->asym_pause)
> -               rmt_adv |= LPA_PAUSE_ASYM;
> -       if (phydev->advertising & ADVERTISED_Pause)
> -               lcl_adv = ADVERTISE_PAUSE_CAP;
> -       if (phydev->advertising & ADVERTISED_Asym_Pause)
> -               lcl_adv |= ADVERTISE_PAUSE_ASYM;
> -       flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
> +       if (phydev->duplex == DUPLEX_FULL &&
> +           phydev->autoneg == AUTONEG_ENABLE) {
> +               if (phydev->pause)
> +                       rmt_adv = LPA_PAUSE_CAP;
> +               if (phydev->asym_pause)
> +                       rmt_adv |= LPA_PAUSE_ASYM;
> +               if (phydev->advertising & ADVERTISED_Pause)
> +                       lcl_adv = ADVERTISE_PAUSE_CAP;
> +               if (phydev->advertising & ADVERTISED_Asym_Pause)
> +                       lcl_adv |= ADVERTISE_PAUSE_ASYM;
> +               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
> +       }
> 
>         if (phydev->link)
>                 reg |= LINK_STS;

Yes, this looks OK, thank you.
diff mbox series

Patch

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 40b3adf7ad99..562b5eb23d90 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -600,7 +600,9 @@  static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 	struct ethtool_eee *p = &priv->port_sts[port].eee;
 	u32 id_mode_dis = 0, port_mode;
+	u16 lcl_adv = 0, rmt_adv = 0;
 	const char *str = NULL;
+	u8 flowctrl = 0;
 	u32 reg;
 
 	switch (phydev->interface) {
@@ -667,10 +669,24 @@  static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
 		break;
 	}
 
+	if (phydev->pause)
+		rmt_adv = LPA_PAUSE_CAP;
+	if (phydev->asym_pause)
+		rmt_adv |= LPA_PAUSE_ASYM;
+	if (phydev->advertising & ADVERTISED_Pause)
+		lcl_adv = ADVERTISE_PAUSE_CAP;
+	if (phydev->advertising & ADVERTISED_Asym_Pause)
+		lcl_adv |= ADVERTISE_PAUSE_ASYM;
+	flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
 	if (phydev->link)
 		reg |= LINK_STS;
 	if (phydev->duplex == DUPLEX_FULL)
 		reg |= DUPLX_MODE;
+	if (flowctrl & FLOW_CTRL_TX)
+		reg |= TXFLOW_CNTL;
+	if (flowctrl & FLOW_CTRL_RX)
+		reg |= RXFLOW_CNTL;
 
 	core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));