netif_stop_queue() prevents new packets from being sent to the driver, but it does not wait for a transmission that is already in progress.
drv_xmit_async() can still be running on another CPU when mac802154_slave_close() calls drv_stop(). Stopping the queue only prevents new transmissions; it does not synchronize with an already running tx operation. This was checked against mac802154_hwsim as well. hwsim_hw_xmit() is synchronous, while hwsim_hw_stop() only sets a flag, so there is no pending work or locking in the driver that needs to be synchronized. The race is in the core between stopping the queue and an in-flight tx operation. The fix therefore belongs in the common mac802154 code, using the same handling already used by ieee802154_suspend(): hold and synchronize the queue around ieee802154_stop_device(). Signed-off-by: Adi Prasan <[email protected]> --- v2: Dropped the explanatory code comment per review feedback; expanded the commit message to explain why the fix stays in net/mac802154/iface.c rather than mac802154_hwsim. Fixed the Author/Signed-off-by name. net/mac802154/iface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 31353795fa24..929ccd464772 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -313,8 +313,12 @@ static int mac802154_slave_close(struct net_device *dev) clear_bit(SDATA_STATE_RUNNING, &sdata->state); - if (!local->open_count) + if (!local->open_count) { + ieee802154_sync_and_hold_queue(local); + synchronize_net(); ieee802154_stop_device(local); + ieee802154_release_queue(local); + } return 0; } -- 2.43.0

