On Wed, Oct 02, 2019 at 03:19:59PM +0300, Leon Romanovsky wrote: > From: Parav Pandit <parav@xxxxxxxxxxxx> > > When macvlan netdevice is used for RoCE, consider the tos->prio->tc > mapping as SL using its lower netdevice. > 1. If lower netdevice is VLAN netdevice, consider such VLAN netdevice > and it's parent netdevice for mapping > 2. If lower netdevice is not a VLAN netdevice, consider tc mapping > directly from such lower netdevice > > Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx> > Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> > drivers/infiniband/core/cma.c | 59 +++++++++++++++++++++++++++++------ > 1 file changed, 50 insertions(+), 9 deletions(-) > > diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c > index 0e3cf3461999..18b5ad8c7d5f 100644 > +++ b/drivers/infiniband/core/cma.c > @@ -2827,22 +2827,63 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv) > return 0; > } > > -static int iboe_tos_to_sl(struct net_device *ndev, int tos) > +static int get_vlan_ndev_tc(struct net_device *vlan_ndev, int prio) > { > - int prio; > struct net_device *dev; > > - prio = rt_tos2priority(tos); > - dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev; > + dev = vlan_dev_real_dev(vlan_ndev); > if (dev->num_tc) > return netdev_get_prio_tc_map(dev, prio); > > -#if IS_ENABLED(CONFIG_VLAN_8021Q) > + return (vlan_dev_get_egress_qos_mask(vlan_ndev, prio) & > + VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; > +} > + > +struct iboe_prio_tc_map { > + int input_prio; > + int output_tc; > + bool found; > +}; > + > +static int get_lower_vlan_dev_tc(struct net_device *dev, void *data) > +{ > + struct iboe_prio_tc_map *map = data; > + > + if (is_vlan_dev(dev)) > + map->output_tc = get_vlan_ndev_tc(dev, map->input_prio); > + else if (dev->num_tc) > + map->output_tc = netdev_get_prio_tc_map(dev, map->input_prio); > + else > + map->output_tc = 0; > + /* We are interested only in first level VLAN device, so always > + * return 1 to stop iterating over next level devices. > + */ > + map->found = true; > + return 1; > +} > + > +static int iboe_tos_to_sl(struct net_device *ndev, int tos) > +{ > + struct iboe_prio_tc_map prio_tc_map = {}; > + int prio = rt_tos2priority(tos); > + > + /* If VLAN device, get it directly from the VLAN netdev */ > if (is_vlan_dev(ndev)) > - return (vlan_dev_get_egress_qos_mask(ndev, prio) & > - VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; > -#endif > - return 0; > + return get_vlan_ndev_tc(ndev, prio); > + > + prio_tc_map.input_prio = prio; > + netdev_walk_all_lower_dev_rcu(ndev, > + get_lower_vlan_dev_tc, > + &prio_tc_map); Kinda looks like you have to hold rcu before calling this? Jason