Commit debd133a authored by Johannes Berg's avatar Johannes Berg Committed by Felix Fietkau

wifi: mt76: use atomic iface iteration for pre-TBTT work

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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent c2fcc83b
......@@ -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),
......
......@@ -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));
......
......@@ -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);
......
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