]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bng_en: implement ethtool pauseparam operations
authorBhargava Marreddy <bhargava.marreddy@broadcom.com>
Mon, 6 Apr 2026 18:04:14 +0000 (23:34 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 18:09:36 +0000 (11:09 -0700)
Implement .get_pauseparam and .set_pauseparam to support flow control
configuration. This allows reporting and setting of autoneg, RX pause,
and TX pause states.

Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
Reviewed-by: Vikas Gupta <vikas.gupta@broadcom.com>
Link: https://patch.msgid.link/20260406180420.279470-5-bhargava.marreddy@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c

index 6bb74a84ea03c676a450bf48f7fc1f7a361f2c52..424bf2d6721ce45e53226930c071bab6231f6908 100644 (file)
@@ -46,6 +46,67 @@ static void bnge_get_drvinfo(struct net_device *dev,
        strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info));
 }
 
+static void bnge_get_pauseparam(struct net_device *dev,
+                               struct ethtool_pauseparam *epause)
+{
+       struct bnge_net *bn = netdev_priv(dev);
+       struct bnge_dev *bd = bn->bd;
+
+       if (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE) {
+               epause->autoneg = 0;
+               epause->rx_pause = 0;
+               epause->tx_pause = 0;
+               return;
+       }
+
+       epause->autoneg = !!(bn->eth_link_info.autoneg &
+                            BNGE_AUTONEG_FLOW_CTRL);
+       epause->rx_pause = !!(bn->eth_link_info.req_flow_ctrl &
+                             BNGE_LINK_PAUSE_RX);
+       epause->tx_pause = !!(bn->eth_link_info.req_flow_ctrl &
+                             BNGE_LINK_PAUSE_TX);
+}
+
+static int bnge_set_pauseparam(struct net_device *dev,
+                              struct ethtool_pauseparam *epause)
+{
+       struct bnge_ethtool_link_info old_elink_info, *elink_info;
+       struct bnge_net *bn = netdev_priv(dev);
+       struct bnge_dev *bd = bn->bd;
+       int rc = 0;
+
+       if (!BNGE_PHY_CFG_ABLE(bd) || (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE))
+               return -EOPNOTSUPP;
+
+       elink_info = &bn->eth_link_info;
+       old_elink_info = *elink_info;
+
+       if (epause->autoneg) {
+               if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED))
+                       return -EINVAL;
+
+               elink_info->autoneg |= BNGE_AUTONEG_FLOW_CTRL;
+       } else {
+               if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL)
+                       elink_info->force_link_chng = true;
+               elink_info->autoneg &= ~BNGE_AUTONEG_FLOW_CTRL;
+       }
+
+       elink_info->req_flow_ctrl = 0;
+       if (epause->rx_pause)
+               elink_info->req_flow_ctrl |= BNGE_LINK_PAUSE_RX;
+       if (epause->tx_pause)
+               elink_info->req_flow_ctrl |= BNGE_LINK_PAUSE_TX;
+
+       if (netif_running(dev)) {
+               rc = bnge_hwrm_set_pause(bn);
+               if (rc)
+                       *elink_info = old_elink_info;
+       }
+
+       return rc;
+}
+
 static const struct ethtool_ops bnge_ethtool_ops = {
        .cap_link_lanes_supported       = 1,
        .get_link_ksettings     = bnge_get_link_ksettings,
@@ -53,6 +114,8 @@ static const struct ethtool_ops bnge_ethtool_ops = {
        .get_drvinfo            = bnge_get_drvinfo,
        .get_link               = bnge_get_link,
        .nway_reset             = bnge_nway_reset,
+       .get_pauseparam         = bnge_get_pauseparam,
+       .set_pauseparam         = bnge_set_pauseparam,
 };
 
 void bnge_set_ethtool_ops(struct net_device *dev)