The MAC can automatically send or respond to pause frames.
This patch supports the function of enabling pause frames
by using ethtool.
Not support pause auto-negotiation.
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
---
.../ethernet/hisilicon/hibmcge/hbg_ethtool.c | 24 +++++++++++++++++++
.../net/ethernet/hisilicon/hibmcge/hbg_hw.c | 21 ++++++++++++++++
.../net/ethernet/hisilicon/hibmcge/hbg_hw.h | 3 +++
.../net/ethernet/hisilicon/hibmcge/hbg_main.c | 1 +
.../net/ethernet/hisilicon/hibmcge/hbg_reg.h | 2 ++
5 files changed, 51 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
index a630c7d8ef5c..1e93d1dcf7a0 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
@@ -341,6 +341,28 @@ static void hbg_ethtool_get_regs(struct net_device *netdev,
}
}
+static void hbg_ethtool_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hbg_priv *priv = netdev_priv(net_dev);
+
+ hbg_hw_get_pause_enable(priv, ¶m->tx_pause, ¶m->rx_pause);
+}
+
+static int hbg_ethtool_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hbg_priv *priv = netdev_priv(net_dev);
+
+ if (param->autoneg) {
+ netdev_err(net_dev, "autoneg unsupported\n");
+ return -EOPNOTSUPP;
+ }
+
+ hbg_hw_set_pause_enable(priv, !!param->tx_pause, !!param->rx_pause);
+ return 0;
+}
+
static const struct ethtool_ops hbg_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
@@ -350,6 +372,8 @@ static const struct ethtool_ops hbg_ethtool_ops = {
.get_ethtool_stats = hbg_ethtool_get_stats,
.get_regs_len = hbg_ethtool_get_regs_len,
.get_regs = hbg_ethtool_get_regs,
+ .get_pauseparam = hbg_ethtool_get_pauseparam,
+ .set_pauseparam = hbg_ethtool_set_pauseparam,
};
void hbg_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
index 29d66a0ea0a6..0cbe9f7229b3 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
@@ -220,6 +220,27 @@ void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable)
HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B, enable);
}
+void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en)
+{
+ hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_TX_B, tx_en);
+ hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_RX_B, rx_en);
+}
+
+void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en)
+{
+ *tx_en = hbg_reg_read_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_TX_B);
+ *rx_en = hbg_reg_read_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_RX_B);
+}
+
+void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *priv, u64 mac_addr)
+{
+ hbg_reg_write64(priv, HBG_REG_FD_FC_ADDR_LOW_ADDR, mac_addr);
+}
+
static void hbg_hw_init_transmit_ctrl(struct hbg_priv *priv)
{
u32 ctrl = 0;
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
index 6eb4b7d2cba8..a4a049b5121d 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
@@ -56,5 +56,8 @@ u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir);
void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc);
void hbg_hw_fill_buffer(struct hbg_priv *priv, u32 buffer_dma_addr);
void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable);
+void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en);
+void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en);
+void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *priv, u64 mac_addr);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index 0b7cfbd166ec..6331cda91575 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -196,6 +196,7 @@ static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
if (is_exists)
hbg_set_mac_to_mac_table(priv, index, NULL);
+ hbg_hw_set_rx_pause_mac_addr(priv, ether_addr_to_u64(mac_addr));
dev_addr_set(netdev, mac_addr);
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
index bbfefe9c1e61..6088f1aef23e 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
@@ -51,6 +51,8 @@
#define HBG_REG_PORT_ENABLE_RX_B BIT(1)
#define HBG_REG_PORT_ENABLE_TX_B BIT(2)
#define HBG_REG_PAUSE_ENABLE_ADDR (HBG_REG_SGMII_BASE + 0x0048)
+#define HBG_REG_PAUSE_ENABLE_RX_B BIT(0)
+#define HBG_REG_PAUSE_ENABLE_TX_B BIT(1)
#define HBG_REG_AN_NEG_STATE_ADDR (HBG_REG_SGMII_BASE + 0x0058)
#define HBG_REG_TRANSMIT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0060)
#define HBG_REG_TRANSMIT_CTRL_PAD_EN_B BIT(7)
--
2.33.0
> +static int hbg_ethtool_set_pauseparam(struct net_device *net_dev, > + struct ethtool_pauseparam *param) > +{ > + struct hbg_priv *priv = netdev_priv(net_dev); > + > + if (param->autoneg) { > + netdev_err(net_dev, "autoneg unsupported\n"); > + return -EOPNOTSUPP; > + } Not being able to do it is not an error, so there is no need for the netdev_err(). Andrew --- pw-bot: cr
on 2024/10/23 22:15, Andrew Lunn wrote: >> +static int hbg_ethtool_set_pauseparam(struct net_device *net_dev, >> + struct ethtool_pauseparam *param) >> +{ >> + struct hbg_priv *priv = netdev_priv(net_dev); >> + >> + if (param->autoneg) { >> + netdev_err(net_dev, "autoneg unsupported\n"); >> + return -EOPNOTSUPP; >> + } > Not being able to do it is not an error, so there is no need for the > netdev_err(). Ok, Thanks! > > > Andrew > > --- > pw-bot: cr >
© 2016 - 2024 Red Hat, Inc.