net: hibmcge: Add pauseparam supported in this module

The MAC can automatically send or respond to pause frames.
This patch supports the function of enabling pause frames
by using ethtool.

Signed-off-by: Jijie Shao <shaojijie@huawei.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20241216040532.1566229-6-shaojijie@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jijie Shao 2024-12-16 12:05:30 +08:00 committed by Jakub Kicinski
parent 51574da8dc
commit 3a03763f38
7 changed files with 68 additions and 0 deletions

View File

@ -115,6 +115,7 @@ struct hbg_mac {
u32 duplex;
u32 autoneg;
u32 link_status;
u32 pause_autoneg;
};
struct hbg_mac_table_entry {

View File

@ -143,12 +143,37 @@ 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);
param->autoneg = priv->mac.pause_autoneg;
hbg_hw_get_pause_enable(priv, &param->tx_pause, &param->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);
priv->mac.pause_autoneg = param->autoneg;
phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause);
if (!param->autoneg)
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,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
.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)

View File

@ -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;

View File

@ -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

View File

@ -191,6 +191,7 @@ static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
if (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;
}

View File

@ -114,6 +114,19 @@ static void hbg_mdio_init_hw(struct hbg_priv *priv)
hbg_mdio_set_command(mac, cmd);
}
static void hbg_flowctrl_cfg(struct hbg_priv *priv)
{
struct phy_device *phydev = priv->mac.phydev;
bool rx_pause;
bool tx_pause;
if (!priv->mac.pause_autoneg)
return;
phy_get_pause(phydev, &tx_pause, &rx_pause);
hbg_hw_set_pause_enable(priv, tx_pause, rx_pause);
}
static void hbg_phy_adjust_link(struct net_device *netdev)
{
struct hbg_priv *priv = netdev_priv(netdev);
@ -140,6 +153,7 @@ static void hbg_phy_adjust_link(struct net_device *netdev)
priv->mac.duplex = phydev->duplex;
priv->mac.autoneg = phydev->autoneg;
hbg_hw_adjust_link(priv, speed, phydev->duplex);
hbg_flowctrl_cfg(priv);
}
priv->mac.link_status = phydev->link;
@ -168,6 +182,7 @@ static int hbg_phy_connect(struct hbg_priv *priv)
return ret;
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
phy_support_asym_pause(phydev);
phy_attached_info(phydev);
return 0;

View File

@ -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)