[PATCH net-next v18 4/4] hinic3: Add ethtool pause param ops

From: Fan Gong

Date: Thu Oct 22 2026 - 08:27:39 EST


This commit adds port pause ops to the hinic3 driver. It implements
the .get_pauseparam and .set_pauseparam callbacks so these can be
read and write with ethtool -a/A.

Co-developed-by: Wu Di <wudi234@xxxxxxxxxx>
Signed-off-by: Wu Di <wudi234@xxxxxxxxxx>
Co-developed-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Teng Peisen <tengpeisen@xxxxxxxxxx>
Signed-off-by: Fan Gong <gongfan1@xxxxxxxxxx>
---
.../ethernet/huawei/hinic3/hinic3_ethtool.c | 41 +++++++++++++++++++
.../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 7 ++++
.../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 2 +
3 files changed, 50 insertions(+)

diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
index e1f23e2477fa..3005441056f9 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
@@ -869,6 +869,45 @@ static void hinic3_get_pause_stats(struct net_device *netdev,
kfree(ps);
}

+static void hinic3_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_nic_pause_config nic_pause = {};
+ int err;
+
+ err = hinic3_get_pause_info(nic_dev, &nic_pause);
+ if (err) {
+ netdev_err_once(netdev, "Failed to get pauseparam\n");
+ } else {
+ pause->autoneg = AUTONEG_DISABLE;
+ pause->rx_pause = nic_pause.rx_pause;
+ pause->tx_pause = nic_pause.tx_pause;
+ }
+}
+
+static int hinic3_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_nic_pause_config nic_pause = {};
+ int err;
+
+ if (HINIC3_IS_VF(nic_dev->hwdev))
+ return -EOPNOTSUPP;
+
+ if (pause->autoneg)
+ return -EOPNOTSUPP;
+
+ nic_pause.rx_pause = (u8)pause->rx_pause;
+ nic_pause.tx_pause = (u8)pause->tx_pause;
+
+ err = hinic3_set_pause_info(nic_dev, &nic_pause);
+ if (err)
+ netdev_err_once(netdev, "Failed to set pauseparam\n");
+ return err;
+}
+
static const struct ethtool_ops hinic3_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
@@ -885,6 +924,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
.get_eth_ctrl_stats = hinic3_get_eth_ctrl_stats,
.get_rmon_stats = hinic3_get_rmon_stats,
.get_pause_stats = hinic3_get_pause_stats,
+ .get_pauseparam = hinic3_get_pauseparam,
+ .set_pauseparam = hinic3_set_pauseparam,
};

void hinic3_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
index e4a3fa6fb8db..b5c696fe6cdf 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
@@ -739,6 +739,13 @@ int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,
nic_pause);
}

+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_nic_pause_config *nic_pause)
+{
+ return hinic3_cfg_hw_pause(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET,
+ nic_pause);
+}
+
int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,
struct l2nic_vport_stats *stats)
{
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
index 63382191446d..beb491d66738 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
@@ -318,6 +318,8 @@ int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id);

int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,
struct hinic3_nic_pause_config *nic_pause);
+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_nic_pause_config *nic_pause);

int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,
struct l2nic_vport_stats *stats);
--
2.43.0