diff mbox series

[RFC,net-next,14/19] net: mvpp2: add ethtool flow control configuration support

Message ID 1610292623-15564-15-git-send-email-stefanc@marvell.com (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series net: mvpp2: Add TX Flow Control support | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count fail Series longer than 15 patches
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 13 this patch: 13
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch warning WARNING: line length of 94 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns
netdev/build_allmodconfig_warn success Errors and warnings before: 13 this patch: 13
netdev/header_inline success Link
netdev/stable success Stable not CCed

Commit Message

Stefan Chulski Jan. 10, 2021, 3:30 p.m. UTC
From: Stefan Chulski <stefanc@marvell.com>

This patch add ethtool flow control configuration support.

Tx flow control retrieved correctly by ethtool get function.
FW per port ethtool configuration capability added.

Patch also takes care about mtu change procedure, if PPv2 switch
BM pools during mtu change.

Signed-off-by: Stefan Chulski <stefanc@marvell.com>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 53 ++++++++++++++++++++
 1 file changed, 53 insertions(+)

Comments

Andrew Lunn Jan. 10, 2021, 5:33 p.m. UTC | #1
> @@ -5373,6 +5402,30 @@ static int mvpp2_ethtool_set_pause_param(struct net_device *dev,
>  					 struct ethtool_pauseparam *pause)
>  {
>  	struct mvpp2_port *port = netdev_priv(dev);
> +	int i;
> +
> +	if (pause->tx_pause && port->priv->global_tx_fc) {
> +		port->tx_fc = true;
> +		mvpp2_rxq_enable_fc(port);
> +		if (port->priv->percpu_pools) {
> +			for (i = 0; i < port->nrxqs; i++)
> +				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], true);
> +		} else {
> +			mvpp2_bm_pool_update_fc(port, port->pool_long, true);
> +			mvpp2_bm_pool_update_fc(port, port->pool_short, true);
> +		}
> +
> +	} else if (port->priv->global_tx_fc) {
> +		port->tx_fc = false;
> +		mvpp2_rxq_disable_fc(port);
> +		if (port->priv->percpu_pools) {
> +			for (i = 0; i < port->nrxqs; i++)
> +				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], false);
> +		} else {
> +			mvpp2_bm_pool_update_fc(port, port->pool_long, false);
> +			mvpp2_bm_pool_update_fc(port, port->pool_short, false);
> +		}
> +	}


This looks wrong. Flow control is normally the result of auto
negotiation. Both ends need to agree to it. Which is why
mvpp2_ethtool_set_pause_param() passes the users request onto phylink.
phylink will handle the autoneg and then ask the MAC to setup flow
control depending on the result in mvpp2_mac_link_up().

	Andrew
