From: Alexander Duyck The fbnic_fw_config_after_crash function resets the MACDA and action TCAM shadows and rewrites them through the __fbnic_set_rx_mode function from the service task, holding RTNL only. fbnic is ops-locked, so since the netdev workqueue moved from RTNL to the ops-compat lock the core calls the fbnic_set_rx_mode function from it holding only the instance lock. The two do not exclude each other. Both sides can then allocate MACDA entries at the same time, one can zero an entry the other is still filling in, and one can clear hardware entries the other has just written. The crash path also syncs the live address lists while the netif_rx_mode_run function works on a snapshot of them, so the reconcile that follows can count the same delta twice and leave an address that is never unsynced. Hold the instance lock across the restore, as the fbnic_bmc_rpc_check function does. The netif_rx_mode_run function holds it from snapshot through reconcile, so the crash path now syncs either before the snapshot or after the reconcile. Fixes: 5a81c72ef9ad ("net: run netdev work under the ops-compat lock") Signed-off-by: Alexander Duyck --- drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c index ad234bb0f75d..09eeb4b4ded8 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c @@ -181,10 +181,15 @@ static int fbnic_fw_config_after_crash(struct fbnic_dev *fbd) return -1; } + /* The rx mode work rewrites the same shadow under the instance lock + * alone, and this runs from the service task under RTNL only. + */ + netdev_lock(fbd->netdev); fbnic_rpc_reset_valid_entries(fbd); netif_addr_lock_bh(fbd->netdev); __fbnic_set_rx_mode(fbd, &fbd->netdev->uc, &fbd->netdev->mc); netif_addr_unlock_bh(fbd->netdev); + netdev_unlock(fbd->netdev); return 0; }