mt76: add channel switch announcement support
authorFelix Fietkau <nbd@nbd.name>
Tue, 15 Jan 2019 13:26:53 +0000 (14:26 +0100)
committerFelix Fietkau <nbd@nbd.name>
Thu, 17 Jan 2019 13:50:15 +0000 (14:50 +0100)
Use the appropriate mac80211 callbacks after beacon transmission

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
drivers/net/wireless/mediatek/mt76/mt76x02_util.c

index 3b09d4560ae2a692c0e7da8327f8978efe648f62..ee3b65a14870ce742ba559d5e83f9475418b989e 100644 (file)
@@ -734,3 +734,42 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        return 0;
 }
 EXPORT_SYMBOL_GPL(mt76_get_txpower);
+
+static void
+__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+       if (vif->csa_active && ieee80211_csa_is_complete(vif))
+           ieee80211_csa_finish(vif);
+}
+
+void mt76_csa_finish(struct mt76_dev *dev)
+{
+       if (!dev->csa_complete)
+               return;
+
+       ieee80211_iterate_active_interfaces_atomic(dev->hw,
+               IEEE80211_IFACE_ITER_RESUME_ALL,
+               __mt76_csa_finish, dev);
+
+       dev->csa_complete = 0;
+}
+EXPORT_SYMBOL_GPL(mt76_csa_finish);
+
+static void
+__mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct mt76_dev *dev = priv;
+
+       if (!vif->csa_active)
+               return;
+
+       dev->csa_complete |= ieee80211_csa_is_complete(vif);
+}
+
+void mt76_csa_check(struct mt76_dev *dev)
+{
+       ieee80211_iterate_active_interfaces_atomic(dev->hw,
+               IEEE80211_IFACE_ITER_RESUME_ALL,
+               __mt76_csa_check, dev);
+}
+EXPORT_SYMBOL_GPL(mt76_csa_check);
index 0435d623e9ad888cf8f477eef9b64ef6b1337585..2bb9db4ed80a9ab96068c9397ef2e77dd4fafa36 100644 (file)
@@ -463,6 +463,8 @@ struct mt76_dev {
        bool led_al;
        u8 led_pin;
 
+       u8 csa_complete;
+
        u32 rxfilter;
 
        union {
@@ -691,6 +693,9 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev);
 int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                     int *dbm);
 
+void mt76_csa_check(struct mt76_dev *dev);
+void mt76_csa_finish(struct mt76_dev *dev);
+
 /* internal */
 void mt76_tx_free(struct mt76_dev *dev);
 struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
index 6236c6121c01cd1588a9edbb14943067b7b600a9..374bc9d91f12f5561c13c44b0f9e31757d8f9d20 100644 (file)
@@ -116,6 +116,11 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
                IEEE80211_IFACE_ITER_RESUME_ALL,
                mt76x02_update_beacon_iter, dev);
 
+       mt76_csa_check(&dev->mt76);
+
+       if (dev->mt76.csa_complete)
+               return;
+
        do {
                nframes = skb_queue_len(&data.q);
                ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
@@ -309,8 +314,12 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
                tasklet_schedule(&dev->pre_tbtt_tasklet);
 
        /* send buffered multicast frames now */
-       if (intr & MT_INT_TBTT)
-               mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
+       if (intr & MT_INT_TBTT) {
+               if (dev->mt76.csa_complete)
+                       mt76_csa_finish(&dev->mt76);
+               else
+                       mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]);
+       }
 
        if (intr & MT_INT_TX_STAT) {
                mt76x02_mac_poll_tx_status(dev, true);
index 0bd23d64db24aa8a6c8e9156cb903eb9dcd4bece..062614ad0d51ceffcb98504853f8c452c253678d 100644 (file)
@@ -160,6 +160,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
 #endif
                        BIT(NL80211_IFTYPE_ADHOC);
 
+               wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
                wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
 
                /* init led callbacks */