Re: [PATCH net-next v6 07/11] net: ti: prueth: Adds support for network filters for traffic control supported by PRU-ICSS

From: ALOK TIWARI
Date: Sat May 03 2025 - 05:29:36 EST



+ /* for LRE, it is a shared table. So lock the access */
+ spin_lock_irqsave(&emac->addr_lock, flags);
+
+ /* VLAN filter table is 512 bytes (4096 bit) bitmap.
+ * Each bit controls enabling or disabling corresponding
+ * VID. Therefore byte index that controls a given VID is
+ * can calculated as vid / 8 and the bit within that byte
+ * that controls VID is given by vid % 8. Allow untagged
+ * frames to host by default.
+ */
+ byte_index = vid / BITS_PER_BYTE;
+ bit_index = vid % BITS_PER_BYTE;
+ val = readb(ram + vlan_filter_tbl + byte_index);
+ if (add)
+ val |= BIT(bit_index);
+ else
+ val &= ~BIT(bit_index);
+ writeb(val, ram + vlan_filter_tbl + byte_index);
+
+ spin_unlock_irqrestore(&emac->addr_lock, flags);
+
+ netdev_dbg(emac->ndev, "%s VID bit at index %d and bit %d\n",
+ add ? "Setting" : "Clearing", byte_index, bit_index);

VID bit at byte index

