[net PATCH 05/13] fbnic: Don't touch host filters from a service task pass after ndo_stop
flat view
WARM1d
From: Alexander Duyck <hidden>
Date: 2026-10-28 21:36:37
Subsystem:
meta ethernet drivers, networking drivers, the rest · Maintainers:
Alexander Duyck, Jakub Kicinski, Andrew Lunn, "David S. Miller", Eric Dumazet, Paolo Abeni, Linus Torvalds
From: Alexander Duyck <alexanderduyck@fb.com> The fbnic_down_noidle function stops the service task by calling the cancel_delayed_work function, which does not wait for a pass that is already executing. It cannot use the cancel_delayed_work_sync function, as ndo_stop holds RTNL and the task takes RTNL itself. A pass that is blocked on RTNL while ndo_stop runs carries on once ndo_stop returns, and only the re-arm at the end of it checks that the interface is still up. By then the fbnic_down function has demoted the host MACDA and action entries to UPDATE and disabled the host queues, and ndo_stop has handed ownership back to firmware. The fbnic_fw_xmit_ownership_msg function clears fw_heartbeat_enabled when it does, so the fbnic_health_check function reports a firmware crash that did not happen, and the fbnic_fw_config_after_crash function reclaims ownership and writes the host rules back to hardware. If the BMC raised FBNIC_FW_CAP_F_BMC_TCAM_REINIT in that window, the fbnic_bmc_rpc_check function does the same through the __fbnic_set_rx_mode function. In both cases host traffic is steered at queues that are no longer running, until the next open and close. Move both calls to the end of the service task, into the netif_running check that re-arms it. The __dev_close_many function clears __LINK_STATE_START under RTNL before it calls ndo_stop, so the late pass now skips them. The BMC flags stay raised for the first pass after the next open, and the __fbnic_open function reclaims ownership, restarts the heartbeat and rebuilds the BMC rules. Fixes: 04a230b27d8f ("fbnic: Add logic to repopulate RPC TCAM if BMC enables channel") Fixes: 6ae7da8e9e06 ("eth: fbnic: reprogram TCAMs after FW crash") Signed-off-by: Alexander Duyck <alexanderduyck@fb.com> --- drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
index ad234bb0f75d..e7744915d001 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c@@ -229,18 +229,23 @@ static void fbnic_service_task(struct work_struct *work) fbnic_fw_check_heartbeat(fbd); - fbnic_health_check(fbd); - - fbnic_bmc_rpc_check(fbd); - if (netif_carrier_ok(fbd->netdev)) { netdev_lock(fbd->netdev); fbnic_napi_depletion_check(fbd->netdev); netdev_unlock(fbd->netdev); } - if (netif_running(netdev)) + /* fbnic_service_task_stop() does not wait for a pass that is already + * blocked on RTNL, so one can run after ndo_stop. Leave host state + * alone in that case; __fbnic_open() reclaims and rebuilds it. + */ + if (netif_running(netdev)) { + fbnic_health_check(fbd); + + fbnic_bmc_rpc_check(fbd); + schedule_delayed_work(&fbd->service_task, HZ); + } rtnl_unlock(); }