Re: [PATCH net v2] bnxt_en: Take RTNL before netif_close() when aborting FW reset
From: Stanislav Fomichev
Date: Tue Nov 03 2026 - 15:10:53 EST
On 11/02, Bryan Cochrane wrote:
> netif_close() must be called with RTNL held in addition to the netdev
> instance lock: __dev_close_many() asserts it, and the NETDEV_GOING_DOWN
> and NETDEV_DOWN notifier chains it runs rely on it for serialization.
>
> Commit 004b5008016a ("eth: bnxt: remove most dependencies on RTNL")
> replaced rtnl_lock() with netdev_lock() in bnxt_fw_reset_task() and
> bnxt_fw_reset(). That is sufficient for the paths that only tear the
> NIC down internally with __bnxt_close_nic(), but the abort paths close
> the netdev via bnxt_fw_reset_abort() -> netif_close(), and the error
> path in bnxt_fw_reset() calls netif_close() directly. Those now run
> without RTNL and trigger a WARN_ONCE() cascade when a firmware reset is
> aborted:
>
> RTNL: assertion failed at net/core/dev.c (1740)
> WARNING: net/core/dev.c:1740 at __dev_close_many+0x1be/0x1f0
> Workqueue: bnxt_pf_wq bnxt_fw_reset_task [bnxt_en]
> Call Trace:
> netif_close_many+0xb5/0x190
> netif_close+0xa2/0xd0
> bnxt_fw_reset_task.cold+0x8d/0x213 [bnxt_en]
> process_one_work+0x19d/0x3a0
> worker_thread+0x1af/0x320
> kthread+0xe3/0x120
>
> followed by the same assertion from call_netdevice_notifiers_info(),
> fib_rules_event(), inetdev_event(), rtnl_fill_ifinfo(),
> devlink_compat_phys_port_name_get() and ip_mc_down().
>
> This was observed on a machine in real use with a BCM57504 (4 PFs,
> FW 236.1.153.0) running v7.1.6: the firmware crashed, announced a
> "Fatal firmware reset event" and then failed to come back within the
> advertised max wait, so bnxt_fw_reset_task() aborted the reset on all
> ports:
>
> bnxt_en 0000:c1:00.1 eno16905np1: Firmware reset aborted
> bnxt_en 0000:c1:00.1 eno16905np1: fw_health_status 0x448100
>
> Take RTNL (before the netdev instance lock, matching the OPENING state
> which already uses rtnl_trylock()) in the fw_reset_abort path of
> bnxt_fw_reset_task() and route the POLL_VF abort through that same
> path.
>
> In bnxt_fw_reset() only the error path that closes the device after
> bnxt_get_registered_vfs() fails needs RTNL: drop the instance lock,
> take RTNL and the instance lock, then clear BNXT_STATE_IN_FW_RESET and
> close. The normal reset flow, which may run on many VFs at the same
> time, keeps running without RTNL. BNXT_STATE_IN_FW_RESET stays set
> across the lock switch, so a concurrent close marks the reset aborted
> as it does today and a concurrent recovery request backs off.
>
> The bug was found by inspecting the kernel log of the affected machine
> and the driver source; the fix was prepared with the help of an AI
> coding assistant (Gemini based) and reviewed by the submitter. It is
> build tested (allmodconfig with W=1, plus the same change on top of
> v7.1.6 built as a module for the affected BCM57504 host). The aborted
> reset path itself only runs when the firmware fails to return from a
> reset, which could not be reproduced on demand.
>
> Fixes: 004b5008016a ("eth: bnxt: remove most dependencies on RTNL")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Bryan Cochrane <bcochrane@xxxxxxxxxx>
> ---
> v2:
> - Keep bnxt_lock_sp() in bnxt_fw_reset() and take RTNL only on the
> bnxt_get_registered_vfs() error path, so that the normal FW reset
> flow does not add RTNL contention when many VFs recover at the same
> time (Michael Chan).
> - Dropped Stanislav's Acked-by because of the change above.
Acked-by: Stanislav Fomichev <sdf@xxxxxxxxxxx>