[PATCH iwl-next] eth: i40e: sync MAC filters before restarting queues after a reset
From: Jakub Kicinski <kuba@kernel.org>
Date: 2026-09-08 18:32:17
Subsystem:
intel ethernet drivers, networking drivers, the rest · Maintainers:
Tony Nguyen, Przemek Kitszel, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
A PF reset clears the VSI's MAC/VLAN filter table. i40e_add_vsi() only
re-marks the software filters as I40E_FILTER_NEW and lets async
i40e_sync_filters_subtask() in the service task program them.
That works for resets driven by the service task, which reruns
i40e_sync_filters_subtask() right after i40e_reset_subtask(). Synchronous
callers - i40e_xdp_setup(), the ethtool private flag and ring paths,
i40e_setup_tc() - return to user space with the rings running and
the carrier up, but no unicast filter and no broadcast promiscuous bit,
so the interface drops all Rx.
i40e_rebuild() does reach i40e_service_event_schedule():
i40e_rebuild()
└─ i40e_pf_unquiesce_all_vsi(pf) (for each VSI on the PF)
└─ i40e_unquiesce_vsi(vsi) (only if __I40E_VSI_NEEDS_RESTART set)
└─ ndo_open(vsi->netdev) (netdev && netif_running())
└─ i40e_open()
└─ i40e_vsi_open()
└─ i40e_up_complete()
└─ i40e_service_event_schedule()
but __I40E_RESET_RECOVERY_PENDING is still set at that point,
which makes it a noop, so the filters are restored during next
periodic run (1 sec later).
This causes ~20% failure rate in XDP sub-tests in NIPA (meaning
that the full test is almost never fully clean). After the fix
I run the test 6 times in a row without a failure.
Push the main VSI's filters to the HW before the queues restart, and kick
the service task once the reset state is clear to pick up what the
rebuild deferred.
No Fixes tag, this only matters to workloads which reconfigure the device
and immediately expect traffic, i.e. CI rather than anything real.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: anthony.l.nguyen@intel.com
CC: przemyslaw.kitszel@intel.com
CC: john.fastabend@gmail.com
CC: sdf@fomichev.me
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index abbc71e815ae..9215bcaecc4b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c@@ -11084,6 +11084,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, pf->main_vsi_seid); + /* Reprogram the filters the reset cleared before the queues start. + * Avoid the wait for the service task, best effort. + */ + i40e_sync_vsi_filters(vsi); + /* restart the VSIs that were rebuilt and running before the reset */ i40e_pf_unquiesce_all_vsi(pf);
@@ -11115,6 +11120,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) clear_recovery: clear_bit(__I40E_RESET_RECOVERY_PENDING, pf->state); clear_bit(__I40E_TIMEOUT_RECOVERY_PENDING, pf->state); + + /* i40e_service_event_schedule() may have been called with + * the RESET bits still set, requeue now that we cleared them. + */ + i40e_service_event_schedule(pf); } /**
--
2.55.0