Stefan Chulski Jan. 10, 2021, 5:53 p.m. UTC | #2
> > @@ -5373,6 +5402,30 @@ static int
> mvpp2_ethtool_set_pause_param(struct net_device *dev,
> >  					 struct ethtool_pauseparam *pause)  {
> >  	struct mvpp2_port *port = netdev_priv(dev);
> > +	int i;
> > +
> > +	if (pause->tx_pause && port->priv->global_tx_fc) {
> > +		port->tx_fc = true;
> > +		mvpp2_rxq_enable_fc(port);
> > +		if (port->priv->percpu_pools) {
> > +			for (i = 0; i < port->nrxqs; i++)
> > +				mvpp2_bm_pool_update_fc(port, &port-
> >priv->bm_pools[i], true);
> > +		} else {
> > +			mvpp2_bm_pool_update_fc(port, port->pool_long,
> true);
> > +			mvpp2_bm_pool_update_fc(port, port->pool_short,
> true);
> > +		}
> > +
> > +	} else if (port->priv->global_tx_fc) {
> > +		port->tx_fc = false;
> > +		mvpp2_rxq_disable_fc(port);
> > +		if (port->priv->percpu_pools) {
> > +			for (i = 0; i < port->nrxqs; i++)
> > +				mvpp2_bm_pool_update_fc(port, &port-
> >priv->bm_pools[i], false);
> > +		} else {
> > +			mvpp2_bm_pool_update_fc(port, port->pool_long,
> false);
> > +			mvpp2_bm_pool_update_fc(port, port->pool_short,
> false);
> > +		}
> > +	}
> 
> 
> This looks wrong. Flow control is normally the result of auto negotiation. Both
> ends need to agree to it. Which is why
> mvpp2_ethtool_set_pause_param() passes the users request onto phylink.
> phylink will handle the autoneg and then ask the MAC to setup flow control
> depending on the result in mvpp2_mac_link_up().
> 
> 	Andrew

Ok, I would move it to mvpp2_mac_link_up.

Stefan,
Thanks.
Russell King (Oracle) Jan. 10, 2021, 6:15 p.m. UTC | #3
On Sun, Jan 10, 2021 at 05:30:18PM +0200, stefanc@marvell.com wrote:
> @@ -5373,6 +5402,30 @@ static int mvpp2_ethtool_set_pause_param(struct net_device *dev,
>  					 struct ethtool_pauseparam *pause)
>  {
>  	struct mvpp2_port *port = netdev_priv(dev);
> +	int i;
> +
> +	if (pause->tx_pause && port->priv->global_tx_fc) {
> +		port->tx_fc = true;
> +		mvpp2_rxq_enable_fc(port);
> +		if (port->priv->percpu_pools) {
> +			for (i = 0; i < port->nrxqs; i++)
> +				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], true);
> +		} else {
> +			mvpp2_bm_pool_update_fc(port, port->pool_long, true);
> +			mvpp2_bm_pool_update_fc(port, port->pool_short, true);
> +		}
> +
> +	} else if (port->priv->global_tx_fc) {
> +		port->tx_fc = false;
> +		mvpp2_rxq_disable_fc(port);
> +		if (port->priv->percpu_pools) {
> +			for (i = 0; i < port->nrxqs; i++)
> +				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], false);
> +		} else {
> +			mvpp2_bm_pool_update_fc(port, port->pool_long, false);
> +			mvpp2_bm_pool_update_fc(port, port->pool_short, false);
> +		}
> +	}

This doesn't look correct to me. This function is only called when
ethtool -A is used to change the flow control settings. This is not
the place to be configuring flow control, as flow control is
negotiated with the link partner.

The final resolved flow control settings are available in
mvpp2_mac_link_up() via the tx_pause and rx_pause parameters.

