wifi: mt76: use atomic iface iteration for pre-TBTT work
authorJohannes Berg <johannes.berg@intel.com>
Mon, 28 Aug 2023 15:18:31 +0000 (17:18 +0200)
committerFelix Fietkau <nbd@nbd.name>
Sat, 30 Sep 2023 18:03:03 +0000 (20:03 +0200)
In addition to the previous series I posted, over time I'd
also like to get rid of the iflist_mtx in mac80211. That
isn't easy now since lots of places use iteration and would
have to be audited, but even a cursory look suggests that
mt76 might be more problematic than most since holding the
wiphy lock for the latency-sensitive pre-TBTT work could be
an issue.

Convert the pre-TBTT work to use atomic iteration and then
sending the device commands outside of it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c

index ad4dc8e17b58e5cdce266ade0f96e65aa31db398..d570b99bccb90cb9584df21f0c7e9192006f091f 100644 (file)
@@ -136,7 +136,8 @@ EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer);
 void
 mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 {
-       struct mt76x02_dev *dev = (struct mt76x02_dev *)priv;
+       struct beacon_bc_data *data = priv;
+       struct mt76x02_dev *dev = data->dev;
        struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
        struct sk_buff *skb = NULL;
 
@@ -147,7 +148,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
        if (!skb)
                return;
 
-       mt76x02_mac_set_beacon(dev, skb);
+       __skb_queue_tail(&data->q, skb);
 }
 EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter);
 
@@ -182,9 +183,6 @@ mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev,
 {
        int i, nframes;
 
-       data->dev = dev;
-       __skb_queue_head_init(&data->q);
-
        do {
                nframes = skb_queue_len(&data->q);
                ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
index e9c5e85ec07c212c5f4f1b7803f8534162c6408f..9b5e3fb7b0dfe43f69a304f3fea4ddc60c9f0755 100644 (file)
@@ -16,13 +16,17 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
        struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet);
        struct mt76_dev *mdev = &dev->mt76;
        struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD];
-       struct beacon_bc_data data = {};
+       struct beacon_bc_data data = {
+               .dev = dev,
+       };
        struct sk_buff *skb;
        int i;
 
        if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
                return;
 
+       __skb_queue_head_init(&data.q);
+
        mt76x02_resync_beacon_timer(dev);
 
        /* Prevent corrupt transmissions during update */
@@ -31,7 +35,10 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
 
        ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
                IEEE80211_IFACE_ITER_RESUME_ALL,
-               mt76x02_update_beacon_iter, dev);
+               mt76x02_update_beacon_iter, &data);
+
+       while ((skb = __skb_dequeue(&data.q)) != NULL)
+               mt76x02_mac_set_beacon(dev, skb);
 
        mt76_wr(dev, MT_BCN_BYPASS_MASK,
                0xff00 | ~(0xff00 >> dev->beacon_data_count));
index 2c6c03809b20eb628b99a22bb851ff07f14be2a6..85a78dea4085f47cbb11d0db68ef3c12b5c8aadf 100644 (file)
@@ -182,7 +182,9 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
 {
        struct mt76x02_dev *dev =
                container_of(work, struct mt76x02_dev, pre_tbtt_work);
-       struct beacon_bc_data data = {};
+       struct beacon_bc_data data = {
+               .dev = dev,
+       };
        struct sk_buff *skb;
        int nbeacons;
 
@@ -192,15 +194,20 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
        if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
                return;
 
+       __skb_queue_head_init(&data.q);
+
        mt76x02_resync_beacon_timer(dev);
 
        /* Prevent corrupt transmissions during update */
        mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff);
        dev->beacon_data_count = 0;
 
-       ieee80211_iterate_active_interfaces(mt76_hw(dev),
+       ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
                IEEE80211_IFACE_ITER_RESUME_ALL,
-               mt76x02_update_beacon_iter, dev);
+               mt76x02_update_beacon_iter, &data);
+
+       while ((skb = __skb_dequeue(&data.q)) != NULL)
+               mt76x02_mac_set_beacon(dev, skb);
 
        mt76_csa_check(&dev->mt76);