[PATCH v2] net: mac802154: fix race between slave_close() and in-flight async tx

From: Adi Prasan

Date: Fri Oct 02 2026 - 10:48:51 EST


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 <itsadi2409@xxxxxxxxx>
---
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