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;