Thread (22 messages) 22 messages, 5 authors, 2013-12-20

[net-next 05/15] i40e: add set settings and pauseparam

flat view
STALE4690d SUPERSEDED: 1 (0M)

From: Jeff Kirsher <hidden>
Date: 2013-12-19 06:34:57
Subsystem: intel ethernet drivers, networking drivers, the rest · Maintainers: Tony Nguyen, Przemek Kitszel, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Revision v1 of 6 in this series; 1 review trailer.

Revisions (6)
  1. v1
  2. v1
  3. v1 current
  4. v2 [diff vs current]
  5. v3 [diff vs current]
  6. v4 [diff vs current]
From: Shannon Nelson <redacted>

This implements the set_settings and set_pauseparam ethtool
functionality.

Change-Id: I4634ee2c8bce00204edac7df9f0af4fb7bf33b75
Signed-off-by: Shannon Nelson <redacted>
Signed-off-by: Jesse Brandeburg <redacted>
Tested-by: Kavindya Deegala <redacted>
Signed-off-by: Jeff Kirsher <redacted>
---
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 97 ++++++++++++++++++++++++++
 1 file changed, 97 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 255a138..a12dd01 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -261,6 +261,61 @@ static int i40e_get_settings(struct net_device *netdev,
 }
 
 /**
+ * i40e_set_settings - Set Speed and Duplex
+ * @netdev: network interface device structure
+ * @ecmd: ethtool command
+ *
+ * Set speed/duplex per media_types advertised/forced
+ **/
+static int i40e_set_settings(struct net_device *netdev,
+			     struct ethtool_cmd *ecmd)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_hw *hw = &pf->hw;
+	u32 old_link, advertised;
+	int err = 0;
+
+	if (vsi != pf->vsi[pf->lan_vsi])
+		return -EOPNOTSUPP;
+
+	while (test_and_set_bit(__I40E_CONFIG_BUSY, &vsi->state))
+		usleep_range(1000, 2000);
+
+	if ((hw->phy.media_type == I40E_MEDIA_TYPE_BASET) ||
+	    (hw->phy.media_type == I40E_MEDIA_TYPE_FIBER)) {
+		if (ecmd->autoneg == AUTONEG_DISABLE)
+			goto clear_reset;
+		if (ecmd->advertising & ~ecmd->supported)
+			goto clear_reset;
+		old_link = hw->phy.autoneg_advertised;
+		advertised = 0;
+
+		if (ecmd->advertising & (ADVERTISED_40000baseCR4_Full |
+					 ADVERTISED_40000baseKR4_Full |
+					 ADVERTISED_40000baseSR4_Full |
+					 ADVERTISED_40000baseLR4_Full))
+			advertised |= I40E_LINK_SPEED_40GB;
+		if (ecmd->advertising & (ADVERTISED_10000baseKX4_Full |
+					 ADVERTISED_10000baseKR_Full |
+					 ADVERTISED_10000baseT_Full))
+			advertised |= I40E_LINK_SPEED_10GB;
+		if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+			advertised |= I40E_LINK_SPEED_1GB;
+		if (old_link == advertised) {
+			err = 0;
+			goto clear_reset;
+		}
+		hw->phy.get_link_info = true;
+	}
+clear_reset:
+	clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+
+	return err;
+}
+
+/**
  * i40e_get_pauseparam -  Get Flow Control status
  * Return tx/rx-pause status
  **/
@@ -286,6 +341,46 @@ static void i40e_get_pauseparam(struct net_device *netdev,
 	}
 }
 
+/**
+ * i40e_set_pauseparam - Set Flow Control parameter
+ * @netdev: network interface device structure
+ * @pause: return tx/rx flow control status
+ **/
+static int i40e_set_pauseparam(struct net_device *netdev,
+			       struct ethtool_pauseparam *pause)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_pf *pf = np->vsi->back;
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_hw *hw = &pf->hw;
+	struct i40e_fc_info fc;
+
+	if (vsi != pf->vsi[pf->lan_vsi])
+		return -EOPNOTSUPP;
+
+	fc = hw->fc;
+	pf->fc_autoneg_status = pause->autoneg;
+
+	if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
+		fc.requested_mode = I40E_FC_FULL;
+	else if (pause->rx_pause && !pause->tx_pause)
+		fc.requested_mode = I40E_FC_RX_PAUSE;
+	else if (!pause->rx_pause && pause->tx_pause)
+		fc.requested_mode = I40E_FC_TX_PAUSE;
+	else if (!pause->rx_pause && !pause->tx_pause)
+		fc.requested_mode = I40E_FC_NONE;
+	else
+		 return -EINVAL;
+
+	fc.current_mode = fc.requested_mode;
+
+	/* if the status changed, then we will use updated autoneg*/
+	if (memcmp(&fc, &hw->fc, sizeof(struct i40e_fc_info)))
+		hw->fc = fc;
+
+	return 0;
+}
+
 static u32 i40e_get_msglevel(struct net_device *netdev)
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
@@ -1599,6 +1694,7 @@ static int i40e_set_channels(struct net_device *dev,
 
 static const struct ethtool_ops i40e_ethtool_ops = {
 	.get_settings		= i40e_get_settings,
+	.set_settings		= i40e_set_settings,
 	.get_drvinfo		= i40e_get_drvinfo,
 	.get_regs_len		= i40e_get_regs_len,
 	.get_regs		= i40e_get_regs,
@@ -1611,6 +1707,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
 	.get_ringparam		= i40e_get_ringparam,
 	.set_ringparam		= i40e_set_ringparam,
 	.get_pauseparam		= i40e_get_pauseparam,
+	.set_pauseparam		= i40e_set_pauseparam,
 	.get_msglevel		= i40e_get_msglevel,
 	.set_msglevel		= i40e_set_msglevel,
 	.get_rxnfc		= i40e_get_rxnfc,
-- 
1.8.3.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help