Skip to content

Commit bbcbe4e

Browse files
orospPaolo Abeni
authored andcommitted
iavf: wait for PF confirmation before removing VLAN filters
The VLAN filter DELETE path was asymmetric with the ADD path: ADD waits for PF confirmation (ADD -> ADDING -> ACTIVE), but DELETE immediately frees the filter struct after sending the DEL message without waiting for the PF response. This is problematic because: - If the PF rejects the DEL, the filter remains in HW but the driver has already freed the tracking structure, losing sync. - Race conditions between DEL pending and other operations (add, reset) cannot be properly resolved if the filter struct is already gone. Add IAVF_VLAN_REMOVING state to make the DELETE path symmetric: REMOVE -> REMOVING (send DEL) -> PF confirms -> kfree -> PF rejects -> ACTIVE In iavf_del_vlans(), transition filters from REMOVE to REMOVING instead of immediately freeing them. The new DEL completion handler in iavf_virtchnl_completion() frees filters on success or reverts them to ACTIVE on error. Update iavf_add_vlan() to handle the REMOVING state: if a DEL is pending and the user re-adds the same VLAN, queue it for ADD so it gets re-programmed after the PF processes the DEL. The !VLAN_FILTERING_ALLOWED early-exit path still frees filters directly since no PF message is sent in that case. Also update iavf_del_vlan() to skip filters already in REMOVING state: DEL has been sent to PF and the completion handler will free the filter when PF confirms. Without this guard, the sequence DEL(pending) -> user-del -> second DEL could cause the PF to return an error for the second DEL (filter already gone), causing the completion handler to incorrectly revert a deleted filter back to ACTIVE. Fixes: 968996c ("iavf: Fix VLAN_V2 addition/rejection") Signed-off-by: Petr Oros <poros@redhat.com> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20260427-jk-iwl-net-petr-oros-fixes-v1-3-cdcb48303fd8@intel.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent f2ce65b commit bbcbe4e

3 files changed

Lines changed: 34 additions & 17 deletions

File tree

drivers/net/ethernet/intel/iavf/iavf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ enum iavf_vlan_state_t {
161161
IAVF_VLAN_ADDING, /* ADD sent to PF, waiting for response */
162162
IAVF_VLAN_ACTIVE, /* PF confirmed, filter is in HW */
163163
IAVF_VLAN_REMOVE, /* filter queued for DEL from PF */
164+
IAVF_VLAN_REMOVING, /* DEL sent to PF, waiting for response */
164165
};
165166

166167
struct iavf_vlan_filter {

drivers/net/ethernet/intel/iavf/iavf_main.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,10 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
757757
adapter->num_vlan_filters++;
758758
iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER);
759759
} else if (f->state == IAVF_VLAN_REMOVE) {
760-
/* Re-add the filter since we cannot tell whether the
761-
* pending delete has already been processed by the PF.
762-
* A duplicate add is harmless.
763-
*/
760+
/* DEL not yet sent to PF, cancel it */
761+
f->state = IAVF_VLAN_ACTIVE;
762+
} else if (f->state == IAVF_VLAN_REMOVING) {
763+
/* DEL already sent to PF, re-add after completion */
764764
f->state = IAVF_VLAN_ADD;
765765
iavf_schedule_aq_request(adapter,
766766
IAVF_FLAG_AQ_ADD_VLAN_FILTER);
@@ -791,11 +791,14 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)
791791
list_del(&f->list);
792792
kfree(f);
793793
adapter->num_vlan_filters--;
794-
} else {
794+
} else if (f->state != IAVF_VLAN_REMOVING) {
795795
f->state = IAVF_VLAN_REMOVE;
796796
iavf_schedule_aq_request(adapter,
797797
IAVF_FLAG_AQ_DEL_VLAN_FILTER);
798798
}
799+
/* If REMOVING, DEL is already sent to PF; completion
800+
* handler will free the filter when PF confirms.
801+
*/
799802
}
800803

801804
spin_unlock_bh(&adapter->mac_vlan_list_lock);

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -948,12 +948,10 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
948948

949949
vvfl->vsi_id = adapter->vsi_res->vsi_id;
950950
vvfl->num_elements = count;
951-
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
951+
list_for_each_entry(f, &adapter->vlan_filter_list, list) {
952952
if (f->state == IAVF_VLAN_REMOVE) {
953953
vvfl->vlan_id[i] = f->vlan.vid;
954-
list_del(&f->list);
955-
kfree(f);
956-
adapter->num_vlan_filters--;
954+
f->state = IAVF_VLAN_REMOVING;
957955
i++;
958956
if (i == count)
959957
break;
@@ -990,7 +988,7 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
990988

991989
vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
992990
vvfl_v2->num_elements = count;
993-
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
991+
list_for_each_entry(f, &adapter->vlan_filter_list, list) {
994992
if (f->state == IAVF_VLAN_REMOVE) {
995993
struct virtchnl_vlan_supported_caps *filtering_support =
996994
&adapter->vlan_v2_caps.filtering.filtering_support;
@@ -1005,9 +1003,7 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
10051003
vlan->tci = f->vlan.vid;
10061004
vlan->tpid = f->vlan.tpid;
10071005

1008-
list_del(&f->list);
1009-
kfree(f);
1010-
adapter->num_vlan_filters--;
1006+
f->state = IAVF_VLAN_REMOVING;
10111007
i++;
10121008
if (i == count)
10131009
break;
@@ -2370,10 +2366,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
23702366
ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
23712367
wake_up(&adapter->vc_waitqueue);
23722368
break;
2373-
case VIRTCHNL_OP_DEL_VLAN:
2374-
dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
2375-
iavf_stat_str(&adapter->hw, v_retval));
2376-
break;
23772369
case VIRTCHNL_OP_DEL_ETH_ADDR:
23782370
dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
23792371
iavf_stat_str(&adapter->hw, v_retval));
@@ -2895,6 +2887,27 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
28952887
spin_unlock_bh(&adapter->mac_vlan_list_lock);
28962888
}
28972889
break;
2890+
case VIRTCHNL_OP_DEL_VLAN:
2891+
case VIRTCHNL_OP_DEL_VLAN_V2: {
2892+
struct iavf_vlan_filter *f, *ftmp;
2893+
2894+
spin_lock_bh(&adapter->mac_vlan_list_lock);
2895+
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list,
2896+
list) {
2897+
if (f->state == IAVF_VLAN_REMOVING) {
2898+
if (v_retval) {
2899+
/* PF rejected DEL, keep filter */
2900+
f->state = IAVF_VLAN_ACTIVE;
2901+
} else {
2902+
list_del(&f->list);
2903+
kfree(f);
2904+
adapter->num_vlan_filters--;
2905+
}
2906+
}
2907+
}
2908+
spin_unlock_bh(&adapter->mac_vlan_list_lock);
2909+
}
2910+
break;
28982911
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
28992912
/* PF enabled vlan strip on this VF.
29002913
* Update netdev->features if needed to be in sync with ethtool.

0 commit comments

Comments
 (0)