Commit a40612f3 authored by Miquel Raynal's avatar Miquel Raynal Committed by Stefan Schmidt

net: mac802154: Introduce a helper to disable the queue

Sometimes calling the stop queue helper is not enough because it does
not hold any lock. In order to be safe and avoid racy situations when
trying to (soon) sync the Tx queue, for instance before sending an MLME
frame, let's now introduce an helper which actually hold the necessary
locks when doing so.
Suggested-by: default avatarAlexander Aring <alex.aring@gmail.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Acked-by: default avatarAlexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/r/20220519150516.443078-8-miquel.raynal@bootlin.comSigned-off-by: default avatarStefan Schmidt <stefan@datenfreihafen.org>
parent 226730e1
...@@ -149,6 +149,18 @@ void ieee802154_hold_queue(struct ieee802154_local *local); ...@@ -149,6 +149,18 @@ void ieee802154_hold_queue(struct ieee802154_local *local);
*/ */
void ieee802154_release_queue(struct ieee802154_local *local); void ieee802154_release_queue(struct ieee802154_local *local);
/**
* ieee802154_disable_queue - disable ieee802154 queue
* @local: main mac object
*
* When trying to sync the Tx queue, we cannot just stop the queue
* (which is basically a bit being set without proper lock handling)
* because it would be racy. We actually need to call netif_tx_disable()
* instead, which is done by this helper. Restarting the queue can
* however still be done with a regular wake call.
*/
void ieee802154_disable_queue(struct ieee802154_local *local);
/* MIB callbacks */ /* MIB callbacks */
void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
......
...@@ -83,6 +83,20 @@ void ieee802154_release_queue(struct ieee802154_local *local) ...@@ -83,6 +83,20 @@ void ieee802154_release_queue(struct ieee802154_local *local)
spin_unlock_irqrestore(&local->phy->queue_lock, flags); spin_unlock_irqrestore(&local->phy->queue_lock, flags);
} }
void ieee802154_disable_queue(struct ieee802154_local *local)
{
struct ieee802154_sub_if_data *sdata;
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!sdata->dev)
continue;
netif_tx_disable(sdata->dev);
}
rcu_read_unlock();
}
enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer) enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
{ {
struct ieee802154_local *local = struct ieee802154_local *local =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment