* [PATCH net-next v3 0/2] Refactoring designware VLAN code. @ 2025-04-08 8:13 Boon Khai Ng 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng 2025-04-08 8:13 ` [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping Boon Khai Ng 0 siblings, 2 replies; 14+ messages in thread From: Boon Khai Ng @ 2025-04-08 8:13 UTC (permalink / raw) To: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan, Boon Khai Ng Refactoring designware VLAN code and introducing support for hardware-accelerated VLAN stripping for dwxgmac2 IP, the current patch set consists of two key changes: 1) Refactoring VLAN Functions: The first change involves moving common VLAN-related functions of the DesignWare Ethernet MAC into a dedicated file, stmmac_vlan.c. This refactoring aims to improve code organization and maintainability by centralizing VLAN handling logic. 2) Enabling VLAN for 10G Ethernet MAC IP: The second change enables VLAN support specifically for the 10G Ethernet MAC IP. This enhancement leverages the hardware capabilities of the to perform VLAN stripping, Changes from previous submmited patches. v2: The hardware VLAN enablement switch was detached from the device tree source (DTS). Instead, the hardware VLAN enablement is now dynamically determined in stmmac_main.c based on the currently running IP. Link: https://lore.kernel.org/lkml/BL3PR11MB5748AC693D9D61FB56DB7313C1F32 @BL3PR11MB5748.namprd11.prod.outlook.com/ v1: The initial submission introduced hardware VLAN support for the 10G Ethernet MAC IP. Link: https://lore.kernel.org/netdev/DM8PR11MB5751E5388AEFCFB80BCB483FC13FA @DM8PR11MB5751.namprd11.prod.outlook.com/ Boon Khai Ng (2): net: stmmac: Refactor VLAN implementation net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 40 --- .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 295 +----------------- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 25 +- .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 89 +----- .../ethernet/stmicro/stmmac/dwxgmac2_descs.c | 18 ++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 8 + drivers/net/ethernet/stmicro/stmmac/hwif.h | 61 ++-- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 294 +++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_vlan.h | 63 ++++ 12 files changed, 434 insertions(+), 464 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h -- 2.25.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-08 8:13 [PATCH net-next v3 0/2] Refactoring designware VLAN code Boon Khai Ng @ 2025-04-08 8:13 ` Boon Khai Ng 2025-04-10 6:38 ` Furong Xu ` (2 more replies) 2025-04-08 8:13 ` [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping Boon Khai Ng 1 sibling, 3 replies; 14+ messages in thread From: Boon Khai Ng @ 2025-04-08 8:13 UTC (permalink / raw) To: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan, Boon Khai Ng Refactor VLAN implementation by moving common code for DWMAC4 and DWXGMAC IPs into a separate VLAN module. VLAN implementation for DWMAC4 and DWXGMAC differs only for CSR base address, the descriptor for the VLAN ID and VLAN VALID bit field. Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 40 --- .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 295 +----------------- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 13 - .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 87 ------ drivers/net/ethernet/stmicro/stmmac/hwif.c | 8 + drivers/net/ethernet/stmicro/stmmac/hwif.h | 61 ++-- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 294 +++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_vlan.h | 63 ++++ 10 files changed, 401 insertions(+), 463 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 594883fb4164..433b65af0c9d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ - stmmac_xdp.o stmmac_est.o stmmac_fpe.o \ + stmmac_xdp.o stmmac_est.o stmmac_fpe.o stmmac_vlan.o\ $(stmmac-y) stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 412b07e77945..ea5da5793362 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -602,6 +602,7 @@ struct mac_device_info { const struct stmmac_tc_ops *tc; const struct stmmac_mmc_ops *mmc; const struct stmmac_est_ops *est; + const struct stmmac_vlan_ops *vlan; struct dw_xpcs *xpcs; struct phylink_pcs *phylink_pcs; struct mii_regs mii; /* MII register Addresses */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h index 42fe29a4e300..c8bca0571624 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -17,11 +17,7 @@ #define GMAC_EXT_CONFIG 0x00000004 #define GMAC_PACKET_FILTER 0x00000008 #define GMAC_HASH_TAB(x) (0x10 + (x) * 4) -#define GMAC_VLAN_TAG 0x00000050 -#define GMAC_VLAN_TAG_DATA 0x00000054 -#define GMAC_VLAN_HASH_TABLE 0x00000058 #define GMAC_RX_FLOW_CTRL 0x00000090 -#define GMAC_VLAN_INCL 0x00000060 #define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4) #define GMAC_TXQ_PRTY_MAP0 0x98 #define GMAC_TXQ_PRTY_MAP1 0x9C @@ -82,42 +78,6 @@ #define GMAC_MAX_PERFECT_ADDRESSES 128 -/* MAC VLAN */ -#define GMAC_VLAN_EDVLP BIT(26) -#define GMAC_VLAN_VTHM BIT(25) -#define GMAC_VLAN_DOVLTC BIT(20) -#define GMAC_VLAN_ESVL BIT(18) -#define GMAC_VLAN_ETV BIT(16) -#define GMAC_VLAN_VID GENMASK(15, 0) -#define GMAC_VLAN_VLTI BIT(20) -#define GMAC_VLAN_CSVL BIT(19) -#define GMAC_VLAN_VLC GENMASK(17, 16) -#define GMAC_VLAN_VLC_SHIFT 16 -#define GMAC_VLAN_VLHT GENMASK(15, 0) - -/* MAC VLAN Tag */ -#define GMAC_VLAN_TAG_VID GENMASK(15, 0) -#define GMAC_VLAN_TAG_ETV BIT(16) - -/* MAC VLAN Tag Control */ -#define GMAC_VLAN_TAG_CTRL_OB BIT(0) -#define GMAC_VLAN_TAG_CTRL_CT BIT(1) -#define GMAC_VLAN_TAG_CTRL_OFS_MASK GENMASK(6, 2) -#define GMAC_VLAN_TAG_CTRL_OFS_SHIFT 2 -#define GMAC_VLAN_TAG_CTRL_EVLS_MASK GENMASK(22, 21) -#define GMAC_VLAN_TAG_CTRL_EVLS_SHIFT 21 -#define GMAC_VLAN_TAG_CTRL_EVLRXS BIT(24) - -#define GMAC_VLAN_TAG_STRIP_NONE (0x0 << GMAC_VLAN_TAG_CTRL_EVLS_SHIFT) -#define GMAC_VLAN_TAG_STRIP_PASS (0x1 << GMAC_VLAN_TAG_CTRL_EVLS_SHIFT) -#define GMAC_VLAN_TAG_STRIP_FAIL (0x2 << GMAC_VLAN_TAG_CTRL_EVLS_SHIFT) -#define GMAC_VLAN_TAG_STRIP_ALL (0x3 << GMAC_VLAN_TAG_CTRL_EVLS_SHIFT) - -/* MAC VLAN Tag Data/Filter */ -#define GMAC_VLAN_TAG_DATA_VID GENMASK(15, 0) -#define GMAC_VLAN_TAG_DATA_VEN BIT(16) -#define GMAC_VLAN_TAG_DATA_ETV BIT(17) - /* MAC RX Queue Enable */ #define GMAC_RX_QUEUE_CLEAR(queue) ~(GENMASK(1, 0) << ((queue) * 2)) #define GMAC_RX_AV_QUEUE_ENABLE(queue) BIT((queue) * 2) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index cc4ddf608652..9c2549d4100f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -18,6 +18,7 @@ #include "stmmac.h" #include "stmmac_fpe.h" #include "stmmac_pcs.h" +#include "stmmac_vlan.h" #include "dwmac4.h" #include "dwmac5.h" @@ -448,165 +449,6 @@ static void dwmac4_set_eee_timer(struct mac_device_info *hw, int ls, int tw) writel(value, ioaddr + GMAC4_LPI_TIMER_CTRL); } -static void dwmac4_write_single_vlan(struct net_device *dev, u16 vid) -{ - void __iomem *ioaddr = (void __iomem *)dev->base_addr; - u32 val; - - val = readl(ioaddr + GMAC_VLAN_TAG); - val &= ~GMAC_VLAN_TAG_VID; - val |= GMAC_VLAN_TAG_ETV | vid; - - writel(val, ioaddr + GMAC_VLAN_TAG); -} - -static int dwmac4_write_vlan_filter(struct net_device *dev, - struct mac_device_info *hw, - u8 index, u32 data) -{ - void __iomem *ioaddr = (void __iomem *)dev->base_addr; - int ret; - u32 val; - - if (index >= hw->num_vlan) - return -EINVAL; - - writel(data, ioaddr + GMAC_VLAN_TAG_DATA); - - val = readl(ioaddr + GMAC_VLAN_TAG); - val &= ~(GMAC_VLAN_TAG_CTRL_OFS_MASK | - GMAC_VLAN_TAG_CTRL_CT | - GMAC_VLAN_TAG_CTRL_OB); - val |= (index << GMAC_VLAN_TAG_CTRL_OFS_SHIFT) | GMAC_VLAN_TAG_CTRL_OB; - - writel(val, ioaddr + GMAC_VLAN_TAG); - - ret = readl_poll_timeout(ioaddr + GMAC_VLAN_TAG, val, - !(val & GMAC_VLAN_TAG_CTRL_OB), - 1000, 500000); - if (ret) { - netdev_err(dev, "Timeout accessing MAC_VLAN_Tag_Filter\n"); - return -EBUSY; - } - - return 0; -} - -static int dwmac4_add_hw_vlan_rx_fltr(struct net_device *dev, - struct mac_device_info *hw, - __be16 proto, u16 vid) -{ - int index = -1; - u32 val = 0; - int i, ret; - - if (vid > 4095) - return -EINVAL; - - /* Single Rx VLAN Filter */ - if (hw->num_vlan == 1) { - /* For single VLAN filter, VID 0 means VLAN promiscuous */ - if (vid == 0) { - netdev_warn(dev, "Adding VLAN ID 0 is not supported\n"); - return -EPERM; - } - - if (hw->vlan_filter[0] & GMAC_VLAN_TAG_VID) { - netdev_err(dev, "Only single VLAN ID supported\n"); - return -EPERM; - } - - hw->vlan_filter[0] = vid; - dwmac4_write_single_vlan(dev, vid); - - return 0; - } - - /* Extended Rx VLAN Filter Enable */ - val |= GMAC_VLAN_TAG_DATA_ETV | GMAC_VLAN_TAG_DATA_VEN | vid; - - for (i = 0; i < hw->num_vlan; i++) { - if (hw->vlan_filter[i] == val) - return 0; - else if (!(hw->vlan_filter[i] & GMAC_VLAN_TAG_DATA_VEN)) - index = i; - } - - if (index == -1) { - netdev_err(dev, "MAC_VLAN_Tag_Filter full (size: %0u)\n", - hw->num_vlan); - return -EPERM; - } - - ret = dwmac4_write_vlan_filter(dev, hw, index, val); - - if (!ret) - hw->vlan_filter[index] = val; - - return ret; -} - -static int dwmac4_del_hw_vlan_rx_fltr(struct net_device *dev, - struct mac_device_info *hw, - __be16 proto, u16 vid) -{ - int i, ret = 0; - - /* Single Rx VLAN Filter */ - if (hw->num_vlan == 1) { - if ((hw->vlan_filter[0] & GMAC_VLAN_TAG_VID) == vid) { - hw->vlan_filter[0] = 0; - dwmac4_write_single_vlan(dev, 0); - } - return 0; - } - - /* Extended Rx VLAN Filter Enable */ - for (i = 0; i < hw->num_vlan; i++) { - if ((hw->vlan_filter[i] & GMAC_VLAN_TAG_DATA_VID) == vid) { - ret = dwmac4_write_vlan_filter(dev, hw, i, 0); - - if (!ret) - hw->vlan_filter[i] = 0; - else - return ret; - } - } - - return ret; -} - -static void dwmac4_restore_hw_vlan_rx_fltr(struct net_device *dev, - struct mac_device_info *hw) -{ - void __iomem *ioaddr = hw->pcsr; - u32 value; - u32 hash; - u32 val; - int i; - - /* Single Rx VLAN Filter */ - if (hw->num_vlan == 1) { - dwmac4_write_single_vlan(dev, hw->vlan_filter[0]); - return; - } - - /* Extended Rx VLAN Filter Enable */ - for (i = 0; i < hw->num_vlan; i++) { - if (hw->vlan_filter[i] & GMAC_VLAN_TAG_DATA_VEN) { - val = hw->vlan_filter[i]; - dwmac4_write_vlan_filter(dev, hw, i, val); - } - } - - hash = readl(ioaddr + GMAC_VLAN_HASH_TABLE); - if (hash & GMAC_VLAN_VLHT) { - value = readl(ioaddr + GMAC_VLAN_TAG); - value |= GMAC_VLAN_VTHM; - writel(value, ioaddr + GMAC_VLAN_TAG); - } -} - static void dwmac4_set_filter(struct mac_device_info *hw, struct net_device *dev) { @@ -965,45 +807,6 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable) writel(value, ioaddr + GMAC_CONFIG); } -static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash, - u16 perfect_match, bool is_double) -{ - void __iomem *ioaddr = hw->pcsr; - u32 value; - - writel(hash, ioaddr + GMAC_VLAN_HASH_TABLE); - - value = readl(ioaddr + GMAC_VLAN_TAG); - - if (hash) { - value |= GMAC_VLAN_VTHM | GMAC_VLAN_ETV; - if (is_double) { - value |= GMAC_VLAN_EDVLP; - value |= GMAC_VLAN_ESVL; - value |= GMAC_VLAN_DOVLTC; - } - - writel(value, ioaddr + GMAC_VLAN_TAG); - } else if (perfect_match) { - u32 value = GMAC_VLAN_ETV; - - if (is_double) { - value |= GMAC_VLAN_EDVLP; - value |= GMAC_VLAN_ESVL; - value |= GMAC_VLAN_DOVLTC; - } - - writel(value | perfect_match, ioaddr + GMAC_VLAN_TAG); - } else { - value &= ~(GMAC_VLAN_VTHM | GMAC_VLAN_ETV); - value &= ~(GMAC_VLAN_EDVLP | GMAC_VLAN_ESVL); - value &= ~GMAC_VLAN_DOVLTC; - value &= ~GMAC_VLAN_VID; - - writel(value, ioaddr + GMAC_VLAN_TAG); - } -} - static void dwmac4_sarc_configure(void __iomem *ioaddr, int val) { u32 value = readl(ioaddr + GMAC_CONFIG); @@ -1014,19 +817,6 @@ static void dwmac4_sarc_configure(void __iomem *ioaddr, int val) writel(value, ioaddr + GMAC_CONFIG); } -static void dwmac4_enable_vlan(struct mac_device_info *hw, u32 type) -{ - void __iomem *ioaddr = hw->pcsr; - u32 value; - - value = readl(ioaddr + GMAC_VLAN_INCL); - value |= GMAC_VLAN_VLTI; - value |= GMAC_VLAN_CSVL; /* Only use SVLAN */ - value &= ~GMAC_VLAN_VLC; - value |= (type << GMAC_VLAN_VLC_SHIFT) & GMAC_VLAN_VLC; - writel(value, ioaddr + GMAC_VLAN_INCL); -} - static void dwmac4_set_arp_offload(struct mac_device_info *hw, bool en, u32 addr) { @@ -1143,35 +933,6 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, return 0; } -static void dwmac4_rx_hw_vlan(struct mac_device_info *hw, - struct dma_desc *rx_desc, struct sk_buff *skb) -{ - if (hw->desc->get_rx_vlan_valid(rx_desc)) { - u16 vid = hw->desc->get_rx_vlan_tci(rx_desc); - - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } -} - -static void dwmac4_set_hw_vlan_mode(struct mac_device_info *hw) -{ - void __iomem *ioaddr = hw->pcsr; - u32 value = readl(ioaddr + GMAC_VLAN_TAG); - - value &= ~GMAC_VLAN_TAG_CTRL_EVLS_MASK; - - if (hw->hw_vlan_en) - /* Always strip VLAN on Receive */ - value |= GMAC_VLAN_TAG_STRIP_ALL; - else - /* Do not strip VLAN on Receive */ - value |= GMAC_VLAN_TAG_STRIP_NONE; - - /* Enable outer VLAN Tag in Rx DMA descriptor */ - value |= GMAC_VLAN_TAG_CTRL_EVLRXS; - writel(value, ioaddr + GMAC_VLAN_TAG); -} - const struct stmmac_ops dwmac4_ops = { .core_init = dwmac4_core_init, .update_caps = dwmac4_update_caps, @@ -1201,17 +962,10 @@ const struct stmmac_ops dwmac4_ops = { .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, .set_mac_loopback = dwmac4_set_mac_loopback, - .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure, - .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, .config_l3_filter = dwmac4_config_l3_filter, .config_l4_filter = dwmac4_config_l4_filter, - .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr, - .del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr, - .restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr, - .rx_hw_vlan = dwmac4_rx_hw_vlan, - .set_hw_vlan_mode = dwmac4_set_hw_vlan_mode, }; const struct stmmac_ops dwmac410_ops = { @@ -1244,18 +998,11 @@ const struct stmmac_ops dwmac410_ops = { .set_filter = dwmac4_set_filter, .flex_pps_config = dwmac5_flex_pps_config, .set_mac_loopback = dwmac4_set_mac_loopback, - .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure, - .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, .config_l3_filter = dwmac4_config_l3_filter, .config_l4_filter = dwmac4_config_l4_filter, .fpe_map_preemption_class = dwmac5_fpe_map_preemption_class, - .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr, - .del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr, - .restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr, - .rx_hw_vlan = dwmac4_rx_hw_vlan, - .set_hw_vlan_mode = dwmac4_set_hw_vlan_mode, }; const struct stmmac_ops dwmac510_ops = { @@ -1292,51 +1039,13 @@ const struct stmmac_ops dwmac510_ops = { .rxp_config = dwmac5_rxp_config, .flex_pps_config = dwmac5_flex_pps_config, .set_mac_loopback = dwmac4_set_mac_loopback, - .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure, - .enable_vlan = dwmac4_enable_vlan, .set_arp_offload = dwmac4_set_arp_offload, .config_l3_filter = dwmac4_config_l3_filter, .config_l4_filter = dwmac4_config_l4_filter, .fpe_map_preemption_class = dwmac5_fpe_map_preemption_class, - .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr, - .del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr, - .restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr, - .rx_hw_vlan = dwmac4_rx_hw_vlan, - .set_hw_vlan_mode = dwmac4_set_hw_vlan_mode, }; -static u32 dwmac4_get_num_vlan(void __iomem *ioaddr) -{ - u32 val, num_vlan; - - val = readl(ioaddr + GMAC_HW_FEATURE3); - switch (val & GMAC_HW_FEAT_NRVF) { - case 0: - num_vlan = 1; - break; - case 1: - num_vlan = 4; - break; - case 2: - num_vlan = 8; - break; - case 3: - num_vlan = 16; - break; - case 4: - num_vlan = 24; - break; - case 5: - num_vlan = 32; - break; - default: - num_vlan = 1; - } - - return num_vlan; -} - int dwmac4_setup(struct stmmac_priv *priv) { struct mac_device_info *mac = priv->hw; @@ -1368,7 +1077,7 @@ int dwmac4_setup(struct stmmac_priv *priv) mac->mii.reg_mask = GENMASK(20, 16); mac->mii.clk_csr_shift = 8; mac->mii.clk_csr_mask = GENMASK(11, 8); - mac->num_vlan = dwmac4_get_num_vlan(priv->ioaddr); + mac->num_vlan = stmmac_get_num_vlan(priv->ioaddr); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index a03f5d771566..5e369a9a2595 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -57,19 +57,6 @@ #define XGMAC_FILTER_PR BIT(0) #define XGMAC_HASH_TABLE(x) (0x00000010 + (x) * 4) #define XGMAC_MAX_HASH_TABLE 8 -#define XGMAC_VLAN_TAG 0x00000050 -#define XGMAC_VLAN_EDVLP BIT(26) -#define XGMAC_VLAN_VTHM BIT(25) -#define XGMAC_VLAN_DOVLTC BIT(20) -#define XGMAC_VLAN_ESVL BIT(18) -#define XGMAC_VLAN_ETV BIT(16) -#define XGMAC_VLAN_VID GENMASK(15, 0) -#define XGMAC_VLAN_HASH_TABLE 0x00000058 -#define XGMAC_VLAN_INCL 0x00000060 -#define XGMAC_VLAN_VLTI BIT(20) -#define XGMAC_VLAN_CSVL BIT(19) -#define XGMAC_VLAN_VLC GENMASK(17, 16) -#define XGMAC_VLAN_VLC_SHIFT 16 #define XGMAC_RXQ_CTRL0 0x000000a0 #define XGMAC_RXQEN(x) GENMASK((x) * 2 + 1, (x) * 2) #define XGMAC_RXQEN_SHIFT(x) ((x) * 2) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index a6d395c6bacd..d9f41c047e5e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -614,76 +614,6 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw, return 0; } -static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, - u16 perfect_match, bool is_double) -{ - void __iomem *ioaddr = hw->pcsr; - - writel(hash, ioaddr + XGMAC_VLAN_HASH_TABLE); - - if (hash) { - u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); - - value |= XGMAC_FILTER_VTFE; - - writel(value, ioaddr + XGMAC_PACKET_FILTER); - - value = readl(ioaddr + XGMAC_VLAN_TAG); - - value |= XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV; - if (is_double) { - value |= XGMAC_VLAN_EDVLP; - value |= XGMAC_VLAN_ESVL; - value |= XGMAC_VLAN_DOVLTC; - } else { - value &= ~XGMAC_VLAN_EDVLP; - value &= ~XGMAC_VLAN_ESVL; - value &= ~XGMAC_VLAN_DOVLTC; - } - - value &= ~XGMAC_VLAN_VID; - writel(value, ioaddr + XGMAC_VLAN_TAG); - } else if (perfect_match) { - u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); - - value |= XGMAC_FILTER_VTFE; - - writel(value, ioaddr + XGMAC_PACKET_FILTER); - - value = readl(ioaddr + XGMAC_VLAN_TAG); - - value &= ~XGMAC_VLAN_VTHM; - value |= XGMAC_VLAN_ETV; - if (is_double) { - value |= XGMAC_VLAN_EDVLP; - value |= XGMAC_VLAN_ESVL; - value |= XGMAC_VLAN_DOVLTC; - } else { - value &= ~XGMAC_VLAN_EDVLP; - value &= ~XGMAC_VLAN_ESVL; - value &= ~XGMAC_VLAN_DOVLTC; - } - - value &= ~XGMAC_VLAN_VID; - writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG); - } else { - u32 value = readl(ioaddr + XGMAC_PACKET_FILTER); - - value &= ~XGMAC_FILTER_VTFE; - - writel(value, ioaddr + XGMAC_PACKET_FILTER); - - value = readl(ioaddr + XGMAC_VLAN_TAG); - - value &= ~(XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV); - value &= ~(XGMAC_VLAN_EDVLP | XGMAC_VLAN_ESVL); - value &= ~XGMAC_VLAN_DOVLTC; - value &= ~XGMAC_VLAN_VID; - - writel(value, ioaddr + XGMAC_VLAN_TAG); - } -} - struct dwxgmac3_error_desc { bool valid; const char *desc; @@ -1300,19 +1230,6 @@ static void dwxgmac2_sarc_configure(void __iomem *ioaddr, int val) writel(value, ioaddr + XGMAC_TX_CONFIG); } -static void dwxgmac2_enable_vlan(struct mac_device_info *hw, u32 type) -{ - void __iomem *ioaddr = hw->pcsr; - u32 value; - - value = readl(ioaddr + XGMAC_VLAN_INCL); - value |= XGMAC_VLAN_VLTI; - value |= XGMAC_VLAN_CSVL; /* Only use SVLAN */ - value &= ~XGMAC_VLAN_VLC; - value |= (type << XGMAC_VLAN_VLC_SHIFT) & XGMAC_VLAN_VLC; - writel(value, ioaddr + XGMAC_VLAN_INCL); -} - static int dwxgmac2_filter_wait(struct mac_device_info *hw) { void __iomem *ioaddr = hw->pcsr; @@ -1534,12 +1451,10 @@ const struct stmmac_ops dwxgmac210_ops = { .safety_feat_dump = dwxgmac3_safety_feat_dump, .set_mac_loopback = dwxgmac2_set_mac_loopback, .rss_configure = dwxgmac2_rss_configure, - .update_vlan_hash = dwxgmac2_update_vlan_hash, .rxp_config = dwxgmac3_rxp_config, .get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp, .flex_pps_config = dwxgmac2_flex_pps_config, .sarc_configure = dwxgmac2_sarc_configure, - .enable_vlan = dwxgmac2_enable_vlan, .config_l3_filter = dwxgmac2_config_l3_filter, .config_l4_filter = dwxgmac2_config_l4_filter, .set_arp_offload = dwxgmac2_set_arp_offload, @@ -1590,12 +1505,10 @@ const struct stmmac_ops dwxlgmac2_ops = { .safety_feat_dump = dwxgmac3_safety_feat_dump, .set_mac_loopback = dwxgmac2_set_mac_loopback, .rss_configure = dwxgmac2_rss_configure, - .update_vlan_hash = dwxgmac2_update_vlan_hash, .rxp_config = dwxgmac3_rxp_config, .get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp, .flex_pps_config = dwxgmac2_flex_pps_config, .sarc_configure = dwxgmac2_sarc_configure, - .enable_vlan = dwxgmac2_enable_vlan, .config_l3_filter = dwxgmac2_config_l3_filter, .config_l4_filter = dwxgmac2_config_l4_filter, .set_arp_offload = dwxgmac2_set_arp_offload, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 31bdbab9a46c..0a57c5e7497d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -9,6 +9,7 @@ #include "stmmac_fpe.h" #include "stmmac_ptp.h" #include "stmmac_est.h" +#include "stmmac_vlan.h" #include "dwmac4_descs.h" #include "dwxgmac2.h" @@ -120,6 +121,7 @@ static const struct stmmac_hwif_entry { const void *tc; const void *mmc; const void *est; + const void *vlan; int (*setup)(struct stmmac_priv *priv); int (*quirks)(struct stmmac_priv *priv); } stmmac_hw[] = { @@ -197,6 +199,7 @@ static const struct stmmac_hwif_entry { .desc = &dwmac4_desc_ops, .dma = &dwmac4_dma_ops, .mac = &dwmac410_ops, + .vlan = &dwmac_vlan_ops, .hwtimestamp = &stmmac_ptp, .ptp = &stmmac_ptp_clock_ops, .mode = &dwmac4_ring_mode_ops, @@ -219,6 +222,7 @@ static const struct stmmac_hwif_entry { .desc = &dwmac4_desc_ops, .dma = &dwmac410_dma_ops, .mac = &dwmac410_ops, + .vlan = &dwmac_vlan_ops, .hwtimestamp = &stmmac_ptp, .ptp = &stmmac_ptp_clock_ops, .mode = &dwmac4_ring_mode_ops, @@ -241,6 +245,7 @@ static const struct stmmac_hwif_entry { .desc = &dwmac4_desc_ops, .dma = &dwmac410_dma_ops, .mac = &dwmac510_ops, + .vlan = &dwmac_vlan_ops, .hwtimestamp = &stmmac_ptp, .ptp = &stmmac_ptp_clock_ops, .mode = &dwmac4_ring_mode_ops, @@ -264,6 +269,7 @@ static const struct stmmac_hwif_entry { .desc = &dwxgmac210_desc_ops, .dma = &dwxgmac210_dma_ops, .mac = &dwxgmac210_ops, + .vlan = &dwmac_vlan_ops, .hwtimestamp = &stmmac_ptp, .ptp = &stmmac_ptp_clock_ops, .mode = NULL, @@ -292,6 +298,7 @@ static const struct stmmac_hwif_entry { .mode = NULL, .tc = &dwmac510_tc_ops, .mmc = &dwxgmac_mmc_ops, + .vlan = &dwxlgmac2_vlan_ops, .est = &dwmac510_est_ops, .setup = dwxlgmac2_setup, .quirks = stmmac_dwxlgmac_quirks, @@ -368,6 +375,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv) mac->tc = mac->tc ? : entry->tc; mac->mmc = mac->mmc ? : entry->mmc; mac->est = mac->est ? : entry->est; + mac->vlan = mac->vlan ? : entry->vlan; priv->hw = mac; priv->fpe_cfg.reg = entry->regs.fpe_reg; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 27c63a9fc163..26af42b8ea93 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -398,21 +398,6 @@ struct stmmac_ops { /* RSS */ int (*rss_configure)(struct mac_device_info *hw, struct stmmac_rss *cfg, u32 num_rxq); - /* VLAN */ - void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, - u16 perfect_match, bool is_double); - void (*enable_vlan)(struct mac_device_info *hw, u32 type); - void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc, - struct sk_buff *skb); - void (*set_hw_vlan_mode)(struct mac_device_info *hw); - int (*add_hw_vlan_rx_fltr)(struct net_device *dev, - struct mac_device_info *hw, - __be16 proto, u16 vid); - int (*del_hw_vlan_rx_fltr)(struct net_device *dev, - struct mac_device_info *hw, - __be16 proto, u16 vid); - void (*restore_hw_vlan_rx_fltr)(struct net_device *dev, - struct mac_device_info *hw); /* TX Timestamp */ int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts); /* Source Address Insertion / Replacement */ @@ -498,20 +483,6 @@ struct stmmac_ops { stmmac_do_void_callback(__priv, mac, set_mac_loopback, __args) #define stmmac_rss_configure(__priv, __args...) \ stmmac_do_callback(__priv, mac, rss_configure, __args) -#define stmmac_update_vlan_hash(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, update_vlan_hash, __args) -#define stmmac_enable_vlan(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, enable_vlan, __args) -#define stmmac_rx_hw_vlan(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, rx_hw_vlan, __args) -#define stmmac_set_hw_vlan_mode(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, set_hw_vlan_mode, __args) -#define stmmac_add_hw_vlan_rx_fltr(__priv, __args...) \ - stmmac_do_callback(__priv, mac, add_hw_vlan_rx_fltr, __args) -#define stmmac_del_hw_vlan_rx_fltr(__priv, __args...) \ - stmmac_do_callback(__priv, mac, del_hw_vlan_rx_fltr, __args) -#define stmmac_restore_hw_vlan_rx_fltr(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, restore_hw_vlan_rx_fltr, __args) #define stmmac_get_mac_tx_timestamp(__priv, __args...) \ stmmac_do_callback(__priv, mac, get_mac_tx_timestamp, __args) #define stmmac_sarc_configure(__priv, __args...) \ @@ -659,6 +630,38 @@ struct stmmac_est_ops { #define stmmac_est_irq_status(__priv, __args...) \ stmmac_do_void_callback(__priv, est, irq_status, __args) +struct stmmac_vlan_ops { + void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash, + __le16 perfect_match, bool is_double); + void (*enable_vlan)(struct mac_device_info *hw, u32 type); + void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc, + struct sk_buff *skb); + void (*set_hw_vlan_mode)(struct mac_device_info *hw); + int (*add_hw_vlan_rx_fltr)(struct net_device *dev, + struct mac_device_info *hw, + __be16 proto, u16 vid); + int (*del_hw_vlan_rx_fltr)(struct net_device *dev, + struct mac_device_info *hw, + __be16 proto, u16 vid); + void (*restore_hw_vlan_rx_fltr)(struct net_device *dev, + struct mac_device_info *hw); +}; + +#define stmmac_update_vlan_hash(__priv, __args...) \ + stmmac_do_void_callback(__priv, vlan, update_vlan_hash, __args) +#define stmmac_enable_vlan(__priv, __args...) \ + stmmac_do_void_callback(__priv, vlan, enable_vlan, __args) +#define stmmac_rx_hw_vlan(__priv, __args...) \ + stmmac_do_void_callback(__priv, vlan, rx_hw_vlan, __args) +#define stmmac_set_hw_vlan_mode(__priv, __args...) \ + stmmac_do_void_callback(__priv, vlan, set_hw_vlan_mode, __args) +#define stmmac_add_hw_vlan_rx_fltr(__priv, __args...) \ + stmmac_do_callback(__priv, vlan, add_hw_vlan_rx_fltr, __args) +#define stmmac_del_hw_vlan_rx_fltr(__priv, __args...) \ + stmmac_do_callback(__priv, vlan, del_hw_vlan_rx_fltr, __args) +#define stmmac_restore_hw_vlan_rx_fltr(__priv, __args...) \ + stmmac_do_void_callback(__priv, vlan, restore_hw_vlan_rx_fltr, __args) + struct stmmac_regs_off { const struct stmmac_fpe_reg *fpe_reg; u32 ptp_off; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c new file mode 100644 index 000000000000..32b05987880e --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025, Altera Corporation + * stmmac VLAN (802.1Q) handling + */ + +#include "stmmac.h" +#include "stmmac_vlan.h" + +static void vlan_write_single(struct net_device *dev, u16 vid) +{ + void __iomem *ioaddr = (void __iomem *)dev->base_addr; + u32 val; + + val = readl(ioaddr + VLAN_TAG); + val &= ~VLAN_TAG_VID; + val |= VLAN_TAG_ETV | vid; + + writel(val, ioaddr + VLAN_TAG); +} + +static int vlan_write_filter(struct net_device *dev, + struct mac_device_info *hw, + u8 index, u32 data) +{ + void __iomem *ioaddr = (void __iomem *)dev->base_addr; + int i, timeout = 10; + u32 val; + + if (index >= hw->num_vlan) + return -EINVAL; + + writel(data, ioaddr + VLAN_TAG_DATA); + + val = readl(ioaddr + VLAN_TAG); + val &= ~(VLAN_TAG_CTRL_OFS_MASK | + VLAN_TAG_CTRL_CT | + VLAN_TAG_CTRL_OB); + val |= (index << VLAN_TAG_CTRL_OFS_SHIFT) | VLAN_TAG_CTRL_OB; + + writel(val, ioaddr + VLAN_TAG); + + for (i = 0; i < timeout; i++) { + val = readl(ioaddr + VLAN_TAG); + if (!(val & VLAN_TAG_CTRL_OB)) + return 0; + udelay(1); + } + + netdev_err(dev, "Timeout accessing MAC_VLAN_Tag_Filter\n"); + + return -EBUSY; +} + +static int vlan_add_hw_rx_fltr(struct net_device *dev, + struct mac_device_info *hw, + __be16 proto, u16 vid) +{ + int index = -1; + u32 val = 0; + int i, ret; + + if (vid > 4095) + return -EINVAL; + + /* Single Rx VLAN Filter */ + if (hw->num_vlan == 1) { + /* For single VLAN filter, VID 0 means VLAN promiscuous */ + if (vid == 0) { + netdev_warn(dev, "Adding VLAN ID 0 is not supported\n"); + return -EPERM; + } + + if (hw->vlan_filter[0] & VLAN_TAG_VID) { + netdev_err(dev, "Only single VLAN ID supported\n"); + return -EPERM; + } + + hw->vlan_filter[0] = vid; + vlan_write_single(dev, vid); + + return 0; + } + + /* Extended Rx VLAN Filter Enable */ + val |= VLAN_TAG_DATA_ETV | VLAN_TAG_DATA_VEN | vid; + + for (i = 0; i < hw->num_vlan; i++) { + if (hw->vlan_filter[i] == val) + return 0; + else if (!(hw->vlan_filter[i] & VLAN_TAG_DATA_VEN)) + index = i; + } + + if (index == -1) { + netdev_err(dev, "MAC_VLAN_Tag_Filter full (size: %0u)\n", + hw->num_vlan); + return -EPERM; + } + + ret = vlan_write_filter(dev, hw, index, val); + + if (!ret) + hw->vlan_filter[index] = val; + + return ret; +} + +static int vlan_del_hw_rx_fltr(struct net_device *dev, + struct mac_device_info *hw, + __be16 proto, u16 vid) +{ + int i, ret = 0; + + /* Single Rx VLAN Filter */ + if (hw->num_vlan == 1) { + if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) { + hw->vlan_filter[0] = 0; + vlan_write_single(dev, 0); + } + return 0; + } + + /* Extended Rx VLAN Filter Enable */ + for (i = 0; i < hw->num_vlan; i++) { + if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid) { + ret = vlan_write_filter(dev, hw, i, 0); + if (!ret) + hw->vlan_filter[i] = 0; + else + return ret; + } + } + + return ret; +} + +static void vlan_restore_hw_rx_fltr(struct net_device *dev, + struct mac_device_info *hw) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + u32 hash; + u32 val; + int i; + + /* Single Rx VLAN Filter */ + if (hw->num_vlan == 1) { + vlan_write_single(dev, hw->vlan_filter[0]); + return; + } + + /* Extended Rx VLAN Filter Enable */ + for (i = 0; i < hw->num_vlan; i++) { + if (hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) { + val = hw->vlan_filter[i]; + vlan_write_filter(dev, hw, i, val); + } + } + + hash = readl(ioaddr + VLAN_HASH_TABLE); + if (hash & VLAN_VLHT) { + value = readl(ioaddr + VLAN_TAG); + value |= VLAN_VTHM; + writel(value, ioaddr + VLAN_TAG); + } +} + +static void vlan_update_hash(struct mac_device_info *hw, u32 hash, + __le16 perfect_match, bool is_double) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + + writel(hash, ioaddr + VLAN_HASH_TABLE); + + value = readl(ioaddr + VLAN_TAG); + + if (hash) { + value |= VLAN_VTHM | VLAN_ETV; + if (is_double) { + value |= VLAN_EDVLP; + value |= VLAN_ESVL; + value |= VLAN_DOVLTC; + } + + writel(value, ioaddr + VLAN_TAG); + } else if (perfect_match) { + u32 value = VLAN_ETV; + + if (is_double) { + value |= VLAN_EDVLP; + value |= VLAN_ESVL; + value |= VLAN_DOVLTC; + } + + writel(value | perfect_match, ioaddr + VLAN_TAG); + } else { + value &= ~(VLAN_VTHM | VLAN_ETV); + value &= ~(VLAN_EDVLP | VLAN_ESVL); + value &= ~VLAN_DOVLTC; + value &= ~VLAN_VID; + + writel(value, ioaddr + VLAN_TAG); + } +} + +static void vlan_enable(struct mac_device_info *hw, u32 type) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value; + + value = readl(ioaddr + VLAN_INCL); + value |= VLAN_VLTI; + value |= VLAN_CSVL; /* Only use SVLAN */ + value &= ~VLAN_VLC; + value |= (type << VLAN_VLC_SHIFT) & VLAN_VLC; + writel(value, ioaddr + VLAN_INCL); +} + +static void vlan_rx_hw(struct mac_device_info *hw, + struct dma_desc *rx_desc, struct sk_buff *skb) +{ + if (hw->desc->get_rx_vlan_valid(rx_desc)) { + u16 vid = hw->desc->get_rx_vlan_tci(rx_desc); + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); + } +} + +static void vlan_set_hw_mode(struct mac_device_info *hw) +{ + void __iomem *ioaddr = hw->pcsr; + u32 value = readl(ioaddr + VLAN_TAG); + + value &= ~VLAN_TAG_CTRL_EVLS_MASK; + + if (hw->hw_vlan_en) + /* Always strip VLAN on Receive */ + value |= VLAN_TAG_STRIP_ALL; + else + /* Do not strip VLAN on Receive */ + value |= VLAN_TAG_STRIP_NONE; + + /* Enable outer VLAN Tag in Rx DMA descriptor */ + value |= VLAN_TAG_CTRL_EVLRXS; + writel(value, ioaddr + VLAN_TAG); +} + +const struct stmmac_vlan_ops dwmac_vlan_ops = { + .update_vlan_hash = vlan_update_hash, + .enable_vlan = vlan_enable, + .add_hw_vlan_rx_fltr = vlan_add_hw_rx_fltr, + .del_hw_vlan_rx_fltr = vlan_del_hw_rx_fltr, + .restore_hw_vlan_rx_fltr = vlan_restore_hw_rx_fltr, + .rx_hw_vlan = vlan_rx_hw, + .set_hw_vlan_mode = vlan_set_hw_mode, +}; + +const struct stmmac_vlan_ops dwxlgmac2_vlan_ops = { + .update_vlan_hash = vlan_update_hash, + .enable_vlan = vlan_enable, +}; + +u32 stmmac_get_num_vlan(void __iomem *ioaddr) +{ + u32 val, num_vlan; + + val = readl(ioaddr + HW_FEATURE3); + switch (val & VLAN_HW_FEAT_NRVF) { + case 0: + num_vlan = 1; + break; + case 1: + num_vlan = 4; + break; + case 2: + num_vlan = 8; + break; + case 3: + num_vlan = 16; + break; + case 4: + num_vlan = 24; + break; + case 5: + num_vlan = 32; + break; + default: + num_vlan = 1; + } + + return num_vlan; +} diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h new file mode 100644 index 000000000000..29e7be83161e --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025, Altera Corporation + * stmmac VLAN(802.1Q) handling + */ + +#ifndef __STMMAC_VLAN_H__ +#define __STMMAC_VLAN_H__ + +#include <linux/bitfield.h> + +#define VLAN_TAG 0x00000050 +#define VLAN_TAG_DATA 0x00000054 +#define VLAN_HASH_TABLE 0x00000058 +#define VLAN_INCL 0x00000060 + +#define HW_FEATURE3 0x00000128 + +/* MAC VLAN */ +#define VLAN_EDVLP BIT(26) +#define VLAN_VTHM BIT(25) +#define VLAN_DOVLTC BIT(20) +#define VLAN_ESVL BIT(18) +#define VLAN_ETV BIT(16) +#define VLAN_VID GENMASK(15, 0) +#define VLAN_VLTI BIT(20) +#define VLAN_CSVL BIT(19) +#define VLAN_VLC GENMASK(17, 16) +#define VLAN_VLC_SHIFT 16 +#define VLAN_VLHT GENMASK(15, 0) + +/* MAC VLAN Tag */ +#define VLAN_TAG_VID GENMASK(15, 0) +#define VLAN_TAG_ETV BIT(16) + +/* MAC VLAN Tag Control */ +#define VLAN_TAG_CTRL_OB BIT(0) +#define VLAN_TAG_CTRL_CT BIT(1) +#define VLAN_TAG_CTRL_OFS_MASK GENMASK(6, 2) +#define VLAN_TAG_CTRL_OFS_SHIFT 2 +#define VLAN_TAG_CTRL_EVLS_MASK GENMASK(22, 21) +#define VLAN_TAG_CTRL_EVLS_SHIFT 21 +#define VLAN_TAG_CTRL_EVLRXS BIT(24) + +#define VLAN_TAG_STRIP_NONE FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x0) +#define VLAN_TAG_STRIP_PASS FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x1) +#define VLAN_TAG_STRIP_FAIL FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x2) +#define VLAN_TAG_STRIP_ALL FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x3) + +/* MAC VLAN Tag Data/Filter */ +#define VLAN_TAG_DATA_VID GENMASK(15, 0) +#define VLAN_TAG_DATA_VEN BIT(16) +#define VLAN_TAG_DATA_ETV BIT(17) + +/* MAC VLAN HW FEAT */ +#define VLAN_HW_FEAT_NRVF GENMASK(2, 0) + +extern const struct stmmac_vlan_ops dwmac_vlan_ops; +extern const struct stmmac_vlan_ops dwxlgmac2_vlan_ops; + +u32 stmmac_get_num_vlan(void __iomem *ioaddr); + +#endif /* __STMMAC_VLAN_H__ */ -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng @ 2025-04-10 6:38 ` Furong Xu 2025-04-21 16:40 ` Ng, Boon Khai 2025-04-10 8:19 ` Furong Xu 2025-04-11 16:36 ` Simon Horman 2 siblings, 1 reply; 14+ messages in thread From: Furong Xu @ 2025-04-10 6:38 UTC (permalink / raw) To: Boon Khai Ng Cc: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan On Tue, 8 Apr 2025 16:13:53 +0800, Boon Khai Ng <boon.khai.ng@altera.com> wrote: > Refactor VLAN implementation by moving common code for DWMAC4 and > DWXGMAC IPs into a separate VLAN module. VLAN implementation for > DWMAC4 and DWXGMAC differs only for CSR base address, the descriptor > for the VLAN ID and VLAN VALID bit field. > > Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> > Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> > --- > drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- > drivers/net/ethernet/stmicro/stmmac/common.h | 1 + > drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 40 --- > .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 295 +----------------- > .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 13 - > .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 87 ------ > drivers/net/ethernet/stmicro/stmmac/hwif.c | 8 + > drivers/net/ethernet/stmicro/stmmac/hwif.h | 61 ++-- > .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 294 +++++++++++++++++ > .../net/ethernet/stmicro/stmmac/stmmac_vlan.h | 63 ++++ > 10 files changed, 401 insertions(+), 463 deletions(-) > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h > [...] > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c > index 31bdbab9a46c..0a57c5e7497d 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c > @@ -9,6 +9,7 @@ > #include "stmmac_fpe.h" > #include "stmmac_ptp.h" > #include "stmmac_est.h" > +#include "stmmac_vlan.h" > #include "dwmac4_descs.h" > #include "dwxgmac2.h" > > @@ -120,6 +121,7 @@ static const struct stmmac_hwif_entry { > const void *tc; > const void *mmc; > const void *est; > + const void *vlan; > int (*setup)(struct stmmac_priv *priv); > int (*quirks)(struct stmmac_priv *priv); > } stmmac_hw[] = { > @@ -197,6 +199,7 @@ static const struct stmmac_hwif_entry { > .desc = &dwmac4_desc_ops, > .dma = &dwmac4_dma_ops, > .mac = &dwmac410_ops, > + .vlan = &dwmac_vlan_ops, Rename dwmac_vlan_ops to dwmac4_vlan_ops will be better, just like dwmac4_desc_ops/dwmac4_dma_ops [...] > +const struct stmmac_vlan_ops dwmac_vlan_ops = { > + .update_vlan_hash = vlan_update_hash, > + .enable_vlan = vlan_enable, > + .add_hw_vlan_rx_fltr = vlan_add_hw_rx_fltr, > + .del_hw_vlan_rx_fltr = vlan_del_hw_rx_fltr, > + .restore_hw_vlan_rx_fltr = vlan_restore_hw_rx_fltr, > + .rx_hw_vlan = vlan_rx_hw, > + .set_hw_vlan_mode = vlan_set_hw_mode, > +}; > + > +const struct stmmac_vlan_ops dwxlgmac2_vlan_ops = { > + .update_vlan_hash = vlan_update_hash, > + .enable_vlan = vlan_enable, > +}; dwxlgmac2_vlan_ops looks redundant here, another new struct contains totally identical members. stmmac_do_void_callback()/stmmac_do_callback() handles NULL function pointers so good, we can leave the un-implemented functions as NULL. Are you trying to avoid something undefined here? > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h > new file mode 100644 > index 000000000000..29e7be83161e > --- /dev/null > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h > @@ -0,0 +1,63 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2025, Altera Corporation > + * stmmac VLAN(802.1Q) handling > + */ > + > +#ifndef __STMMAC_VLAN_H__ > +#define __STMMAC_VLAN_H__ > + > +#include <linux/bitfield.h> > + > +#define VLAN_TAG 0x00000050 > +#define VLAN_TAG_DATA 0x00000054 > +#define VLAN_HASH_TABLE 0x00000058 > +#define VLAN_INCL 0x00000060 > + > +#define HW_FEATURE3 0x00000128 > + > +/* MAC VLAN */ > +#define VLAN_EDVLP BIT(26) > +#define VLAN_VTHM BIT(25) > +#define VLAN_DOVLTC BIT(20) > +#define VLAN_ESVL BIT(18) > +#define VLAN_ETV BIT(16) > +#define VLAN_VID GENMASK(15, 0) > +#define VLAN_VLTI BIT(20) > +#define VLAN_CSVL BIT(19) > +#define VLAN_VLC GENMASK(17, 16) > +#define VLAN_VLC_SHIFT 16 > +#define VLAN_VLHT GENMASK(15, 0) > + > +/* MAC VLAN Tag */ > +#define VLAN_TAG_VID GENMASK(15, 0) > +#define VLAN_TAG_ETV BIT(16) > + > +/* MAC VLAN Tag Control */ > +#define VLAN_TAG_CTRL_OB BIT(0) > +#define VLAN_TAG_CTRL_CT BIT(1) > +#define VLAN_TAG_CTRL_OFS_MASK GENMASK(6, 2) > +#define VLAN_TAG_CTRL_OFS_SHIFT 2 > +#define VLAN_TAG_CTRL_EVLS_MASK GENMASK(22, 21) > +#define VLAN_TAG_CTRL_EVLS_SHIFT 21 > +#define VLAN_TAG_CTRL_EVLRXS BIT(24) > + > +#define VLAN_TAG_STRIP_NONE FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x0) > +#define VLAN_TAG_STRIP_PASS FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x1) > +#define VLAN_TAG_STRIP_FAIL FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x2) > +#define VLAN_TAG_STRIP_ALL FIELD_PREP(VLAN_TAG_CTRL_EVLS_MASK, 0x3) > + > +/* MAC VLAN Tag Data/Filter */ > +#define VLAN_TAG_DATA_VID GENMASK(15, 0) > +#define VLAN_TAG_DATA_VEN BIT(16) > +#define VLAN_TAG_DATA_ETV BIT(17) > + > +/* MAC VLAN HW FEAT */ > +#define VLAN_HW_FEAT_NRVF GENMASK(2, 0) > + > +extern const struct stmmac_vlan_ops dwmac_vlan_ops; > +extern const struct stmmac_vlan_ops dwxlgmac2_vlan_ops; > + > +u32 stmmac_get_num_vlan(void __iomem *ioaddr); > + > +#endif /* __STMMAC_VLAN_H__ */ It is a good practice to only keep inside the header those definitions which are truly exported by stmmac_vlan.c towards external callers. That means those #defines which are only used within stmmac_vlan.c shouldn't be here, but inside stmmac_vlan.c file. ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-10 6:38 ` Furong Xu @ 2025-04-21 16:40 ` Ng, Boon Khai 0 siblings, 0 replies; 14+ messages in thread From: Ng, Boon Khai @ 2025-04-21 16:40 UTC (permalink / raw) To: Furong Xu Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan > Rename dwmac_vlan_ops to dwmac4_vlan_ops will be better, > just like dwmac4_desc_ops/dwmac4_dma_ops Hi Furong thanks for the feedback, This dwmac_vlan_ops is defined the same at dwmac4, dwmac510, and dwxgmac210, thus consolidate them in the same ops: dwmac_vlan_ops. > dwxlgmac2_vlan_ops looks redundant here, another new struct contains > totally identical members. > > stmmac_do_void_callback()/stmmac_do_callback() handles NULL function > pointers so good, we can leave the un-implemented functions as NULL. > > Are you trying to avoid something undefined here? Nope, since dwxlgmac2_vlan_ops does not hold the same ops with dwxgmac210, dwmac4, dwmac510, this is not newly enabled, just move over from the initial implementation on the ops assignment. > > It is a good practice to only keep inside the header those definitions > which are truly exported by stmmac_vlan.c towards external callers. > That means those #defines which are only used within stmmac_vlan.c > shouldn't be here, but inside stmmac_vlan.c file. I prefer to keep all #define directives in the header file to enhance code readability and debugging efficiency by providing a single reference point for developers. Regards, Boon Khai. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng 2025-04-10 6:38 ` Furong Xu @ 2025-04-10 8:19 ` Furong Xu 2025-04-11 16:27 ` Simon Horman 2025-04-11 16:36 ` Simon Horman 2 siblings, 1 reply; 14+ messages in thread From: Furong Xu @ 2025-04-10 8:19 UTC (permalink / raw) To: Boon Khai Ng Cc: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan On Tue, 8 Apr 2025 16:13:53 +0800, Boon Khai Ng <boon.khai.ng@altera.com> wrote: > Refactor VLAN implementation by moving common code for DWMAC4 and > DWXGMAC IPs into a separate VLAN module. VLAN implementation for > DWMAC4 and DWXGMAC differs only for CSR base address, the descriptor > for the VLAN ID and VLAN VALID bit field. > > Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> > Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> > --- > drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- > drivers/net/ethernet/stmicro/stmmac/common.h | 1 + > drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 40 --- > .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 295 +----------------- > .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 13 - > .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 87 ------ > drivers/net/ethernet/stmicro/stmmac/hwif.c | 8 + > drivers/net/ethernet/stmicro/stmmac/hwif.h | 61 ++-- > .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 294 +++++++++++++++++ > .../net/ethernet/stmicro/stmmac/stmmac_vlan.h | 63 ++++ > 10 files changed, 401 insertions(+), 463 deletions(-) > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h > [...] > +static void vlan_update_hash(struct mac_device_info *hw, u32 hash, > + __le16 perfect_match, bool is_double) > +{ > + void __iomem *ioaddr = hw->pcsr; > + u32 value; > + > + writel(hash, ioaddr + VLAN_HASH_TABLE); > + > + value = readl(ioaddr + VLAN_TAG); > + > + if (hash) { > + value |= VLAN_VTHM | VLAN_ETV; > + if (is_double) { > + value |= VLAN_EDVLP; > + value |= VLAN_ESVL; > + value |= VLAN_DOVLTC; I can confirm that 802.1ad (QinQ) has been broken on stmmac for years, and it will be so nice if this refactoring includes some fixes for QinQ > + } > + > + writel(value, ioaddr + VLAN_TAG); > + } else if (perfect_match) { > + u32 value = VLAN_ETV; > + > + if (is_double) { > + value |= VLAN_EDVLP; > + value |= VLAN_ESVL; > + value |= VLAN_DOVLTC; > + } > + > + writel(value | perfect_match, ioaddr + VLAN_TAG); > + } else { > + value &= ~(VLAN_VTHM | VLAN_ETV); > + value &= ~(VLAN_EDVLP | VLAN_ESVL); > + value &= ~VLAN_DOVLTC; > + value &= ~VLAN_VID; > + > + writel(value, ioaddr + VLAN_TAG); > + } > +} > + > +static void vlan_enable(struct mac_device_info *hw, u32 type) > +{ > + void __iomem *ioaddr = hw->pcsr; > + u32 value; > + > + value = readl(ioaddr + VLAN_INCL); > + value |= VLAN_VLTI; > + value |= VLAN_CSVL; /* Only use SVLAN */ > + value &= ~VLAN_VLC; > + value |= (type << VLAN_VLC_SHIFT) & VLAN_VLC; > + writel(value, ioaddr + VLAN_INCL); > +} > + > +static void vlan_rx_hw(struct mac_device_info *hw, > + struct dma_desc *rx_desc, struct sk_buff *skb) > +{ > + if (hw->desc->get_rx_vlan_valid(rx_desc)) { > + u16 vid = hw->desc->get_rx_vlan_tci(rx_desc); > + > + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); So, as the comment above, ETH_P_8021AD or ETH_P_8021Q shall be set selectively depend on the frame type. > + } > +} ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-10 8:19 ` Furong Xu @ 2025-04-11 16:27 ` Simon Horman 2025-04-21 16:52 ` Ng, Boon Khai 0 siblings, 1 reply; 14+ messages in thread From: Simon Horman @ 2025-04-11 16:27 UTC (permalink / raw) To: Furong Xu Cc: Boon Khai Ng, netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan On Thu, Apr 10, 2025 at 04:19:12PM +0800, Furong Xu wrote: > On Tue, 8 Apr 2025 16:13:53 +0800, Boon Khai Ng <boon.khai.ng@altera.com> wrote: > > > Refactor VLAN implementation by moving common code for DWMAC4 and > > DWXGMAC IPs into a separate VLAN module. VLAN implementation for > > DWMAC4 and DWXGMAC differs only for CSR base address, the descriptor > > for the VLAN ID and VLAN VALID bit field. > > > > Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> > > Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> > > --- > > drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- > > drivers/net/ethernet/stmicro/stmmac/common.h | 1 + > > drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 40 --- > > .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 295 +----------------- > > .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 13 - > > .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 87 ------ > > drivers/net/ethernet/stmicro/stmmac/hwif.c | 8 + > > drivers/net/ethernet/stmicro/stmmac/hwif.h | 61 ++-- > > .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 294 +++++++++++++++++ > > .../net/ethernet/stmicro/stmmac/stmmac_vlan.h | 63 ++++ > > 10 files changed, 401 insertions(+), 463 deletions(-) > > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c > > create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.h > > > [...] > > +static void vlan_update_hash(struct mac_device_info *hw, u32 hash, > > + __le16 perfect_match, bool is_double) > > +{ > > + void __iomem *ioaddr = hw->pcsr; > > + u32 value; > > + > > + writel(hash, ioaddr + VLAN_HASH_TABLE); > > + > > + value = readl(ioaddr + VLAN_TAG); > > + > > + if (hash) { > > + value |= VLAN_VTHM | VLAN_ETV; > > + if (is_double) { > > + value |= VLAN_EDVLP; > > + value |= VLAN_ESVL; > > + value |= VLAN_DOVLTC; > > I can confirm that 802.1ad (QinQ) has been broken on stmmac for years, > and it will be so nice if this refactoring includes some fixes for QinQ FWIIW, please be sure that fixes are separate patches from refactoring. ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-11 16:27 ` Simon Horman @ 2025-04-21 16:52 ` Ng, Boon Khai 0 siblings, 0 replies; 14+ messages in thread From: Ng, Boon Khai @ 2025-04-21 16:52 UTC (permalink / raw) To: Simon Horman, Furong Xu Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan > > I can confirm that 802.1ad (QinQ) has been broken on stmmac for years, > > and it will be so nice if this refactoring includes some fixes for > > QinQ > > FWIIW, please be sure that fixes are separate patches from refactoring. Hi Furong, Simon, This refactor is intended to combine the VLAN driver for dwmac4 and dwxgmac2. From our perspective, on our board, we do not actually use the QinQ feature of the xgmac2 IP. However, I agree with Simon that the fixes should be separate from the refactoring process Regards, Boon Khai. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng 2025-04-10 6:38 ` Furong Xu 2025-04-10 8:19 ` Furong Xu @ 2025-04-11 16:36 ` Simon Horman 2025-04-21 16:47 ` Ng, Boon Khai 2 siblings, 1 reply; 14+ messages in thread From: Simon Horman @ 2025-04-11 16:36 UTC (permalink / raw) To: Boon Khai Ng Cc: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan On Tue, Apr 08, 2025 at 04:13:53PM +0800, Boon Khai Ng wrote: > Refactor VLAN implementation by moving common code for DWMAC4 and > DWXGMAC IPs into a separate VLAN module. VLAN implementation for > DWMAC4 and DWXGMAC differs only for CSR base address, the descriptor > for the VLAN ID and VLAN VALID bit field. > > Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> > Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> ... > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c ... > @@ -965,45 +807,6 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable) > writel(value, ioaddr + GMAC_CONFIG); > } > > -static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash, > - u16 perfect_match, bool is_double) ... > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c > index a6d395c6bacd..d9f41c047e5e 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c > @@ -614,76 +614,6 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw, > return 0; > } > > -static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash, > - u16 perfect_match, bool is_double) ... > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c ... > +static void vlan_update_hash(struct mac_device_info *hw, u32 hash, > + __le16 perfect_match, bool is_double) ... Hi, The signature of this new function does not appear to match that of the functions it replaces. And it appears to regress the endian annotation of perfect_match which was corrected in commit e9dbebae2e3c ("net: stmmac: Correct byte order of perfect_match") Flagged by Sparse. ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation 2025-04-11 16:36 ` Simon Horman @ 2025-04-21 16:47 ` Ng, Boon Khai 0 siblings, 0 replies; 14+ messages in thread From: Ng, Boon Khai @ 2025-04-21 16:47 UTC (permalink / raw) To: Simon Horman Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan > > Hi, > > The signature of this new function does not appear to match that of the > functions it replaces. And it appears to regress the endian annotation of > perfect_match which was corrected in commit e9dbebae2e3c ("net: stmmac: > Correct byte order of perfect_match") > > Flagged by Sparse. Hi Simon, Thanks for highlighting this issue, I have fixed it in v4 Regards, Boon Khai ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping 2025-04-08 8:13 [PATCH net-next v3 0/2] Refactoring designware VLAN code Boon Khai Ng 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng @ 2025-04-08 8:13 ` Boon Khai Ng 2025-04-08 19:08 ` Andrew Lunn 1 sibling, 1 reply; 14+ messages in thread From: Boon Khai Ng @ 2025-04-08 8:13 UTC (permalink / raw) To: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan, Boon Khai Ng This patch adds support for MAC level VLAN tag stripping for the dwxgmac2 IP. This feature can be configured through ethtool. If the rx-vlan-offload is off, then the VLAN tag will be stripped by the driver. If the rx-vlan-offload is on then the VLAN tag will be stripped by the MAC. Signed-off-by: Boon Khai Ng <boon.khai.ng@altera.com> Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 12 ++++++++++++ .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 2 ++ .../ethernet/stmicro/stmmac/dwxgmac2_descs.c | 18 ++++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 5e369a9a2595..0d408ee17f33 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -464,6 +464,7 @@ #define XGMAC_RDES3_RSV BIT(26) #define XGMAC_RDES3_L34T GENMASK(23, 20) #define XGMAC_RDES3_L34T_SHIFT 20 +#define XGMAC_RDES3_ET_LT GENMASK(19, 16) #define XGMAC_L34T_IP4TCP 0x1 #define XGMAC_L34T_IP4UDP 0x2 #define XGMAC_L34T_IP6TCP 0x9 @@ -473,6 +474,17 @@ #define XGMAC_RDES3_TSD BIT(6) #define XGMAC_RDES3_TSA BIT(4) +/* RDES0 (write back format) */ +#define XGMAC_RDES0_VLAN_TAG_MASK GENMASK(15, 0) + +/* Error Type or L2 Type(ET/LT) Field Number */ +#define XGMAC_ET_LT_VLAN_STAG 8 +#define XGMAC_ET_LT_VLAN_CTAG 9 +#define XGMAC_ET_LT_DVLAN_CTAG_CTAG 10 +#define XGMAC_ET_LT_DVLAN_STAG_STAG 11 +#define XGMAC_ET_LT_DVLAN_CTAG_STAG 12 +#define XGMAC_ET_LT_DVLAN_STAG_CTAG 13 + extern const struct stmmac_ops dwxgmac210_ops; extern const struct stmmac_ops dwxlgmac2_ops; extern const struct stmmac_dma_ops dwxgmac210_dma_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index d9f41c047e5e..6cadf8de4fdf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -10,6 +10,7 @@ #include "stmmac.h" #include "stmmac_fpe.h" #include "stmmac_ptp.h" +#include "stmmac_vlan.h" #include "dwxlgmac2.h" #include "dwxgmac2.h" @@ -1551,6 +1552,7 @@ int dwxgmac2_setup(struct stmmac_priv *priv) mac->mii.reg_mask = GENMASK(15, 0); mac->mii.clk_csr_shift = 19; mac->mii.clk_csr_mask = GENMASK(21, 19); + mac->num_vlan = stmmac_get_num_vlan(priv->ioaddr); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c index 389aad7b5c1e..55921c88efd0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c @@ -4,6 +4,7 @@ * stmmac XGMAC support. */ +#include <linux/bitfield.h> #include <linux/stmmac.h> #include "common.h" #include "dwxgmac2.h" @@ -69,6 +70,21 @@ static int dwxgmac2_get_tx_ls(struct dma_desc *p) return (le32_to_cpu(p->des3) & XGMAC_RDES3_LD) > 0; } +static u16 dwxgmac2_wrback_get_rx_vlan_tci(struct dma_desc *p) +{ + return (le32_to_cpu(p->des0) & XGMAC_RDES0_VLAN_TAG_MASK); +} + +static inline bool dwxgmac2_wrback_get_rx_vlan_valid(struct dma_desc *p) +{ + u32 et_lt; + + et_lt = FIELD_GET(XGMAC_RDES3_ET_LT, le32_to_cpu(p->des3)); + + return et_lt >= XGMAC_ET_LT_VLAN_STAG && + et_lt <= XGMAC_ET_LT_DVLAN_STAG_CTAG; +} + static int dwxgmac2_get_rx_frame_len(struct dma_desc *p, int rx_coe) { return (le32_to_cpu(p->des3) & XGMAC_RDES3_PL); @@ -351,6 +367,8 @@ const struct stmmac_desc_ops dwxgmac210_desc_ops = { .set_tx_owner = dwxgmac2_set_tx_owner, .set_rx_owner = dwxgmac2_set_rx_owner, .get_tx_ls = dwxgmac2_get_tx_ls, + .get_rx_vlan_tci = dwxgmac2_wrback_get_rx_vlan_tci, + .get_rx_vlan_valid = dwxgmac2_wrback_get_rx_vlan_valid, .get_rx_frame_len = dwxgmac2_get_rx_frame_len, .enable_tx_timestamp = dwxgmac2_enable_tx_timestamp, .get_tx_timestamp_status = dwxgmac2_get_tx_timestamp_status, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 279532609707..eb03d6950903 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7644,7 +7644,7 @@ int stmmac_dvr_probe(struct device *device, #ifdef STMMAC_VLAN_TAG_USED /* Both mac100 and gmac support receive VLAN tag detection */ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; - if (priv->plat->has_gmac4) { + if (priv->plat->has_gmac4 || priv->plat->has_xgmac) { ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; priv->hw->hw_vlan_en = true; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping 2025-04-08 8:13 ` [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping Boon Khai Ng @ 2025-04-08 19:08 ` Andrew Lunn 2025-04-09 3:12 ` Ng, Boon Khai 0 siblings, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2025-04-08 19:08 UTC (permalink / raw) To: Boon Khai Ng Cc: netdev, linux-stm32, linux-arm-kernel, linux-kernel, bpf, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Matthew Gerlach, Tien Sung Ang, Mun Yew Tham, G Thomas Rohan > +static u16 dwxgmac2_wrback_get_rx_vlan_tci(struct dma_desc *p) > +{ > + return (le32_to_cpu(p->des0) & XGMAC_RDES0_VLAN_TAG_MASK); > +} This appears to be identical to dwmac4_wrback_get_rx_vlan_tci() ? Can it be moved into the shared code, or am i missing something? Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping 2025-04-08 19:08 ` Andrew Lunn @ 2025-04-09 3:12 ` Ng, Boon Khai 2025-04-09 12:04 ` Andrew Lunn 0 siblings, 1 reply; 14+ messages in thread From: Ng, Boon Khai @ 2025-04-09 3:12 UTC (permalink / raw) To: Andrew Lunn Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan > This appears to be identical to dwmac4_wrback_get_rx_vlan_tci() ? > > Can it be moved into the shared code, or am i missing something? > > Andrew Hi Andrew thanks for the quick response. For the dwmac4 IP it has the following format at the Receive Normal Descriptor 0 (RDES0) 31 0 ------------------------------------- ----------------------------------- RDES0 | Inner VLAN TAG [31:16] | Outer VLAN TAG [31:16 | ------------------------------------- ----------------------------------- While for dwxgmac2 IP it has the following format at the RDES0 Depending on the Tunneled Frame bit (TNP) For Non-Tunneled Frame (TNP=0) 31 0 ------------------------------------- ----------------------------------- RDES0 | Inner VLAN TAG [31:16 ] | Outer VLAN TAG [31:16] | ------------------------------------- ----------------------------------- For Tunneled Frame (TNP=1) 31 8 7 3 2 0 -------------------------------- ----------------------- ---------------- RDES0 | VNID/VSID | Reserved | OL2L3 | -------------------------------- ----------------------- ---------------- While the logic for handling Tunneled Frame and Non-Tunneled Frame is not yet implemented in the dwxgmac2_wrback_get_rx_vlan_tci() function, I believe it is prudent to maintain separate functions within their respective descriptor driver files, (dwxgmac2_descs.c and dwmac4_descs.c) ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping 2025-04-09 3:12 ` Ng, Boon Khai @ 2025-04-09 12:04 ` Andrew Lunn 2025-04-10 2:19 ` Ng, Boon Khai 0 siblings, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2025-04-09 12:04 UTC (permalink / raw) To: Ng, Boon Khai Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan On Wed, Apr 09, 2025 at 03:12:53AM +0000, Ng, Boon Khai wrote: > > This appears to be identical to dwmac4_wrback_get_rx_vlan_tci() ? > > > > Can it be moved into the shared code, or am i missing something? > > > > Andrew > > Hi Andrew thanks for the quick response. > > For the dwmac4 IP it has the following format at the > Receive Normal Descriptor 0 (RDES0) > > 31 0 > ------------------------------------- ----------------------------------- > RDES0 | Inner VLAN TAG [31:16] | Outer VLAN TAG [31:16 | > ------------------------------------- ----------------------------------- > > While for dwxgmac2 IP it has the following format at the RDES0 > Depending on the Tunneled Frame bit (TNP) > > For Non-Tunneled Frame (TNP=0) > 31 0 > ------------------------------------- ----------------------------------- > RDES0 | Inner VLAN TAG [31:16 ] | Outer VLAN TAG [31:16] | > ------------------------------------- ----------------------------------- > > For Tunneled Frame (TNP=1) > 31 8 7 3 2 0 > -------------------------------- ----------------------- ---------------- > RDES0 | VNID/VSID | Reserved | OL2L3 | > -------------------------------- ----------------------- ---------------- > > While the logic for handling Tunneled Frame and Non-Tunneled > Frame is not yet implemented in the > dwxgmac2_wrback_get_rx_vlan_tci() function, I believe it is > prudent to maintain separate functions within their respective > descriptor driver files, (dwxgmac2_descs.c and dwmac4_descs.c) Please add a comment, or describe this in the commit message. Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping 2025-04-09 12:04 ` Andrew Lunn @ 2025-04-10 2:19 ` Ng, Boon Khai 0 siblings, 0 replies; 14+ messages in thread From: Ng, Boon Khai @ 2025-04-10 2:19 UTC (permalink / raw) To: Andrew Lunn Cc: netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Russell King, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend, Gerlach, Matthew, Ang, Tien Sung, Tham, Mun Yew, G Thomas, Rohan > > > > While the logic for handling Tunneled Frame and Non-Tunneled Frame is > > not yet implemented in the > > dwxgmac2_wrback_get_rx_vlan_tci() function, I believe it is prudent to > > maintain separate functions within their respective descriptor driver > > files, (dwxgmac2_descs.c and dwmac4_descs.c) > > Please add a comment, or describe this in the commit message. > > Andrew Hi Adrew, Thank you for your feedback, sure, I will include the description in the commit message on v4. Regarding the overall changes, I believe they effectively consolidated while maintaining the necessary separation for descriptor function. Please let me know if there are any additional areas you would like me to address or further suggestion of improvement. Thanks you for your guidance and support. Regards, Boon Khai ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-04-21 16:52 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-08 8:13 [PATCH net-next v3 0/2] Refactoring designware VLAN code Boon Khai Ng 2025-04-08 8:13 ` [PATCH net-next v3 1/2] net: stmmac: Refactor VLAN implementation Boon Khai Ng 2025-04-10 6:38 ` Furong Xu 2025-04-21 16:40 ` Ng, Boon Khai 2025-04-10 8:19 ` Furong Xu 2025-04-11 16:27 ` Simon Horman 2025-04-21 16:52 ` Ng, Boon Khai 2025-04-11 16:36 ` Simon Horman 2025-04-21 16:47 ` Ng, Boon Khai 2025-04-08 8:13 ` [PATCH net-next v3 2/2] net: stmmac: dwxgmac2: Add support for HW-accelerated VLAN stripping Boon Khai Ng 2025-04-08 19:08 ` Andrew Lunn 2025-04-09 3:12 ` Ng, Boon Khai 2025-04-09 12:04 ` Andrew Lunn 2025-04-10 2:19 ` Ng, Boon Khai
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).