[PATCH net-next v10 4/5] net: rnpgbe: Add receive mode support
From: Dong Yibo <dong100@mucse.com>
Date: 2026-08-31 07:37:35
Also in:
lkml
Subsystem:
mucse ethernet driver, networking drivers, the rest · Maintainers:
Yibo Dong, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add chip-level receive filtering and the ndo_set_rx_mode callback. Program the primary and additional unicast addresses into the available RAR entries, and use the 4096-bit multicast hash table for multicast addresses. Fall back to accepting all unicast addresses when the RAR table is exhausted, and handle IFF_PROMISC and IFF_ALLMULTI through the chip-level filter control register. Signed-off-by: Dong Yibo <dong100@mucse.com> --- drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h | 1 + .../net/ethernet/mucse/rnpgbe/rnpgbe_chip.c | 73 +++++++++++++++++++ drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h | 15 ++++ .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c | 14 +++- 4 files changed, 99 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
index 8c3d8bbfcc1a..8d7c6f8301cd 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h@@ -233,6 +233,7 @@ int rnpgbe_send_notify(struct mucse_hw *hw, bool enable, int mode); int rnpgbe_init_hw(struct mucse_hw *hw, int board_type); +void rnpgbe_set_rx_mode(struct net_device *netdev); /* Device IDs */ #define PCI_VENDOR_ID_MUCSE 0x8848
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
index 291e77d573fe..c7d5b53f6209 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_chip.c@@ -149,3 +149,76 @@ int rnpgbe_init_hw(struct mucse_hw *hw, int board_type) return 0; } + +static void rnpgbe_set_rar(struct mucse_hw *hw, u32 index, const u8 *addr) +{ + u32 rar_low, rar_high; + + /* The RAR stores the Ethernet address in reverse byte order. */ + 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) | + RNPGBE_RX_RAR_VALID; + mucse_hw_wr32(hw, RNPGBE_RX_RAR_LOW(index), rar_low); + mucse_hw_wr32(hw, RNPGBE_RX_RAR_HIGH(index), rar_high); +} + +static void rnpgbe_clear_rar(struct mucse_hw *hw, u32 index) +{ + mucse_hw_wr32(hw, RNPGBE_RX_RAR_LOW(index), 0); + mucse_hw_wr32(hw, RNPGBE_RX_RAR_HIGH(index), 0); +} + +void rnpgbe_set_rx_mode(struct net_device *netdev) +{ + u32 mcast_hash[RNPGBE_RX_MCAST_HASH_ENTRIES] = {}; + u32 mcast_ctrl = RNPGBE_RX_UCAST_TABLE_EN; + u32 filter_ctrl = RNPGBE_RX_FILTER_BCAST; + struct netdev_hw_addr *ha; + struct mucse_hw *hw; + struct mucse *mucse; + int rar = 1; + u16 hash; + int i; + + mucse = netdev_priv(netdev); + hw = &mucse->hw; + + /* RAR 0 always holds the interface's primary unicast address. */ + rnpgbe_set_rar(hw, 0, netdev->dev_addr); + + netdev_for_each_uc_addr(ha, netdev) { + if (rar == RNPGBE_RX_RAR_ENTRIES) { + filter_ctrl |= RNPGBE_RX_FILTER_UCAST_ALL; + break; + } + + rnpgbe_set_rar(hw, rar, ha->addr); + rar++; + } + + for (; rar < RNPGBE_RX_RAR_ENTRIES; rar++) + rnpgbe_clear_rar(hw, rar); + + if (netdev->flags & IFF_PROMISC) { + filter_ctrl |= RNPGBE_RX_FILTER_UCAST_ALL | + RNPGBE_RX_FILTER_MCAST_ALL; + } else if (netdev->flags & IFF_ALLMULTI) { + filter_ctrl |= RNPGBE_RX_FILTER_MCAST_ALL; + } else { + /* The MTA index is the 12 address bits from 36 through 47. */ + netdev_for_each_mc_addr(ha, netdev) { + hash = ((ha->addr[4] & 0xf) << 8) | ha->addr[5]; + mcast_hash[hash >> 5] |= BIT(hash & 0x1f); + } + + if (!netdev_mc_empty(netdev)) + mcast_ctrl |= RNPGBE_RX_MCAST_HASH_EN; + } + + for (i = 0; i < RNPGBE_RX_MCAST_HASH_ENTRIES; i++) + mucse_hw_wr32(hw, RNPGBE_RX_MCAST_HASH(i), mcast_hash[i]); + + mucse_hw_wr32(hw, RNPGBE_RX_MCAST_CTRL, mcast_ctrl); + mucse_hw_wr32(hw, RNPGBE_RX_FILTER_CTRL, filter_ctrl); +}
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
index 1d87edfba3d7..feb84704d602 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_hw.h@@ -24,5 +24,20 @@ #define RNPGBE_DMA_AXI_EN 0x0010 #define RNPGBE_TX_MIN_PKT_LEN 33 +#define MUCSE_ETH_OFF(_n) (0x10000 + (_n)) +#define RNPGBE_RX_RAR_LOW(_n) MUCSE_ETH_OFF(0xa000 + 4 * (_n)) +#define RNPGBE_RX_RAR_HIGH(_n) MUCSE_ETH_OFF(0xa400 + 4 * (_n)) +#define RNPGBE_RX_MCAST_HASH(_n) MUCSE_ETH_OFF(0xac00 + 4 * (_n)) +#define RNPGBE_RX_FILTER_CTRL MUCSE_ETH_OFF(0x9110) +#define RNPGBE_RX_MCAST_CTRL MUCSE_ETH_OFF(0x9114) +#define RNPGBE_RX_RAR_VALID BIT(31) +#define RNPGBE_RX_FILTER_BCAST BIT(10) +#define RNPGBE_RX_FILTER_UCAST_ALL BIT(9) +#define RNPGBE_RX_FILTER_MCAST_ALL BIT(8) +#define RNPGBE_RX_MCAST_HASH_EN BIT(4) +#define RNPGBE_RX_UCAST_TABLE_EN BIT(3) +/* The final two of the 32 hardware RAR entries are reserved for NCSI. */ +#define RNPGBE_RX_RAR_ENTRIES 30 +#define RNPGBE_RX_MCAST_HASH_ENTRIES 128 #define RNPGBE_MAX_QUEUES 8 #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 e62366291b2a..817081e24bb5 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c@@ -43,7 +43,12 @@ static int rnpgbe_configure(struct mucse *mucse) if (err) return err; - return rnpgbe_configure_rx(mucse); + err = rnpgbe_configure_rx(mucse); + if (err) + return err; + + rnpgbe_set_rx_mode(mucse->netdev); + return 0; } /**
@@ -142,9 +147,10 @@ static netdev_tx_t rnpgbe_xmit_frame(struct sk_buff *skb, } static const struct net_device_ops rnpgbe_netdev_ops = { - .ndo_open = rnpgbe_open, - .ndo_stop = rnpgbe_close, - .ndo_start_xmit = rnpgbe_xmit_frame, + .ndo_open = rnpgbe_open, + .ndo_stop = rnpgbe_close, + .ndo_start_xmit = rnpgbe_xmit_frame, + .ndo_set_rx_mode = rnpgbe_set_rx_mode, .ndo_get_stats64 = rnpgbe_get_stats64, };
--
2.50.1