mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-31 22:23:05 +00:00
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:
parent
51574da8dc
commit
3a03763f38
@ -115,6 +115,7 @@ struct hbg_mac {
|
||||
u32 duplex;
|
||||
u32 autoneg;
|
||||
u32 link_status;
|
||||
u32 pause_autoneg;
|
||||
};
|
||||
|
||||
struct hbg_mac_table_entry {
|
||||
|
@ -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, ¶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);
|
||||
|
||||
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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user