| From aa92afb8a1f6ade6b78711eefca24cb9e66aec4a Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 7 Sep 2023 17:44:57 +0200 |
| Subject: i40e: Fix VF VLAN offloading when port VLAN is configured |
| |
| From: Ivan Vecera <ivecera@redhat.com> |
| |
| [ Upstream commit d0d362ffa33da4acdcf7aee2116ceef8c8fef658 ] |
| |
| If port VLAN is configured on a VF then any other VLANs on top of this VF |
| are broken. |
| |
| During i40e_ndo_set_vf_port_vlan() call the i40e driver reset the VF and |
| iavf driver asks PF (using VIRTCHNL_OP_GET_VF_RESOURCES) for VF capabilities |
| but this reset occurs too early, prior setting of vf->info.pvid field |
| and because this field can be zero during i40e_vc_get_vf_resources_msg() |
| then VIRTCHNL_VF_OFFLOAD_VLAN capability is reported to iavf driver. |
| |
| This is wrong because iavf driver should not report VLAN offloading |
| capability when port VLAN is configured as i40e does not support QinQ |
| offloading. |
| |
| Fix the issue by moving VF reset after setting of vf->port_vlan_id |
| field. |
| |
| Without this patch: |
| $ echo 1 > /sys/class/net/enp2s0f0/device/sriov_numvfs |
| $ ip link set enp2s0f0 vf 0 vlan 3 |
| $ ip link set enp2s0f0v0 up |
| $ ip link add link enp2s0f0v0 name vlan4 type vlan id 4 |
| $ ip link set vlan4 up |
| ... |
| $ ethtool -k enp2s0f0v0 | grep vlan-offload |
| rx-vlan-offload: on |
| tx-vlan-offload: on |
| $ dmesg -l err | grep iavf |
| [1292500.742914] iavf 0000:02:02.0: Failed to add VLAN filter, error IAVF_ERR_INVALID_QP_ID |
| |
| With this patch: |
| $ echo 1 > /sys/class/net/enp2s0f0/device/sriov_numvfs |
| $ ip link set enp2s0f0 vf 0 vlan 3 |
| $ ip link set enp2s0f0v0 up |
| $ ip link add link enp2s0f0v0 name vlan4 type vlan id 4 |
| $ ip link set vlan4 up |
| ... |
| $ ethtool -k enp2s0f0v0 | grep vlan-offload |
| rx-vlan-offload: off [requested on] |
| tx-vlan-offload: off [requested on] |
| $ dmesg -l err | grep iavf |
| |
| Fixes: f9b4b6278d51 ("i40e: Reset the VF upon conflicting VLAN configuration") |
| Signed-off-by: Ivan Vecera <ivecera@redhat.com> |
| Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com> |
| Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> |
| Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |
| index cb7cf672f6971..547e67d9470b7 100644 |
| --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |
| +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |
| @@ -4397,9 +4397,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, |
| goto error_pvid; |
| |
| i40e_vlan_stripping_enable(vsi); |
| - i40e_vc_reset_vf(vf, true); |
| - /* During reset the VF got a new VSI, so refresh a pointer. */ |
| - vsi = pf->vsi[vf->lan_vsi_idx]; |
| + |
| /* Locked once because multiple functions below iterate list */ |
| spin_lock_bh(&vsi->mac_filter_hash_lock); |
| |
| @@ -4485,6 +4483,10 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, |
| */ |
| vf->port_vlan_id = le16_to_cpu(vsi->info.pvid); |
| |
| + i40e_vc_reset_vf(vf, true); |
| + /* During reset the VF got a new VSI, so refresh a pointer. */ |
| + vsi = pf->vsi[vf->lan_vsi_idx]; |
| + |
| ret = i40e_config_vf_promiscuous_mode(vf, vsi->id, allmulti, alluni); |
| if (ret) { |
| dev_err(&pf->pdev->dev, "Unable to config vf promiscuous mode\n"); |
| -- |
| 2.40.1 |
| |