[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250703014859.210110-8-dong100@mucse.com>
Date: Thu, 3 Jul 2025 09:48:51 +0800
From: Dong Yibo <dong100@...se.com>
To: davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com,
horms@...nel.org,
corbet@....net,
andrew+netdev@...n.ch,
gur.stavi@...wei.com,
maddy@...ux.ibm.com,
mpe@...erman.id.au,
danishanwar@...com,
lee@...ger.us,
gongfan1@...wei.com,
lorenzo@...nel.org,
geert+renesas@...der.be,
Parthiban.Veerasooran@...rochip.com,
lukas.bulwahn@...hat.com,
alexanderduyck@...com
Cc: netdev@...r.kernel.org,
linux-doc@...r.kernel.org,
linux-kernel@...r.kernel.org,
dong100@...se.com
Subject: [PATCH 07/15] net: rnpgbe: Add get mac from hw
Initialize gets mac function for driver use.
Signed-off-by: Dong Yibo <dong100@...se.com>
---
drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 65 ++++++++-
.../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 126 ++++++++++++++++++
drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 9 +-
.../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 30 +++++
.../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 63 +++++++++
.../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 17 +++
6 files changed, 306 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
index 17297f9ff9c1..93c3e8f50a80 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
@@ -33,8 +33,18 @@ struct mucse_dma_info {
u32 dma_version;
};
+struct mucse_eth_info;
+
+struct mucse_eth_operations {
+ s32 (*get_mac_addr)(struct mucse_eth_info *eth, u8 *addr);
+ s32 (*set_rar)(struct mucse_eth_info *eth, u32 index, u8 *addr);
+ s32 (*clear_rar)(struct mucse_eth_info *eth, u32 index);
+ void (*clr_mc_addr)(struct mucse_eth_info *eth);
+};
+
#define RNPGBE_MAX_MTA 128
struct mucse_eth_info {
+ struct mucse_eth_operations ops;
u8 __iomem *eth_base_addr;
void *back;
u32 mta_shadow[RNPGBE_MAX_MTA];
@@ -61,8 +71,13 @@ struct mucse_mac_info {
struct mii_regs mii;
int phy_addr;
int clk_csr;
- u8 addr[ETH_ALEN];
- u8 perm_addr[ETH_ALEN];
+};
+
+struct mucse_addr_filter_info {
+ u32 num_mc_addrs;
+ u32 rar_used_count;
+ u32 mta_in_use;
+ bool user_set_promisc;
};
struct mucse_hw;
@@ -154,6 +169,7 @@ struct mucse_hw_operations {
int (*init_hw)(struct mucse_hw *hw);
int (*reset_hw)(struct mucse_hw *hw);
void (*start_hw)(struct mucse_hw *hw);
+ void (*init_rx_addrs)(struct mucse_hw *hw);
/* ops to fw */
void (*driver_status)(struct mucse_hw *hw, bool enable, int mode);
};
@@ -177,6 +193,10 @@ struct mucse_hw {
u16 subsystem_vendor_id;
u32 wol;
u32 wol_en;
+ u16 min_len_cap;
+ u16 max_len_cap;
+ u16 min_len_cur;
+ u16 max_len_cur;
u32 fw_version;
u32 axi_mhz;
u32 bd_uid;
@@ -191,6 +211,7 @@ struct mucse_hw {
struct mucse_eth_info eth;
struct mucse_mac_info mac;
struct mucse_mbx_info mbx;
+ struct mucse_addr_filter_info addr_ctrl;
#define M_NET_FEATURE_SG ((u32)(1 << 0))
#define M_NET_FEATURE_TX_CHECKSUM ((u32)(1 << 1))
#define M_NET_FEATURE_RX_CHECKSUM ((u32)(1 << 2))
@@ -211,11 +232,27 @@ struct mucse_hw {
#define M_HW_FEATURE_EEE ((u32)(1 << 17))
#define M_HW_SOFT_MASK_OTHER_IRQ ((u32)(1 << 18))
u32 feature_flags;
+ u32 flags;
+#define M_FLAGS_INIT_MAC_ADDRESS ((u32)(1 << 27))
u32 driver_version;
u16 usecstocount;
+ u16 max_msix_vectors;
int nr_lane;
struct lldp_status lldp_status;
int link;
+ u8 addr[ETH_ALEN];
+ u8 perm_addr[ETH_ALEN];
+};
+
+enum mucse_state_t {
+ __MUCSE_DOWN,
+ __MUCSE_SERVICE_SCHED,
+ __MUCSE_PTP_TX_IN_PROGRESS,
+ __MUCSE_USE_VFINFI,
+ __MUCSE_IN_IRQ,
+ __MUCSE_REMOVE,
+ __MUCSE_SERVICE_CHECK,
+ __MUCSE_EEE_REMOVE,
};
struct mucse {
@@ -224,9 +261,20 @@ struct mucse {
struct mucse_hw hw;
/* board number */
u16 bd_number;
+ u16 tx_work_limit;
u32 flags2;
#define M_FLAG2_NO_NET_REG ((u32)(1 << 0))
-
+ u32 priv_flags;
+#define M_PRIV_FLAG_TX_COALESCE ((u32)(1 << 25))
+#define M_PRIV_FLAG_RX_COALESCE ((u32)(1 << 26))
+ int tx_ring_item_count;
+ int rx_ring_item_count;
+ int napi_budge;
+ u16 rx_usecs;
+ u16 rx_frames;
+ u16 tx_frames;
+ u16 tx_usecs;
+ unsigned long state;
char name[60];
};
@@ -247,6 +295,15 @@ struct rnpgbe_info {
#define PCI_DEVICE_ID_N210 0x8208
#define PCI_DEVICE_ID_N210L 0x820a
+#define M_DEFAULT_TXD (512)
+#define M_DEFAULT_TX_WORK (128)
+#define M_PKT_TIMEOUT_TX (200)
+#define M_TX_PKT_POLL_BUDGET (0x30)
+
+#define M_DEFAULT_RXD (512)
+#define M_PKT_TIMEOUT (30)
+#define M_RX_PKT_POLL_BUDGET (64)
+
#define m_rd_reg(reg) readl((void *)(reg))
#define m_wr_reg(reg, val) writel((val), (void *)(reg))
#define hw_wr32(hw, reg, val) m_wr_reg((hw)->hw_addr + (reg), (val))
@@ -261,4 +318,6 @@ struct rnpgbe_info {
#define mucse_dbg(mucse, fmt, arg...) \
dev_dbg(&(mucse)->pdev->dev, fmt, ##arg)
+/* error codes */
+#define MUCSE_ERR_INVALID_ARGUMENT (-1)
#endif /* _RNPGBE_H */
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
index c495a6f79fd0..5b01ecd641f2 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
@@ -3,12 +3,88 @@
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/etherdevice.h>
#include "rnpgbe.h"
#include "rnpgbe_hw.h"
#include "rnpgbe_mbx.h"
#include "rnpgbe_mbx_fw.h"
+/**
+ * rnpgbe_eth_set_rar_n500 - Set Rx address register
+ * @eth: pointer to eth structure
+ * @index: Receive address register to write
+ * @addr: Address to put into receive address register
+ *
+ * Puts an ethernet address into a receive address register.
+ **/
+static s32 rnpgbe_eth_set_rar_n500(struct mucse_eth_info *eth,
+ u32 index, u8 *addr)
+{
+ u32 mcstctrl;
+ u32 rar_low, rar_high = 0;
+ u32 rar_entries = eth->num_rar_entries;
+
+ /* Make sure we are using a valid rar index range */
+ if (index >= rar_entries)
+ return MUCSE_ERR_INVALID_ARGUMENT;
+
+ /*
+ * HW expects these in big endian so we reverse the byte
+ * order from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[5] | ((u32)addr[4] << 8) |
+ ((u32)addr[3] << 16) |
+ ((u32)addr[2] << 24));
+ rar_high |= ((u32)addr[1] | ((u32)addr[0] << 8));
+ rar_high |= RNPGBE_RAH_AV;
+
+ eth_wr32(eth, RNPGBE_ETH_RAR_RL(index), rar_low);
+ eth_wr32(eth, RNPGBE_ETH_RAR_RH(index), rar_high);
+ /* open unicast filter */
+ mcstctrl = eth_rd32(eth, RNPGBE_ETH_DMAC_MCSTCTRL);
+ mcstctrl |= RNPGBE_MCSTCTRL_UNICASE_TBL_EN;
+ eth_wr32(eth, RNPGBE_ETH_DMAC_MCSTCTRL, mcstctrl);
+
+ return 0;
+}
+
+/**
+ * rnpgbe_eth_clear_rar_n500 - Remove Rx address register
+ * @eth: pointer to eth structure
+ * @index: Receive address register to write
+ *
+ * Clears an ethernet address from a receive address register.
+ **/
+static s32 rnpgbe_eth_clear_rar_n500(struct mucse_eth_info *eth,
+ u32 index)
+{
+ u32 rar_entries = eth->num_rar_entries;
+
+ /* Make sure we are using a valid rar index range */
+ if (index >= rar_entries)
+ return MUCSE_ERR_INVALID_ARGUMENT;
+
+ eth_wr32(eth, RNPGBE_ETH_RAR_RL(index), 0);
+ eth_wr32(eth, RNPGBE_ETH_RAR_RH(index), 0);
+
+ return 0;
+}
+
+static void rnpgbe_eth_clr_mc_addr_n500(struct mucse_eth_info *eth)
+{
+ int i;
+
+ for (i = 0; i < eth->mcft_size; i++)
+ eth_wr32(eth, RNPGBE_ETH_MUTICAST_HASH_TABLE(i), 0);
+}
+
+static struct mucse_eth_operations eth_ops_n500 = {
+ .set_rar = &rnpgbe_eth_set_rar_n500,
+ .clear_rar = &rnpgbe_eth_clear_rar_n500,
+ .clr_mc_addr = &rnpgbe_eth_clr_mc_addr_n500
+};
+
static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw)
{
int status = 0;
@@ -20,6 +96,19 @@ static int rnpgbe_init_hw_ops_n500(struct mucse_hw *hw)
return status;
}
+static void rnpgbe_get_permtion_mac(struct mucse_hw *hw,
+ u8 *mac_addr)
+{
+ if (mucse_fw_get_macaddr(hw, hw->pfvfnum, mac_addr, hw->nr_lane)) {
+ eth_random_addr(mac_addr);
+ } else {
+ if (!is_valid_ether_addr(mac_addr))
+ eth_random_addr(mac_addr);
+ }
+
+ hw->flags |= M_FLAGS_INIT_MAC_ADDRESS;
+}
+
/**
* rnpgbe_reset_hw_ops_n500 - Do a hardware reset
* @hw: hw information structure
@@ -37,7 +126,13 @@ static int rnpgbe_reset_hw_ops_n500(struct mucse_hw *hw)
dma_wr32(dma, RNPGBE_DMA_AXI_EN, 0);
if (mucse_mbx_fw_reset_phy(hw))
return -EIO;
+ /* Store the permanent mac address */
+ if (!(hw->flags & M_FLAGS_INIT_MAC_ADDRESS)) {
+ rnpgbe_get_permtion_mac(hw, hw->perm_addr);
+ memcpy(hw->addr, hw->perm_addr, ETH_ALEN);
+ }
+ hw->ops.init_rx_addrs(hw);
eth_wr32(eth, RNPGBE_ETH_ERR_MASK_VECTOR,
RNPGBE_PKT_LEN_ERR | RNPGBE_HDR_LEN_ERR);
dma_wr32(dma, RNPGBE_DMA_RX_PROG_FULL_THRESH, 0xa);
@@ -89,10 +184,38 @@ static void rnpgbe_driver_status_hw_ops_n500(struct mucse_hw *hw,
}
}
+static void rnpgbe_init_rx_addrs_hw_ops_n500(struct mucse_hw *hw)
+{
+ struct mucse_eth_info *eth = &hw->eth;
+ u32 i;
+ u32 rar_entries = eth->num_rar_entries;
+ u32 v;
+
+ /* hw->addr maybe set by sw */
+ if (!is_valid_ether_addr(hw->addr))
+ memcpy(hw->addr, hw->perm_addr, ETH_ALEN);
+ else
+ eth->ops.set_rar(eth, 0, hw->addr);
+
+ hw->addr_ctrl.rar_used_count = 1;
+ /* Clear other rar addresses. */
+ for (i = 1; i < rar_entries; i++)
+ eth->ops.clear_rar(eth, i);
+
+ /* Clear the MTA */
+ hw->addr_ctrl.mta_in_use = 0;
+ v = eth_rd32(eth, RNPGBE_ETH_DMAC_MCSTCTRL);
+ v &= (~0x3);
+ v |= eth->mc_filter_type;
+ eth_wr32(eth, RNPGBE_ETH_DMAC_MCSTCTRL, v);
+ eth->ops.clr_mc_addr(eth);
+}
+
static struct mucse_hw_operations hw_ops_n500 = {
.init_hw = &rnpgbe_init_hw_ops_n500,
.reset_hw = &rnpgbe_reset_hw_ops_n500,
.start_hw = &rnpgbe_start_hw_ops_n500,
+ .init_rx_addrs = &rnpgbe_init_rx_addrs_hw_ops_n500,
.driver_status = &rnpgbe_driver_status_hw_ops_n500,
};
@@ -121,6 +244,7 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *hw)
dma->max_rx_queues = RNPGBE_MAX_QUEUES;
dma->back = hw;
/* setup eth info */
+ memcpy(&hw->eth.ops, ð_ops_n500, sizeof(hw->eth.ops));
eth->eth_base_addr = hw->hw_addr + RNPGBE_ETH_BASE;
eth->back = hw;
eth->mc_filter_type = 0;
@@ -170,6 +294,8 @@ static void rnpgbe_get_invariants_n500(struct mucse_hw *hw)
hw->usecstocount = 125;
hw->max_vfs_noari = 1;
hw->max_vfs = 7;
+ hw->min_len_cap = RNPGBE_MIN_LEN;
+ hw->max_len_cap = RNPGBE_MAX_LEN;
memcpy(&hw->ops, &hw_ops_n500, sizeof(hw->ops));
}
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
index 35e3cb77a38b..bcb4da45feac 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
@@ -29,6 +29,12 @@
#define RNPGBE_ETH_DEFAULT_RX_RING (0x806c)
#define RNPGBE_PKT_LEN_ERR (2)
#define RNPGBE_HDR_LEN_ERR (1)
+#define RNPGBE_MCSTCTRL_UNICASE_TBL_EN BIT(3)
+#define RNPGBE_ETH_DMAC_MCSTCTRL (0x9114)
+#define RNPGBE_RAH_AV (0x80000000)
+#define RNPGBE_ETH_RAR_RL(n) (0xa000 + 0x04 * (n))
+#define RNPGBE_ETH_RAR_RH(n) (0xa400 + 0x04 * (n))
+#define RNPGBE_ETH_MUTICAST_HASH_TABLE(n) (0xac00 + 0x04 * (n))
/* chip resourse */
#define RNPGBE_MAX_QUEUES (8)
/* multicast control table */
@@ -36,7 +42,8 @@
/* vlan filter table */
#define RNPGBE_VFT_TBL_SIZE (128)
#define RNPGBE_RAR_ENTRIES (32)
-
+#define RNPGBE_MIN_LEN (68)
+#define RNPGBE_MAX_LEN (9722)
#define RNPGBE_MII_ADDR 0x00000010 /* MII Address */
#define RNPGBE_MII_DATA 0x00000014 /* MII Data */
#endif /* _RNPGBE_HW_H */
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
index e811e9624ead..d99da9838e27 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
@@ -150,6 +150,27 @@ static int init_firmware_for_n210(struct mucse_hw *hw)
static int rnpgbe_sw_init(struct mucse *mucse)
{
+ struct mucse_hw *hw = &mucse->hw;
+ struct pci_dev *pdev = mucse->pdev;
+
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_device_id = pdev->subsystem_device;
+ mucse->napi_budge = 64;
+ /* set default work limits */
+ mucse->tx_work_limit = M_DEFAULT_TX_WORK;
+ mucse->tx_usecs = M_PKT_TIMEOUT_TX;
+ mucse->tx_frames = M_TX_PKT_POLL_BUDGET;
+ mucse->rx_usecs = M_PKT_TIMEOUT;
+ mucse->rx_frames = M_RX_PKT_POLL_BUDGET;
+ mucse->priv_flags &= ~M_PRIV_FLAG_RX_COALESCE;
+ mucse->priv_flags &= ~M_PRIV_FLAG_TX_COALESCE;
+ /* set default ring sizes */
+ mucse->tx_ring_item_count = M_DEFAULT_TXD;
+ mucse->rx_ring_item_count = M_DEFAULT_RXD;
+ set_bit(__MUCSE_DOWN, &mucse->state);
+
return 0;
}
@@ -257,6 +278,15 @@ static int rnpgbe_add_adpater(struct pci_dev *pdev,
goto err_free_net;
}
+ netdev->min_mtu = hw->min_len_cap;
+ netdev->max_mtu = hw->max_len_cap - (ETH_HLEN + 2 * ETH_FCS_LEN);
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+ netdev->priv_flags |= IFF_SUPP_NOFCS;
+ eth_hw_addr_set(netdev, hw->perm_addr);
+ strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
+ memcpy(netdev->perm_addr, hw->perm_addr, netdev->addr_len);
+
return 0;
err_free_net:
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
index 8e26ffcabfda..a9c5caa764a0 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
@@ -348,3 +348,66 @@ int mucse_mbx_fw_reset_phy(struct mucse_hw *hw)
return mucse_fw_send_cmd_wait(hw, &req, &reply);
}
}
+
+/**
+ * mucse_fw_get_macaddr - Posts a mbx req to request macaddr
+ * @hw: Pointer to the HW structure
+ * @pfvfnum: Index of pf/vf num
+ * @mac_addr: Pointer to store mac_addr
+ * @nr_lane: Lane index
+ *
+ * mucse_fw_get_macaddr posts a mbx req to firmware to get mac_addr.
+ * It uses mucse_fw_send_cmd_wait if no irq, and mucse_mbx_fw_post_req
+ * if other irq is registered.
+ *
+ * Returns 0 on success, negative on failure
+ **/
+int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum,
+ u8 *mac_addr,
+ int nr_lane)
+{
+ int err = 0;
+ struct mbx_fw_cmd_req req;
+ struct mbx_fw_cmd_reply reply;
+
+ memset(&req, 0, sizeof(req));
+ memset(&reply, 0, sizeof(reply));
+
+ if (!mac_addr)
+ return -EINVAL;
+
+ if (hw->mbx.other_irq_enabled) {
+ struct mbx_req_cookie *cookie =
+ mbx_cookie_zalloc(sizeof(reply.mac_addr));
+ struct mac_addr *mac = (struct mac_addr *)cookie->priv;
+
+ if (!cookie)
+ return -ENOMEM;
+
+ build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, cookie);
+ err = mucse_mbx_fw_post_req(hw, &req, cookie);
+ if (err) {
+ kfree(cookie);
+ goto out;
+ }
+
+ if ((1 << nr_lane) & mac->lanes)
+ memcpy(mac_addr, mac->addrs[nr_lane].mac, ETH_ALEN);
+ else
+ err = -ENODATA;
+
+ kfree(cookie);
+ } else {
+ build_get_macaddress_req(&req, 1 << nr_lane, pfvfnum, &req);
+ err = mucse_fw_send_cmd_wait(hw, &req, &reply);
+ if (err)
+ goto out;
+
+ if ((1 << nr_lane) & reply.mac_addr.lanes)
+ memcpy(mac_addr, reply.mac_addr.addrs[nr_lane].mac, 6);
+ else
+ err = -ENODATA;
+ }
+out:
+ return err;
+}
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
index 66d8cd02bc0e..babdfc1f56f1 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
@@ -594,11 +594,28 @@ static inline void build_reset_phy_req(struct mbx_fw_cmd_req *req,
req->cookie = cookie;
}
+static inline void build_get_macaddress_req(struct mbx_fw_cmd_req *req,
+ int lane_mask, int pfvfnum,
+ void *cookie)
+{
+ req->flags = 0;
+ req->opcode = GET_MAC_ADDRES;
+ req->datalen = sizeof(req->get_mac_addr);
+ req->cookie = cookie;
+ req->reply_lo = 0;
+ req->reply_hi = 0;
+
+ req->get_mac_addr.lane_mask = lane_mask;
+ req->get_mac_addr.pfvf_num = pfvfnum;
+}
+
int mucse_mbx_get_capability(struct mucse_hw *hw);
int rnpgbe_mbx_lldp_get(struct mucse_hw *hw);
int mucse_mbx_ifinsmod(struct mucse_hw *hw, int status);
int mucse_mbx_ifsuspuse(struct mucse_hw *hw, int status);
int mucse_mbx_ifforce_control_mac(struct mucse_hw *hw, int status);
int mucse_mbx_fw_reset_phy(struct mucse_hw *hw);
+int mucse_fw_get_macaddr(struct mucse_hw *hw, int pfvfnum,
+ u8 *mac_addr, int nr_lane);
#endif /* _RNPGBE_MBX_FW_H */
--
2.25.1
Powered by blists - more mailing lists