# devlink dev eswitch set pci/0000:05:00.0 mode switchdev # echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs # ip l show 297: enp5s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop portid 6805ca2e7268 state DOWN mode DEFAULT group default qlen 1000 link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off 299: enp5s0f0-vf0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 300: enp5s0f0-vf1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff static int i40e_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode) { struct i40e_pf *pf = devlink_priv(devlink); int err = 0; struct i40e_vf *vf; int i, j, err = 0; if (mode == pf->eswitch_mode) goto done; switch (mode) { case DEVLINK_ESWITCH_MODE_LEGACY: for (i = 0; i < pf->num_alloc_vfs; i++) { vf = &(pf->vf[i]); i40e_free_vfpr_netdev(vf); } pf->eswitch_mode = mode; break; case DEVLINK_ESWITCH_MODE_SWITCHDEV: for (i = 0; i < pf->num_alloc_vfs; i++) { vf = &(pf->vf[i]); err = i40e_alloc_vfpr_netdev(vf, i); if (err) { for (j = 0; j < i; j++) { vf = &(pf->vf[j]); i40e_free_vfpr_netdev(vf); } goto done; } } pf->eswitch_mode = mode; break; } int i40e_alloc_vfpr_netdev(struct i40e_vf *vf, u16 vf_num) { struct net_device *vfpr_netdev; char netdev_name[IFNAMSIZ]; struct i40e_vfpr_netdev_priv *priv; struct i40e_pf *pf = vf->pf; struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; int err; snprintf(netdev_name, IFNAMSIZ, "%s-vf%d", vsi->netdev->name, vf_num); vfpr_netdev = alloc_netdev(sizeof(struct i40e_vfpr_netdev_priv), netdev_name, NET_NAME_UNKNOWN, ether_setup); if (!vfpr_netdev) { dev_err(&pf->pdev->dev, "alloc_netdev failed for vf:%d ", vf_num); return -ENOMEM; } pf->vf[vf_num].vfpr_netdev = vfpr_netdev; priv = netdev_priv(vfpr_netdev); priv->vf = &(pf->vf[vf_num]); vfpr_netdev->netdev_ops = &i40e_vfpr_netdev_ops; netif_carrier_off(vfpr_netdev); netif_tx_disable(vfpr_netdev); err = register_netdev(vfpr_netdev); if (err) { dev_err(&pf->pdev->dev, "register_netdev failed for vf: %s ", vf->vfpr_netdev->name); free_netdev(vfpr_netdev); return err; } dev_info(&pf->pdev->dev, "VF Port representor(%s) created for VF %d ", vf->vfpr_netdev->name, vf_num); /* Delete broadcast filter for VF */ i40e_update_vf_broadcast_filter(vf, false); return 0; }
struct mlx5_eswitch_rep_ops { int (*load)(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep); void (*unload)(struct mlx5_eswitch_rep *rep); void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep); }; struct mlx5_eswitch_rep_data { void *priv; atomic_t state; }; struct mlx5_eswitch_rep { struct mlx5_eswitch_rep_data rep_data[NUM_REP_TYPES]; u16 vport; u16 vlan; /* Only IB rep is using vport_index */ u16 vport_index; u32 vlan_refcount; }; static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep) { struct mlx5e_rep_priv *rpriv; rpriv = mlx5e_rep_to_rep_priv(rep); return rpriv->netdev; } static inline struct mlx5e_rep_priv *mlx5e_rep_to_rep_priv(struct mlx5_eswitch_rep *rep) { return rep->rep_data[REP_ETH].priv; } /* e-Switch vport representors */ static int mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) { const struct mlx5e_profile *profile; struct mlx5e_rep_priv *rpriv; struct net_device *netdev; int nch, err; rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL); if (!rpriv) return -ENOMEM; /* rpriv->rep to be looked up when profile->init() is called */ rpriv->rep = rep; nch = mlx5e_get_max_num_channels(dev); profile = (rep->vport == MLX5_VPORT_UPLINK) ? &mlx5e_uplink_rep_profile : &mlx5e_rep_profile; netdev = mlx5e_create_netdev(dev, profile, nch, rpriv); rpriv->netdev = netdev; rep->rep_data[REP_ETH].priv = rpriv; INIT_LIST_HEAD(&rpriv->vport_sqs_list); if (rep->vport == MLX5_VPORT_UPLINK) { err = mlx5e_create_mdev_resources(dev); if (err) goto err_destroy_netdev; } err = mlx5e_attach_netdev(netdev_priv(netdev)); err = mlx5e_rep_neigh_init(rpriv); err = register_devlink_port(dev, rpriv); err = register_netdev(netdev); }