What also concerns me is whether flow control is supported in the
existing driver at all, given this patch set. If it isn't supported
without the firmware's help, then we should _not_ be negotiating flow
control with the link partner unless we actually support it, so the
Pause and Asym_Pause bits in mvpp2_phylink_validate() should be
cleared.
Stefan Chulski Jan. 10, 2021, 6:27 p.m. UTC | #4
> > @@ -5373,6 +5402,30 @@ static int
> mvpp2_ethtool_set_pause_param(struct net_device *dev,
> >  					 struct ethtool_pauseparam *pause)  {
> >  	struct mvpp2_port *port = netdev_priv(dev);
> > +	int i;
> > +
> > +	if (pause->tx_pause && port->priv->global_tx_fc) {
> > +		port->tx_fc = true;
> > +		mvpp2_rxq_enable_fc(port);
> > +		if (port->priv->percpu_pools) {
> > +			for (i = 0; i < port->nrxqs; i++)
> > +				mvpp2_bm_pool_update_fc(port, &port-
> >priv->bm_pools[i], true);
> > +		} else {
> > +			mvpp2_bm_pool_update_fc(port, port->pool_long,
> true);
> > +			mvpp2_bm_pool_update_fc(port, port->pool_short,
> true);
> > +		}
> > +
> > +	} else if (port->priv->global_tx_fc) {
> > +		port->tx_fc = false;
> > +		mvpp2_rxq_disable_fc(port);
> > +		if (port->priv->percpu_pools) {
> > +			for (i = 0; i < port->nrxqs; i++)
> > +				mvpp2_bm_pool_update_fc(port, &port-
> >priv->bm_pools[i], false);
> > +		} else {
> > +			mvpp2_bm_pool_update_fc(port, port->pool_long,
> false);
> > +			mvpp2_bm_pool_update_fc(port, port->pool_short,
> false);
> > +		}
> > +	}
> 
> This doesn't look correct to me. This function is only called when ethtool -A is
> used to change the flow control settings. This is not the place to be
> configuring flow control, as flow control is negotiated with the link partner.
> 
> The final resolved flow control settings are available in
> mvpp2_mac_link_up() via the tx_pause and rx_pause parameters.

I would move this to mvpp2_mac_link_up.
Thanks.
 
> What also concerns me is whether flow control is supported in the existing
> driver at all, given this patch set. If it isn't supported without the firmware's
> help, then we should _not_ be negotiating flow control with the link partner
> unless we actually support it, so the Pause and Asym_Pause bits in
> mvpp2_phylink_validate() should be cleared.

RX FC supported, issue only with TX FC.

Stefan,
Regards.
Russell King (Oracle) Jan. 10, 2021, 6:33 p.m. UTC | #5
On Sun, Jan 10, 2021 at 06:27:57PM +0000, Stefan Chulski wrote:
> > What also concerns me is whether flow control is supported in the existing
> > driver at all, given this patch set. If it isn't supported without the firmware's
> > help, then we should _not_ be negotiating flow control with the link partner
> > unless we actually support it, so the Pause and Asym_Pause bits in
> > mvpp2_phylink_validate() should be cleared.
> 
> RX FC supported, issue only with TX FC.

That doesn't seem relevant given table 28B in IEEE 802.3. There is
no advertisement combination that allows one to advertise an ability
to receive FC frames but not transmit FC frames.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 3b85aec..4869b14 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1243,6 +1243,16 @@  static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 		new_long_pool = MVPP2_BM_LONG;
 
 	if (new_long_pool != port->pool_long->id) {
+		if (port->tx_fc) {
+			if (pkt_size > MVPP2_BM_LONG_PKT_SIZE)
+				mvpp2_bm_pool_update_fc(port,
+							port->pool_short,
+							false);
+			else
+				mvpp2_bm_pool_update_fc(port, port->pool_long,
+							false);
+		}
+
 		/* Remove port from old short & long pool */
 		port->pool_long = mvpp2_bm_pool_use(port, port->pool_long->id,
 						    port->pool_long->pkt_size);
@@ -1260,6 +1270,25 @@  static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 		mvpp2_swf_bm_pool_init(port);
 
 		mvpp2_set_hw_csum(port, new_long_pool);
+
+		if (port->tx_fc) {
+			if (pkt_size > MVPP2_BM_LONG_PKT_SIZE)
+				mvpp2_bm_pool_update_fc(port, port->pool_long,
+							true);
+			else
+				mvpp2_bm_pool_update_fc(port, port->pool_short,
+							true);
+		}
+
+		/* Update L4 checksum when jumbo enable/disable on port */
+		if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
+			dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+			dev->hw_features &= ~(NETIF_F_IP_CSUM |
+					      NETIF_F_IPV6_CSUM);
+		} else {
+			dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+			dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+		}
 	}
 
 out_set:
@@ -5373,6 +5402,30 @@  static int mvpp2_ethtool_set_pause_param(struct net_device *dev,
 					 struct ethtool_pauseparam *pause)
 {
 	struct mvpp2_port *port = netdev_priv(dev);
+	int i;
+
+	if (pause->tx_pause && port->priv->global_tx_fc) {
+		port->tx_fc = true;
+		mvpp2_rxq_enable_fc(port);
+		if (port->priv->percpu_pools) {
+			for (i = 0; i < port->nrxqs; i++)
+				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], true);
+		} else {
+			mvpp2_bm_pool_update_fc(port, port->pool_long, true);
+			mvpp2_bm_pool_update_fc(port, port->pool_short, true);
+		}
+
+	} else if (port->priv->global_tx_fc) {
+		port->tx_fc = false;
+		mvpp2_rxq_disable_fc(port);
+		if (port->priv->percpu_pools) {
+			for (i = 0; i < port->nrxqs; i++)
+				mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], false);
+		} else {
+			mvpp2_bm_pool_update_fc(port, port->pool_long, false);
+			mvpp2_bm_pool_update_fc(port, port->pool_short, false);
+		}
+	}
 
 	if (!port->phylink)
 		return -ENOTSUPP;