diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hibmcge')
7 files changed, 108 insertions, 0 deletions
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h index 7725cb0c5c8a..ea09a09c451b 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h @@ -258,6 +258,7 @@ struct hbg_stats { u64 tx_dma_err_cnt; u64 np_link_fail_cnt; + u64 reset_fail_cnt; }; struct hbg_priv { diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c index f23fb5920c3c..c0ce74cf7382 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c @@ -156,6 +156,7 @@ static const struct hbg_push_stats_info hbg_push_stats_list[] = { HBG_PUSH_STATS_I(tx_drop_cnt, 84), HBG_PUSH_STATS_I(tx_excessive_length_drop_cnt, 85), HBG_PUSH_STATS_I(tx_dma_err_cnt, 86), + HBG_PUSH_STATS_I(reset_fail_cnt, 87), }; static int hbg_push_msg_send(struct hbg_priv *priv, diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c index ff3295b60a69..503cfbfb4a8a 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c @@ -68,6 +68,7 @@ static int hbg_reset_prepare(struct hbg_priv *priv, enum hbg_reset_type type) clear_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET); if (ret) { + priv->stats.reset_fail_cnt++; set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); } @@ -88,6 +89,7 @@ static int hbg_reset_done(struct hbg_priv *priv, enum hbg_reset_type type) clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); ret = hbg_rebuild(priv); if (ret) { + priv->stats.reset_fail_cnt++; set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); dev_err(&priv->pdev->dev, "failed to rebuild after reset\n"); return ret; diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c index 55520053270a..1d62ff913737 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c @@ -84,6 +84,7 @@ static const struct hbg_ethtool_stats hbg_ethtool_stats_info[] = { HBG_REG_TX_EXCESSIVE_LENGTH_DROP_ADDR), HBG_STATS_I(tx_dma_err_cnt), HBG_STATS_I(tx_timeout_cnt), + HBG_STATS_I(reset_fail_cnt), }; static const struct hbg_ethtool_stats hbg_ethtool_rmon_stats_info[] = { diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c index 9b65eef62b3f..8cca8316ba40 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c @@ -18,6 +18,13 @@ #define HBG_ENDIAN_CTRL_LE_DATA_BE 0x0 #define HBG_PCU_FRAME_LEN_PLUS 4 +#define HBG_FIFO_TX_FULL_THRSLD 0x3F0 +#define HBG_FIFO_TX_EMPTY_THRSLD 0x1F0 +#define HBG_FIFO_RX_FULL_THRSLD 0x240 +#define HBG_FIFO_RX_EMPTY_THRSLD 0x190 +#define HBG_CFG_FIFO_FULL_THRSLD 0x10 +#define HBG_CFG_FIFO_EMPTY_THRSLD 0x01 + static bool hbg_hw_spec_is_valid(struct hbg_priv *priv) { return hbg_reg_read(priv, HBG_REG_SPEC_VALID_ADDR) && @@ -168,6 +175,11 @@ static void hbg_hw_set_mac_max_frame_len(struct hbg_priv *priv, void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu) { + /* burst_len BIT(29) set to 1 can improve the TX performance. + * But packet drop occurs when mtu > 2000. + * So, BIT(29) reset to 0 when mtu > 2000. + */ + u32 burst_len_bit = (mtu > 2000) ? 0 : 1; u32 frame_len; frame_len = mtu + VLAN_HLEN * priv->dev_specs.vlan_layers + @@ -175,6 +187,9 @@ void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu) hbg_hw_set_pcu_max_frame_len(priv, frame_len); hbg_hw_set_mac_max_frame_len(priv, frame_len); + + hbg_reg_write_field(priv, HBG_REG_BRUST_LENGTH_ADDR, + HBG_REG_BRUST_LENGTH_B, burst_len_bit); } void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable) @@ -264,6 +279,41 @@ 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_set_fifo_thrsld(struct hbg_priv *priv, + u32 full, u32 empty, enum hbg_dir dir) +{ + u32 value = 0; + + value |= FIELD_PREP(HBG_REG_FIFO_THRSLD_FULL_M, full); + value |= FIELD_PREP(HBG_REG_FIFO_THRSLD_EMPTY_M, empty); + + if (dir & HBG_DIR_TX) + hbg_reg_write(priv, HBG_REG_TX_FIFO_THRSLD_ADDR, value); + + if (dir & HBG_DIR_RX) + hbg_reg_write(priv, HBG_REG_RX_FIFO_THRSLD_ADDR, value); +} + +static void hbg_hw_set_cfg_fifo_thrsld(struct hbg_priv *priv, + u32 full, u32 empty, enum hbg_dir dir) +{ + u32 value; + + value = hbg_reg_read(priv, HBG_REG_CFG_FIFO_THRSLD_ADDR); + + if (dir & HBG_DIR_TX) { + value |= FIELD_PREP(HBG_REG_CFG_FIFO_THRSLD_TX_FULL_M, full); + value |= FIELD_PREP(HBG_REG_CFG_FIFO_THRSLD_TX_EMPTY_M, empty); + } + + if (dir & HBG_DIR_RX) { + value |= FIELD_PREP(HBG_REG_CFG_FIFO_THRSLD_RX_FULL_M, full); + value |= FIELD_PREP(HBG_REG_CFG_FIFO_THRSLD_RX_EMPTY_M, empty); + } + + hbg_reg_write(priv, HBG_REG_CFG_FIFO_THRSLD_ADDR, value); +} + static void hbg_hw_init_transmit_ctrl(struct hbg_priv *priv) { u32 ctrl = 0; @@ -324,5 +374,12 @@ int hbg_hw_init(struct hbg_priv *priv) hbg_hw_init_rx_control(priv); hbg_hw_init_transmit_ctrl(priv); + + hbg_hw_set_fifo_thrsld(priv, HBG_FIFO_TX_FULL_THRSLD, + HBG_FIFO_TX_EMPTY_THRSLD, HBG_DIR_TX); + hbg_hw_set_fifo_thrsld(priv, HBG_FIFO_RX_FULL_THRSLD, + HBG_FIFO_RX_EMPTY_THRSLD, HBG_DIR_RX); + hbg_hw_set_cfg_fifo_thrsld(priv, HBG_CFG_FIFO_FULL_THRSLD, + HBG_CFG_FIFO_EMPTY_THRSLD, HBG_DIR_TX_RX); return 0; } diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c index 42b0083c9193..8b7b476ed7fb 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c @@ -2,6 +2,7 @@ // Copyright (c) 2024 Hisilicon Limited. #include <linux/phy.h> +#include <linux/phy_fixed.h> #include <linux/rtnetlink.h> #include "hbg_common.h" #include "hbg_hw.h" @@ -19,6 +20,7 @@ #define HBG_MDIO_OP_INTERVAL_US (5 * 1000) #define HBG_NP_LINK_FAIL_RETRY_TIMES 5 +#define HBG_NO_PHY 0xFF static void hbg_mdio_set_command(struct hbg_mac *mac, u32 cmd) { @@ -229,6 +231,39 @@ void hbg_phy_stop(struct hbg_priv *priv) phy_stop(priv->mac.phydev); } +static void hbg_fixed_phy_uninit(void *data) +{ + fixed_phy_unregister((struct phy_device *)data); +} + +static int hbg_fixed_phy_init(struct hbg_priv *priv) +{ + struct fixed_phy_status hbg_fixed_phy_status = { + .link = 1, + .speed = SPEED_1000, + .duplex = DUPLEX_FULL, + .pause = 1, + .asym_pause = 1, + }; + struct device *dev = &priv->pdev->dev; + struct phy_device *phydev; + int ret; + + phydev = fixed_phy_register(&hbg_fixed_phy_status, NULL); + if (IS_ERR(phydev)) { + dev_err_probe(dev, PTR_ERR(phydev), + "failed to register fixed PHY device\n"); + return PTR_ERR(phydev); + } + + ret = devm_add_action_or_reset(dev, hbg_fixed_phy_uninit, phydev); + if (ret) + return ret; + + priv->mac.phydev = phydev; + return hbg_phy_connect(priv); +} + int hbg_mdio_init(struct hbg_priv *priv) { struct device *dev = &priv->pdev->dev; @@ -238,6 +273,9 @@ int hbg_mdio_init(struct hbg_priv *priv) int ret; mac->phy_addr = priv->dev_specs.phy_addr; + if (mac->phy_addr == HBG_NO_PHY) + return hbg_fixed_phy_init(priv); + mdio_bus = devm_mdiobus_alloc(dev); if (!mdio_bus) return dev_err_probe(dev, -ENOMEM, diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h index a6e7f5e62b48..a39d1e796e4a 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h @@ -141,7 +141,13 @@ /* PCU */ #define HBG_REG_TX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0420) #define HBG_REG_RX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0424) +#define HBG_REG_FIFO_THRSLD_FULL_M GENMASK(25, 16) +#define HBG_REG_FIFO_THRSLD_EMPTY_M GENMASK(9, 0) #define HBG_REG_CFG_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0428) +#define HBG_REG_CFG_FIFO_THRSLD_TX_FULL_M GENMASK(31, 24) +#define HBG_REG_CFG_FIFO_THRSLD_TX_EMPTY_M GENMASK(23, 16) +#define HBG_REG_CFG_FIFO_THRSLD_RX_FULL_M GENMASK(15, 8) +#define HBG_REG_CFG_FIFO_THRSLD_RX_EMPTY_M GENMASK(7, 0) #define HBG_REG_CF_INTRPT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x042C) #define HBG_INT_MSK_WE_ERR_B BIT(31) #define HBG_INT_MSK_RBREQ_ERR_B BIT(30) @@ -185,6 +191,8 @@ #define HBG_REG_TX_CFF_ADDR_2_ADDR (HBG_REG_SGMII_BASE + 0x0490) #define HBG_REG_TX_CFF_ADDR_3_ADDR (HBG_REG_SGMII_BASE + 0x0494) #define HBG_REG_RX_CFF_ADDR_ADDR (HBG_REG_SGMII_BASE + 0x04A0) +#define HBG_REG_BRUST_LENGTH_ADDR (HBG_REG_SGMII_BASE + 0x04C4) +#define HBG_REG_BRUST_LENGTH_B BIT(29) #define HBG_REG_RX_BUF_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x04E4) #define HBG_REG_RX_BUF_SIZE_M GENMASK(15, 0) #define HBG_REG_BUS_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x04E8) |