mt76: mt7615: add csa support
authorLorenzo Bianconi <lorenzo@kernel.org>
Sat, 29 Jun 2019 10:36:10 +0000 (12:36 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 5 Sep 2019 15:42:28 +0000 (17:42 +0200)
Add Channel Switch Announcement support to mt7615 driver updating beacon
template with CSA IE received from mac80211

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7615/init.c
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.h

index 5dc4cced57895ac6773885ea422526d7da6a90f9..095b22671e7193a1b0ffcc4f93b96ed7ad5a9c53 100644 (file)
@@ -257,6 +257,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
        wiphy->iface_combinations = if_comb;
        wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
        wiphy->reg_notifier = mt7615_regd_notifier;
+       wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
        ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
        ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
index cf9be4944cf7e055fedae6e95f7d8b0d420cb332..1ee6dda579a86407e4b1bd9ff39ceb517eab6da7 100644 (file)
@@ -305,6 +305,18 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
        mutex_unlock(&dev->mt76.mutex);
 }
 
+static void
+mt7615_channel_switch_beacon(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif,
+                            struct cfg80211_chan_def *chandef)
+{
+       struct mt7615_dev *dev = hw->priv;
+
+       mutex_lock(&dev->mt76.mutex);
+       mt7615_mcu_set_bcn(dev, vif, true);
+       mutex_unlock(&dev->mt76.mutex);
+}
+
 int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                   struct ieee80211_sta *sta)
 {
@@ -496,4 +508,5 @@ const struct ieee80211_ops mt7615_ops = {
        .sw_scan_complete = mt7615_sw_scan_complete,
        .release_buffered_frames = mt76_release_buffered_frames,
        .get_txpower = mt76_get_txpower,
+       .channel_switch_beacon = mt7615_channel_switch_beacon,
 };
index 397ae4f95db8bad4a1b81767bd39c0c0465ecd1a..951849e4dd09fcd443ca1be7a4b4fa4a9ef05ba6 100644 (file)
@@ -159,6 +159,13 @@ out:
        return ret;
 }
 
+static void
+mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+       if (vif->csa_active)
+               ieee80211_csa_finish(vif);
+}
+
 static void
 mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
 {
@@ -169,6 +176,11 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
                ieee80211_radar_detected(dev->mt76.hw);
                dev->hw_pattern++;
                break;
+       case MCU_EXT_EVENT_CSA_NOTIFY:
+               ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
+                               IEEE80211_IFACE_ITER_RESUME_ALL,
+                               mt7615_mcu_csa_finish, dev);
+               break;
        default:
                break;
        }
@@ -1143,6 +1155,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
 {
        struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
        struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+       struct ieee80211_mutable_offsets offs;
        struct req {
                u8 omac_idx;
                u8 enable;
@@ -1163,13 +1176,10 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
                .enable = en,
                .wlan_idx = wcid->idx,
                .band_idx = mvif->band_idx,
-               /* pky_type: 0 for bcn, 1 for tim */
-               .pkt_type = 0,
        };
        struct sk_buff *skb;
-       u16 tim_off;
 
-       skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, NULL);
+       skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
        if (!skb)
                return -EINVAL;
 
@@ -1183,8 +1193,14 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
                              0, NULL);
        memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
        req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
-       req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off);
+       req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
+       if (offs.csa_counter_offs[0]) {
+               u16 csa_offs;
 
+               csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4;
+               req.csa_ie_pos = cpu_to_le16(csa_offs);
+               req.csa_cnt = skb->data[offs.csa_counter_offs[0]];
+       }
        dev_kfree_skb(skb);
 
        return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD,
index 5fe492189f56fef82a31bba5703a7ea43c2aa115..73ce9fe8bfed86a5dd94f8fd9790e63ea809742b 100644 (file)
@@ -42,6 +42,7 @@ enum {
        MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
        MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
        MCU_EXT_EVENT_RDD_REPORT = 0x3a,
+       MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
 };
 
 struct mt7615_mcu_rxd {