diff mbox series

[wpan-next,v2,10/11] net: mac802154: Introduce a global device lock

Message ID 20220826144049.256134-11-miquel.raynal@bootlin.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series net: ieee802154: Support scanning/beaconing | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Miquel Raynal Aug. 26, 2022, 2:40 p.m. UTC
The purpose of this device lock is to prevent the removal of the device
while an asynchronous MLME operation happens. The RTNL works well for
that but in a later series having the RTNL taken here will be
problematic and will cause lockdep to warn us about a circular
dependency. We don't really need the RTNL here, just a serialization
over this operation.

Replace the RTNL calls with this new lock.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/ieee802154_i.h |  2 ++
 net/mac802154/iface.c        |  4 ++++
 net/mac802154/main.c         |  1 +
 net/mac802154/tx.c           | 12 ++++++------
 4 files changed, 13 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 010365a6364e..b8775bcc9003 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -29,7 +29,9 @@  struct ieee802154_local {
 	/* ieee802154 phy */
 	struct wpan_phy *phy;
 
+	/* Open/close counter and lock */
 	int open_count;
+	struct mutex device_lock;
 
 	/* As in mac80211 slaves list is modified:
 	 * 1) under the RTNL
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 8467a629e21f..29af3f80b4d0 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -315,11 +315,15 @@  static int mac802154_slave_close(struct net_device *dev)
 
 	ASSERT_RTNL();
 
+	mutex_lock(&local->device_lock);
+
 	netif_stop_queue(dev);
 	local->open_count--;
 
 	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
+	mutex_unlock(&local->device_lock);
+
 	if (!local->open_count)
 		ieee802154_stop_device(local);
 
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 95100df6489a..7657fb46c9e1 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -90,6 +90,7 @@  ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_LIST_HEAD(&local->interfaces);
 	mutex_init(&local->iflist_mtx);
+	mutex_init(&local->device_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 9d8d43cf1e64..fb555797f326 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -143,14 +143,14 @@  int ieee802154_mlme_tx(struct ieee802154_local *local,
 {
 	int ret;
 
-	/* Avoid possible calls to ->ndo_stop() when we asynchronously perform
-	 * MLME transmissions.
+	/* Serialize possible calls to ->ndo_stop() when we asynchronously
+	 * perform MLME transmissions.
 	 */
-	rtnl_lock();
+	mutex_lock(&local->device_lock);
 
 	/* Ensure the device was not stopped, otherwise error out */
 	if (!local->open_count) {
-		rtnl_unlock();
+		mutex_unlock(&local->device_lock);
 		return -ENETDOWN;
 	}
 
@@ -158,14 +158,14 @@  int ieee802154_mlme_tx(struct ieee802154_local *local,
 	 * net interface expects this cannot happen.
 	 */
 	if (WARN_ON_ONCE(!netif_running(sdata->dev))) {
-		rtnl_unlock();
+		mutex_unlock(&local->device_lock);
 		return -ENETDOWN;
 	}
 
 	ieee802154_tx(local, skb);
 	ret = ieee802154_sync_queue(local);
 
-	rtnl_unlock();
+	mutex_unlock(&local->device_lock);
 
 	return ret;
 }