From f985358f4ee231a77e00eb45c5b0f99a30c0a3d4 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jun 2026 14:23:09 +0300 Subject: [PATCH] dpaa2-switch: add support for imprecise source port Switch ports configured as part of a LAG group are not able to provide a precise source port for all packets which reach the control interface. The only frames which will have a precise source port are those that are explicitly trapped, for example STP and LCAP frames. For any other frames (for example, those which are flooded) we can only know the ingress LAG group. Take into account the DPAA2_ETHSW_FLC_IMPRECISE_IF_ID bit and based on its value target the bond device or the specific source netdevice. Signed-off-by: Ioana Ciornei Link: https://patch.msgid.link/20260629112309.154328-14-ioana.ciornei@nxp.com Signed-off-by: Paolo Abeni --- .../net/ethernet/freescale/dpaa2/dpaa2-switch.c | 15 +++++++++++++-- .../net/ethernet/freescale/dpaa2/dpaa2-switch.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index b94d83f5ef06..8320b26c3f72 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -3120,19 +3120,22 @@ static void dpaa2_switch_rx(struct dpaa2_switch_fq *fq, dma_addr_t addr = dpaa2_fd_get_addr(fd); struct ethsw_core *ethsw = fq->ethsw; struct ethsw_port_priv *port_priv; + struct dpaa2_switch_lag *lag; struct net_device *netdev; struct vlan_ethhdr *hdr; struct sk_buff *skb; u16 vlan_tci, vid; int if_id, err; void *vaddr; + u64 flc; vaddr = dpaa2_iova_to_virt(ethsw->iommu_domain, addr); dma_unmap_page(ethsw->dev, addr, DPAA2_SWITCH_RX_BUF_SIZE, DMA_FROM_DEVICE); /* get switch ingress interface ID */ - if_id = upper_32_bits(dpaa2_fd_get_flc(fd)) & 0x0000FFFF; + flc = dpaa2_fd_get_flc(fd); + if_id = DPAA2_ETHSW_FLC_IF_ID(flc); if (if_id >= ethsw->sw_attr.num_ifs) { dev_err(ethsw->dev, "Frame received from unknown interface!\n"); goto err_free_fd; @@ -3171,12 +3174,20 @@ static void dpaa2_switch_rx(struct dpaa2_switch_fq *fq, } } - skb->dev = netdev; + rcu_read_lock(); + + lag = rcu_dereference(port_priv->lag); + if (DPAA2_ETHSW_FLC_IMPRECISE_IF_ID(flc) && lag) + skb->dev = lag->bond_dev; + else + skb->dev = netdev; skb->protocol = eth_type_trans(skb, skb->dev); /* Setup the offload_fwd_mark only if the port is under a bridge */ skb->offload_fwd_mark = !!(port_priv->fdb->bridge_dev); + rcu_read_unlock(); + netif_receive_skb(skb); return; diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h index e8bc1469cbf7..63b702b0000c 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h @@ -87,6 +87,9 @@ #define DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE 256 +#define DPAA2_ETHSW_FLC_IF_ID(flc) (((flc) >> 32) & GENMASK(15, 0)) +#define DPAA2_ETHSW_FLC_IMPRECISE_IF_ID(flc) ((flc) & BIT_ULL(63)) + extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; struct ethsw_core;