+
+ return 0;
+}
+
+static int icssm_emac_ndo_vlan_rx_add_vid(struct net_device *dev,
+ __be16 proto, u16 vid)
+{
+ struct prueth_emac *emac = netdev_priv(dev);
+
+ return icssm_emac_add_del_vid(emac, true, proto, vid);
+}
+
+static int icssm_emac_ndo_vlan_rx_kill_vid(struct net_device *dev,
+ __be16 proto, u16 vid)
+{
+ struct prueth_emac *emac = netdev_priv(dev);
+
+ return icssm_emac_add_del_vid(emac, false, proto, vid);
+}
+
+static int icssm_emac_get_port_parent_id(struct net_device *dev,
+ struct netdev_phys_item_id *ppid)
+{
+ struct prueth_emac *emac = netdev_priv(dev);
+ struct prueth *prueth = emac->prueth;
+
+ ppid->id_len = sizeof(prueth->base_mac);
+ memcpy(&ppid->id, &prueth->base_mac, ppid->id_len);
+
+ return 0;
+}
+
+static int icssm_emac_ndo_get_phys_port_name(struct net_device *ndev,
+ char *name, size_t len)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ int err;
+
+ err = snprintf(name, len, "p%d", emac->port_id);
+
+ if (err >= len)
+ return -EINVAL;
+
+ return 0;
+}
+
static const struct net_device_ops emac_netdev_ops = {
.ndo_open = icssm_emac_ndo_open,
.ndo_stop = icssm_emac_ndo_stop,
.ndo_start_xmit = icssm_emac_ndo_start_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = icssm_emac_ndo_tx_timeout,
.ndo_get_stats64 = icssm_emac_ndo_get_stats64,
+ .ndo_set_rx_mode = icssm_emac_ndo_set_rx_mode,
.ndo_eth_ioctl = icssm_emac_ndo_ioctl,
+ .ndo_vlan_rx_add_vid = icssm_emac_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = icssm_emac_ndo_vlan_rx_kill_vid,
+ .ndo_setup_tc = icssm_emac_ndo_setup_tc,
+ .ndo_get_port_parent_id = icssm_emac_get_port_parent_id,
+ .ndo_get_phys_port_name = icssm_emac_ndo_get_phys_port_name,
};
/* get emac_port corresponding to eth_node name */
@@ -1567,6 +1865,7 @@ static int icssm_prueth_netdev_init(struct prueth *prueth,
emac->prueth = prueth;
emac->ndev = ndev;
emac->port_id = port;
+ memset(&emac->mc_filter_mask[0], 0xff, ETH_ALEN); /* default mask */
/* by default eth_type is EMAC */
switch (port) {
@@ -1608,7 +1907,9 @@ static int icssm_prueth_netdev_init(struct prueth *prueth,
dev_err(prueth->dev, "could not get ptp tx irq. Skipping PTP support\n");
}
+ spin_lock_init(&emac->lock);
spin_lock_init(&emac->ptp_skb_lock);
+ spin_lock_init(&emac->addr_lock);
/* get mac address from DT and set private and netdev addr */
ret = of_get_ethdev_address(eth_node, ndev);
@@ -1637,6 +1938,10 @@ static int icssm_prueth_netdev_init(struct prueth *prueth,
phy_remove_link_mode(emac->phydev, ETHTOOL_LINK_MODE_Pause_BIT);
phy_remove_link_mode(emac->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
+ ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
+
+ ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+
ndev->netdev_ops = &emac_netdev_ops;
ndev->ethtool_ops = &emac_ethtool_ops;
@@ -1689,6 +1994,7 @@ static int icssm_prueth_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, prueth);
prueth->dev = dev;
prueth->fw_data = device_get_match_data(dev);
+ prueth->fw_offsets = &fw_offsets_v2_1;
eth_ports_node = of_get_child_by_name(np, "ethernet-ports");
if (!eth_ports_node)
@@ -1875,6 +2181,8 @@ static int icssm_prueth_probe(struct platform_device *pdev)
prueth->emac[PRUETH_MAC1]->ndev;
}
+ eth_random_addr(prueth->base_mac);
+
dev_info(dev, "TI PRU ethernet driver initialized: %s EMAC mode\n",
(!eth0_node || !eth1_node) ? "single" : "dual");
diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth.h b/drivers/net/ethernet/ti/icssm/icssm_prueth.h
index 1709b3b6c2be..8a5f1647466a 100644
--- a/drivers/net/ethernet/ti/icssm/icssm_prueth.h
+++ b/drivers/net/ethernet/ti/icssm/icssm_prueth.h
@@ -28,6 +28,9 @@
#define EMAC_MAX_FRM_SUPPORT (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN + \
ICSSM_LRE_TAG_SIZE)
+/* default timer for NSP and HSR/PRP */
+#define PRUETH_NSP_TIMER_MS (100) /* Refresh NSP counters every 100ms */
+
#define PRUETH_REG_DUMP_VER 1
/* Encoding: 32-16: Reserved, 16-8: Reg dump version, 8-0: Ethertype */

remove extra ' ' after Ethertype

@@ -293,6 +296,29 @@ enum prueth_mem {
PRUETH_MEM_MAX,
};
+/* Firmware offsets/size information */
+struct prueth_fw_offsets {
+ u32 index_array_offset;
+ u32 bin_array_offset;
+ u32 nt_array_offset;
+ u32 index_array_loc;
+ u32 bin_array_loc;
+ u32 nt_array_loc;
+ u32 index_array_max_entries;
+ u32 bin_array_max_entries;
+ u32 nt_array_max_entries;
+ u32 vlan_ctrl_byte;
+ u32 vlan_filter_tbl;
+ u32 mc_ctrl_byte;
+ u32 mc_filter_mask;
+ u32 mc_filter_tbl;
+ /* IEP wrap is used in the rx packet ordering logic and
+ * is different for ICSSM v1.0 vs 2.1
+ */
+ u32 iep_wrap;
+ u16 hash_mask;
+};
+
[clip]
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* Copyright (C) 2015-2021 Texas Instruments Incorporated - https://urldefense.com/v3/__https://www.ti.com__;!!ACWV5N9M2RV99hQ!Pnt8LQPwsRI73TtUPzBpwVw_Cn90DbuNXinXJ5m2isPHfFxjNTp4JBlr6UedPapFerELKSzV4SFNoiUfE1xa8g$
+ *
+ * This file contains VLAN/Multicast filtering feature memory map
+ *
+ */
+
+#ifndef ICSS_VLAN_MULTICAST_FILTER_MM_H
+#define ICSS_VLAN_MULTICAST_FILTER_MM_H
+
+/* VLAN/Multicast filter defines & offsets,
+ * present on both PRU0 and PRU1 DRAM

remove extra ' '

+ */
+
+/* Feature enable/disable values for multicast filtering */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_DISABLED 0x00
+#define ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_ENABLED 0x01
+
+/* Feature enable/disable values for VLAN filtering */

remove extra ' ' after values

+#define ICSS_EMAC_FW_VLAN_FILTER_CTRL_DISABLED 0x00
+#define ICSS_EMAC_FW_VLAN_FILTER_CTRL_ENABLED 0x01
+
+/* Add/remove multicast mac id for filtering bin */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_HOST_RCV_ALLOWED 0x01
+#define ICSS_EMAC_FW_MULTICAST_FILTER_HOST_RCV_NOT_ALLOWED 0x00
+
+/* Default HASH value for the multicast filtering Mask */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_INIT_VAL 0xFF
+
+/* Size requirements for Multicast filtering feature */
+#define ICSS_EMAC_FW_MULTICAST_TABLE_SIZE_BYTES 256
+#define ICSS_EMAC_FW_MULTICAST_FILTER_MASK_SIZE_BYTES 6
+#define ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_SIZE_BYTES 1
+#define ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OVERRIDE_STATUS_SIZE_BYTES 1
+#define ICSS_EMAC_FW_MULTICAST_FILTER_DROP_CNT_SIZE_BYTES 4
+
+/* Size requirements for VLAN filtering feature : 4096 bits = 512 bytes */
+#define ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES 512
+#define ICSS_EMAC_FW_VLAN_FILTER_CTRL_SIZE_BYTES 1
+#define ICSS_EMAC_FW_VLAN_FILTER_DROP_CNT_SIZE_BYTES 4
+
+/* Mask override set status */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OVERRIDE_SET 1
+/* Mask override not set status */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OVERRIDE_NOT_SET 0
+/* 6 bytes HASH Mask for the MAC */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OFFSET 0xF4
+/* 0 -> multicast filtering disabled | 1 -> multicast filtering enabled */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_OFFSET \
+ (ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OFFSET + \
+ ICSS_EMAC_FW_MULTICAST_FILTER_MASK_SIZE_BYTES)
+/* Status indicating if the HASH override is done or not: 0: no, 1: yes */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_OVERRIDE_STATUS \
+ (ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_OFFSET + \
+ ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_SIZE_BYTES)
+/* Multicast drop statistics */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_DROP_CNT_OFFSET \
+ (ICSS_EMAC_FW_MULTICAST_FILTER_OVERRIDE_STATUS +\
+ ICSS_EMAC_FW_MULTICAST_FILTER_MASK_OVERRIDE_STATUS_SIZE_BYTES)
+/* Multicast table */
+#define ICSS_EMAC_FW_MULTICAST_FILTER_TABLE \
+ (ICSS_EMAC_FW_MULTICAST_FILTER_DROP_CNT_OFFSET +\
+ ICSS_EMAC_FW_MULTICAST_FILTER_DROP_CNT_SIZE_BYTES)
+
+/* Multicast filter defines & offsets for LRE
+ */
+#define ICSS_LRE_FW_MULTICAST_TABLE_SEARCH_OP_CONTROL_BIT 0xE0
+/* one byte field :
+ * 0 -> multicast filtering disabled
+ * 1 -> multicast filtering enabled
+ */
+#define ICSS_LRE_FW_MULTICAST_FILTER_MASK 0xE4
+#define ICSS_LRE_FW_MULTICAST_FILTER_TABLE 0x100
+
+/* VLAN table Offsets */
+#define ICSS_EMAC_FW_VLAN_FLTR_TBL_BASE_ADDR 0x200
+#define ICSS_EMAC_FW_VLAN_FILTER_CTRL_BITMAP_OFFSET 0xEF
+#define ICSS_EMAC_FW_VLAN_FILTER_DROP_CNT_OFFSET \
+ (ICSS_EMAC_FW_VLAN_FILTER_CTRL_BITMAP_OFFSET + \
+ ICSS_EMAC_FW_VLAN_FILTER_CTRL_SIZE_BYTES)
+
+/* VLAN filter Control Bit maps */
+/* one bit field, bit 0: | 0 : VLAN filter disabled (default),
+ * 1: VLAN filter enabled
+ */
+#define ICSS_EMAC_FW_VLAN_FILTER_CTRL_ENABLE_BIT 0
+/* one bit field, bit 1: | 0 : untagged host rcv allowed (default),
+ * 1: untagged host rcv not allowed
+ */
+#define ICSS_EMAC_FW_VLAN_FILTER_UNTAG_HOST_RCV_ALLOW_CTRL_BIT 1
+/* one bit field, bit 1: | 0 : priotag host rcv allowed (default),
+ * 1: priotag host rcv not allowed
+ */
+#define ICSS_EMAC_FW_VLAN_FILTER_PRIOTAG_HOST_RCV_ALLOW_CTRL_BIT 2
+/* one bit field, bit 1: | 0 : skip sv vlan flow
+ * :1 : take sv vlan flow (not applicable for dual emac )
+ */
+#define ICSS_EMAC_FW_VLAN_FILTER_SV_VLAN_FLOW_HOST_RCV_ALLOW_CTRL_BIT 3
+
+/* VLAN IDs */
+#define ICSS_EMAC_FW_VLAN_FILTER_PRIOTAG_VID 0
+#define ICSS_EMAC_FW_VLAN_FILTER_VID_MIN 0x0000
+#define ICSS_EMAC_FW_VLAN_FILTER_VID_MAX 0x0FFF
+
+/* VLAN Filtering Commands */
+#define ICSS_EMAC_FW_VLAN_FILTER_ADD_VLAN_VID_CMD 0x00
+#define ICSS_EMAC_FW_VLAN_FILTER_REMOVE_VLAN_VID_CMD 0x01
+
+/* Switch defines for VLAN/MC filtering */
+/* SRAM
+ * VLAN filter defines & offsets
+ */
+#define ICSS_LRE_FW_VLAN_FLTR_CTRL_BYTE 0x1FE

lowercase hex please, all place.

+/* one bit field | 0 : VLAN filter disabled
+ * | 1 : VLAN filter enabled
+ */
+#define ICSS_LRE_FW_VLAN_FLTR_TBL_BASE_ADDR 0x200
+
+#endif /* ICSS_MULTICAST_FILTER_MM_H */


Thanks,
Alok