Merge tag 'mt76-for-kvalo-2021-06-18' of https://github.com/nbd168/wireless into...
authorKalle Valo <kvalo@codeaurora.org>
Sat, 19 Jun 2021 08:49:26 +0000 (11:49 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Sat, 19 Jun 2021 08:49:26 +0000 (11:49 +0300)
mt76 patches for 5.14

* mt7915 MSI support
* disable ASPM on mt7915
* mt7915 tx status reporting
* mt7921 decap offload
* driver fixes
* cleanups
* mt7921 runtime power management improvements
* testmode improvements/fixes
* runtime PM improvements

64 files changed:
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/init.c
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
drivers/net/wireless/mediatek/mt76/mt7603/regs.h
drivers/net/wireless/mediatek/mt76/mt7615/Makefile
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7615/dma.c
drivers/net/wireless/mediatek/mt76/mt7615/init.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.h
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
drivers/net/wireless/mediatek/mt76/mt7615/regs.h
drivers/net/wireless/mediatek/mt76/mt7615/sdio.h
drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c
drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
drivers/net/wireless/mediatek/mt76/mt76_connac.h
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
drivers/net/wireless/mediatek/mt76/mt7915/Makefile
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7915/dma.c
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.h
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
drivers/net/wireless/mediatek/mt76/mt7915/pci.c
drivers/net/wireless/mediatek/mt76/mt7915/regs.h
drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
drivers/net/wireless/mediatek/mt76/mt7921/Makefile
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7921/dma.c
drivers/net/wireless/mediatek/mt76/mt7921/init.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.h
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/mediatek/mt76/sdio.c
drivers/net/wireless/mediatek/mt76/testmode.c
drivers/net/wireless/mediatek/mt76/tx.c
drivers/net/wireless/mediatek/mt76/usb.c

index 72b1cc0..5e1c150 100644 (file)
@@ -191,6 +191,7 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
 
        q->entry[idx].txwi = txwi;
        q->entry[idx].skb = skb;
+       q->entry[idx].wcid = 0xffff;
 
        return idx;
 }
@@ -349,6 +350,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
                      struct sk_buff *skb, struct mt76_wcid *wcid,
                      struct ieee80211_sta *sta)
 {
+       struct ieee80211_tx_status status = {
+               .sta = sta,
+       };
        struct mt76_tx_info tx_info = {
                .skb = skb,
        };
@@ -360,11 +364,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
        u8 *txwi;
 
        t = mt76_get_txwi(dev);
-       if (!t) {
-               hw = mt76_tx_status_get_hw(dev, skb);
-               ieee80211_free_txskb(hw, skb);
-               return -ENOMEM;
-       }
+       if (!t)
+               goto free_skb;
+
        txwi = mt76_get_txwi_ptr(dev, t);
 
        skb->prev = skb->next = NULL;
@@ -427,8 +429,13 @@ free:
        }
 #endif
 
-       dev_kfree_skb(tx_info.skb);
        mt76_put_txwi(dev, t);
+
+free_skb:
+       status.skb = tx_info.skb;
+       hw = mt76_tx_status_get_hw(dev, tx_info.skb);
+       ieee80211_tx_status_ext(hw, &status);
+
        return ret;
 }
 
index 03fe628..d03aedc 100644 (file)
@@ -83,6 +83,22 @@ static const struct ieee80211_tpt_blink mt76_tpt_blink[] = {
        { .throughput = 300 * 1024, .blink_time =  50 },
 };
 
+struct ieee80211_rate mt76_rates[] = {
+       CCK_RATE(0, 10),
+       CCK_RATE(1, 20),
+       CCK_RATE(2, 55),
+       CCK_RATE(3, 110),
+       OFDM_RATE(11, 60),
+       OFDM_RATE(15, 90),
+       OFDM_RATE(10, 120),
+       OFDM_RATE(14, 180),
+       OFDM_RATE(9,  240),
+       OFDM_RATE(13, 360),
+       OFDM_RATE(8,  480),
+       OFDM_RATE(12, 540),
+};
+EXPORT_SYMBOL_GPL(mt76_rates);
+
 static int mt76_led_init(struct mt76_dev *dev)
 {
        struct device_node *np = dev->dev->of_node;
@@ -315,17 +331,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
        ieee80211_hw_set(hw, MFP_CAPABLE);
        ieee80211_hw_set(hw, AP_LINK_PS);
        ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
-
-       wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-       wiphy->interface_modes =
-               BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_AP) |
-#ifdef CONFIG_MAC80211_MESH
-               BIT(NL80211_IFTYPE_MESH_POINT) |
-#endif
-               BIT(NL80211_IFTYPE_P2P_CLIENT) |
-               BIT(NL80211_IFTYPE_P2P_GO) |
-               BIT(NL80211_IFTYPE_ADHOC);
 }
 
 struct mt76_phy *
@@ -346,6 +351,17 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
        phy->hw = hw;
        phy->priv = hw->priv + phy_size;
 
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+               BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_ADHOC);
+
        return phy;
 }
 EXPORT_SYMBOL_GPL(mt76_alloc_phy);
@@ -428,6 +444,17 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
        mutex_init(&dev->mcu.mutex);
        dev->tx_worker.fn = mt76_tx_worker;
 
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+               BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+               BIT(NL80211_IFTYPE_P2P_CLIENT) |
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_ADHOC);
+
        spin_lock_init(&dev->token_lock);
        idr_init(&dev->token);
 
@@ -632,20 +659,19 @@ void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time)
 }
 EXPORT_SYMBOL_GPL(mt76_update_survey_active_time);
 
-void mt76_update_survey(struct mt76_dev *dev)
+void mt76_update_survey(struct mt76_phy *phy)
 {
+       struct mt76_dev *dev = phy->dev;
        ktime_t cur_time;
 
        if (dev->drv->update_survey)
-               dev->drv->update_survey(dev);
+               dev->drv->update_survey(phy);
 
        cur_time = ktime_get_boottime();
-       mt76_update_survey_active_time(&dev->phy, cur_time);
-       if (dev->phy2)
-               mt76_update_survey_active_time(dev->phy2, cur_time);
+       mt76_update_survey_active_time(phy, cur_time);
 
        if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) {
-               struct mt76_channel_state *state = dev->phy.chan_state;
+               struct mt76_channel_state *state = phy->chan_state;
 
                spin_lock_bh(&dev->cc_lock);
                state->cc_bss_rx += dev->cur_cc_bss_rx;
@@ -664,7 +690,7 @@ void mt76_set_channel(struct mt76_phy *phy)
        int timeout = HZ / 5;
 
        wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
-       mt76_update_survey(dev);
+       mt76_update_survey(phy);
 
        phy->chandef = *chandef;
        phy->chan_state = mt76_channel_state(phy, chandef->chan);
@@ -689,7 +715,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
 
        mutex_lock(&dev->mutex);
        if (idx == 0 && dev->drv->update_survey)
-               mt76_update_survey(dev);
+               mt76_update_survey(phy);
 
        sband = &phy->sband_2g;
        if (idx >= sband->sband.n_channels) {
index 36ede65..25c5cee 100644 (file)
@@ -87,6 +87,22 @@ enum mt76_rxq_id {
        __MT_RXQ_MAX
 };
 
+enum mt76_cipher_type {
+       MT_CIPHER_NONE,
+       MT_CIPHER_WEP40,
+       MT_CIPHER_TKIP,
+       MT_CIPHER_TKIP_NO_MIC,
+       MT_CIPHER_AES_CCMP,
+       MT_CIPHER_WEP104,
+       MT_CIPHER_BIP_CMAC_128,
+       MT_CIPHER_WEP128,
+       MT_CIPHER_WAPI,
+       MT_CIPHER_CCMP_CCX,
+       MT_CIPHER_CCMP_256,
+       MT_CIPHER_GCMP,
+       MT_CIPHER_GCMP_256,
+};
+
 struct mt76_queue_buf {
        dma_addr_t addr;
        u16 len;
@@ -320,6 +336,7 @@ enum {
 struct mt76_hw_cap {
        bool has_2ghz;
        bool has_5ghz;
+       bool has_6ghz;
 };
 
 #define MT_DRV_TXWI_NO_FREE            BIT(0)
@@ -336,7 +353,7 @@ struct mt76_driver_ops {
        u16 token_size;
        u8 mcs_rates;
 
-       void (*update_survey)(struct mt76_dev *dev);
+       void (*update_survey)(struct mt76_phy *phy);
 
        int (*tx_prepare_skb)(struct mt76_dev *dev, void *txwi_ptr,
                              enum mt76_txq_id qid, struct mt76_wcid *wcid,
@@ -738,6 +755,21 @@ enum mt76_phy_type {
        MT_PHY_TYPE_HE_MU,
 };
 
+#define CCK_RATE(_idx, _rate) {                                        \
+       .bitrate = _rate,                                       \
+       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                 \
+       .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),            \
+       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx),  \
+}
+
+#define OFDM_RATE(_idx, _rate) {                               \
+       .bitrate = _rate,                                       \
+       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),           \
+       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),     \
+}
+
+extern struct ieee80211_rate mt76_rates[12];
+
 #define __mt76_rr(dev, ...)    (dev)->bus->rr((dev), __VA_ARGS__)
 #define __mt76_wr(dev, ...)    (dev)->bus->wr((dev), __VA_ARGS__)
 #define __mt76_rmw(dev, ...)   (dev)->bus->rmw((dev), __VA_ARGS__)
@@ -1031,7 +1063,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,
                                  bool more_data);
 bool mt76_has_tx_pending(struct mt76_phy *phy);
 void mt76_set_channel(struct mt76_phy *phy);
-void mt76_update_survey(struct mt76_dev *dev);
+void mt76_update_survey(struct mt76_phy *phy);
 void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time);
 int mt76_get_survey(struct ieee80211_hw *hw, int idx,
                    struct survey_info *survey);
@@ -1056,7 +1088,14 @@ struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev,
                                       struct sk_buff_head *list);
 void mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb,
                             struct sk_buff_head *list);
-void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb);
+void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb,
+                           struct list_head *free_list);
+static inline void
+mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb)
+{
+    __mt76_tx_complete_skb(dev, wcid, skb, NULL);
+}
+
 void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid,
                          bool flush);
 int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -1253,4 +1292,15 @@ mt76_token_put(struct mt76_dev *dev, int token)
 
        return txwi;
 }
+
+static inline int
+mt76_get_next_pkt_id(struct mt76_wcid *wcid)
+{
+       wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
+       if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
+           wcid->packet_id == MT_PACKET_ID_NO_SKB)
+               wcid->packet_id = MT_PACKET_ID_FIRST;
+
+       return wcid->packet_id;
+}
 #endif
index e1b2cfa..031d39a 100644 (file)
@@ -304,34 +304,6 @@ mt7603_init_hardware(struct mt7603_dev *dev)
        return 0;
 }
 
-#define CCK_RATE(_idx, _rate) {                                        \
-       .bitrate = _rate,                                       \
-       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                 \
-       .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),            \
-       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx),  \
-}
-
-#define OFDM_RATE(_idx, _rate) {                               \
-       .bitrate = _rate,                                       \
-       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),           \
-       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),     \
-}
-
-static struct ieee80211_rate mt7603_rates[] = {
-       CCK_RATE(0, 10),
-       CCK_RATE(1, 20),
-       CCK_RATE(2, 55),
-       CCK_RATE(3, 110),
-       OFDM_RATE(11, 60),
-       OFDM_RATE(15, 90),
-       OFDM_RATE(10, 120),
-       OFDM_RATE(14, 180),
-       OFDM_RATE(9,  240),
-       OFDM_RATE(13, 360),
-       OFDM_RATE(8,  480),
-       OFDM_RATE(12, 540),
-};
-
 static const struct ieee80211_iface_limit if_limits[] = {
        {
                .max = 1,
@@ -569,8 +541,8 @@ int mt7603_register_device(struct mt7603_dev *dev)
 
        wiphy->reg_notifier = mt7603_regd_notifier;
 
-       ret = mt76_register_device(&dev->mt76, true, mt7603_rates,
-                                  ARRAY_SIZE(mt7603_rates));
+       ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+                                  ARRAY_SIZE(mt76_rates));
        if (ret)
                return ret;
 
index fbceb07..3972c56 100644 (file)
@@ -550,14 +550,27 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
                u8 *data = (u8 *)rxd;
 
                if (status->flag & RX_FLAG_DECRYPTED) {
-                       status->iv[0] = data[5];
-                       status->iv[1] = data[4];
-                       status->iv[2] = data[3];
-                       status->iv[3] = data[2];
-                       status->iv[4] = data[1];
-                       status->iv[5] = data[0];
-
-                       insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                       switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) {
+                       case MT_CIPHER_AES_CCMP:
+                       case MT_CIPHER_CCMP_CCX:
+                       case MT_CIPHER_CCMP_256:
+                               insert_ccmp_hdr =
+                                       FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                               fallthrough;
+                       case MT_CIPHER_TKIP:
+                       case MT_CIPHER_TKIP_NO_MIC:
+                       case MT_CIPHER_GCMP:
+                       case MT_CIPHER_GCMP_256:
+                               status->iv[0] = data[5];
+                               status->iv[1] = data[4];
+                               status->iv[2] = data[3];
+                               status->iv[3] = data[2];
+                               status->iv[4] = data[1];
+                               status->iv[5] = data[0];
+                               break;
+                       default:
+                               break;
+                       }
                }
 
                rxd += 4;
@@ -831,7 +844,7 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta,
        sta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
 }
 
-static enum mt7603_cipher_type
+static enum mt76_cipher_type
 mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
 {
        memset(key_data, 0, 32);
@@ -863,7 +876,7 @@ mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
 int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
                        struct ieee80211_key_conf *key)
 {
-       enum mt7603_cipher_type cipher;
+       enum mt76_cipher_type cipher;
        u32 addr = mt7603_wtbl3_addr(wcid);
        u8 key_data[32];
        int key_len = sizeof(key_data);
@@ -1213,7 +1226,7 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (!mt7603_fill_txs(dev, sta, info, txs_data)) {
-                       ieee80211_tx_info_clear_status(info);
+                       info->status.rates[0].count = 0;
                        info->status.rates[0].idx = -1;
                }
 
@@ -1584,12 +1597,12 @@ trigger:
        return true;
 }
 
-void mt7603_update_channel(struct mt76_dev *mdev)
+void mt7603_update_channel(struct mt76_phy *mphy)
 {
-       struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+       struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, mt76);
        struct mt76_channel_state *state;
 
-       state = mdev->phy.chan_state;
+       state = mphy->chan_state;
        state->cc_busy += mt76_rr(dev, MT_MIB_STAT_CCA);
 }
 
@@ -1806,7 +1819,7 @@ void mt7603_mac_work(struct work_struct *work)
        mutex_lock(&dev->mt76.mutex);
 
        dev->mphy.mac_work_count++;
-       mt76_update_survey(&dev->mt76);
+       mt76_update_survey(&dev->mphy);
        mt7603_edcca_check(dev);
 
        for (i = 0, idx = 0; i < 2; i++) {
index 1df5b9f..0fd46d9 100644 (file)
@@ -256,7 +256,7 @@ void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 
 void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t);
 
-void mt7603_update_channel(struct mt76_dev *mdev);
+void mt7603_update_channel(struct mt76_phy *mphy);
 
 void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val);
 void mt7603_cca_stats_reset(struct mt7603_dev *dev);
index 6741e69..3b90109 100644 (file)
@@ -765,16 +765,4 @@ enum {
 #define MT_WTBL1_OR                    (MT_WTBL1_BASE + 0x2300)
 #define MT_WTBL1_OR_PSM_WRITE          BIT(31)
 
-enum mt7603_cipher_type {
-       MT_CIPHER_NONE,
-       MT_CIPHER_WEP40,
-       MT_CIPHER_TKIP,
-       MT_CIPHER_TKIP_NO_MIC,
-       MT_CIPHER_AES_CCMP,
-       MT_CIPHER_WEP104,
-       MT_CIPHER_BIP_CMAC_128,
-       MT_CIPHER_WEP128,
-       MT_CIPHER_WAPI,
-};
-
 #endif
index e8fc4a7..83f9861 100644 (file)
@@ -1,4 +1,4 @@
-#SPDX-License-Identifier: ISC
+# SPDX-License-Identifier: ISC
 
 obj-$(CONFIG_MT7615_COMMON) += mt7615-common.o
 obj-$(CONFIG_MT7615E) += mt7615e.o
index 676bb22..cb46597 100644 (file)
@@ -75,7 +75,7 @@ mt7615_pm_set(void *data, u64 val)
        if (!mt7615_wait_for_mcu_init(dev))
                return 0;
 
-       if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76))
+       if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76))
                return -EOPNOTSUPP;
 
        if (val == pm->enable)
@@ -319,24 +319,6 @@ mt7615_radio_read(struct seq_file *s, void *data)
        return 0;
 }
 
-static int mt7615_read_temperature(struct seq_file *s, void *data)
-{
-       struct mt7615_dev *dev = dev_get_drvdata(s->private);
-       int temp;
-
-       if (!mt7615_wait_for_mcu_init(dev))
-               return 0;
-
-       /* cpu */
-       mt7615_mutex_acquire(dev);
-       temp = mt7615_mcu_get_temperature(dev, 0);
-       mt7615_mutex_release(dev);
-
-       seq_printf(s, "Temperature: %d\n", temp);
-
-       return 0;
-}
-
 static int
 mt7615_queues_acq(struct seq_file *s, void *data)
 {
@@ -566,8 +548,6 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
 
        debugfs_create_file("reset_test", 0200, dir, dev,
                            &fops_reset_test);
-       debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,
-                                   mt7615_read_temperature);
        debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);
 
        debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);
index 8004ae5..00aefea 100644 (file)
@@ -81,7 +81,7 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
        if (napi_complete(napi))
                mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev));
 
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 
        return 0;
 }
@@ -99,7 +99,7 @@ static int mt7615_poll_rx(struct napi_struct *napi, int budget)
                return 0;
        }
        done = mt76_dma_rx_poll(napi, budget);
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 
        return done;
 }
@@ -222,14 +222,9 @@ void mt7615_dma_start(struct mt7615_dev *dev)
 int mt7615_dma_init(struct mt7615_dev *dev)
 {
        int rx_ring_size = MT7615_RX_RING_SIZE;
-       int rx_buf_size = MT_RX_BUF_SIZE;
        u32 mask;
        int ret;
 
-       /* Increase buffer size to receive large VHT MPDUs */
-       if (dev->mphy.cap.has_5ghz)
-               rx_buf_size *= 2;
-
        mt76_dma_attach(&dev->mt76);
 
        mt76_wr(dev, MT_WPDMA_GLO_CFG,
@@ -270,7 +265,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
 
        /* init rx queues */
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
-                              MT7615_RX_MCU_RING_SIZE, rx_buf_size,
+                              MT7615_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE,
                               MT_RX_RING_BASE);
        if (ret)
                return ret;
@@ -279,7 +274,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
            rx_ring_size /= 2;
 
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
-                              rx_ring_size, rx_buf_size, MT_RX_RING_BASE);
+                              rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE);
        if (ret)
                return ret;
 
index d20f05a..2f1ac64 100644 (file)
@@ -8,11 +8,61 @@
  */
 
 #include <linux/etherdevice.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include "mt7615.h"
 #include "mac.h"
 #include "mcu.h"
 #include "eeprom.h"
 
+static ssize_t mt7615_thermal_show_temp(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct mt7615_dev *mdev = dev_get_drvdata(dev);
+       int temperature;
+
+       if (!mt7615_wait_for_mcu_init(mdev))
+               return 0;
+
+       mt7615_mutex_acquire(mdev);
+       temperature = mt7615_mcu_get_temperature(mdev);
+       mt7615_mutex_release(mdev);
+
+       if (temperature < 0)
+               return temperature;
+
+       /* display in millidegree celcius */
+       return sprintf(buf, "%u\n", temperature * 1000);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7615_thermal_show_temp,
+                         NULL, 0);
+
+static struct attribute *mt7615_hwmon_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(mt7615_hwmon);
+
+int mt7615_thermal_init(struct mt7615_dev *dev)
+{
+       struct wiphy *wiphy = mt76_hw(dev)->wiphy;
+       struct device *hwmon;
+
+       if (!IS_REACHABLE(CONFIG_HWMON))
+               return 0;
+
+       hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
+                                                      wiphy_name(wiphy), dev,
+                                                      mt7615_hwmon_groups);
+       if (IS_ERR(hwmon))
+               return PTR_ERR(hwmon);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt7615_thermal_init);
+
 static void
 mt7615_phy_init(struct mt7615_dev *dev)
 {
@@ -174,35 +224,6 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt7615_wait_for_mcu_init);
 
-#define CCK_RATE(_idx, _rate) {                                                \
-       .bitrate = _rate,                                               \
-       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                         \
-       .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),                    \
-       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),        \
-}
-
-#define OFDM_RATE(_idx, _rate) {                                       \
-       .bitrate = _rate,                                               \
-       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),                   \
-       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),             \
-}
-
-struct ieee80211_rate mt7615_rates[] = {
-       CCK_RATE(0, 10),
-       CCK_RATE(1, 20),
-       CCK_RATE(2, 55),
-       CCK_RATE(3, 110),
-       OFDM_RATE(11, 60),
-       OFDM_RATE(15, 90),
-       OFDM_RATE(10, 120),
-       OFDM_RATE(14, 180),
-       OFDM_RATE(9,  240),
-       OFDM_RATE(13, 360),
-       OFDM_RATE(8,  480),
-       OFDM_RATE(12, 540),
-};
-EXPORT_SYMBOL_GPL(mt7615_rates);
-
 static const struct ieee80211_iface_limit if_limits[] = {
        {
                .max = 1,
@@ -362,7 +383,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
        wiphy->reg_notifier = mt7615_regd_notifier;
 
        wiphy->max_sched_scan_plan_interval =
-               MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL;
+               MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;
        wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
        wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
        wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
@@ -472,8 +493,8 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
        for (i = 0; i <= MT_TXQ_PSD ; i++)
                mphy->q_tx[i] = dev->mphy.q_tx[i];
 
-       ret = mt76_register_phy(mphy, true, mt7615_rates,
-                               ARRAY_SIZE(mt7615_rates));
+       ret = mt76_register_phy(mphy, true, mt76_rates,
+                               ARRAY_SIZE(mt76_rates));
        if (ret)
                ieee80211_free_hw(mphy->hw);
 
index e2dcfee..ff3f85e 100644 (file)
@@ -20,7 +20,7 @@
 #define to_rssi(field, rxv)            ((FIELD_GET(field, rxv) - 220) / 2)
 
 static const struct mt7615_dfs_radar_spec etsi_radar_specs = {
-       .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
+       .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
        .radar_pattern = {
                [5] =  { 1, 0,  6, 32, 28, 0, 17,  990, 5010, 1, 1 },
                [6] =  { 1, 0,  9, 32, 28, 0, 27,  615, 5010, 1, 1 },
@@ -34,7 +34,7 @@ static const struct mt7615_dfs_radar_spec etsi_radar_specs = {
 };
 
 static const struct mt7615_dfs_radar_spec fcc_radar_specs = {
-       .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
+       .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
        .radar_pattern = {
                [0] = { 1, 0,  9,  32, 28, 0, 13, 508, 3076, 1,  1 },
                [1] = { 1, 0, 12,  32, 28, 0, 17, 140,  240, 1,  1 },
@@ -45,7 +45,7 @@ static const struct mt7615_dfs_radar_spec fcc_radar_specs = {
 };
 
 static const struct mt7615_dfs_radar_spec jp_radar_specs = {
-       .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
+       .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
        .radar_pattern = {
                [0] =  { 1, 0,  8, 32, 28, 0, 13,  508, 3076, 1,  1 },
                [1] =  { 1, 0, 12, 32, 28, 0, 17,  140,  240, 1,  1 },
@@ -57,6 +57,33 @@ static const struct mt7615_dfs_radar_spec jp_radar_specs = {
        },
 };
 
+static enum mt76_cipher_type
+mt7615_mac_get_cipher(int cipher)
+{
+       switch (cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+               return MT_CIPHER_WEP40;
+       case WLAN_CIPHER_SUITE_WEP104:
+               return MT_CIPHER_WEP104;
+       case WLAN_CIPHER_SUITE_TKIP:
+               return MT_CIPHER_TKIP;
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+               return MT_CIPHER_BIP_CMAC_128;
+       case WLAN_CIPHER_SUITE_CCMP:
+               return MT_CIPHER_AES_CCMP;
+       case WLAN_CIPHER_SUITE_CCMP_256:
+               return MT_CIPHER_CCMP_256;
+       case WLAN_CIPHER_SUITE_GCMP:
+               return MT_CIPHER_GCMP;
+       case WLAN_CIPHER_SUITE_GCMP_256:
+               return MT_CIPHER_GCMP_256;
+       case WLAN_CIPHER_SUITE_SMS4:
+               return MT_CIPHER_WAPI;
+       default:
+               return MT_CIPHER_NONE;
+       }
+}
+
 static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
                                            u8 idx, bool unicast)
 {
@@ -313,14 +340,27 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
                u8 *data = (u8 *)rxd;
 
                if (status->flag & RX_FLAG_DECRYPTED) {
-                       status->iv[0] = data[5];
-                       status->iv[1] = data[4];
-                       status->iv[2] = data[3];
-                       status->iv[3] = data[2];
-                       status->iv[4] = data[1];
-                       status->iv[5] = data[0];
-
-                       insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                       switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) {
+                       case MT_CIPHER_AES_CCMP:
+                       case MT_CIPHER_CCMP_CCX:
+                       case MT_CIPHER_CCMP_256:
+                               insert_ccmp_hdr =
+                                       FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                               fallthrough;
+                       case MT_CIPHER_TKIP:
+                       case MT_CIPHER_TKIP_NO_MIC:
+                       case MT_CIPHER_GCMP:
+                       case MT_CIPHER_GCMP_256:
+                               status->iv[0] = data[5];
+                               status->iv[1] = data[4];
+                               status->iv[2] = data[3];
+                               status->iv[3] = data[2];
+                               status->iv[4] = data[1];
+                               status->iv[5] = data[0];
+                               break;
+                       default:
+                               break;
+                       }
                }
                rxd += 4;
                if ((u8 *)rxd - skb->data >= skb->len)
@@ -1062,7 +1102,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
        idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
        addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
 
-       mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
+       mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */
        sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0);
        sta->rate_set_tsf |= rd.rateset;
 
@@ -1078,7 +1118,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
 static int
 mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
                           struct ieee80211_key_conf *key,
-                          enum mt7615_cipher_type cipher, u16 cipher_mask,
+                          enum mt76_cipher_type cipher, u16 cipher_mask,
                           enum set_key_cmd cmd)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
@@ -1118,7 +1158,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 
 static int
 mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
-                         enum mt7615_cipher_type cipher, u16 cipher_mask,
+                         enum mt76_cipher_type cipher, u16 cipher_mask,
                          int keyidx, enum set_key_cmd cmd)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
@@ -1157,7 +1197,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 
 static void
 mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
-                             enum mt7615_cipher_type cipher, u16 cipher_mask,
+                             enum mt76_cipher_type cipher, u16 cipher_mask,
                              enum set_key_cmd cmd)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
@@ -1183,7 +1223,7 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
                              struct ieee80211_key_conf *key,
                              enum set_key_cmd cmd)
 {
-       enum mt7615_cipher_type cipher;
+       enum mt76_cipher_type cipher;
        u16 cipher_mask = wcid->cipher;
        int err;
 
@@ -1235,22 +1275,20 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
        int first_idx = 0, last_idx;
        int i, idx, count;
        bool fixed_rate, ack_timeout;
-       bool probe, ampdu, cck = false;
+       bool ampdu, cck = false;
        bool rs_idx;
        u32 rate_set_tsf;
        u32 final_rate, final_rate_flags, final_nss, txs;
 
-       fixed_rate = info->status.rates[0].count;
-       probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
-
        txs = le32_to_cpu(txs_data[1]);
-       ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU);
+       ampdu = txs & MT_TXS1_AMPDU;
 
        txs = le32_to_cpu(txs_data[3]);
        count = FIELD_GET(MT_TXS3_TX_COUNT, txs);
        last_idx = FIELD_GET(MT_TXS3_LAST_TX_RATE, txs);
 
        txs = le32_to_cpu(txs_data[0]);
+       fixed_rate = txs & MT_TXS0_FIXED_RATE;
        final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs);
        ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;
 
@@ -1272,7 +1310,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
 
        first_idx = max_t(int, 0, last_idx - (count - 1) / MT7615_RATE_RETRY);
 
-       if (fixed_rate && !probe) {
+       if (fixed_rate) {
                info->status.rates[0].count = count;
                i = 0;
                goto out;
@@ -1391,7 +1429,7 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (!mt7615_fill_txs(dev, sta, info, txs_data)) {
-                       ieee80211_tx_info_clear_status(info);
+                       info->status.rates[0].count = 0;
                        info->status.rates[0].idx = -1;
                }
 
@@ -1821,43 +1859,41 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
        state->noise = -(phy->noise >> 4);
 }
 
-static void __mt7615_update_channel(struct mt7615_dev *dev)
+static void mt7615_update_survey(struct mt7615_dev *dev)
 {
        struct mt76_dev *mdev = &dev->mt76;
+       ktime_t cur_time;
+
+       /* MT7615 can only update both phys simultaneously
+        * since some reisters are shared across bands.
+        */
 
        mt7615_phy_update_channel(&mdev->phy, 0);
        if (mdev->phy2)
                mt7615_phy_update_channel(mdev->phy2, 1);
 
+       cur_time = ktime_get_boottime();
+
+       mt76_update_survey_active_time(&mdev->phy, cur_time);
+       if (mdev->phy2)
+               mt76_update_survey_active_time(mdev->phy2, cur_time);
+
        /* reset obss airtime */
        mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);
 }
 
-void mt7615_update_channel(struct mt76_dev *mdev)
+void mt7615_update_channel(struct mt76_phy *mphy)
 {
-       struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
+       struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76);
 
        if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
                return;
 
-       __mt7615_update_channel(dev);
+       mt7615_update_survey(dev);
        mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
 }
 EXPORT_SYMBOL_GPL(mt7615_update_channel);
 
-static void mt7615_update_survey(struct mt7615_dev *dev)
-{
-       struct mt76_dev *mdev = &dev->mt76;
-       ktime_t cur_time;
-
-       __mt7615_update_channel(dev);
-       cur_time = ktime_get_boottime();
-
-       mt76_update_survey_active_time(&mdev->phy, cur_time);
-       if (mdev->phy2)
-               mt76_update_survey_active_time(mdev->phy2, cur_time);
-}
-
 static void
 mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
 {
@@ -1906,15 +1942,26 @@ void mt7615_pm_wake_work(struct work_struct *work)
        mphy = dev->phy.mt76;
 
        if (!mt7615_mcu_set_drv_ctrl(dev)) {
+               struct mt76_dev *mdev = &dev->mt76;
                int i;
 
-               mt76_for_each_q_rx(&dev->mt76, i)
-                       napi_schedule(&dev->mt76.napi[i]);
-               mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
-               mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
-               if (test_bit(MT76_STATE_RUNNING, &mphy->state))
+               if (mt76_is_sdio(mdev)) {
+                       mt76_worker_schedule(&mdev->sdio.txrx_worker);
+               } else {
+                       mt76_for_each_q_rx(mdev, i)
+                               napi_schedule(&mdev->napi[i]);
+                       mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
+                       mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM],
+                                             false);
+               }
+
+               if (test_bit(MT76_STATE_RUNNING, &mphy->state)) {
+                       unsigned long timeout;
+
+                       timeout = mt7615_get_macwork_timeout(dev);
                        ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
-                                                    MT7615_WATCHDOG_TIME);
+                                                    timeout);
+               }
        }
 
        ieee80211_wake_queues(mphy->hw);
@@ -1949,6 +1996,7 @@ void mt7615_mac_work(struct work_struct *work)
 {
        struct mt7615_phy *phy;
        struct mt76_phy *mphy;
+       unsigned long timeout;
 
        mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
                                               mac_work.work);
@@ -1967,8 +2015,9 @@ void mt7615_mac_work(struct work_struct *work)
        mt7615_mutex_release(phy->dev);
 
        mt76_tx_status_check(mphy->dev, NULL, false);
-       ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
-                                    MT7615_WATCHDOG_TIME);
+
+       timeout = mt7615_get_macwork_timeout(phy->dev);
+       ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, timeout);
 }
 
 void mt7615_tx_token_put(struct mt7615_dev *dev)
@@ -2049,14 +2098,12 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
 {
        const struct mt7615_dfs_radar_spec *radar_specs;
        struct mt7615_dev *dev = phy->dev;
-       int err, i;
+       int err, i, lpn = 500;
 
        switch (dev->mt76.region) {
        case NL80211_DFS_FCC:
                radar_specs = &fcc_radar_specs;
-               err = mt7615_mcu_set_fcc5_lpn(dev, 8);
-               if (err < 0)
-                       return err;
+               lpn = 8;
                break;
        case NL80211_DFS_ETSI:
                radar_specs = &etsi_radar_specs;
@@ -2068,6 +2115,11 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
                return -EINVAL;
        }
 
+       /* avoid FCC radar detection in non-FCC region */
+       err = mt7615_mcu_set_fcc5_lpn(dev, lpn);
+       if (err < 0)
+               return err;
+
        for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {
                err = mt7615_mcu_set_radar_th(dev, i,
                                              &radar_specs->radar_pattern[i]);
index 6bf9da0..46f283e 100644 (file)
@@ -383,48 +383,6 @@ struct mt7615_dfs_radar_spec {
        struct mt7615_dfs_pattern radar_pattern[16];
 };
 
-enum mt7615_cipher_type {
-       MT_CIPHER_NONE,
-       MT_CIPHER_WEP40,
-       MT_CIPHER_TKIP,
-       MT_CIPHER_TKIP_NO_MIC,
-       MT_CIPHER_AES_CCMP,
-       MT_CIPHER_WEP104,
-       MT_CIPHER_BIP_CMAC_128,
-       MT_CIPHER_WEP128,
-       MT_CIPHER_WAPI,
-       MT_CIPHER_CCMP_256 = 10,
-       MT_CIPHER_GCMP,
-       MT_CIPHER_GCMP_256,
-};
-
-static inline enum mt7615_cipher_type
-mt7615_mac_get_cipher(int cipher)
-{
-       switch (cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-               return MT_CIPHER_WEP40;
-       case WLAN_CIPHER_SUITE_WEP104:
-               return MT_CIPHER_WEP104;
-       case WLAN_CIPHER_SUITE_TKIP:
-               return MT_CIPHER_TKIP;
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-               return MT_CIPHER_BIP_CMAC_128;
-       case WLAN_CIPHER_SUITE_CCMP:
-               return MT_CIPHER_AES_CCMP;
-       case WLAN_CIPHER_SUITE_CCMP_256:
-               return MT_CIPHER_CCMP_256;
-       case WLAN_CIPHER_SUITE_GCMP:
-               return MT_CIPHER_GCMP;
-       case WLAN_CIPHER_SUITE_GCMP_256:
-               return MT_CIPHER_GCMP_256;
-       case WLAN_CIPHER_SUITE_SMS4:
-               return MT_CIPHER_WAPI;
-       default:
-               return MT_CIPHER_NONE;
-       }
-}
-
 static inline struct mt7615_txp_common *
 mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
 {
index 39733b3..dada43d 100644 (file)
@@ -28,6 +28,7 @@ static int mt7615_start(struct ieee80211_hw *hw)
 {
        struct mt7615_dev *dev = mt7615_hw_dev(hw);
        struct mt7615_phy *phy = mt7615_hw_phy(hw);
+       unsigned long timeout;
        bool running;
        int ret;
 
@@ -78,8 +79,8 @@ static int mt7615_start(struct ieee80211_hw *hw)
 
        set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
 
-       ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-                                    MT7615_WATCHDOG_TIME);
+       timeout = mt7615_get_macwork_timeout(dev);
+       ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, timeout);
 
        if (!running)
                mt7615_mac_reset_counters(dev);
@@ -240,8 +241,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
        }
 
        ret = mt7615_mcu_add_dev_info(phy, vif, true);
-       if (ret)
-               goto out;
 out:
        mt7615_mutex_release(dev);
 
@@ -352,10 +351,12 @@ out:
        mt7615_mutex_release(dev);
 
        mt76_worker_schedule(&dev->mt76.tx_worker);
-       if (!mt76_testmode_enabled(phy->mt76))
+       if (!mt76_testmode_enabled(phy->mt76)) {
+               unsigned long timeout = mt7615_get_macwork_timeout(dev);
+
                ieee80211_queue_delayed_work(phy->mt76->hw,
-                                            &phy->mt76->mac_work,
-                                            MT7615_WATCHDOG_TIME);
+                                            &phy->mt76->mac_work, timeout);
+       }
 
        return ret;
 }
@@ -695,7 +696,7 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,
        msta->n_rates = i;
        if (mt76_connac_pm_ref(phy->mt76, &dev->pm)) {
                mt7615_mac_set_rates(phy, msta, NULL, msta->rates);
-               mt76_connac_pm_unref(&dev->pm);
+               mt76_connac_pm_unref(phy->mt76, &dev->pm);
        }
        spin_unlock_bh(&dev->mt76.lock);
 }
@@ -711,7 +712,7 @@ void mt7615_tx_worker(struct mt76_worker *w)
        }
 
        mt76_tx_worker_run(&dev->mt76);
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 }
 
 static void mt7615_tx(struct ieee80211_hw *hw,
@@ -741,7 +742,7 @@ static void mt7615_tx(struct ieee80211_hw *hw,
 
        if (mt76_connac_pm_ref(mphy, &dev->pm)) {
                mt76_tx(mphy, control->sta, wcid, skb);
-               mt76_connac_pm_unref(&dev->pm);
+               mt76_connac_pm_unref(mphy, &dev->pm);
                return;
        }
 
@@ -881,7 +882,8 @@ mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        mt7615_mutex_acquire(dev);
 
-       mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */
+       /* TSF read */
+       mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_READ);
        tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0);
        tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1);
 
@@ -911,7 +913,33 @@ mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
        mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
        /* TSF software overwrite */
-       mt76_set(dev, reg, MT_LPON_TCR_WRITE);
+       mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_WRITE);
+
+       mt7615_mutex_release(dev);
+}
+
+static void
+mt7615_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                 s64 timestamp)
+{
+       struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
+       struct mt7615_dev *dev = mt7615_hw_dev(hw);
+       union {
+               u64 t64;
+               u32 t32[2];
+       } tsf = { .t64 = timestamp, };
+       u16 idx = mvif->mt76.omac_idx;
+       u32 reg;
+
+       idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
+       reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
+
+       mt7615_mutex_acquire(dev);
+
+       mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
+       mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
+       /* TSF software adjust*/
+       mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_ADJUST);
 
        mt7615_mutex_release(dev);
 }
@@ -1162,7 +1190,7 @@ static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,
        else
                clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
 
-       mt7615_mcu_sta_update_hdr_trans(dev, vif, sta);
+       mt7615_mcu_set_sta_decap_offload(dev, vif, sta);
 }
 
 #ifdef CONFIG_PM
@@ -1200,6 +1228,7 @@ static int mt7615_resume(struct ieee80211_hw *hw)
 {
        struct mt7615_phy *phy = mt7615_hw_phy(hw);
        struct mt7615_dev *dev = mt7615_hw_dev(hw);
+       unsigned long timeout;
        bool running;
 
        mt7615_mutex_acquire(dev);
@@ -1223,8 +1252,8 @@ static int mt7615_resume(struct ieee80211_hw *hw)
                                            mt76_connac_mcu_set_suspend_iter,
                                            phy->mt76);
 
-       ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-                                    MT7615_WATCHDOG_TIME);
+       timeout = mt7615_get_macwork_timeout(dev);
+       ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, timeout);
 
        mt7615_mutex_release(dev);
 
@@ -1278,6 +1307,7 @@ const struct ieee80211_ops mt7615_ops = {
        .get_stats = mt7615_get_stats,
        .get_tsf = mt7615_get_tsf,
        .set_tsf = mt7615_set_tsf,
+       .offset_tsf = mt7615_offset_tsf,
        .get_survey = mt76_get_survey,
        .get_antenna = mt76_get_antenna,
        .set_antenna = mt7615_set_antenna,
index aa42af9..f8a0969 100644 (file)
@@ -411,6 +411,9 @@ mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
 
        c = (struct mt7615_mcu_csa_notify *)skb->data;
 
+       if (c->omac_idx > EXT_BSSID_MAX)
+               return;
+
        if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
                mphy = dev->mt76.phy2;
 
@@ -427,6 +430,10 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
 
        r = (struct mt7615_mcu_rdd_report *)skb->data;
 
+       if (!dev->radar_pattern.n_pulses && !r->long_detected &&
+           !r->constant_prf_detected && !r->staggered_prf_detected)
+               return;
+
        if (r->band_idx && dev->mt76.phy2)
                mphy = dev->mt76.phy2;
 
@@ -1021,9 +1028,10 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
        if (IS_ERR(sskb))
                return PTR_ERR(sskb);
 
-       mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable);
+       mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true);
        if (enable && sta)
-               mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0);
+               mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
+                                       MT76_STA_INFO_STATE_ASSOC);
 
        wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
                                                  WTBL_RESET_AND_SET, NULL,
@@ -1037,8 +1045,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
                if (sta)
                        mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
                                                    NULL, wtbl_hdr);
-               mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL,
-                                                  wtbl_hdr);
+               mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,
+                                                  NULL, wtbl_hdr);
        }
 
        cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE;
@@ -1058,6 +1066,26 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
        return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);
 }
 
+static int
+mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta)
+{
+       struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
+       struct wtbl_req_hdr *wtbl_hdr;
+       struct sk_buff *skb = NULL;
+
+       wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
+                                                 WTBL_SET, NULL, &skb);
+       if (IS_ERR(wtbl_hdr))
+               return PTR_ERR(wtbl_hdr);
+
+       mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, &msta->wcid, NULL,
+                                          wtbl_hdr);
+       return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
+                                    true);
+}
+
 static const struct mt7615_mcu_ops wtbl_update_ops = {
        .add_beacon_offload = mt7615_mcu_add_beacon_offload,
        .set_pm_state = mt7615_mcu_ctrl_pm_state,
@@ -1068,6 +1096,7 @@ static const struct mt7615_mcu_ops wtbl_update_ops = {
        .sta_add = mt7615_mcu_wtbl_sta_add,
        .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
        .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
+       .set_sta_decap_offload = mt7615_mcu_wtbl_update_hdr_trans,
 };
 
 static int
@@ -1120,18 +1149,21 @@ mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev,
 
 static int
 __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
-                    struct ieee80211_sta *sta, bool enable, int cmd)
+                    struct ieee80211_sta *sta, bool enable, int cmd,
+                    bool offload_fw)
 {
        struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
        struct mt76_sta_cmd_info info = {
                .sta = sta,
                .vif = vif,
+               .offload_fw = offload_fw,
                .enable = enable,
+               .newly = true,
                .cmd = cmd,
        };
 
        info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
-       return mt76_connac_mcu_add_sta_cmd(phy, &info);
+       return mt76_connac_mcu_sta_cmd(phy, &info);
 }
 
 static int
@@ -1139,7 +1171,19 @@ mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,
                   struct ieee80211_sta *sta, bool enable)
 {
        return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,
-                                   MCU_EXT_CMD_STA_REC_UPDATE);
+                                   MCU_EXT_CMD_STA_REC_UPDATE, false);
+}
+
+static int
+mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_sta *sta)
+{
+       struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
+
+       return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
+                                                   vif, &msta->wcid,
+                                                   MCU_EXT_CMD_STA_REC_UPDATE);
 }
 
 static const struct mt7615_mcu_ops sta_update_ops = {
@@ -1152,27 +1196,9 @@ static const struct mt7615_mcu_ops sta_update_ops = {
        .sta_add = mt7615_mcu_add_sta,
        .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
        .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
+       .set_sta_decap_offload = mt7615_mcu_sta_update_hdr_trans,
 };
 
-int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
-                                   struct ieee80211_vif *vif,
-                                   struct ieee80211_sta *sta)
-{
-       struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
-       struct wtbl_req_hdr *wtbl_hdr;
-       struct sk_buff *skb = NULL;
-
-       wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
-                                                 WTBL_SET, NULL, &skb);
-       if (IS_ERR(wtbl_hdr))
-               return PTR_ERR(wtbl_hdr);
-
-       mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr);
-
-       return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
-                                    true);
-}
-
 static int
 mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
 {
@@ -1280,7 +1306,7 @@ mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta, bool enable)
 {
        return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,
-                                   MCU_UNI_CMD_STA_REC_UPDATE);
+                                   MCU_UNI_CMD_STA_REC_UPDATE, true);
 }
 
 static int
@@ -1338,6 +1364,18 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,
                                     MCU_UNI_CMD_STA_REC_UPDATE, true);
 }
 
+static int
+mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_sta *sta)
+{
+       struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
+
+       return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
+                                                   vif, &msta->wcid,
+                                                   MCU_UNI_CMD_STA_REC_UPDATE);
+}
+
 static const struct mt7615_mcu_ops uni_update_ops = {
        .add_beacon_offload = mt7615_mcu_uni_add_beacon_offload,
        .set_pm_state = mt7615_mcu_uni_ctrl_pm_state,
@@ -1348,6 +1386,7 @@ static const struct mt7615_mcu_ops uni_update_ops = {
        .sta_add = mt7615_mcu_uni_add_sta,
        .set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,
        .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
+       .set_sta_decap_offload = mt7615_mcu_sta_uni_update_hdr_trans,
 };
 
 int mt7615_mcu_restart(struct mt76_dev *dev)
@@ -2322,14 +2361,12 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
        return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
 }
 
-int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index)
+int mt7615_mcu_get_temperature(struct mt7615_dev *dev)
 {
        struct {
                u8 action;
                u8 rsv[3];
-       } req = {
-               .action = index,
-       };
+       } req = {};
 
        return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req,
                                 sizeof(req), true);
index 202ea23..71719c7 100644 (file)
@@ -229,7 +229,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
                               GFP_KERNEL);
        if (!bus_ops) {
                ret = -ENOMEM;
-               goto error;
+               goto err_free_dev;
        }
 
        bus_ops->rr = mt7615_rr;
@@ -242,17 +242,20 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
        ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler,
                               IRQF_SHARED, KBUILD_MODNAME, dev);
        if (ret)
-               goto error;
+               goto err_free_dev;
 
        if (is_mt7663(mdev))
                mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
 
        ret = mt7615_register_device(dev);
        if (ret)
-               goto error;
+               goto err_free_irq;
 
        return 0;
-error:
+
+err_free_irq:
+       devm_free_irq(pdev, irq, dev);
+err_free_dev:
        mt76_free_device(&dev->mt76);
 
        return ret;
index 989f05e..d0c64a9 100644 (file)
@@ -20,7 +20,6 @@
                                         MT7615_MAX_INTERFACES)
 
 #define MT7615_PM_TIMEOUT              (HZ / 12)
-#define MT7615_WATCHDOG_TIME           (HZ / 10)
 #define MT7615_HW_SCAN_TIMEOUT         (HZ / 10)
 #define MT7615_RESET_TIMEOUT           (30 * HZ)
 #define MT7615_RATE_RETRY              2
@@ -202,6 +201,7 @@ struct mt7615_phy {
 #define mt7615_mcu_set_pm(dev, ...)    (dev)->mcu_ops->set_pm_state((dev),  __VA_ARGS__)
 #define mt7615_mcu_set_drv_ctrl(dev)   (dev)->mcu_ops->set_drv_ctrl((dev))
 #define mt7615_mcu_set_fw_ctrl(dev)    (dev)->mcu_ops->set_fw_ctrl((dev))
+#define mt7615_mcu_set_sta_decap_offload(dev, ...) (dev)->mcu_ops->set_sta_decap_offload((dev), __VA_ARGS__)
 struct mt7615_mcu_ops {
        int (*add_tx_ba)(struct mt7615_dev *dev,
                         struct ieee80211_ampdu_params *params,
@@ -221,6 +221,9 @@ struct mt7615_mcu_ops {
        int (*set_pm_state)(struct mt7615_dev *dev, int band, int state);
        int (*set_drv_ctrl)(struct mt7615_dev *dev);
        int (*set_fw_ctrl)(struct mt7615_dev *dev);
+       int (*set_sta_decap_offload)(struct mt7615_dev *dev,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_sta *sta);
 };
 
 struct mt7615_dev {
@@ -356,6 +359,7 @@ static inline int mt7622_wmac_init(struct mt7615_dev *dev)
 }
 #endif
 
+int mt7615_thermal_init(struct mt7615_dev *dev);
 int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
                      int irq, const u32 *map);
 u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
@@ -456,6 +460,12 @@ static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev)
        return MT_INT_TX_DONE(dev->mt76.q_mcu[MT_MCUQ_WM]->hw_idx);
 }
 
+static inline unsigned long
+mt7615_get_macwork_timeout(struct mt7615_dev *dev)
+{
+       return dev->pm.enable ? HZ / 3 : HZ / 10;
+}
+
 void mt7615_dma_reset(struct mt7615_dev *dev);
 void mt7615_scan_work(struct work_struct *work);
 void mt7615_roc_work(struct work_struct *work);
@@ -466,7 +476,7 @@ int mt7615_set_channel(struct mt7615_phy *phy);
 void mt7615_init_work(struct mt7615_dev *dev);
 
 int mt7615_mcu_restart(struct mt76_dev *dev);
-void mt7615_update_channel(struct mt76_dev *mdev);
+void mt7615_update_channel(struct mt76_phy *mphy);
 bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask);
 void mt7615_mac_reset_counters(struct mt7615_dev *dev);
 void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
@@ -494,7 +504,7 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg);
 int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val);
 int mt7615_mcu_set_dbdc(struct mt7615_dev *dev);
 int mt7615_mcu_set_eeprom(struct mt7615_dev *dev);
-int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index);
+int mt7615_mcu_get_temperature(struct mt7615_dev *dev);
 int mt7615_mcu_set_tx_power(struct mt7615_phy *phy);
 void mt7615_mcu_exit(struct mt7615_dev *dev);
 void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
@@ -518,9 +528,6 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 void mt7615_mac_work(struct work_struct *work);
 void mt7615_txp_skb_unmap(struct mt76_dev *dev,
                          struct mt76_txwi_cache *txwi);
-int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
-                                   struct ieee80211_vif *vif,
-                                   struct ieee80211_sta *sta);
 int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
 int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
 int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
index ec8ec1a..a2465b4 100644 (file)
@@ -98,7 +98,7 @@ mt7615_led_set_config(struct led_classdev *led_cdev,
        addr = mt7615_reg_map(dev, MT_LED_CTRL);
        mt76_wr(dev, addr, val);
 
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 }
 
 static int
@@ -147,8 +147,12 @@ int mt7615_register_device(struct mt7615_dev *dev)
        if (ret)
                return ret;
 
-       ret = mt76_register_device(&dev->mt76, true, mt7615_rates,
-                                  ARRAY_SIZE(mt7615_rates));
+       ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+                                  ARRAY_SIZE(mt76_rates));
+       if (ret)
+               return ret;
+
+       ret = mt7615_thermal_init(dev);
        if (ret)
                return ret;
 
index d7cbef7..da87c02 100644 (file)
@@ -131,20 +131,21 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                          struct mt76_tx_info *tx_info)
 {
        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-       struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
        struct ieee80211_key_conf *key = info->control.hw_key;
        int pid, id;
        u8 *txwi = (u8 *)txwi_ptr;
        struct mt76_txwi_cache *t;
+       struct mt7615_sta *msta;
        void *txp;
 
+       msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
        if (!wcid)
                wcid = &dev->mt76.global_wcid;
 
        pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
 
-       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
+       if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
                struct mt7615_phy *phy = &dev->phy;
 
                if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
@@ -267,6 +268,7 @@ void mt7615_mac_reset_work(struct work_struct *work)
        struct mt7615_phy *phy2;
        struct mt76_phy *ext_phy;
        struct mt7615_dev *dev;
+       unsigned long timeout;
 
        dev = container_of(work, struct mt7615_dev, reset_work);
        ext_phy = dev->mt76.phy2;
@@ -344,11 +346,11 @@ void mt7615_mac_reset_work(struct work_struct *work)
 
        mt7615_mutex_release(dev);
 
+       timeout = mt7615_get_macwork_timeout(dev);
        ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
-                                    MT7615_WATCHDOG_TIME);
+                                    timeout);
        if (phy2)
                ieee80211_queue_delayed_work(ext_phy->hw,
-                                            &phy2->mt76->mac_work,
-                                            MT7615_WATCHDOG_TIME);
+                                            &phy2->mt76->mac_work, timeout);
 
 }
index 63c081b..6712ad9 100644 (file)
@@ -463,7 +463,9 @@ enum mt7615_reg_base {
 #define MT_LPON_TCR0(_n)               MT_LPON(0x010 + ((_n) * 4))
 #define MT_LPON_TCR2(_n)               MT_LPON(0x0f8 + ((_n) - 2) * 4)
 #define MT_LPON_TCR_MODE               GENMASK(1, 0)
+#define MT_LPON_TCR_READ               GENMASK(1, 0)
 #define MT_LPON_TCR_WRITE              BIT(0)
+#define MT_LPON_TCR_ADJUST             BIT(1)
 
 #define MT_LPON_UTTR0                  MT_LPON(0x018)
 #define MT_LPON_UTTR1                  MT_LPON(0x01c)
index 0518097..03877d8 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: ISC
+/* SPDX-License-Identifier: ISC */
 /* Copyright (C) 2020 MediaTek Inc.
  *
  * Author: Sean Wang <sean.wang@mediatek.com>
index d1be78b..45c1cd3 100644 (file)
@@ -55,6 +55,7 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
 {
        struct sdio_func *func = dev->mt76.sdio.func;
        struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt76_connac_pm *pm = &dev->pm;
        u32 status;
        int ret;
 
@@ -66,37 +67,45 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
                                 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
        if (ret < 0) {
                dev_err(dev->mt76.dev, "Cannot get ownership from device");
-               set_bit(MT76_STATE_PM, &mphy->state);
-               sdio_release_host(func);
+       } else {
+               clear_bit(MT76_STATE_PM, &mphy->state);
 
-               return ret;
+               pm->stats.last_wake_event = jiffies;
+               pm->stats.doze_time += pm->stats.last_wake_event -
+                                      pm->stats.last_doze_event;
        }
-
        sdio_release_host(func);
-       dev->pm.last_activity = jiffies;
 
-       return 0;
+       return ret;
 }
 
 static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
 {
        struct mt76_phy *mphy = &dev->mt76.phy;
+       int ret = 0;
 
-       if (test_and_clear_bit(MT76_STATE_PM, &mphy->state))
-               return __mt7663s_mcu_drv_pmctrl(dev);
+       mutex_lock(&dev->pm.mutex);
 
-       return 0;
+       if (test_bit(MT76_STATE_PM, &mphy->state))
+               ret = __mt7663s_mcu_drv_pmctrl(dev);
+
+       mutex_unlock(&dev->pm.mutex);
+
+       return ret;
 }
 
 static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
 {
        struct sdio_func *func = dev->mt76.sdio.func;
        struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt76_connac_pm *pm = &dev->pm;
+       int ret = 0;
        u32 status;
-       int ret;
 
-       if (test_and_set_bit(MT76_STATE_PM, &mphy->state))
-               return 0;
+       mutex_lock(&pm->mutex);
+
+       if (mt76_connac_skip_fw_pmctrl(mphy, pm))
+               goto out;
 
        sdio_claim_host(func);
 
@@ -107,9 +116,15 @@ static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
        if (ret < 0) {
                dev_err(dev->mt76.dev, "Cannot set ownership to device");
                clear_bit(MT76_STATE_PM, &mphy->state);
+       } else {
+               pm->stats.last_doze_event = jiffies;
+               pm->stats.awake_time += pm->stats.last_doze_event -
+                                       pm->stats.last_wake_event;
        }
 
        sdio_release_host(func);
+out:
+       mutex_unlock(&pm->mutex);
 
        return ret;
 }
index 4393dd2..04f4c89 100644 (file)
@@ -283,9 +283,15 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
 {
        struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
                                              txrx_worker);
-       struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
+       struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
+       struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
        int i, nframes, ret;
 
+       if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
+               queue_work(mdev->wq, &dev->pm.wake_work);
+               return;
+       }
+
        /* disable interrupt */
        sdio_claim_host(sdio->func);
        sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
@@ -295,16 +301,16 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
 
                /* tx */
                for (i = 0; i <= MT_TXQ_PSD; i++) {
-                       ret = mt7663s_tx_run_queue(dev, dev->phy.q_tx[i]);
+                       ret = mt7663s_tx_run_queue(mdev, mdev->phy.q_tx[i]);
                        if (ret > 0)
                                nframes += ret;
                }
-               ret = mt7663s_tx_run_queue(dev, dev->q_mcu[MT_MCUQ_WM]);
+               ret = mt7663s_tx_run_queue(mdev, mdev->q_mcu[MT_MCUQ_WM]);
                if (ret > 0)
                        nframes += ret;
 
                /* rx */
-               ret = mt7663s_rx_handler(dev);
+               ret = mt7663s_rx_handler(mdev);
                if (ret > 0)
                        nframes += ret;
        } while (nframes > 0);
@@ -312,6 +318,8 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
        /* enable interrupt */
        sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
        sdio_release_host(sdio->func);
+
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 }
 
 void mt7663s_sdio_irq(struct sdio_func *func)
index f8d3673..996d48c 100644 (file)
@@ -123,7 +123,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
        idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
        addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
 
-       mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
+       mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */
        val = mt76_rr(dev, MT_LPON_UTTR0);
        sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset;
 
@@ -191,14 +191,15 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                                   struct ieee80211_sta *sta,
                                   struct mt76_tx_info *tx_info)
 {
-       struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
        struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
        struct sk_buff *skb = tx_info->skb;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct mt7615_sta *msta;
        int pad;
 
+       msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
        if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
-           !msta->rate_probe) {
+           msta && !msta->rate_probe) {
                /* request to configure sampling rate */
                spin_lock_bh(&dev->mt76.lock);
                mt7615_mac_set_rates(&dev->phy, msta, &info->control.rates[0],
@@ -323,8 +324,8 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev)
                        hw->max_tx_fragments = 1;
        }
 
-       err = mt76_register_device(&dev->mt76, true, mt7615_rates,
-                                  ARRAY_SIZE(mt7615_rates));
+       err = mt76_register_device(&dev->mt76, true, mt76_rates,
+                                  ARRAY_SIZE(mt76_rates));
        if (err < 0)
                return err;
 
index 6c889b9..f49d97d 100644 (file)
@@ -7,12 +7,13 @@
 #include "mt76.h"
 
 #define MT76_CONNAC_SCAN_IE_LEN                        600
-#define MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL    10
+#define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL         10
+#define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX
 #define MT76_CONNAC_MAX_SCHED_SCAN_SSID                10
 #define MT76_CONNAC_MAX_SCAN_MATCH             16
 
 #define MT76_CONNAC_COREDUMP_TIMEOUT           (HZ / 20)
-#define MT76_CONNAC_COREDUMP_SZ                        (128 * 1024)
+#define MT76_CONNAC_COREDUMP_SZ                        (1300 * 1024)
 
 enum {
        CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
@@ -45,6 +46,8 @@ enum {
 
 struct mt76_connac_pm {
        bool enable;
+       bool ds_enable;
+       bool suspended;
 
        spinlock_t txq_lock;
        struct {
@@ -116,19 +119,27 @@ out:
 }
 
 static inline void
-mt76_connac_pm_unref(struct mt76_connac_pm *pm)
+mt76_connac_pm_unref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
 {
        spin_lock_bh(&pm->wake.lock);
-       pm->wake.count--;
+
        pm->last_activity = jiffies;
+       if (--pm->wake.count == 0 &&
+           test_bit(MT76_STATE_MCU_RUNNING, &phy->state))
+               mt76_connac_power_save_sched(phy, pm);
+
        spin_unlock_bh(&pm->wake.lock);
 }
 
 static inline bool
 mt76_connac_skip_fw_pmctrl(struct mt76_phy *phy, struct mt76_connac_pm *pm)
 {
+       struct mt76_dev *dev = phy->dev;
        bool ret;
 
+       if (dev->token_count)
+               return true;
+
        spin_lock_bh(&pm->wake.lock);
        ret = pm->wake.count || test_and_set_bit(MT76_STATE_PM, &phy->state);
        spin_unlock_bh(&pm->wake.lock);
index 6f180c9..af43bcb 100644 (file)
@@ -10,13 +10,16 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
        if (!pm->enable)
                return 0;
 
-       if (!mt76_is_mmio(dev))
+       if (mt76_is_usb(dev))
                return 0;
 
        cancel_delayed_work_sync(&pm->ps_work);
        if (!test_bit(MT76_STATE_PM, &phy->state))
                return 0;
 
+       if (pm->suspended)
+               return 0;
+
        queue_work(dev->wq, &pm->wake_work);
        if (!wait_event_timeout(pm->wait,
                                !test_bit(MT76_STATE_PM, &phy->state),
@@ -34,12 +37,15 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy,
 {
        struct mt76_dev *dev = phy->dev;
 
-       if (!mt76_is_mmio(dev))
+       if (mt76_is_usb(dev))
                return;
 
        if (!pm->enable)
                return;
 
+       if (pm->suspended)
+               return;
+
        pm->last_activity = jiffies;
 
        if (!test_bit(MT76_STATE_PM, &phy->state)) {
index 6195616..5c3a81e 100644 (file)
@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req);
 void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
                                   struct ieee80211_vif *vif,
                                   struct ieee80211_sta *sta,
-                                  bool enable)
+                                  bool enable, bool newly)
 {
        struct sta_rec_basic *basic;
        struct tlv *tlv;
@@ -316,7 +316,8 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
        basic->extra_info = cpu_to_le16(EXTRA_INFO_VER);
 
        if (enable) {
-               basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
+               if (newly)
+                       basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
                basic->conn_state = CONN_STATE_PORT_SECURE;
        } else {
                basic->conn_state = CONN_STATE_DISCONNECT;
@@ -393,6 +394,7 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
 }
 
 void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
+                                       struct ieee80211_vif *vif,
                                        struct mt76_wcid *wcid,
                                        void *sta_wtbl, void *wtbl_tlv)
 {
@@ -404,9 +406,46 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
                                             wtbl_tlv, sta_wtbl);
        htr = (struct wtbl_hdr_trans *)tlv;
        htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
+
+       if (vif->type == NL80211_IFTYPE_STATION)
+               htr->to_ds = true;
+       else
+               htr->from_ds = true;
+
+       if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
+               htr->to_ds = true;
+               htr->from_ds = true;
+       }
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
 
+int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
+                                        struct ieee80211_vif *vif,
+                                        struct mt76_wcid *wcid, int cmd)
+{
+       struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
+       struct wtbl_req_hdr *wtbl_hdr;
+       struct tlv *sta_wtbl;
+       struct sk_buff *skb;
+
+       skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
+                                          sizeof(struct tlv));
+
+       wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET,
+                                                 sta_wtbl, &skb);
+       if (IS_ERR(wtbl_hdr))
+               return PTR_ERR(wtbl_hdr);
+
+       mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, sta_wtbl, wtbl_hdr);
+
+       return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_update_hdr_trans);
+
 void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
                                      struct sk_buff *skb,
                                      struct ieee80211_vif *vif,
@@ -671,7 +710,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
                             struct ieee80211_sta *sta,
                             struct ieee80211_vif *vif,
-                            u8 rcpi)
+                            u8 rcpi, u8 sta_state)
 {
        struct cfg80211_chan_def *chandef = &mphy->chandef;
        enum nl80211_band band = chandef->chan->band;
@@ -736,7 +775,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
 
        tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state));
        state = (struct sta_rec_state *)tlv;
-       state->state = 2;
+       state->state = sta_state;
 
        if (sta->vht_cap.vht_supported) {
                state->vht_opmode = sta->bandwidth;
@@ -828,8 +867,8 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);
 
-int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-                               struct mt76_sta_cmd_info *info)
+int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
+                           struct mt76_sta_cmd_info *info)
 {
        struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
        struct mt76_dev *dev = phy->dev;
@@ -841,10 +880,13 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
-       mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, info->enable);
-       if (info->enable && info->sta)
-               mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif,
-                                       info->rcpi);
+       if (info->sta || !info->offload_fw)
+               mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta,
+                                             info->enable, info->newly);
+       if (info->sta && info->enable)
+               mt76_connac_mcu_sta_tlv(phy, skb, info->sta,
+                                       info->vif, info->rcpi,
+                                       info->state);
 
        sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
                                           sizeof(struct tlv));
@@ -859,6 +901,8 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
                mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
                                                 info->sta, sta_wtbl,
                                                 wtbl_hdr);
+               mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,
+                                                  sta_wtbl, wtbl_hdr);
                if (info->sta)
                        mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
                                                    sta_wtbl, wtbl_hdr);
@@ -866,7 +910,7 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
 
        return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
 }
-EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd);
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_cmd);
 
 void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                 struct ieee80211_ampdu_params *params,
@@ -895,8 +939,10 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                ba->rst_ba_sb = 1;
        }
 
-       if (is_mt7921(dev))
+       if (is_mt7921(dev)) {
+               ba->ba_winsize = enable ? cpu_to_le16(params->buf_size) : 0;
                return;
+       }
 
        if (enable && tx) {
                u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
@@ -1271,6 +1317,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
                                u8 pad[3];
                        } __packed hdr;
                        struct bss_info_uni_he he;
+                       struct bss_info_uni_bss_color bss_color;
                } he_req = {
                        .hdr = {
                                .bss_idx = mvif->idx,
@@ -1279,8 +1326,21 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
                                .tag = cpu_to_le16(UNI_BSS_INFO_HE_BASIC),
                                .len = cpu_to_le16(sizeof(struct bss_info_uni_he)),
                        },
+                       .bss_color = {
+                               .tag = cpu_to_le16(UNI_BSS_INFO_BSS_COLOR),
+                               .len = cpu_to_le16(sizeof(struct bss_info_uni_bss_color)),
+                               .enable = 0,
+                               .bss_color = 0,
+                       },
                };
 
+               if (enable) {
+                       he_req.bss_color.enable =
+                               vif->bss_conf.he_bss_color.enabled;
+                       he_req.bss_color.bss_color =
+                               vif->bss_conf.he_bss_color.color;
+               }
+
                mt76_connac_mcu_uni_bss_he_tlv(phy, vif,
                                               (struct tlv *)&he_req.he);
                err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD_BSS_INFO_UPDATE,
@@ -1463,14 +1523,16 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
        req->version = 1;
        req->seq_num = mvif->scan_seq_num | ext_phy << 7;
 
-       if (is_mt7663(phy->dev) &&
-           (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) {
-               get_random_mask_addr(req->mt7663.random_mac, sreq->mac_addr,
-                                    sreq->mac_addr_mask);
+       if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+               u8 *addr = is_mt7663(phy->dev) ? req->mt7663.random_mac
+                                              : req->mt7921.random_mac;
+
                req->scan_func = 1;
-       } else if (is_mt7921(phy->dev)) {
-               req->mt7921.bss_idx = mvif->idx;
+               get_random_mask_addr(addr, sreq->mac_addr,
+                                    sreq->mac_addr_mask);
        }
+       if (is_mt7921(phy->dev))
+               req->mt7921.bss_idx = mvif->idx;
 
        req->ssids_num = sreq->n_ssids;
        for (i = 0; i < req->ssids_num; i++) {
@@ -1556,6 +1618,26 @@ int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable)
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_deep_sleep);
 
+int mt76_connac_sta_state_dp(struct mt76_dev *dev,
+                            enum ieee80211_sta_state old_state,
+                            enum ieee80211_sta_state new_state)
+{
+       if ((old_state == IEEE80211_STA_ASSOC &&
+            new_state == IEEE80211_STA_AUTHORIZED) ||
+           (old_state == IEEE80211_STA_NONE &&
+            new_state == IEEE80211_STA_NOTEXIST))
+               mt76_connac_mcu_set_deep_sleep(dev, true);
+
+       if ((old_state == IEEE80211_STA_NOTEXIST &&
+            new_state == IEEE80211_STA_NONE) ||
+           (old_state == IEEE80211_STA_AUTHORIZED &&
+            new_state == IEEE80211_STA_ASSOC))
+               mt76_connac_mcu_set_deep_sleep(dev, false);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_connac_sta_state_dp);
+
 void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
                                    struct mt76_connac_coredump *coredump)
 {
@@ -1570,6 +1652,60 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
 
+int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
+{
+       struct mt76_connac_cap_hdr {
+               __le16 n_element;
+               u8 rsv[2];
+       } __packed * hdr;
+       struct sk_buff *skb;
+       int ret, i;
+
+       ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CMD_GET_NIC_CAPAB, NULL,
+                                       0, true, &skb);
+       if (ret)
+               return ret;
+
+       hdr = (struct mt76_connac_cap_hdr *)skb->data;
+       if (skb->len < sizeof(*hdr)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       skb_pull(skb, sizeof(*hdr));
+
+       for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
+               struct tlv_hdr {
+                       __le32 type;
+                       __le32 len;
+               } __packed * tlv = (struct tlv_hdr *)skb->data;
+               int len;
+
+               if (skb->len < sizeof(*tlv))
+                       break;
+
+               skb_pull(skb, sizeof(*tlv));
+
+               len = le32_to_cpu(tlv->len);
+               if (skb->len < len)
+                       break;
+
+               switch (le32_to_cpu(tlv->type)) {
+               case MT_NIC_CAP_6G:
+                       phy->cap.has_6ghz = skb->data[0];
+                       break;
+               default:
+                       break;
+               }
+               skb_pull(skb, len);
+       }
+out:
+       dev_kfree_skb(skb);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_get_nic_capability);
+
 static void
 mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
                          struct mt76_power_limits *limits,
@@ -1632,12 +1768,15 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
                142, 144, 149, 151, 153, 155, 157,
                159, 161, 165
        };
+       int i, n_chan, batch_size, idx = 0, tx_power, last_ch;
        struct mt76_connac_sku_tlv sku_tlbv;
-       int i, n_chan, batch_size, idx = 0;
        struct mt76_power_limits limits;
        const u8 *ch_list;
 
        sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
+       tx_power = 2 * phy->hw->conf.power_level;
+       if (!tx_power)
+               tx_power = 127;
 
        if (band == NL80211_BAND_2GHZ) {
                n_chan = ARRAY_SIZE(chan_list_2ghz);
@@ -1648,39 +1787,48 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
        }
        batch_size = DIV_ROUND_UP(n_chan, batch_len);
 
+       if (!phy->cap.has_5ghz)
+               last_ch = chan_list_2ghz[n_chan - 1];
+       else
+               last_ch = chan_list_5ghz[n_chan - 1];
+
        for (i = 0; i < batch_size; i++) {
-               bool last_msg = i == batch_size - 1;
-               int num_ch = last_msg ? n_chan % batch_len : batch_len;
                struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {
                        .band = band == NL80211_BAND_2GHZ ? 1 : 2,
-                       .n_chan = num_ch,
-                       .last_msg = last_msg,
                };
+               int j, err, msg_len, num_ch;
                struct sk_buff *skb;
-               int j, err, msg_len;
 
+               num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len;
                msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
                skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
                if (!skb)
                        return -ENOMEM;
 
+               skb_reserve(skb, sizeof(tx_power_tlv));
+
                BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv.alpha2));
                memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));
+               tx_power_tlv.n_chan = num_ch;
 
-               skb_put_data(skb, &tx_power_tlv, sizeof(tx_power_tlv));
                for (j = 0; j < num_ch; j++, idx++) {
                        struct ieee80211_channel chan = {
                                .hw_value = ch_list[idx],
                                .band = band,
                        };
 
-                       mt76_get_rate_power_limits(phy, &chan, &limits, 127);
+                       mt76_get_rate_power_limits(phy, &chan, &limits,
+                                                  tx_power);
 
+                       tx_power_tlv.last_msg = ch_list[idx] == last_ch;
                        sku_tlbv.channel = ch_list[idx];
+
                        mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
                                                  &limits, band);
                        skb_put_data(skb, &sku_tlbv, sku_len);
                }
+               __skb_push(skb, sizeof(tx_power_tlv));
+               memcpy(skb->data, &tx_power_tlv, sizeof(tx_power_tlv));
 
                err = mt76_mcu_skb_send_msg(dev, skb,
                                            MCU_CMD_SET_RATE_TX_POWER, false);
@@ -1695,11 +1843,20 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
 {
        int err;
 
-       err = mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_2GHZ);
-       if (err < 0)
-               return err;
+       if (phy->cap.has_2ghz) {
+               err = mt76_connac_mcu_rate_txpower_band(phy,
+                                                       NL80211_BAND_2GHZ);
+               if (err < 0)
+                       return err;
+       }
+       if (phy->cap.has_5ghz) {
+               err = mt76_connac_mcu_rate_txpower_band(phy,
+                                                       NL80211_BAND_5GHZ);
+               if (err < 0)
+                       return err;
+       }
 
-       return mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_5GHZ);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
 
@@ -1939,7 +2096,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
        ptlv->index = index;
 
        memcpy(ptlv->pattern, pattern->pattern, pattern->pattern_len);
-       memcpy(ptlv->mask, pattern->mask, pattern->pattern_len / 8);
+       memcpy(ptlv->mask, pattern->mask, DIV_ROUND_UP(pattern->pattern_len, 8));
 
        return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD_SUSPEND, true);
 }
@@ -1974,14 +2131,17 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
        };
 
        if (wowlan->magic_pkt)
-               req.wow_ctrl_tlv.trigger |= BIT(0);
+               req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_MAGIC;
        if (wowlan->disconnect)
-               req.wow_ctrl_tlv.trigger |= BIT(2);
+               req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |
+                                            UNI_WOW_DETECT_TYPE_BCN_LOST);
        if (wowlan->nd_config) {
                mt76_connac_mcu_sched_scan_req(phy, vif, wowlan->nd_config);
-               req.wow_ctrl_tlv.trigger |= BIT(5);
+               req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;
                mt76_connac_mcu_sched_scan_enable(phy, vif, suspend);
        }
+       if (wowlan->n_patterns)
+               req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_BITMAP;
 
        if (mt76_is_mmio(dev))
                req.wow_ctrl_tlv.wakeup_hif = WOW_PCIE;
index a109686..1c73beb 100644 (file)
@@ -559,6 +559,7 @@ enum {
        MCU_CMD_SET_RATE_TX_POWER = MCU_CE_PREFIX | 0x5d,
        MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
        MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
+       MCU_CMD_GET_NIC_CAPAB = MCU_CE_PREFIX | 0x8a,
        MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0,
        MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0,
        MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca,
@@ -575,6 +576,7 @@ enum {
 enum {
        UNI_BSS_INFO_BASIC = 0,
        UNI_BSS_INFO_RLM = 2,
+       UNI_BSS_INFO_BSS_COLOR = 4,
        UNI_BSS_INFO_HE_BASIC = 5,
        UNI_BSS_INFO_BCN_CONTENT = 7,
        UNI_BSS_INFO_QBSS = 15,
@@ -590,6 +592,36 @@ enum {
        UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
 };
 
+enum {
+       MT_NIC_CAP_TX_RESOURCE,
+       MT_NIC_CAP_TX_EFUSE_ADDR,
+       MT_NIC_CAP_COEX,
+       MT_NIC_CAP_SINGLE_SKU,
+       MT_NIC_CAP_CSUM_OFFLOAD,
+       MT_NIC_CAP_HW_VER,
+       MT_NIC_CAP_SW_VER,
+       MT_NIC_CAP_MAC_ADDR,
+       MT_NIC_CAP_PHY,
+       MT_NIC_CAP_MAC,
+       MT_NIC_CAP_FRAME_BUF,
+       MT_NIC_CAP_BEAM_FORM,
+       MT_NIC_CAP_LOCATION,
+       MT_NIC_CAP_MUMIMO,
+       MT_NIC_CAP_BUFFER_MODE_INFO,
+       MT_NIC_CAP_HW_ADIE_VERSION = 0x14,
+       MT_NIC_CAP_ANTSWP = 0x16,
+       MT_NIC_CAP_WFDMA_REALLOC,
+       MT_NIC_CAP_6G,
+};
+
+#define UNI_WOW_DETECT_TYPE_MAGIC              BIT(0)
+#define UNI_WOW_DETECT_TYPE_ANY                        BIT(1)
+#define UNI_WOW_DETECT_TYPE_DISCONNECT         BIT(2)
+#define UNI_WOW_DETECT_TYPE_GTK_REKEY_FAIL     BIT(3)
+#define UNI_WOW_DETECT_TYPE_BCN_LOST           BIT(4)
+#define UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT       BIT(5)
+#define UNI_WOW_DETECT_TYPE_BITMAP             BIT(6)
+
 enum {
        UNI_SUSPEND_MODE_SETTING,
        UNI_SUSPEND_WOW_CTRL,
@@ -762,7 +794,7 @@ struct mt76_connac_sched_scan_req {
        u8 intervals_num;
        u8 scan_func; /* MT7663: BIT(0) eable random mac address */
        struct mt76_connac_mcu_scan_channel channels[64];
-       __le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL];
+       __le16 intervals[MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL];
        union {
                struct {
                        u8 random_mac[ETH_ALEN];
@@ -770,7 +802,9 @@ struct mt76_connac_sched_scan_req {
                } mt7663;
                struct {
                        u8 bss_idx;
-                       u8 pad2[63];
+                       u8 pad2[19];
+                       u8 random_mac[ETH_ALEN];
+                       u8 pad3[38];
                } mt7921;
        };
 } __packed;
@@ -781,6 +815,14 @@ struct mt76_connac_sched_scan_done {
        __le16 pad;
 } __packed;
 
+struct bss_info_uni_bss_color {
+       __le16 tag;
+       __le16 len;
+       u8 enable;
+       u8 bss_color;
+       u8 rsv[2];
+} __packed;
+
 struct bss_info_uni_he {
        __le16 tag;
        __le16 len;
@@ -885,15 +927,24 @@ struct mt76_connac_suspend_tlv {
        u8 pad[5];
 } __packed;
 
+enum mt76_sta_info_state {
+       MT76_STA_INFO_STATE_NONE,
+       MT76_STA_INFO_STATE_AUTH,
+       MT76_STA_INFO_STATE_ASSOC
+};
+
 struct mt76_sta_cmd_info {
        struct ieee80211_sta *sta;
        struct mt76_wcid *wcid;
 
        struct ieee80211_vif *vif;
 
+       bool offload_fw;
        bool enable;
+       bool newly;
        int cmd;
        u8 rcpi;
+       u8 state;
 };
 
 #define MT_SKU_POWER_LIMIT     161
@@ -963,18 +1014,23 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
 int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
 void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
                                   struct ieee80211_vif *vif,
-                                  struct ieee80211_sta *sta, bool enable);
+                                  struct ieee80211_sta *sta, bool enable,
+                                  bool newly);
 void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                      struct ieee80211_vif *vif,
                                      struct ieee80211_sta *sta, void *sta_wtbl,
                                      void *wtbl_tlv);
 void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
+                                       struct ieee80211_vif *vif,
                                        struct mt76_wcid *wcid,
                                        void *sta_wtbl, void *wtbl_tlv);
+int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
+                                        struct ieee80211_vif *vif,
+                                        struct mt76_wcid *wcid, int cmd);
 void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
                             struct ieee80211_sta *sta,
                             struct ieee80211_vif *vif,
-                            u8 rcpi);
+                            u8 rcpi, u8 state);
 void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
                                 struct ieee80211_sta *sta, void *sta_wtbl,
                                 void *wtbl_tlv);
@@ -996,8 +1052,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
                                struct ieee80211_vif *vif,
                                struct mt76_wcid *wcid,
                                bool enable);
-int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-                               struct mt76_sta_cmd_info *info);
+int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
+                           struct mt76_sta_cmd_info *info);
 void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
                                      struct ieee80211_vif *vif);
 int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);
@@ -1008,6 +1064,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
 int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
 int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
 int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
+int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy);
 
 int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
                            struct ieee80211_scan_request *scan_req);
@@ -1028,6 +1085,9 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
 int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
 void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
                                      struct ieee80211_vif *vif);
+int mt76_connac_sta_state_dp(struct mt76_dev *dev,
+                            enum ieee80211_sta_state old_state,
+                            enum ieee80211_sta_state new_state);
 int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
 int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
 void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
index dd66fd1..cea2421 100644 (file)
@@ -68,7 +68,7 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
                nic_conf1 &= 0xff00;
 
        if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
-               dev_err(dev->mt76.dev,
+               dev_dbg(dev->mt76.dev,
                        "driver does not support HW RF ctrl\n");
 
        if (!mt76x02_field_valid(nic_conf0 >> 8))
index 0da3786..c32e6dc 100644 (file)
@@ -34,24 +34,24 @@ mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
 {
        memset(key_data, 0, 32);
        if (!key)
-               return MT_CIPHER_NONE;
+               return MT76X02_CIPHER_NONE;
 
        if (key->keylen > 32)
-               return MT_CIPHER_NONE;
+               return MT76X02_CIPHER_NONE;
 
        memcpy(key_data, key->key, key->keylen);
 
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_WEP40:
-               return MT_CIPHER_WEP40;
+               return MT76X02_CIPHER_WEP40;
        case WLAN_CIPHER_SUITE_WEP104:
-               return MT_CIPHER_WEP104;
+               return MT76X02_CIPHER_WEP104;
        case WLAN_CIPHER_SUITE_TKIP:
-               return MT_CIPHER_TKIP;
+               return MT76X02_CIPHER_TKIP;
        case WLAN_CIPHER_SUITE_CCMP:
-               return MT_CIPHER_AES_CCMP;
+               return MT76X02_CIPHER_AES_CCMP;
        default:
-               return MT_CIPHER_NONE;
+               return MT76X02_CIPHER_NONE;
        }
 }
 
@@ -63,7 +63,7 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx,
        u32 val;
 
        cipher = mt76x02_mac_get_key_info(key, key_data);
-       if (cipher == MT_CIPHER_NONE && key)
+       if (cipher == MT76X02_CIPHER_NONE && key)
                return -EOPNOTSUPP;
 
        val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
@@ -91,10 +91,10 @@ void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx,
        eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4);
 
        pn = (u64)eiv << 16;
-       if (cipher == MT_CIPHER_TKIP) {
+       if (cipher == MT76X02_CIPHER_TKIP) {
                pn |= (iv >> 16) & 0xff;
                pn |= (iv & 0xff) << 8;
-       } else if (cipher >= MT_CIPHER_AES_CCMP) {
+       } else if (cipher >= MT76X02_CIPHER_AES_CCMP) {
                pn |= iv & 0xffff;
        } else {
                return;
@@ -112,7 +112,7 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
        u64 pn;
 
        cipher = mt76x02_mac_get_key_info(key, key_data);
-       if (cipher == MT_CIPHER_NONE && key)
+       if (cipher == MT76X02_CIPHER_NONE && key)
                return -EOPNOTSUPP;
 
        mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
@@ -126,16 +126,16 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx,
                pn = atomic64_read(&key->tx_pn);
 
                iv_data[3] = key->keyidx << 6;
-               if (cipher >= MT_CIPHER_TKIP) {
+               if (cipher >= MT76X02_CIPHER_TKIP) {
                        iv_data[3] |= 0x20;
                        put_unaligned_le32(pn >> 16, &iv_data[4]);
                }
 
-               if (cipher == MT_CIPHER_TKIP) {
+               if (cipher == MT76X02_CIPHER_TKIP) {
                        iv_data[0] = (pn >> 8) & 0xff;
                        iv_data[1] = (iv_data[0] | 0x20) & 0x7f;
                        iv_data[2] = pn & 0xff;
-               } else if (cipher >= MT_CIPHER_AES_CCMP) {
+               } else if (cipher >= MT76X02_CIPHER_AES_CCMP) {
                        put_unaligned_le16((pn & 0xffff), &iv_data[0]);
                }
        }
@@ -1022,12 +1022,12 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
                mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]);
 }
 
-void mt76x02_update_channel(struct mt76_dev *mdev)
+void mt76x02_update_channel(struct mt76_phy *mphy)
 {
-       struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
+       struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76);
        struct mt76_channel_state *state;
 
-       state = mdev->phy.chan_state;
+       state = mphy->chan_state;
        state->cc_busy += mt76_rr(dev, MT_CH_BUSY);
 
        spin_lock_bh(&dev->mt76.cc_lock);
@@ -1169,7 +1169,7 @@ void mt76x02_mac_work(struct work_struct *work)
 
        mutex_lock(&dev->mt76.mutex);
 
-       mt76_update_survey(&dev->mt76);
+       mt76_update_survey(&dev->mphy);
        for (i = 0, idx = 0; i < 16; i++) {
                u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i));
 
index 0cfbaca..5dc6c83 100644 (file)
@@ -195,7 +195,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
                            struct ieee80211_sta *sta, int len);
 void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq);
 void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
-void mt76x02_update_channel(struct mt76_dev *mdev);
+void mt76x02_update_channel(struct mt76_phy *mphy);
 void mt76x02_mac_work(struct work_struct *work);
 
 void mt76x02_mac_cc_reset(struct mt76x02_dev *dev);
index 3e72227..fa7872a 100644 (file)
@@ -692,15 +692,15 @@ struct mt76_wcid_key {
 } __packed __aligned(4);
 
 enum mt76x02_cipher_type {
-       MT_CIPHER_NONE,
-       MT_CIPHER_WEP40,
-       MT_CIPHER_WEP104,
-       MT_CIPHER_TKIP,
-       MT_CIPHER_AES_CCMP,
-       MT_CIPHER_CKIP40,
-       MT_CIPHER_CKIP104,
-       MT_CIPHER_CKIP128,
-       MT_CIPHER_WAPI,
+       MT76X02_CIPHER_NONE,
+       MT76X02_CIPHER_WEP40,
+       MT76X02_CIPHER_WEP104,
+       MT76X02_CIPHER_TKIP,
+       MT76X02_CIPHER_AES_CCMP,
+       MT76X02_CIPHER_CKIP40,
+       MT76X02_CIPHER_CKIP104,
+       MT76X02_CIPHER_CKIP128,
+       MT76X02_CIPHER_WAPI,
 };
 
 #endif
index 02db5d6..ccdbab3 100644 (file)
@@ -7,24 +7,18 @@
 #include <linux/module.h>
 #include "mt76x02.h"
 
-#define CCK_RATE(_idx, _rate) {                                        \
+#define MT76x02_CCK_RATE(_idx, _rate) {                                        \
        .bitrate = _rate,                                       \
        .flags = IEEE80211_RATE_SHORT_PREAMBLE,                 \
        .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),            \
        .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + (_idx)),        \
 }
 
-#define OFDM_RATE(_idx, _rate) {                               \
-       .bitrate = _rate,                                       \
-       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),           \
-       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),     \
-}
-
 struct ieee80211_rate mt76x02_rates[] = {
-       CCK_RATE(0, 10),
-       CCK_RATE(1, 20),
-       CCK_RATE(2, 55),
-       CCK_RATE(3, 110),
+       MT76x02_CCK_RATE(0, 10),
+       MT76x02_CCK_RATE(1, 20),
+       MT76x02_CCK_RATE(2, 55),
+       MT76x02_CCK_RATE(3, 110),
        OFDM_RATE(0, 60),
        OFDM_RATE(1, 90),
        OFDM_RATE(2, 120),
index 40c8061..80e4924 100644 (file)
@@ -1,4 +1,4 @@
-#SPDX-License-Identifier: ISC
+# SPDX-License-Identifier: ISC
 
 obj-$(CONFIG_MT7915E) += mt7915e.o
 
index 6a8ddee..6404824 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "mt7915.h"
 #include "eeprom.h"
+#include "mcu.h"
 
 /** global debugfs **/
 
@@ -16,7 +17,7 @@ mt7915_implicit_txbf_set(void *data, u64 val)
 
        dev->ibf = !!val;
 
-       return mt7915_mcu_set_txbf_type(dev);
+       return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
 }
 
 static int
@@ -147,6 +148,9 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
 {
        struct mt7915_dev *dev = s->private;
        bool ext_phy = phy != &dev->phy;
+       static const char * const bw[] = {
+               "BW20", "BW40", "BW80", "BW160"
+       };
        int cnt;
 
        if (!phy)
@@ -164,11 +168,16 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
        seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
 
        cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
-       seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld\n",
+       seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld",
                   FIELD_GET(MT_ETBF_RX_FB_ALL, cnt),
                   FIELD_GET(MT_ETBF_RX_FB_HE, cnt),
                   FIELD_GET(MT_ETBF_RX_FB_VHT, cnt),
                   FIELD_GET(MT_ETBF_RX_FB_HT, cnt));
+       cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
+       seq_printf(s, "%s, NC: %ld, NR: %ld\n",
+                  bw[FIELD_GET(MT_ETBF_RX_FB_BW, cnt)],
+                  FIELD_GET(MT_ETBF_RX_FB_NC, cnt),
+                  FIELD_GET(MT_ETBF_RX_FB_NR, cnt));
 
        /* Tx Beamformee Rx NDPA & Tx feedback report */
        cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
@@ -204,7 +213,7 @@ mt7915_tx_stats_show(struct seq_file *file, void *data)
        mt7915_txbf_stat_read_phy(mt7915_ext_phy(dev), file);
 
        /* Tx amsdu info */
-       seq_puts(file, "Tx MSDU stat:\n");
+       seq_puts(file, "Tx MSDU statistics:\n");
        for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) {
                stat[i] = mt76_rr(dev,  MT_PLE_AMSDU_PACK_MSDU_CNT(i));
                n += stat[i];
@@ -224,18 +233,6 @@ mt7915_tx_stats_show(struct seq_file *file, void *data)
 
 DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats);
 
-static int mt7915_read_temperature(struct seq_file *s, void *data)
-{
-       struct mt7915_dev *dev = dev_get_drvdata(s->private);
-       int temp;
-
-       /* cpu */
-       temp = mt7915_mcu_get_temperature(dev, 0);
-       seq_printf(s, "Temperature: %d\n", temp);
-
-       return 0;
-}
-
 static int
 mt7915_queues_acq(struct seq_file *s, void *data)
 {
@@ -307,54 +304,23 @@ mt7915_puts_rate_txpower(struct seq_file *s, struct mt7915_phy *phy)
                "RU26", "RU52", "RU106", "RU242/SU20",
                "RU484/SU40", "RU996/SU80", "RU2x996/SU160"
        };
-       struct mt7915_dev *dev = dev_get_drvdata(s->private);
-       bool ext_phy = phy != &dev->phy;
-       u32 reg_base;
-       int i, idx = 0;
+       s8 txpower[MT7915_SKU_RATE_NUM], *buf;
+       int i;
 
        if (!phy)
                return;
 
-       reg_base = MT_TMAC_FP0R0(ext_phy);
-       seq_printf(s, "\nBand %d\n", ext_phy);
+       seq_printf(s, "\nBand %d\n", phy != &phy->dev->phy);
 
-       for (i = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
-               u8 cnt, mcs_num = mt7915_sku_group_len[i];
-               s8 txpower[12];
-               int j;
+       mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower));
+       for (i = 0, buf = txpower; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
+               u8 mcs_num = mt7915_sku_group_len[i];
 
-               if (i == SKU_HT_BW20 || i == SKU_HT_BW40) {
-                       mcs_num = 8;
-               } else if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160) {
+               if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160)
                        mcs_num = 10;
-               } else if (i == SKU_HE_RU26) {
-                       reg_base = MT_TMAC_FP0R18(ext_phy);
-                       idx = 0;
-               }
-
-               for (j = 0, cnt = 0; j < DIV_ROUND_UP(mcs_num, 4); j++) {
-                       u32 val;
-
-                       if (i == SKU_VHT_BW160 && idx == 60) {
-                               reg_base = MT_TMAC_FP0R15(ext_phy);
-                               idx = 0;
-                       }
-
-                       val = mt76_rr(dev, reg_base + (idx / 4) * 4);
-
-                       if (idx && idx % 4)
-                               val >>= (idx % 4) * 8;
-
-                       while (val > 0 && cnt < mcs_num) {
-                               s8 pwr = FIELD_GET(MT_TMAC_FP_MASK, val);
-
-                               txpower[cnt++] = pwr;
-                               val >>= 8;
-                               idx++;
-                       }
-               }
 
-               mt76_seq_puts_array(s, sku_group_name[i], txpower, mcs_num);
+               mt76_seq_puts_array(s, sku_group_name[i], buf, mcs_num);
+               buf += mt7915_sku_group_len[i];
        }
 }
 
@@ -390,8 +356,6 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)
        debugfs_create_file("radar_trigger", 0200, dir, dev,
                            &fops_radar_trigger);
        debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
-       debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,
-                                   mt7915_read_temperature);
        debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
                                    mt7915_read_rate_txpower);
 
index 11d0b76..9182568 100644 (file)
@@ -19,39 +19,6 @@ int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc)
        return 0;
 }
 
-void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
-                        struct sk_buff *skb)
-{
-       struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-       __le32 *rxd = (__le32 *)skb->data;
-       enum rx_pkt_type type;
-
-       type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
-
-       switch (type) {
-       case PKT_TYPE_TXRX_NOTIFY:
-               mt7915_mac_tx_free(dev, skb);
-               break;
-       case PKT_TYPE_RX_EVENT:
-               mt7915_mcu_rx_event(dev, skb);
-               break;
-#ifdef CONFIG_NL80211_TESTMODE
-       case PKT_TYPE_TXRXV:
-               mt7915_mac_fill_rx_vector(dev, skb);
-               break;
-#endif
-       case PKT_TYPE_NORMAL:
-               if (!mt7915_mac_fill_rx(dev, skb)) {
-                       mt76_rx(&dev->mt76, q, skb);
-                       return;
-               }
-               fallthrough;
-       default:
-               dev_kfree_skb(skb);
-               break;
-       }
-}
-
 static void
 mt7915_tx_cleanup(struct mt7915_dev *dev)
 {
@@ -112,8 +79,6 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev)
 
 int mt7915_dma_init(struct mt7915_dev *dev)
 {
-       /* Increase buffer size to receive large VHT/HE MPDUs */
-       int rx_buf_size = MT_RX_BUF_SIZE * 2;
        u32 hif1_ofs = 0;
        int ret;
 
@@ -177,28 +142,28 @@ int mt7915_dma_init(struct mt7915_dev *dev)
        /* event from WM */
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
                               MT7915_RXQ_MCU_WM, MT7915_RX_MCU_RING_SIZE,
-                              rx_buf_size, MT_RX_EVENT_RING_BASE);
+                              MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
        if (ret)
                return ret;
 
        /* event from WA */
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
                               MT7915_RXQ_MCU_WA, MT7915_RX_MCU_RING_SIZE,
-                              rx_buf_size, MT_RX_EVENT_RING_BASE);
+                              MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
        if (ret)
                return ret;
 
        /* rx data queue */
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
                               MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE,
-                              rx_buf_size, MT_RX_DATA_RING_BASE);
+                              MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
        if (ret)
                return ret;
 
        if (dev->dbdc_support) {
                ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
                                       MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE,
-                                      rx_buf_size,
+                                      MT_RX_BUF_SIZE,
                                       MT_RX_DATA_RING_BASE + hif1_ofs);
                if (ret)
                        return ret;
@@ -207,7 +172,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
                ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA],
                                       MT7915_RXQ_MCU_WA_EXT,
                                       MT7915_RX_MCU_RING_SIZE,
-                                      rx_buf_size,
+                                      MT_RX_BUF_SIZE,
                                       MT_RX_EVENT_RING_BASE + hif1_ofs);
                if (ret)
                        return ret;
index 8ededf2..ee3d644 100644 (file)
@@ -4,22 +4,12 @@
 #include "mt7915.h"
 #include "eeprom.h"
 
-static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset)
-{
-       u8 *data = dev->mt76.eeprom.data;
-
-       if (data[offset] == 0xff && !dev->flash_mode)
-               mt7915_mcu_get_eeprom(dev, offset);
-
-       return data[offset];
-}
-
 static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
 {
        struct mt76_dev *mdev = &dev->mt76;
-       u32 val;
+       u8 *eeprom = mdev->eeprom.data;
+       u32 val = eeprom[MT_EE_DO_PRE_CAL];
 
-       val = mt7915_eeprom_read(dev, MT_EE_DO_PRE_CAL);
        if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
                return 0;
 
@@ -43,7 +33,13 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
                dev->flash_mode = true;
                ret = mt7915_eeprom_load_precal(dev);
        } else {
-               memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE);
+               u32 block_num, i;
+
+               block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE,
+                                        MT7915_EEPROM_BLOCK_SIZE);
+               for (i = 0; i < block_num; i++)
+                       mt7915_mcu_get_eeprom(dev,
+                                             i * MT7915_EEPROM_BLOCK_SIZE);
        }
 
        return ret;
@@ -52,10 +48,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
 static int mt7915_check_eeprom(struct mt7915_dev *dev)
 {
        u8 *eeprom = dev->mt76.eeprom.data;
-       u16 val;
-
-       mt7915_eeprom_read(dev, MT_EE_CHIP_ID);
-       val = get_unaligned_le16(eeprom);
+       u16 val = get_unaligned_le16(eeprom);
 
        switch (val) {
        case 0x7915:
@@ -69,9 +62,10 @@ void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
 {
        struct mt7915_dev *dev = phy->dev;
        bool ext_phy = phy != &dev->phy;
+       u8 *eeprom = dev->mt76.eeprom.data;
        u32 val;
 
-       val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);
+       val = eeprom[MT_EE_WIFI_CONF + ext_phy];
        val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
        if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
                val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
@@ -143,6 +137,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
                                   struct ieee80211_channel *chan,
                                   u8 chain_idx)
 {
+       u8 *eeprom = dev->mt76.eeprom.data;
        int index, target_power;
        bool tssi_on;
 
@@ -153,18 +148,18 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
 
        if (chan->band == NL80211_BAND_2GHZ) {
                index = MT_EE_TX0_POWER_2G + chain_idx * 3;
-               target_power = mt7915_eeprom_read(dev, index);
+               target_power = eeprom[index];
 
                if (!tssi_on)
-                       target_power += mt7915_eeprom_read(dev, index + 1);
+                       target_power += eeprom[index + 1];
        } else {
                int group = mt7915_get_channel_group(chan->hw_value);
 
                index = MT_EE_TX0_POWER_5G + chain_idx * 12;
-               target_power = mt7915_eeprom_read(dev, index + group);
+               target_power = eeprom[index + group];
 
                if (!tssi_on)
-                       target_power += mt7915_eeprom_read(dev, index + 8);
+                       target_power += eeprom[index + 8];
        }
 
        return target_power;
@@ -172,13 +167,14 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
 
 s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
 {
+       u8 *eeprom = dev->mt76.eeprom.data;
        u32 val;
        s8 delta;
 
        if (band == NL80211_BAND_2GHZ)
-               val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_2G);
+               val = eeprom[MT_EE_RATE_DELTA_2G];
        else
-               val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_5G);
+               val = eeprom[MT_EE_RATE_DELTA_5G];
 
        if (!(val & MT_EE_RATE_DELTA_EN))
                return 0;
index 033fb59..a43389a 100644 (file)
@@ -33,7 +33,7 @@ enum mt7915_eeprom_field {
 #define MT_EE_WIFI_CAL_GROUP                   BIT(0)
 #define MT_EE_WIFI_CAL_DPD                     GENMASK(2, 1)
 #define MT_EE_CAL_UNIT                         1024
-#define MT_EE_CAL_GROUP_SIZE                   (44 * MT_EE_CAL_UNIT)
+#define MT_EE_CAL_GROUP_SIZE                   (49 * MT_EE_CAL_UNIT + 16)
 #define MT_EE_CAL_DPD_SIZE                     (54 * MT_EE_CAL_UNIT)
 
 #define MT_EE_WIFI_CONF0_TX_PATH               GENMASK(2, 0)
@@ -99,12 +99,15 @@ static inline bool
 mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
 {
        u8 *eep = dev->mt76.eeprom.data;
+       u8 val = eep[MT_EE_WIFI_CONF + 7];
 
-       /* TODO: DBDC */
-       if (band == NL80211_BAND_5GHZ)
-               return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_5G;
+       if (band == NL80211_BAND_2GHZ)
+               return val & MT_EE_WIFI_CONF7_TSSI0_2G;
+
+       if (dev->dbdc_support)
+               return val & MT_EE_WIFI_CONF7_TSSI1_5G;
        else
-               return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_2G;
+               return val & MT_EE_WIFI_CONF7_TSSI0_5G;
 }
 
 extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
index 822f3aa..4798d63 100644 (file)
@@ -2,39 +2,14 @@
 /* Copyright (C) 2020 MediaTek Inc. */
 
 #include <linux/etherdevice.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/thermal.h>
 #include "mt7915.h"
 #include "mac.h"
 #include "mcu.h"
 #include "eeprom.h"
 
-#define CCK_RATE(_idx, _rate) {                                                \
-       .bitrate = _rate,                                               \
-       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                         \
-       .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),                    \
-       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),        \
-}
-
-#define OFDM_RATE(_idx, _rate) {                                       \
-       .bitrate = _rate,                                               \
-       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),                   \
-       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),             \
-}
-
-static struct ieee80211_rate mt7915_rates[] = {
-       CCK_RATE(0, 10),
-       CCK_RATE(1, 20),
-       CCK_RATE(2, 55),
-       CCK_RATE(3, 110),
-       OFDM_RATE(11, 60),
-       OFDM_RATE(15, 90),
-       OFDM_RATE(10, 120),
-       OFDM_RATE(14, 180),
-       OFDM_RATE(9,  240),
-       OFDM_RATE(13, 360),
-       OFDM_RATE(8,  480),
-       OFDM_RATE(12, 540),
-};
-
 static const struct ieee80211_iface_limit if_limits[] = {
        {
                .max = 1,
@@ -67,6 +42,117 @@ static const struct ieee80211_iface_combination if_comb[] = {
        }
 };
 
+static ssize_t mt7915_thermal_show_temp(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct mt7915_phy *phy = dev_get_drvdata(dev);
+       int temperature;
+
+       temperature = mt7915_mcu_get_temperature(phy);
+       if (temperature < 0)
+               return temperature;
+
+       /* display in millidegree celcius */
+       return sprintf(buf, "%u\n", temperature * 1000);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7915_thermal_show_temp,
+                         NULL, 0);
+
+static struct attribute *mt7915_hwmon_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(mt7915_hwmon);
+
+static int
+mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
+                                     unsigned long *state)
+{
+       *state = MT7915_THERMAL_THROTTLE_MAX;
+
+       return 0;
+}
+
+static int
+mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
+                                     unsigned long *state)
+{
+       struct mt7915_phy *phy = cdev->devdata;
+
+       *state = phy->throttle_state;
+
+       return 0;
+}
+
+static int
+mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
+                                     unsigned long state)
+{
+       struct mt7915_phy *phy = cdev->devdata;
+       int ret;
+
+       if (state > MT7915_THERMAL_THROTTLE_MAX)
+               return -EINVAL;
+
+       if (state == phy->throttle_state)
+               return 0;
+
+       ret = mt7915_mcu_set_thermal_throttling(phy, state);
+       if (ret)
+               return ret;
+
+       phy->throttle_state = state;
+
+       return 0;
+}
+
+static const struct thermal_cooling_device_ops mt7915_thermal_ops = {
+       .get_max_state = mt7915_thermal_get_max_throttle_state,
+       .get_cur_state = mt7915_thermal_get_cur_throttle_state,
+       .set_cur_state = mt7915_thermal_set_cur_throttle_state,
+};
+
+static void mt7915_unregister_thermal(struct mt7915_phy *phy)
+{
+       struct wiphy *wiphy = phy->mt76->hw->wiphy;
+
+       if (!phy->cdev)
+           return;
+
+       sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
+       thermal_cooling_device_unregister(phy->cdev);
+}
+
+static int mt7915_thermal_init(struct mt7915_phy *phy)
+{
+       struct wiphy *wiphy = phy->mt76->hw->wiphy;
+       struct thermal_cooling_device *cdev;
+       struct device *hwmon;
+
+       cdev = thermal_cooling_device_register(wiphy_name(wiphy), phy,
+                                              &mt7915_thermal_ops);
+       if (!IS_ERR(cdev)) {
+               if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
+                                     "cooling_device") < 0)
+                       thermal_cooling_device_unregister(cdev);
+               else
+                       phy->cdev = cdev;
+       }
+
+       if (!IS_REACHABLE(CONFIG_HWMON))
+               return 0;
+
+       hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
+                                                      wiphy_name(wiphy), phy,
+                                                      mt7915_hwmon_groups);
+       if (IS_ERR(hwmon))
+               return PTR_ERR(hwmon);
+
+       return 0;
+}
+
 static void
 mt7915_init_txpower(struct mt7915_dev *dev,
                    struct ieee80211_supported_band *sband)
@@ -201,7 +287,6 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
              FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
        mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
 
-       mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
        mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
 
        mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
@@ -228,20 +313,19 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
 {
        int ret;
 
-
        if (dev->dbdc_support) {
-               ret = mt7915_mcu_set_txbf_module(dev);
+               ret = mt7915_mcu_set_txbf(dev, MT_BF_MODULE_UPDATE);
                if (ret)
                        return ret;
        }
 
        /* trigger sounding packets */
-       ret = mt7915_mcu_set_txbf_sounding(dev);
+       ret = mt7915_mcu_set_txbf(dev, MT_BF_SOUNDING_ON);
        if (ret)
                return ret;
 
        /* enable eBF */
-       return mt7915_mcu_set_txbf_type(dev);
+       return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
 }
 
 static int mt7915_register_ext_phy(struct mt7915_dev *dev)
@@ -281,8 +365,12 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
        if (ret)
                goto error;
 
-       ret = mt76_register_phy(mphy, true, mt7915_rates,
-                               ARRAY_SIZE(mt7915_rates));
+       ret = mt76_register_phy(mphy, true, mt76_rates,
+                               ARRAY_SIZE(mt76_rates));
+       if (ret)
+               goto error;
+
+       ret = mt7915_thermal_init(phy);
        if (ret)
                goto error;
 
@@ -480,6 +568,9 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
        if (nss < 2)
                return;
 
+       /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
+       elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3;
+
        if (vif != NL80211_IFTYPE_AP)
                return;
 
@@ -493,9 +584,6 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
        c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
            IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
        elem->phy_cap_info[6] |= c;
-
-       /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
-       elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3;
 }
 
 static void
@@ -579,8 +667,6 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
 
                switch (i) {
                case NL80211_IFTYPE_AP:
-                       he_cap_elem->mac_cap_info[0] |=
-                               IEEE80211_HE_MAC_CAP0_TWT_RES;
                        he_cap_elem->mac_cap_info[2] |=
                                IEEE80211_HE_MAC_CAP2_BSR;
                        he_cap_elem->mac_cap_info[4] |=
@@ -594,8 +680,6 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
                                IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
                        break;
                case NL80211_IFTYPE_STATION:
-                       he_cap_elem->mac_cap_info[0] |=
-                               IEEE80211_HE_MAC_CAP0_TWT_REQ;
                        he_cap_elem->mac_cap_info[1] |=
                                IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
 
@@ -690,6 +774,7 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
        if (!phy)
                return;
 
+       mt7915_unregister_thermal(phy);
        mt76_unregister_phy(mphy);
        ieee80211_free_hw(mphy->hw);
 }
@@ -731,8 +816,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
        dev->mt76.test_ops = &mt7915_testmode_ops;
 #endif
 
-       ret = mt76_register_device(&dev->mt76, true, mt7915_rates,
-                                  ARRAY_SIZE(mt7915_rates));
+       ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+                                  ARRAY_SIZE(mt76_rates));
+       if (ret)
+               return ret;
+
+       ret = mt7915_thermal_init(&dev->phy);
        if (ret)
                return ret;
 
@@ -748,10 +837,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
 void mt7915_unregister_device(struct mt7915_dev *dev)
 {
        mt7915_unregister_ext_phy(dev);
+       mt7915_unregister_thermal(&dev->phy);
        mt76_unregister_device(&dev->mt76);
        mt7915_mcu_exit(dev);
        mt7915_tx_token_put(dev);
        mt7915_dma_cleanup(dev);
+       tasklet_disable(&dev->irq_tasklet);
 
        mt76_free_device(&dev->mt76);
 }
index 7a9759f..2462704 100644 (file)
@@ -307,7 +307,8 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
        }
 }
 
-int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
+static int
+mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
 {
        struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
        struct mt76_phy *mphy = &dev->mt76.phy;
@@ -412,14 +413,27 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
                u8 *data = (u8 *)rxd;
 
                if (status->flag & RX_FLAG_DECRYPTED) {
-                       status->iv[0] = data[5];
-                       status->iv[1] = data[4];
-                       status->iv[2] = data[3];
-                       status->iv[3] = data[2];
-                       status->iv[4] = data[1];
-                       status->iv[5] = data[0];
-
-                       insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                       switch (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1)) {
+                       case MT_CIPHER_AES_CCMP:
+                       case MT_CIPHER_CCMP_CCX:
+                       case MT_CIPHER_CCMP_256:
+                               insert_ccmp_hdr =
+                                       FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                               fallthrough;
+                       case MT_CIPHER_TKIP:
+                       case MT_CIPHER_TKIP_NO_MIC:
+                       case MT_CIPHER_GCMP:
+                       case MT_CIPHER_GCMP_256:
+                               status->iv[0] = data[5];
+                               status->iv[1] = data[4];
+                               status->iv[2] = data[3];
+                               status->iv[3] = data[2];
+                               status->iv[4] = data[1];
+                               status->iv[5] = data[0];
+                               break;
+                       default:
+                               break;
+                       }
                }
                rxd += 4;
                if ((u8 *)rxd - skb->data >= skb->len)
@@ -610,9 +624,10 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
        return 0;
 }
 
-#ifdef CONFIG_NL80211_TESTMODE
-void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
+static void
+mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
 {
+#ifdef CONFIG_NL80211_TESTMODE
        struct mt7915_phy *phy = &dev->phy;
        __le32 *rxd = (__le32 *)skb->data;
        __le32 *rxv_hdr = rxd + 2;
@@ -650,10 +665,10 @@ void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
 
        phy->test.last_freq_offset = foe;
        phy->test.last_snr = snr;
+#endif
 
        dev_kfree_skb(skb);
 }
-#endif
 
 static void
 mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -885,7 +900,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
 }
 
 void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
-                          struct sk_buff *skb, struct mt76_wcid *wcid,
+                          struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
                           struct ieee80211_key_conf *key, bool beacon)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -944,7 +959,12 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
 
        txwi[3] = cpu_to_le32(val);
        txwi[4] = 0;
-       txwi[5] = 0;
+
+       val = FIELD_PREP(MT_TXD5_PID, pid);
+       if (pid >= MT_PACKET_ID_FIRST)
+               val |= MT_TXD5_TX_STATUS_HOST;
+       txwi[5] = cpu_to_le32(val);
+
        txwi[6] = 0;
        txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
 
@@ -984,11 +1004,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
        struct ieee80211_key_conf *key = info->control.hw_key;
        struct ieee80211_vif *vif = info->control.vif;
-       struct mt76_tx_cb *cb = mt76_tx_skb_cb(tx_info->skb);
        struct mt76_txwi_cache *t;
        struct mt7915_txp *txp;
        int id, i, nbuf = tx_info->nbuf - 1;
        u8 *txwi = (u8 *)txwi_ptr;
+       int pid;
 
        if (unlikely(tx_info->skb->len <= ETH_HLEN))
                return -EINVAL;
@@ -996,10 +1016,10 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        if (!wcid)
                wcid = &dev->mt76.global_wcid;
 
-       mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
-                             false);
+       pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
 
-       cb->wcid = wcid->idx;
+       mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
+                             false);
 
        txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
        for (i = 0; i < nbuf; i++) {
@@ -1071,54 +1091,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
 }
 
 static void
-mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
-                         struct ieee80211_sta *sta, u8 stat,
-                         struct list_head *free_list)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_tx_status status = {
-               .sta = sta,
-               .info = info,
-               .skb = skb,
-               .free_list = free_list,
-       };
-       struct ieee80211_hw *hw;
-
-       if (sta) {
-               struct mt7915_sta *msta;
-
-               msta = (struct mt7915_sta *)sta->drv_priv;
-               status.rate = &msta->stats.tx_rate;
-       }
-
-#ifdef CONFIG_NL80211_TESTMODE
-       if (mt76_is_testmode_skb(mdev, skb, &hw)) {
-               struct mt7915_phy *phy = mt7915_hw_phy(hw);
-               struct ieee80211_vif *vif = phy->monitor_vif;
-               struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-
-               mt76_tx_complete_skb(mdev, mvif->sta.wcid.idx, skb);
-               return;
-       }
-#endif
-
-       hw = mt76_tx_status_get_hw(mdev, skb);
-
-       if (info->flags & IEEE80211_TX_CTL_AMPDU)
-               info->flags |= IEEE80211_TX_STAT_AMPDU;
-
-       if (stat)
-               ieee80211_tx_info_clear_status(info);
-
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
-               info->flags |= IEEE80211_TX_STAT_ACK;
-
-       info->status.tx_time = 0;
-       ieee80211_tx_status_ext(hw, &status);
-}
-
-void mt7915_txp_skb_unmap(struct mt76_dev *dev,
-                         struct mt76_txwi_cache *t)
+mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
 {
        struct mt7915_txp *txp;
        int i;
@@ -1129,7 +1102,39 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev,
                                 le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
 }
 
-void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
+static void
+mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
+                struct ieee80211_sta *sta, struct list_head *free_list)
+{
+       struct mt76_dev *mdev = &dev->mt76;
+       struct mt76_wcid *wcid;
+       __le32 *txwi;
+       u16 wcid_idx;
+
+       mt7915_txp_skb_unmap(mdev, t);
+       if (!t->skb)
+               goto out;
+
+       txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
+       if (sta) {
+               wcid = (struct mt76_wcid *)sta->drv_priv;
+               wcid_idx = wcid->idx;
+
+               if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
+                       mt7915_tx_check_aggr(sta, txwi);
+       } else {
+               wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
+       }
+
+       __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
+
+out:
+       t->skb = NULL;
+       mt76_put_txwi(mdev, t);
+}
+
+static void
+mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
 {
        struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data;
        struct mt76_dev *mdev = &dev->mt76;
@@ -1194,28 +1199,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
                if (!txwi)
                        continue;
 
-               mt7915_txp_skb_unmap(mdev, txwi);
-               if (txwi->skb) {
-                       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txwi->skb);
-                       void *txwi_ptr = mt76_get_txwi_ptr(mdev, txwi);
-
-                       if (likely(txwi->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-                               mt7915_tx_check_aggr(sta, txwi_ptr);
-
-                       if (sta && !info->tx_time_est) {
-                               struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
-                               int pending;
-
-                               pending = atomic_dec_return(&wcid->non_aql_packets);
-                               if (pending < 0)
-                                       atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
-                       }
-
-                       mt7915_tx_complete_status(mdev, txwi->skb, sta, stat, &free_list);
-                       txwi->skb = NULL;
-               }
-
-               mt76_put_txwi(mdev, txwi);
+               mt7915_txwi_free(dev, txwi, sta, &free_list);
        }
 
        mt7915_mac_sta_poll(dev);
@@ -1233,6 +1217,120 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
        }
 }
 
+static bool
+mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
+                      __le32 *txs_data)
+{
+       struct mt76_dev *mdev = &dev->mt76;
+       struct ieee80211_tx_info *info;
+       struct sk_buff_head list;
+       struct sk_buff *skb;
+
+       mt76_tx_status_lock(mdev, &list);
+       skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+       if (!skb)
+               goto out;
+
+       info = IEEE80211_SKB_CB(skb);
+       if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK)))
+               info->flags |= IEEE80211_TX_STAT_ACK;
+
+       info->status.ampdu_len = 1;
+       info->status.ampdu_ack_len = !!(info->flags &
+                                       IEEE80211_TX_STAT_ACK);
+
+       info->status.rates[0].idx = -1;
+       mt76_tx_status_skb_done(mdev, skb, &list);
+
+out:
+       mt76_tx_status_unlock(mdev, &list);
+
+       return !!skb;
+}
+
+static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
+{
+       struct mt7915_sta *msta = NULL;
+       struct mt76_wcid *wcid;
+       __le32 *txs_data = data;
+       u16 wcidx;
+       u32 txs;
+       u8 pid;
+
+       txs = le32_to_cpu(txs_data[0]);
+       if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
+               return;
+
+       txs = le32_to_cpu(txs_data[2]);
+       wcidx = FIELD_GET(MT_TXS2_WCID, txs);
+
+       txs = le32_to_cpu(txs_data[3]);
+       pid = FIELD_GET(MT_TXS3_PID, txs);
+
+       if (pid < MT_PACKET_ID_FIRST)
+               return;
+
+       if (wcidx >= MT7915_WTBL_SIZE)
+               return;
+
+       rcu_read_lock();
+
+       wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
+       if (!wcid)
+               goto out;
+
+       mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data);
+
+       if (!wcid->sta)
+               goto out;
+
+       msta = container_of(wcid, struct mt7915_sta, wcid);
+       spin_lock_bh(&dev->sta_poll_lock);
+       if (list_empty(&msta->poll_list))
+               list_add_tail(&msta->poll_list, &dev->sta_poll_list);
+       spin_unlock_bh(&dev->sta_poll_lock);
+
+out:
+       rcu_read_unlock();
+}
+
+void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+                        struct sk_buff *skb)
+{
+       struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+       __le32 *rxd = (__le32 *)skb->data;
+       __le32 *end = (__le32 *)&skb->data[skb->len];
+       enum rx_pkt_type type;
+
+       type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
+
+       switch (type) {
+       case PKT_TYPE_TXRX_NOTIFY:
+               mt7915_mac_tx_free(dev, skb);
+               break;
+       case PKT_TYPE_RX_EVENT:
+               mt7915_mcu_rx_event(dev, skb);
+               break;
+       case PKT_TYPE_TXRXV:
+               mt7915_mac_fill_rx_vector(dev, skb);
+               break;
+       case PKT_TYPE_TXS:
+               for (rxd += 2; rxd + 8 <= end; rxd += 8)
+                   mt7915_mac_add_txs(dev, rxd);
+               dev_kfree_skb(skb);
+               break;
+       case PKT_TYPE_NORMAL:
+               if (!mt7915_mac_fill_rx(dev, skb)) {
+                       mt76_rx(&dev->mt76, q, skb);
+                       return;
+               }
+               fallthrough;
+       default:
+               dev_kfree_skb(skb);
+               break;
+       }
+}
+
 void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
 {
        struct mt7915_dev *dev;
@@ -1254,15 +1352,8 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
                e->skb = t ? t->skb : NULL;
        }
 
-       if (e->skb) {
-               struct mt76_tx_cb *cb = mt76_tx_skb_cb(e->skb);
-               struct mt76_wcid *wcid;
-
-               wcid = rcu_dereference(dev->mt76.wcid[cb->wcid]);
-
-               mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0,
-                                         NULL);
-       }
+       if (e->skb)
+               mt76_tx_complete_skb(mdev, e->wcid, e->skb);
 }
 
 void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy)
@@ -1296,14 +1387,10 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy)
        memset(&dev->mt76.aggr_stats[i], 0, sizeof(dev->mt76.aggr_stats) / 2);
 
        /* reset airtime counters */
-       mt76_rr(dev, MT_MIB_SDR9(ext_phy));
-       mt76_rr(dev, MT_MIB_SDR36(ext_phy));
-       mt76_rr(dev, MT_MIB_SDR37(ext_phy));
-
-       mt76_set(dev, MT_WF_RMAC_MIB_TIME0(ext_phy),
-                MT_WF_RMAC_MIB_RXTIME_CLR);
        mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(ext_phy),
                 MT_WF_RMAC_MIB_RXTIME_CLR);
+
+       mt7915_mcu_get_chan_mib_info(phy, true);
 }
 
 void mt7915_mac_set_timing(struct mt7915_phy *phy)
@@ -1397,53 +1484,24 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
        return sum / n;
 }
 
-static void
-mt7915_phy_update_channel(struct mt76_phy *mphy, int idx)
+void mt7915_update_channel(struct mt76_phy *mphy)
 {
-       struct mt7915_dev *dev = container_of(mphy->dev, struct mt7915_dev, mt76);
        struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv;
-       struct mt76_channel_state *state;
-       u64 busy_time, tx_time, rx_time, obss_time;
+       struct mt76_channel_state *state = mphy->chan_state;
+       bool ext_phy = phy != &phy->dev->phy;
        int nf;
 
-       busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
-                                  MT_MIB_SDR9_BUSY_MASK);
-       tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
-                                MT_MIB_SDR36_TXTIME_MASK);
-       rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
-                                MT_MIB_SDR37_RXTIME_MASK);
-       obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
-                                  MT_MIB_OBSSTIME_MASK);
+       mt7915_mcu_get_chan_mib_info(phy, false);
 
-       nf = mt7915_phy_get_nf(phy, idx);
+       nf = mt7915_phy_get_nf(phy, ext_phy);
        if (!phy->noise)
                phy->noise = nf << 4;
        else if (nf)
                phy->noise += nf - (phy->noise >> 4);
 
-       state = mphy->chan_state;
-       state->cc_busy += busy_time;
-       state->cc_tx += tx_time;
-       state->cc_rx += rx_time + obss_time;
-       state->cc_bss_rx += rx_time;
        state->noise = -(phy->noise >> 4);
 }
 
-void mt7915_update_channel(struct mt76_dev *mdev)
-{
-       struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-
-       mt7915_phy_update_channel(&mdev->phy, 0);
-       if (mdev->phy2)
-               mt7915_phy_update_channel(mdev->phy2, 1);
-
-       /* reset obss airtime */
-       mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
-       if (mdev->phy2)
-               mt76_set(dev, MT_WF_RMAC_MIB_TIME0(1),
-                        MT_WF_RMAC_MIB_RXTIME_CLR);
-}
-
 static bool
 mt7915_wait_reset_state(struct mt7915_dev *dev, u32 state)
 {
@@ -1530,14 +1588,18 @@ mt7915_dma_reset(struct mt7915_dev *dev)
        mt76_set(dev, MT_WFDMA0_GLO_CFG,
                 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
        mt76_set(dev, MT_WFDMA1_GLO_CFG,
-                MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
+                MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN |
+                MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
+                MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
        if (dev->hif2) {
                mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
                        (MT_WFDMA0_GLO_CFG_TX_DMA_EN |
                         MT_WFDMA0_GLO_CFG_RX_DMA_EN));
                mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
                        (MT_WFDMA1_GLO_CFG_TX_DMA_EN |
-                        MT_WFDMA1_GLO_CFG_RX_DMA_EN));
+                        MT_WFDMA1_GLO_CFG_RX_DMA_EN |
+                        MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
+                        MT_WFDMA1_GLO_CFG_OMIT_RX_INFO));
        }
 }
 
@@ -1548,14 +1610,7 @@ void mt7915_tx_token_put(struct mt7915_dev *dev)
 
        spin_lock_bh(&dev->mt76.token_lock);
        idr_for_each_entry(&dev->mt76.token, txwi, id) {
-               mt7915_txp_skb_unmap(&dev->mt76, txwi);
-               if (txwi->skb) {
-                       struct ieee80211_hw *hw;
-
-                       hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
-                       ieee80211_free_txskb(hw, txwi->skb);
-               }
-               mt76_put_txwi(&dev->mt76, txwi);
+               mt7915_txwi_free(dev, txwi, NULL, NULL);
                dev->mt76.token_count--;
        }
        spin_unlock_bh(&dev->mt76.token_lock);
@@ -1588,11 +1643,6 @@ void mt7915_mac_reset_work(struct work_struct *work)
                set_bit(MT76_RESET, &phy2->mt76->state);
                cancel_delayed_work_sync(&phy2->mt76->mac_work);
        }
-       /* lock/unlock all queues to ensure that no tx is pending */
-       mt76_txq_schedule_all(&dev->mphy);
-       if (ext_phy)
-               mt76_txq_schedule_all(ext_phy);
-
        mt76_worker_disable(&dev->mt76.tx_worker);
        napi_disable(&dev->mt76.napi[0]);
        napi_disable(&dev->mt76.napi[1]);
@@ -1618,10 +1668,6 @@ void mt7915_mac_reset_work(struct work_struct *work)
        if (phy2)
                clear_bit(MT76_RESET, &phy2->mt76->state);
 
-       mt76_worker_enable(&dev->mt76.tx_worker);
-       napi_enable(&dev->mt76.tx_napi);
-       napi_schedule(&dev->mt76.tx_napi);
-
        napi_enable(&dev->mt76.napi[0]);
        napi_schedule(&dev->mt76.napi[0]);
 
@@ -1630,14 +1676,20 @@ void mt7915_mac_reset_work(struct work_struct *work)
 
        napi_enable(&dev->mt76.napi[2]);
        napi_schedule(&dev->mt76.napi[2]);
+       tasklet_schedule(&dev->irq_tasklet);
+
+       mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
+       mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
+
+       mt76_worker_enable(&dev->mt76.tx_worker);
+
+       napi_enable(&dev->mt76.tx_napi);
+       napi_schedule(&dev->mt76.tx_napi);
 
        ieee80211_wake_queues(mt76_hw(dev));
        if (ext_phy)
                ieee80211_wake_queues(ext_phy->hw);
 
-       mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
-       mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
-
        mutex_unlock(&dev->mt76.mutex);
 
        mt7915_update_beacons(dev);
@@ -1651,7 +1703,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
 }
 
 static void
-mt7915_mac_update_mib_stats(struct mt7915_phy *phy)
+mt7915_mac_update_stats(struct mt7915_phy *phy)
 {
        struct mt7915_dev *dev = phy->dev;
        struct mib_stats *mib = &phy->mib;
@@ -1733,8 +1785,10 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
 
                if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
                               IEEE80211_RC_NSS_CHANGED |
-                              IEEE80211_RC_BW_CHANGED))
+                              IEEE80211_RC_BW_CHANGED)) {
+                       mt7915_mcu_add_he(dev, vif, sta);
                        mt7915_mcu_add_rate_ctrl(dev, vif, sta);
+               }
 
                if (changed & IEEE80211_RC_SMPS_CHANGED)
                        mt7915_mcu_add_smps(dev, vif, sta);
@@ -1756,11 +1810,11 @@ void mt7915_mac_work(struct work_struct *work)
 
        mutex_lock(&mphy->dev->mutex);
 
-       mt76_update_survey(mphy->dev);
+       mt76_update_survey(mphy);
        if (++mphy->mac_work_count == 5) {
                mphy->mac_work_count = 0;
 
-               mt7915_mac_update_mib_stats(phy);
+               mt7915_mac_update_stats(phy);
        }
 
        if (++phy->sta_work_count == 10) {
@@ -1770,6 +1824,8 @@ void mt7915_mac_work(struct work_struct *work)
 
        mutex_unlock(&mphy->dev->mutex);
 
+       mt76_tx_status_check(mphy->dev, NULL, false);
+
        ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
                                     MT7915_WATCHDOG_TIME);
 }
index 0f929fb..eb1885f 100644 (file)
@@ -304,6 +304,62 @@ struct mt7915_tx_free {
 /* will support this field in further revision */
 #define MT_TX_FREE_RATE                        GENMASK(13, 0)
 
+#define MT_TXS0_FIXED_RATE             BIT(31)
+#define MT_TXS0_BW                     GENMASK(30, 29)
+#define MT_TXS0_TID                    GENMASK(28, 26)
+#define MT_TXS0_AMPDU                  BIT(25)
+#define MT_TXS0_TXS_FORMAT             GENMASK(24, 23)
+#define MT_TXS0_BA_ERROR               BIT(22)
+#define MT_TXS0_PS_FLAG                        BIT(21)
+#define MT_TXS0_TXOP_TIMEOUT           BIT(20)
+#define MT_TXS0_BIP_ERROR              BIT(19)
+
+#define MT_TXS0_QUEUE_TIMEOUT          BIT(18)
+#define MT_TXS0_RTS_TIMEOUT            BIT(17)
+#define MT_TXS0_ACK_TIMEOUT            BIT(16)
+#define MT_TXS0_ACK_ERROR_MASK         GENMASK(18, 16)
+
+#define MT_TXS0_TX_STATUS_HOST         BIT(15)
+#define MT_TXS0_TX_STATUS_MCU          BIT(14)
+#define MT_TXS0_TX_RATE                        GENMASK(13, 0)
+
+#define MT_TXS1_SEQNO                  GENMASK(31, 20)
+#define MT_TXS1_RESP_RATE              GENMASK(19, 16)
+#define MT_TXS1_RXV_SEQNO              GENMASK(15, 8)
+#define MT_TXS1_TX_POWER_DBM           GENMASK(7, 0)
+
+#define MT_TXS2_BF_STATUS              GENMASK(31, 30)
+#define MT_TXS2_LAST_TX_RATE           GENMASK(29, 27)
+#define MT_TXS2_SHARED_ANTENNA         BIT(26)
+#define MT_TXS2_WCID                   GENMASK(25, 16)
+#define MT_TXS2_TX_DELAY               GENMASK(15, 0)
+
+#define MT_TXS3_PID                    GENMASK(31, 24)
+#define MT_TXS3_ANT_ID                 GENMASK(23, 0)
+
+#define MT_TXS4_TIMESTAMP              GENMASK(31, 0)
+
+#define MT_TXS5_F0_FINAL_MPDU          BIT(31)
+#define MT_TXS5_F0_QOS                 BIT(30)
+#define MT_TXS5_F0_TX_COUNT            GENMASK(29, 25)
+#define MT_TXS5_F0_FRONT_TIME          GENMASK(24, 0)
+#define MT_TXS5_F1_MPDU_TX_COUNT       GENMASK(31, 24)
+#define MT_TXS5_F1_MPDU_TX_BYTES       GENMASK(23, 0)
+
+#define MT_TXS6_F0_NOISE_3             GENMASK(31, 24)
+#define MT_TXS6_F0_NOISE_2             GENMASK(23, 16)
+#define MT_TXS6_F0_NOISE_1             GENMASK(15, 8)
+#define MT_TXS6_F0_NOISE_0             GENMASK(7, 0)
+#define MT_TXS6_F1_MPDU_FAIL_COUNT     GENMASK(31, 24)
+#define MT_TXS6_F1_MPDU_FAIL_BYTES     GENMASK(23, 0)
+
+#define MT_TXS7_F0_RCPI_3              GENMASK(31, 24)
+#define MT_TXS7_F0_RCPI_2              GENMASK(23, 16)
+#define MT_TXS7_F0_RCPI_1              GENMASK(15, 8)
+#define MT_TXS7_F0_RCPI_0              GENMASK(7, 0)
+#define MT_TXS7_F1_MPDU_RETRY_COUNT    GENMASK(31, 24)
+#define MT_TXS7_F1_MPDU_RETRY_BYTES    GENMASK(23, 0)
+
 struct mt7915_dfs_pulse {
        u32 max_width;          /* us */
        int max_pwr;            /* dbm */
index e5bd687..c25f8da 100644 (file)
@@ -139,12 +139,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
                if (type != NL80211_IFTYPE_STATION)
                        break;
 
-               /* next, try to find a free repeater entry for the sta */
-               i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
-                                REPEATER_BSSID_MAX - REPEATER_BSSID_START);
-               if (i)
-                       return i + 32 - 1;
-
                i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
                if (i)
                        return i - 1;
@@ -172,6 +166,22 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
        return -1;
 }
 
+static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
+               mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
+               memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
+                      sizeof(mvif->bitrate_mask.control[i].ht_mcs));
+               memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0),
+                      sizeof(mvif->bitrate_mask.control[i].vht_mcs));
+               memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0),
+                      sizeof(mvif->bitrate_mask.control[i].he_mcs));
+       }
+}
+
 static int mt7915_add_interface(struct ieee80211_hw *hw,
                                struct ieee80211_vif *vif)
 {
@@ -241,6 +251,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
                vif->offload_flags = 0;
        vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
 
+       mt7915_init_bitrate_mask(vif);
+
 out:
        mutex_unlock(&dev->mt76.mutex);
 
@@ -798,7 +810,8 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
        /* TSF software read */
-       mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE);
+       mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
+                MT_LPON_TCR_SW_READ);
        tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
        tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
 
@@ -827,7 +840,34 @@ mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
        mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
        /* TSF software overwrite */
-       mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE);
+       mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
+                MT_LPON_TCR_SW_WRITE);
+
+       mutex_unlock(&dev->mt76.mutex);
+}
+
+static void
+mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                 s64 timestamp)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_dev *dev = mt7915_hw_dev(hw);
+       struct mt7915_phy *phy = mt7915_hw_phy(hw);
+       bool band = phy != &dev->phy;
+       union {
+               u64 t64;
+               u32 t32[2];
+       } tsf = { .t64 = timestamp, };
+       u16 n;
+
+       mutex_lock(&dev->mt76.mutex);
+
+       n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
+       mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
+       mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
+       /* TSF software adjust*/
+       mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
+                MT_LPON_TCR_SW_ADJUST);
 
        mutex_unlock(&dev->mt76.mutex);
 }
@@ -911,17 +951,15 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
 }
 
-static void
-mt7915_sta_rc_update(struct ieee80211_hw *hw,
-                    struct ieee80211_vif *vif,
-                    struct ieee80211_sta *sta,
-                    u32 changed)
+static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
 {
-       struct mt7915_dev *dev = mt7915_hw_dev(hw);
        struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct mt7915_dev *dev = msta->vif->phy->dev;
+       struct ieee80211_hw *hw = msta->vif->phy->mt76->hw;
+       u32 *changed = data;
 
        spin_lock_bh(&dev->sta_poll_lock);
-       msta->stats.changed |= changed;
+       msta->stats.changed |= *changed;
        if (list_empty(&msta->rc_list))
                list_add_tail(&msta->rc_list, &dev->sta_rc_list);
        spin_unlock_bh(&dev->sta_poll_lock);
@@ -929,6 +967,39 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw,
        ieee80211_queue_work(hw, &dev->rc_work);
 }
 
+static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                u32 changed)
+{
+       mt7915_sta_rc_work(&changed, sta);
+}
+
+static int
+mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       const struct cfg80211_bitrate_mask *mask)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       enum nl80211_band band = mvif->phy->mt76->chandef.chan->band;
+       u32 changed;
+
+       if (mask->control[band].gi == NL80211_TXRATE_FORCE_LGI)
+               return -EINVAL;
+
+       changed = IEEE80211_RC_SUPP_RATES_CHANGED;
+       mvif->bitrate_mask = *mask;
+
+       /* Update firmware rate control to add a boundary on top of table
+        * to limit the rate selection for each peer, so when set bitrates
+        * vht-mcs-5 1:9, which actually means nss = 1 mcs = 0~9. This only
+        * applies to data frames as for the other mgmt, mcast, bcast still
+        * use legacy rates as it is.
+        */
+       ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);
+
+       return 0;
+}
+
 static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
                                 struct ieee80211_vif *vif,
                                 struct ieee80211_sta *sta,
@@ -987,9 +1058,11 @@ const struct ieee80211_ops mt7915_ops = {
        .get_stats = mt7915_get_stats,
        .get_tsf = mt7915_get_tsf,
        .set_tsf = mt7915_set_tsf,
+       .offset_tsf = mt7915_offset_tsf,
        .get_survey = mt76_get_survey,
        .get_antenna = mt76_get_antenna,
        .set_antenna = mt7915_set_antenna,
+       .set_bitrate_mask = mt7915_set_bitrate_mask,
        .set_coverage_class = mt7915_set_coverage_class,
        .sta_statistics = mt7915_sta_statistics,
        .sta_set_4addr = mt7915_sta_set_4addr,
index b3f14ff..863aa18 100644 (file)
@@ -88,28 +88,28 @@ struct mt7915_fw_region {
 #define HE_PHY(p, c)                   u8_get_bits(c, IEEE80211_HE_PHY_##p)
 #define HE_MAC(m, c)                   u8_get_bits(c, IEEE80211_HE_MAC_##m)
 
-static enum mt7915_cipher_type
+static enum mcu_cipher_type
 mt7915_mcu_get_cipher(int cipher)
 {
        switch (cipher) {
        case WLAN_CIPHER_SUITE_WEP40:
-               return MT_CIPHER_WEP40;
+               return MCU_CIPHER_WEP40;
        case WLAN_CIPHER_SUITE_WEP104:
-               return MT_CIPHER_WEP104;
+               return MCU_CIPHER_WEP104;
        case WLAN_CIPHER_SUITE_TKIP:
-               return MT_CIPHER_TKIP;
+               return MCU_CIPHER_TKIP;
        case WLAN_CIPHER_SUITE_AES_CMAC:
-               return MT_CIPHER_BIP_CMAC_128;
+               return MCU_CIPHER_BIP_CMAC_128;
        case WLAN_CIPHER_SUITE_CCMP:
-               return MT_CIPHER_AES_CCMP;
+               return MCU_CIPHER_AES_CCMP;
        case WLAN_CIPHER_SUITE_CCMP_256:
-               return MT_CIPHER_CCMP_256;
+               return MCU_CIPHER_CCMP_256;
        case WLAN_CIPHER_SUITE_GCMP:
-               return MT_CIPHER_GCMP;
+               return MCU_CIPHER_GCMP;
        case WLAN_CIPHER_SUITE_GCMP_256:
-               return MT_CIPHER_GCMP_256;
+               return MCU_CIPHER_GCMP_256;
        case WLAN_CIPHER_SUITE_SMS4:
-               return MT_CIPHER_WAPI;
+               return MCU_CIPHER_WAPI;
        default:
                return MT_CIPHER_NONE;
        }
@@ -147,10 +147,10 @@ mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif)
 }
 
 static u8
-mt7915_get_phy_mode(struct mt76_phy *mphy, struct ieee80211_vif *vif,
-                   struct ieee80211_sta *sta)
+mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
 {
-       enum nl80211_band band = mphy->chandef.chan->band;
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       enum nl80211_band band = mvif->phy->mt76->chandef.chan->band;
        struct ieee80211_sta_ht_cap *ht_cap;
        struct ieee80211_sta_vht_cap *vht_cap;
        const struct ieee80211_sta_he_cap *he_cap;
@@ -163,7 +163,7 @@ mt7915_get_phy_mode(struct mt76_phy *mphy, struct ieee80211_vif *vif,
        } else {
                struct ieee80211_supported_band *sband;
 
-               sband = mphy->hw->wiphy->bands[band];
+               sband = mvif->phy->mt76->hw->wiphy->bands[band];
 
                ht_cap = &sband->ht_cap;
                vht_cap = &sband->vht_cap;
@@ -209,6 +209,112 @@ mt7915_mcu_get_sta_nss(u16 mcs_map)
        return nss - 1;
 }
 
+static void
+mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
+                         const u16 *mask)
+{
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct cfg80211_chan_def *chandef = &msta->vif->phy->mt76->chandef;
+       int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
+       u16 mcs_map;
+
+       switch (chandef->width) {
+       case NL80211_CHAN_WIDTH_80P80:
+               mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80p80);
+               break;
+       case NL80211_CHAN_WIDTH_160:
+               mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160);
+               break;
+       default:
+               mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80);
+               break;
+       }
+
+       for (nss = 0; nss < max_nss; nss++) {
+               int mcs;
+
+               switch ((mcs_map >> (2 * nss)) & 0x3) {
+               case IEEE80211_HE_MCS_SUPPORT_0_11:
+                       mcs = GENMASK(11, 0);
+                       break;
+               case IEEE80211_HE_MCS_SUPPORT_0_9:
+                       mcs = GENMASK(9, 0);
+                       break;
+               case IEEE80211_HE_MCS_SUPPORT_0_7:
+                       mcs = GENMASK(7, 0);
+                       break;
+               default:
+                       mcs = 0;
+               }
+
+               mcs = mcs ? fls(mcs & mask[nss]) - 1 : -1;
+
+               switch (mcs) {
+               case 0 ... 7:
+                       mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
+                       break;
+               case 8 ... 9:
+                       mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
+                       break;
+               case 10 ... 11:
+                       mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
+                       break;
+               default:
+                       mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
+                       break;
+               }
+               mcs_map &= ~(0x3 << (nss * 2));
+               mcs_map |= mcs << (nss * 2);
+
+               /* only support 2ss on 160MHz */
+               if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
+                       break;
+       }
+
+       *he_mcs = cpu_to_le16(mcs_map);
+}
+
+static void
+mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
+                          const u16 *mask)
+{
+       u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
+       int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
+       u16 mcs;
+
+       for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {
+               switch (mcs_map & 0x3) {
+               case IEEE80211_VHT_MCS_SUPPORT_0_9:
+                       mcs = GENMASK(9, 0);
+                       break;
+               case IEEE80211_VHT_MCS_SUPPORT_0_8:
+                       mcs = GENMASK(8, 0);
+                       break;
+               case IEEE80211_VHT_MCS_SUPPORT_0_7:
+                       mcs = GENMASK(7, 0);
+                       break;
+               default:
+                       mcs = 0;
+               }
+
+               vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]);
+
+               /* only support 2ss on 160MHz */
+               if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
+                       break;
+       }
+}
+
+static void
+mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
+                         const u8 *mask)
+{
+       int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
+
+       for (nss = 0; nss < max_nss; nss++)
+               ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
+}
+
 static int
 mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
                          struct sk_buff *skb, int seq)
@@ -349,6 +455,24 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
                        mt7915_mcu_csa_finish, mphy->hw);
 }
 
+static void
+mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
+{
+       struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt7915_mcu_thermal_notify *t;
+       struct mt7915_phy *phy;
+
+       t = (struct mt7915_mcu_thermal_notify *)skb->data;
+       if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
+               return;
+
+       if (t->ctrl.band_idx && dev->mt76.phy2)
+               mphy = dev->mt76.phy2;
+
+       phy = (struct mt7915_phy *)mphy->priv;
+       phy->throttle_state = t->ctrl.duty.duty_cycle;
+}
+
 static void
 mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
 {
@@ -469,6 +593,7 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
        u16 attempts = le16_to_cpu(ra->attempts);
        u16 curr = le16_to_cpu(ra->curr_rate);
        u16 wcidx = le16_to_cpu(ra->wlan_idx);
+       struct ieee80211_tx_status status = {};
        struct mt76_phy *mphy = &dev->mphy;
        struct mt7915_sta_stats *stats;
        struct mt7915_sta *msta;
@@ -500,6 +625,13 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
 
                stats->per = 1000 * (attempts - success) / attempts;
        }
+
+       status.sta = wcid_to_sta(wcid);
+       if (!status.sta)
+               return;
+
+       status.rate = &stats->tx_rate;
+       ieee80211_tx_status_ext(mphy->hw, &status);
 }
 
 static void
@@ -531,6 +663,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
        struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
 
        switch (rxd->ext_eid) {
+       case MCU_EXT_EVENT_THERMAL_PROTECT:
+               mt7915_mcu_rx_thermal_notify(dev, skb);
+               break;
        case MCU_EXT_EVENT_RDD_REPORT:
                mt7915_mcu_rx_radar_detected(dev, skb);
                break;
@@ -733,7 +868,7 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
                memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
                bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
                bss->dtim_period = vif->bss_conf.dtim_period;
-               bss->phy_mode = mt7915_get_phy_mode(phy->mt76, vif, NULL);
+               bss->phy_mode = mt7915_get_phy_mode(vif, NULL);
        } else {
                memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN);
        }
@@ -1072,14 +1207,14 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb,
                sec_key = &sec->key[0];
                sec_key->cipher_len = sizeof(*sec_key);
 
-               if (cipher == MT_CIPHER_BIP_CMAC_128) {
-                       sec_key->cipher_id = MT_CIPHER_AES_CCMP;
+               if (cipher == MCU_CIPHER_BIP_CMAC_128) {
+                       sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
                        sec_key->key_id = bip->keyidx;
                        sec_key->key_len = 16;
                        memcpy(sec_key->key, bip->key, 16);
 
                        sec_key = &sec->key[1];
-                       sec_key->cipher_id = MT_CIPHER_BIP_CMAC_128;
+                       sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
                        sec_key->cipher_len = sizeof(*sec_key);
                        sec_key->key_len = 16;
                        memcpy(sec_key->key, key->key, 16);
@@ -1091,14 +1226,14 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb,
                        sec_key->key_len = key->keylen;
                        memcpy(sec_key->key, key->key, key->keylen);
 
-                       if (cipher == MT_CIPHER_TKIP) {
+                       if (cipher == MCU_CIPHER_TKIP) {
                                /* Rx/Tx MIC keys are swapped */
                                memcpy(sec_key->key + 16, key->key + 24, 8);
                                memcpy(sec_key->key + 24, key->key + 16, 8);
                        }
 
                        /* store key_conf for BIP batch update */
-                       if (cipher == MT_CIPHER_AES_CCMP) {
+                       if (cipher == MCU_CIPHER_AES_CCMP) {
                                memcpy(bip->key, key->key, key->keylen);
                                bip->keyidx = key->keyidx;
                        }
@@ -1336,8 +1471,11 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
 static void
 mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 {
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
        struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
        struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
+       enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band;
+       const u16 *mcs_mask = msta->vif->bitrate_mask.control[band].he_mcs;
        struct sta_rec_he *he;
        struct tlv *tlv;
        u32 cap = 0;
@@ -1428,15 +1566,18 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
        case IEEE80211_STA_RX_BW_160:
                if (elem->phy_cap_info[0] &
                    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-                       he->max_nss_mcs[CMD_HE_MCS_BW8080] =
-                               he_cap->he_mcs_nss_supp.rx_mcs_80p80;
+                       mt7915_mcu_set_sta_he_mcs(sta,
+                                                 &he->max_nss_mcs[CMD_HE_MCS_BW8080],
+                                                 mcs_mask);
 
-               he->max_nss_mcs[CMD_HE_MCS_BW160] =
-                               he_cap->he_mcs_nss_supp.rx_mcs_160;
+               mt7915_mcu_set_sta_he_mcs(sta,
+                                         &he->max_nss_mcs[CMD_HE_MCS_BW160],
+                                         mcs_mask);
                fallthrough;
        default:
-               he->max_nss_mcs[CMD_HE_MCS_BW80] =
-                               he_cap->he_mcs_nss_supp.rx_mcs_80;
+               mt7915_mcu_set_sta_he_mcs(sta,
+                                         &he->max_nss_mcs[CMD_HE_MCS_BW80],
+                                         mcs_mask);
                break;
        }
 
@@ -1544,27 +1685,18 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
                HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
 }
 
-static int
-mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                 struct ieee80211_sta *sta)
+static void
+mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
 {
-       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-       struct sk_buff *skb;
-       int len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_muru);
-
-       if (!sta->vht_cap.vht_supported && !sta->he_cap.has_he)
-               return 0;
-
-       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
-       if (IS_ERR(skb))
-               return PTR_ERR(skb);
+       struct sta_rec_vht *vht;
+       struct tlv *tlv;
 
-       /* starec muru */
-       mt7915_mcu_sta_muru_tlv(skb, sta);
+       tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
 
-       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
+       vht = (struct sta_rec_vht *)tlv;
+       vht->vht_cap = cpu_to_le32(sta->vht_cap.cap);
+       vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
+       vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map;
 }
 
 static void
@@ -1616,17 +1748,6 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
                        mt7915_mcu_sta_amsdu_tlv(skb, sta);
        }
 
-       /* starec vht */
-       if (sta->vht_cap.vht_supported) {
-               struct sta_rec_vht *vht;
-
-               tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
-               vht = (struct sta_rec_vht *)tlv;
-               vht->vht_cap = cpu_to_le32(sta->vht_cap.cap);
-               vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
-               vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map;
-       }
-
        /* starec he */
        if (sta->he_cap.has_he)
                mt7915_mcu_sta_he_tlv(skb, sta);
@@ -2016,26 +2137,21 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                vc = mt7915_get_he_phy_cap(phy, vif);
                ve = &vc->he_cap_elem;
 
-               ebfee = !!((HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]) ||
-                           HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4])) &&
+               ebfee = !!(HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]) &&
                           HE_PHY(CAP4_SU_BEAMFORMEE, ve->phy_cap_info[4]));
-               ebf = !!((HE_PHY(CAP3_SU_BEAMFORMER, ve->phy_cap_info[3]) ||
-                         HE_PHY(CAP4_MU_BEAMFORMER, ve->phy_cap_info[4])) &&
+               ebf = !!(HE_PHY(CAP3_SU_BEAMFORMER, ve->phy_cap_info[3]) &&
                         HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]));
        } else if (sta->vht_cap.vht_supported) {
                struct ieee80211_sta_vht_cap *pc;
                struct ieee80211_sta_vht_cap *vc;
-               u32 cr, ce;
 
                pc = &sta->vht_cap;
                vc = &phy->mt76->sband_5g.sband.vht_cap;
-               cr = IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
-                    IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
-               ce = IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-                    IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
 
-               ebfee = !!((pc->cap & cr) && (vc->cap & ce));
-               ebf = !!((vc->cap & cr) && (pc->cap & ce));
+               ebfee = !!((pc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
+                          (vc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
+               ebf = !!((vc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
+                        (pc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
        }
 
        /* must keep each tag independent */
@@ -2079,57 +2195,47 @@ static void
 mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                             struct ieee80211_vif *vif, struct ieee80211_sta *sta)
 {
-       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-       struct mt76_phy *mphy = &dev->mphy;
-       enum nl80211_band band;
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
+       struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
+       enum nl80211_band band = chandef->chan->band;
        struct sta_rec_ra *ra;
        struct tlv *tlv;
-       u32 supp_rate, n_rates, cap = sta->wme ? STA_CAP_WMM : 0;
-       u8 i, nss = sta->rx_nss, mcs = 0;
+       u32 supp_rate = sta->supp_rates[band];
+       u32 cap = sta->wme ? STA_CAP_WMM : 0;
 
        tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
        ra = (struct sta_rec_ra *)tlv;
 
-       if (msta->wcid.ext_phy && dev->mt76.phy2)
-               mphy = dev->mt76.phy2;
-
-       band = mphy->chandef.chan->band;
-       supp_rate = sta->supp_rates[band];
-       n_rates = hweight32(supp_rate);
-
        ra->valid = true;
        ra->auto_rate = true;
-       ra->phy_mode = mt7915_get_phy_mode(mphy, vif, sta);
-       ra->channel = mphy->chandef.chan->hw_value;
+       ra->phy_mode = mt7915_get_phy_mode(vif, sta);
+       ra->channel = chandef->chan->hw_value;
        ra->bw = sta->bandwidth;
-       ra->rate_len = n_rates;
        ra->phy.bw = sta->bandwidth;
 
-       if (n_rates) {
+       if (supp_rate) {
+               supp_rate &= mask->control[band].legacy;
+               ra->rate_len = hweight32(supp_rate);
+
                if (band == NL80211_BAND_2GHZ) {
                        ra->supp_mode = MODE_CCK;
                        ra->supp_cck_rate = supp_rate & GENMASK(3, 0);
-                       ra->phy.type = MT_PHY_TYPE_CCK;
 
-                       if (n_rates > 4) {
+                       if (ra->rate_len > 4) {
                                ra->supp_mode |= MODE_OFDM;
                                ra->supp_ofdm_rate = supp_rate >> 4;
-                               ra->phy.type = MT_PHY_TYPE_OFDM;
                        }
                } else {
                        ra->supp_mode = MODE_OFDM;
                        ra->supp_ofdm_rate = supp_rate;
-                       ra->phy.type = MT_PHY_TYPE_OFDM;
                }
        }
 
        if (sta->ht_cap.ht_supported) {
-               for (i = 0; i < nss; i++)
-                       ra->ht_mcs[i] = sta->ht_cap.mcs.rx_mask[i];
+               const u8 *mcs_mask = mask->control[band].ht_mcs;
 
-               ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
                ra->supp_mode |= MODE_HT;
-               mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1;
                ra->af = sta->ht_cap.ampdu_factor;
                ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
 
@@ -2144,13 +2250,16 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                        cap |= STA_CAP_RX_STBC;
                if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
                        cap |= STA_CAP_LDPC;
+
+               mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, mcs_mask);
+               ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
        }
 
        if (sta->vht_cap.vht_supported) {
-               u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
-               u16 vht_mcs;
-               u8 af, mcs_prev;
+               const u16 *mcs_mask = mask->control[band].vht_mcs;
+               u8 af;
 
+               ra->supp_mode |= MODE_VHT;
                af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
                               sta->vht_cap.cap);
                ra->af = max_t(u8, ra->af, af);
@@ -2167,33 +2276,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
                        cap |= STA_CAP_VHT_LDPC;
 
-               ra->supp_mode |= MODE_VHT;
-               for (mcs = 0, i = 0; i < nss; i++, mcs_map >>= 2) {
-                       switch (mcs_map & 0x3) {
-                       case IEEE80211_VHT_MCS_SUPPORT_0_9:
-                               vht_mcs = GENMASK(9, 0);
-                               break;
-                       case IEEE80211_VHT_MCS_SUPPORT_0_8:
-                               vht_mcs = GENMASK(8, 0);
-                               break;
-                       case IEEE80211_VHT_MCS_SUPPORT_0_7:
-                               vht_mcs = GENMASK(7, 0);
-                               break;
-                       default:
-                               vht_mcs = 0;
-                       }
-
-                       ra->supp_vht_mcs[i] = cpu_to_le16(vht_mcs);
-
-                       mcs_prev = hweight16(vht_mcs) - 1;
-                       if (mcs_prev > mcs)
-                               mcs = mcs_prev;
-
-                       /* only support 2ss on 160MHz */
-                       if (i > 1 && (ra->bw == CMD_CBW_160MHZ ||
-                                     ra->bw == CMD_CBW_8080MHZ))
-                               break;
-               }
+               mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mcs_mask);
        }
 
        if (sta->he_cap.has_he) {
@@ -2201,28 +2284,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                cap |= STA_CAP_HE;
        }
 
-       ra->sta_status = cpu_to_le32(cap);
-
-       switch (BIT(fls(ra->supp_mode) - 1)) {
-       case MODE_VHT:
-               ra->phy.type = MT_PHY_TYPE_VHT;
-               ra->phy.mcs = mcs;
-               ra->phy.nss = nss;
-               ra->phy.stbc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC);
-               ra->phy.ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
-               ra->phy.sgi =
-                       !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
-               break;
-       case MODE_HT:
-               ra->phy.type = MT_PHY_TYPE_HT;
-               ra->phy.mcs = mcs;
-               ra->phy.ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING;
-               ra->phy.stbc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC);
-               ra->phy.sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
-               break;
-       default:
-               break;
-       }
+       ra->sta_cap = cpu_to_le32(cap);
 }
 
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
@@ -2243,6 +2305,87 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                                     MCU_EXT_CMD(STA_REC_UPDATE), true);
 }
 
+int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct sk_buff *skb;
+       int len;
+
+       if (!sta->he_cap.has_he)
+               return 0;
+
+       len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_he);
+
+       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       mt7915_mcu_sta_he_tlv(skb, sta);
+
+       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
+}
+
+static int
+mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+                    struct ieee80211_sta *sta)
+{
+#define MT_STA_BSS_GROUP               1
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct {
+               __le32 action;
+               u8 wlan_idx_lo;
+               u8 status;
+               u8 wlan_idx_hi;
+               u8 rsv0[5];
+               __le32 val;
+               u8 rsv1[8];
+       } __packed req = {
+               .action = cpu_to_le32(MT_STA_BSS_GROUP),
+               .wlan_idx_lo = to_wcid_lo(msta->wcid.idx),
+               .wlan_idx_hi = to_wcid_hi(msta->wcid.idx),
+               .val = cpu_to_le32(mvif->idx % 16),
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_DRR_CTRL), &req,
+                                sizeof(req), true);
+}
+
+static int
+mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+                 struct ieee80211_sta *sta)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct sk_buff *skb;
+       int ret;
+
+       if (!sta->vht_cap.vht_supported && !sta->he_cap.has_he)
+               return 0;
+
+       ret = mt7915_mcu_add_group(dev, vif, sta);
+       if (ret)
+               return ret;
+
+       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta,
+                                      MT7915_STA_UPDATE_MAX_SIZE);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       /* wait until TxBF and MU ready to update stare vht */
+
+       /* starec muru */
+       mt7915_mcu_sta_muru_tlv(skb, sta);
+       /* starec vht */
+       mt7915_mcu_sta_vht_tlv(skb, sta);
+
+       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
+}
+
 int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, bool enable)
 {
@@ -2253,17 +2396,14 @@ int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,
 
        /* must keep the order */
        ret = mt7915_mcu_add_txbf(dev, vif, sta, enable);
-       if (ret)
+       if (ret || !enable)
                return ret;
 
        ret = mt7915_mcu_add_mu(dev, vif, sta);
        if (ret)
                return ret;
 
-       if (enable)
-               return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
-
-       return 0;
+       return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
 }
 
 int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
@@ -2432,7 +2572,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
                cont->csa_ofs = cpu_to_le16(offs->cntdwn_counter_offs[0] - 4);
 
        buf = (u8 *)tlv + sizeof(*cont);
-       mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
+       mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
                              true);
        memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
 }
@@ -3307,7 +3447,8 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
 int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
 {
        struct mt7915_mcu_eeprom_info req = {
-               .addr = cpu_to_le32(round_down(offset, 16)),
+               .addr = cpu_to_le32(round_down(offset,
+                                   MT7915_EEPROM_BLOCK_SIZE)),
        };
        struct mt7915_mcu_eeprom_info *res;
        struct sk_buff *skb;
@@ -3321,7 +3462,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
 
        res = (struct mt7915_mcu_eeprom_info *)skb->data;
        buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
-       memcpy(buf, res->data, 16);
+       memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
        dev_kfree_skb(skb);
 
        return 0;
@@ -3440,8 +3581,9 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
 {
        struct mt7915_dev *dev = phy->dev;
        struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
-       u16 total = 2, idx, center_freq = chandef->center_freq1;
+       u16 total = 2, center_freq = chandef->center_freq1;
        u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
+       int idx;
 
        if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD))
                return 0;
@@ -3469,22 +3611,128 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
        return 0;
 }
 
-int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index)
+int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
+{
+       /* strict order */
+       static const enum mt7915_chan_mib_offs offs[] = {
+               MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME
+       };
+       struct mt76_channel_state *state = phy->mt76->chan_state;
+       struct mt76_channel_state *state_ts = &phy->state_ts;
+       struct mt7915_dev *dev = phy->dev;
+       struct mt7915_mcu_mib *res, req[4];
+       struct sk_buff *skb;
+       int i, ret;
+
+       for (i = 0; i < 4; i++) {
+               req[i].band = cpu_to_le32(phy != &dev->phy);
+               req[i].offs = cpu_to_le32(offs[i]);
+       }
+
+       ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
+                                       req, sizeof(req), true, &skb);
+       if (ret)
+               return ret;
+
+       res = (struct mt7915_mcu_mib *)(skb->data + 20);
+
+       if (chan_switch)
+               goto out;
+
+#define __res_u64(s) le64_to_cpu(res[s].data)
+       state->cc_busy += __res_u64(0) - state_ts->cc_busy;
+       state->cc_tx += __res_u64(1) - state_ts->cc_tx;
+       state->cc_bss_rx += __res_u64(2) - state_ts->cc_bss_rx;
+       state->cc_rx += __res_u64(2) + __res_u64(3) - state_ts->cc_rx;
+
+out:
+       state_ts->cc_busy = __res_u64(0);
+       state_ts->cc_tx = __res_u64(1);
+       state_ts->cc_bss_rx = __res_u64(2);
+       state_ts->cc_rx = __res_u64(2) + __res_u64(3);
+#undef __res_u64
+
+       dev_kfree_skb(skb);
+
+       return 0;
+}
+
+int mt7915_mcu_get_temperature(struct mt7915_phy *phy)
 {
+       struct mt7915_dev *dev = phy->dev;
        struct {
                u8 ctrl_id;
                u8 action;
-               u8 band;
+               u8 dbdc_idx;
                u8 rsv[5];
        } req = {
                .ctrl_id = THERMAL_SENSOR_TEMP_QUERY,
-               .action = index,
+               .dbdc_idx = phy != &dev->phy,
        };
 
        return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,
                                 sizeof(req), true);
 }
 
+int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
+{
+       struct mt7915_dev *dev = phy->dev;
+       struct {
+               struct mt7915_mcu_thermal_ctrl ctrl;
+
+               __le32 trigger_temp;
+               __le32 restore_temp;
+               __le16 sustain_time;
+               u8 rsv[2];
+       } __packed req = {
+               .ctrl = {
+                       .band_idx = phy != &dev->phy,
+               },
+       };
+       int level;
+
+#define TRIGGER_TEMPERATURE    122
+#define RESTORE_TEMPERATURE    116
+#define SUSTAIN_PERIOD         10
+
+       if (!state) {
+               req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;
+               goto out;
+       }
+
+       /* set duty cycle and level */
+       for (level = 0; level < 4; level++) {
+               int ret;
+
+               req.ctrl.ctrl_id = THERMAL_PROTECT_DUTY_CONFIG;
+               req.ctrl.duty.duty_level = level;
+               req.ctrl.duty.duty_cycle = state;
+               state = state * 4 / 5;
+
+               ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
+                                       &req, sizeof(req.ctrl), false);
+               if (ret)
+                       return ret;
+       }
+
+       /* currently use fixed values for throttling, and would be better
+        * to implement thermal zone for dynamic trip in the long run.
+        */
+
+       /* set high-temperature trigger threshold */
+       req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE;
+       req.trigger_temp = cpu_to_le32(TRIGGER_TEMPERATURE);
+       req.restore_temp = cpu_to_le32(RESTORE_TEMPERATURE);
+       req.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
+
+out:
+       req.ctrl.type.protect_type = 1;
+       req.ctrl.type.trigger_type = 1;
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
+                                &req, sizeof(req), false);
+}
+
 int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)
 {
        struct {
@@ -3505,7 +3753,6 @@ int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)
 
 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
 {
-#define MT7915_SKU_RATE_NUM            161
        struct mt7915_dev *dev = phy->dev;
        struct mt76_phy *mphy = phy->mt76;
        struct ieee80211_hw *hw = mphy->hw;
@@ -3555,6 +3802,39 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
                                 sizeof(req), true);
 }
 
+int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
+{
+#define RATE_POWER_INFO        2
+       struct mt7915_dev *dev = phy->dev;
+       struct {
+               u8 format_id;
+               u8 category;
+               u8 band;
+               u8 _rsv;
+       } __packed req = {
+               .format_id = 7,
+               .category = RATE_POWER_INFO,
+               .band = phy != &dev->phy,
+       };
+       s8 res[MT7915_SKU_RATE_NUM][2];
+       struct sk_buff *skb;
+       int ret, i;
+
+       ret = mt76_mcu_send_and_get_msg(&dev->mt76,
+                                       MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
+                                       &req, sizeof(req), true, &skb);
+       if (ret)
+               return ret;
+
+       memcpy(res, skb->data + 4, sizeof(res));
+       for (i = 0; i < len; i++)
+               txpower[i] = res[i][req.band];
+
+       dev_kfree_skb(skb);
+
+       return 0;
+}
+
 int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
                              u8 en)
 {
@@ -3613,57 +3893,50 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
                                 &req, sizeof(req), false);
 }
 
-int mt7915_mcu_set_txbf_module(struct mt7915_dev *dev)
-{
-#define MT_BF_MODULE_UPDATE               25
-       struct {
-               u8 action;
-               u8 bf_num;
-               u8 bf_bitmap;
-               u8 bf_sel[8];
-               u8 rsv[8];
-       } __packed req = {
-               .action = MT_BF_MODULE_UPDATE,
-               .bf_num = 2,
-               .bf_bitmap = GENMASK(1, 0),
-       };
-
-       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
-                                sizeof(req), true);
-}
-
-int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev)
+int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
 {
-#define MT_BF_TYPE_UPDATE              20
        struct {
                u8 action;
-               bool ebf;
-               bool ibf;
-               u8 rsv;
+               union {
+                       struct {
+                               u8 snd_mode;
+                               u8 sta_num;
+                               u8 rsv;
+                               u8 wlan_idx[4];
+                               __le32 snd_period;      /* ms */
+                       } __packed snd;
+                       struct {
+                               bool ebf;
+                               bool ibf;
+                               u8 rsv;
+                       } __packed type;
+                       struct {
+                               u8 bf_num;
+                               u8 bf_bitmap;
+                               u8 bf_sel[8];
+                               u8 rsv[5];
+                       } __packed mod;
+               };
        } __packed req = {
-               .action = MT_BF_TYPE_UPDATE,
-               .ebf = true,
-               .ibf = dev->ibf,
+               .action = action,
        };
 
-       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
-                                sizeof(req), true);
-}
-
-int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev)
-{
-#define MT_BF_PROCESSING               4
-       struct {
-               u8 action;
-               u8 snd_mode;
-               u8 sta_num;
-               u8 rsv;
-               u8 wlan_idx[4];
-               __le32 snd_period;      /* ms */
-       } __packed req = {
-               .action = true,
-               .snd_mode = MT_BF_PROCESSING,
-       };
+#define MT_BF_PROCESSING       4
+       switch (action) {
+       case MT_BF_SOUNDING_ON:
+               req.snd.snd_mode = MT_BF_PROCESSING;
+               break;
+       case MT_BF_TYPE_UPDATE:
+               req.type.ebf = true;
+               req.type.ibf = dev->ibf;
+               break;
+       case MT_BF_MODULE_UPDATE:
+               req.mod.bf_num = 2;
+               req.mod.bf_bitmap = GENMASK(1, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
 
        return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
                                 sizeof(req), true);
index 42582a6..edd3ba3 100644 (file)
@@ -68,6 +68,29 @@ struct mt7915_mcu_rxd {
        u8 s2d_index;
 };
 
+struct mt7915_mcu_thermal_ctrl {
+       u8 ctrl_id;
+       u8 band_idx;
+       union {
+               struct {
+                       u8 protect_type; /* 1: duty admit, 2: radio off */
+                       u8 trigger_type; /* 0: low, 1: high */
+               } __packed type;
+               struct {
+                       u8 duty_level;  /* level 0~3 */
+                       u8 duty_cycle;
+               } __packed duty;
+       };
+} __packed;
+
+struct mt7915_mcu_thermal_notify {
+       struct mt7915_mcu_rxd rxd;
+
+       struct mt7915_mcu_thermal_ctrl ctrl;
+       __le32 temperature;
+       u8 rsv[8];
+} __packed;
+
 struct mt7915_mcu_csa_notify {
        struct mt7915_mcu_rxd rxd;
 
@@ -193,6 +216,19 @@ struct mt7915_mcu_phy_rx_info {
 #define MT_RA_RATE_DCM_EN              BIT(4)
 #define MT_RA_RATE_BW                  GENMASK(14, 13)
 
+struct mt7915_mcu_mib {
+       __le32 band;
+       __le32 offs;
+       __le64 data;
+} __packed;
+
+enum mt7915_chan_mib_offs {
+       MIB_BUSY_TIME = 14,
+       MIB_TX_TIME = 81,
+       MIB_RX_TIME,
+       MIB_OBSS_AIRTIME = 86
+};
+
 struct edca {
        u8 queue;
        u8 set;
@@ -262,6 +298,7 @@ enum {
        MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
        MCU_EXT_CMD_TXBF_ACTION = 0x1e,
        MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
+       MCU_EXT_CMD_THERMAL_PROT = 0x23,
        MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
        MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
        MCU_EXT_CMD_EDCA_UPDATE = 0x27,
@@ -277,6 +314,7 @@ enum {
        MCU_EXT_CMD_MUAR_UPDATE = 0x48,
        MCU_EXT_CMD_SET_RX_PATH = 0x4e,
        MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
+       MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
        MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
        MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
        MCU_EXT_CMD_SCS_CTRL = 0x82,
@@ -919,7 +957,7 @@ struct sta_rec_ra {
        u8 op_vht_rx_nss;
        u8 op_vht_rx_nss_type;
 
-       __le32 sta_status;
+       __le32 sta_cap;
 
        struct ra_phy phy;
 } __packed;
@@ -1034,18 +1072,17 @@ enum {
        STA_REC_MAX_NUM
 };
 
-enum mt7915_cipher_type {
-       MT_CIPHER_NONE,
-       MT_CIPHER_WEP40,
-       MT_CIPHER_WEP104,
-       MT_CIPHER_WEP128,
-       MT_CIPHER_TKIP,
-       MT_CIPHER_AES_CCMP,
-       MT_CIPHER_CCMP_256,
-       MT_CIPHER_GCMP,
-       MT_CIPHER_GCMP_256,
-       MT_CIPHER_WAPI,
-       MT_CIPHER_BIP_CMAC_128,
+enum mcu_cipher_type {
+       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_WEP104,
+       MCU_CIPHER_WEP128,
+       MCU_CIPHER_TKIP,
+       MCU_CIPHER_AES_CCMP,
+       MCU_CIPHER_CCMP_256,
+       MCU_CIPHER_GCMP,
+       MCU_CIPHER_GCMP_256,
+       MCU_CIPHER_WAPI,
+       MCU_CIPHER_BIP_CMAC_128,
 };
 
 enum {
@@ -1066,11 +1103,28 @@ enum {
        THERMAL_SENSOR_TASK_CTRL,
 };
 
+enum {
+       THERMAL_PROTECT_PARAMETER_CTRL,
+       THERMAL_PROTECT_BASIC_INFO,
+       THERMAL_PROTECT_ENABLE,
+       THERMAL_PROTECT_DISABLE,
+       THERMAL_PROTECT_DUTY_CONFIG,
+       THERMAL_PROTECT_MECH_INFO,
+       THERMAL_PROTECT_DUTY_INFO,
+       THERMAL_PROTECT_STATE_ACT,
+};
+
 enum {
        MT_EBF = BIT(0),        /* explicit beamforming */
        MT_IBF = BIT(1)         /* implicit beamforming */
 };
 
+enum {
+       MT_BF_SOUNDING_ON = 1,
+       MT_BF_TYPE_UPDATE = 20,
+       MT_BF_MODULE_UPDATE = 25
+};
+
 #define MT7915_WTBL_UPDATE_MAX_SIZE    (sizeof(struct wtbl_req_hdr) +  \
                                         sizeof(struct wtbl_generic) +  \
                                         sizeof(struct wtbl_rx) +       \
index 4ea8972..3f613fa 100644 (file)
@@ -9,7 +9,7 @@
 #include "../mt76.h"
 #include "regs.h"
 
-#define MT7915_MAX_INTERFACES          32
+#define MT7915_MAX_INTERFACES          19
 #define MT7915_MAX_WMM_SETS            4
 #define MT7915_WTBL_SIZE               288
 #define MT7915_WTBL_RESERVED           (MT7915_WTBL_SIZE - 1)
@@ -31,6 +31,7 @@
 #define MT7915_ROM_PATCH               "mediatek/mt7915_rom_patch.bin"
 
 #define MT7915_EEPROM_SIZE             3584
+#define MT7915_EEPROM_BLOCK_SIZE       16
 #define MT7915_TOKEN_SIZE              8192
 
 #define MT7915_CFEND_RATE_DEFAULT      0x49    /* OFDM 24M */
 #define MT7915_5G_RATE_DEFAULT         0x4b    /* OFDM 6M */
 #define MT7915_2G_RATE_DEFAULT         0x0     /* CCK 1M */
 
+#define MT7915_THERMAL_THROTTLE_MAX    100
+
+#define MT7915_SKU_RATE_NUM            161
+
 struct mt7915_vif;
 struct mt7915_sta;
 struct mt7915_dfs_pulse;
@@ -100,6 +105,7 @@ struct mt7915_vif {
        struct mt7915_phy *phy;
 
        struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
+       struct cfg80211_bitrate_mask bitrate_mask;
 };
 
 struct mib_stats {
@@ -126,6 +132,9 @@ struct mt7915_phy {
 
        struct ieee80211_vif *monitor_vif;
 
+       struct thermal_cooling_device *cdev;
+       u8 throttle_state;
+
        u32 rxfilter;
        u64 omac_mask;
 
@@ -141,6 +150,7 @@ struct mt7915_phy {
        u32 ampdu_ref;
 
        struct mib_stats mib;
+       struct mt76_channel_state state_ts;
        struct list_head stats_list;
 
        u8 sta_work_count;
@@ -169,6 +179,7 @@ struct mt7915_dev {
        struct mt7915_hif *hif2;
 
        const struct mt76_bus_ops *bus_ops;
+       struct tasklet_struct irq_tasklet;
        struct mt7915_phy phy;
 
        u16 chainmask;
@@ -322,6 +333,8 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                             bool enable);
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta);
+int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta);
 int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta);
 int mt7915_set_channel(struct mt7915_phy *phy);
@@ -342,9 +355,8 @@ int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val);
 int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter);
 int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
 int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
-int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev);
-int mt7915_mcu_set_txbf_module(struct mt7915_dev *dev);
-int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev);
+int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
+int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action);
 int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
 int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,
                            const struct mt7915_dfs_pulse *pulse);
@@ -352,7 +364,9 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
                            const struct mt7915_dfs_pattern *pattern);
 int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev);
 int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy);
-int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index);
+int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch);
+int mt7915_mcu_get_temperature(struct mt7915_phy *phy);
+int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state);
 int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx);
 int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, struct rate_info *rate);
@@ -374,9 +388,11 @@ void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg,
 static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask)
 {
        if (dev->hif2)
-               mt7915_dual_hif_set_irq_mask(dev, true, 0, mask);
+               mt7915_dual_hif_set_irq_mask(dev, false, 0, mask);
        else
-               mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
+               mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
+
+       tasklet_schedule(&dev->irq_tasklet);
 }
 
 static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
@@ -392,12 +408,9 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy);
 void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
 void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
 void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
-                          struct sk_buff *skb, struct mt76_wcid *wcid,
+                          struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
                           struct ieee80211_key_conf *key, bool beacon);
 void mt7915_mac_set_timing(struct mt7915_phy *phy);
-int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb);
-void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb);
-void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb);
 int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
 void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -417,13 +430,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
                         struct sk_buff *skb);
 void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
 void mt7915_stats_work(struct work_struct *work);
-void mt7915_txp_skb_unmap(struct mt76_dev *dev,
-                         struct mt76_txwi_cache *txwi);
 int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
 int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
 void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
 void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
-void mt7915_update_channel(struct mt76_dev *mdev);
+void mt7915_update_channel(struct mt76_phy *mphy);
 int mt7915_init_debugfs(struct mt7915_dev *dev);
 #ifdef CONFIG_MAC80211_DEBUGFS
 void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
index 643f171..340b364 100644 (file)
@@ -94,11 +94,15 @@ mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
 }
 
 /* TODO: support 2/4/6/8 MSI-X vectors */
-static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
+static void mt7915_irq_tasklet(struct tasklet_struct *t)
 {
-       struct mt7915_dev *dev = dev_instance;
+       struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
        u32 intr, intr1, mask;
 
+       mt76_wr(dev, MT_INT_MASK_CSR, 0);
+       if (dev->hif2)
+               mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+
        intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
        intr &= dev->mt76.mmio.irqmask;
        mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
@@ -111,9 +115,6 @@ static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
                intr |= intr1;
        }
 
-       if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
-               return IRQ_NONE;
-
        trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
 
        mask = intr & MT_INT_RX_DONE_ALL;
@@ -150,6 +151,20 @@ static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
                        wake_up(&dev->reset_wait);
                }
        }
+}
+
+static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
+{
+       struct mt7915_dev *dev = dev_instance;
+
+       mt76_wr(dev, MT_INT_MASK_CSR, 0);
+       if (dev->hif2)
+               mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+
+       if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
+               return IRQ_NONE;
+
+       tasklet_schedule(&dev->irq_tasklet);
 
        return IRQ_HANDLED;
 }
@@ -240,6 +255,8 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
+       mt76_pci_disable_aspm(pdev);
+
        if (id->device == 0x7916)
                return mt7915_pci_hif2_probe(pdev);
 
@@ -250,10 +267,18 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
 
        dev = container_of(mdev, struct mt7915_dev, mt76);
 
+       ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+       if (ret < 0)
+               goto free;
+
        ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq);
        if (ret)
                goto error;
 
+       tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
+
+       mt76_wr(dev, MT_INT_MASK_CSR, 0);
+
        /* master switch of PCIe tnterrupt enable */
        mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
 
@@ -266,10 +291,14 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
 
        ret = mt7915_register_device(dev);
        if (ret)
-               goto error;
+               goto free_irq;
 
        return 0;
+free_irq:
+       devm_free_irq(mdev->dev, pdev->irq, dev);
 error:
+       pci_free_irq_vectors(pdev);
+free:
        mt76_free_device(&dev->mt76);
 
        return ret;
index efe0f29..a213b5c 100644 (file)
 #define MT_TMAC_CTCR0_INS_DDLMT_EN             BIT(17)
 #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN   BIT(18)
 
-#define MT_TMAC_FP0R0(_band)           MT_WF_TMAC(_band, 0x020)
-#define MT_TMAC_FP0R15(_band)          MT_WF_TMAC(_band, 0x080)
-#define MT_TMAC_FP0R18(_band)          MT_WF_TMAC(_band, 0x270)
-#define MT_TMAC_FP_MASK                        GENMASK(7, 0)
-
 #define MT_TMAC_TFCR0(_band)           MT_WF_TMAC(_band, 0x1e0)
 
 #define MT_WF_DMA_BASE(_band)          ((_band) ? 0xa1e00 : 0x21e00)
 #define MT_ETBF_TX_FB_CPL              GENMASK(31, 16)
 #define MT_ETBF_TX_FB_TRI              GENMASK(15, 0)
 
+#define MT_ETBF_RX_FB_CONT(_band)      MT_WF_ETBF(_band, 0x068)
+#define MT_ETBF_RX_FB_BW               GENMASK(7, 6)
+#define MT_ETBF_RX_FB_NC               GENMASK(5, 3)
+#define MT_ETBF_RX_FB_NR               GENMASK(2, 0)
+
 #define MT_ETBF_TX_APP_CNT(_band)      MT_WF_ETBF(_band, 0x0f0)
 #define MT_ETBF_TX_IBF_CNT             GENMASK(31, 16)
 #define MT_ETBF_TX_EBF_CNT             GENMASK(15, 0)
 #define MT_LPON_TCR(_band, n)          MT_WF_LPON(_band, 0x0a8 + (n) * 4)
 #define MT_LPON_TCR_SW_MODE            GENMASK(1, 0)
 #define MT_LPON_TCR_SW_WRITE           BIT(0)
+#define MT_LPON_TCR_SW_ADJUST          BIT(1)
+#define MT_LPON_TCR_SW_READ            GENMASK(1, 0)
 
 /* MIB: band 0(0x24800), band 1(0xa4800) */
 #define MT_WF_MIB_BASE(_band)          ((_band) ? 0xa4800 : 0x24800)
 #define MT_MIB_SDR3(_band)             MT_WF_MIB(_band, 0x014)
 #define MT_MIB_SDR3_FCS_ERR_MASK       GENMASK(15, 0)
 
-#define MT_MIB_SDR9(_band)             MT_WF_MIB(_band, 0x02c)
-#define MT_MIB_SDR9_BUSY_MASK          GENMASK(23, 0)
-
-#define MT_MIB_SDR16(_band)            MT_WF_MIB(_band, 0x048)
-#define MT_MIB_SDR16_BUSY_MASK         GENMASK(23, 0)
-
 #define MT_MIB_SDR34(_band)            MT_WF_MIB(_band, 0x090)
 #define MT_MIB_MU_BF_TX_CNT            GENMASK(15, 0)
 
-#define MT_MIB_SDR36(_band)            MT_WF_MIB(_band, 0x098)
-#define MT_MIB_SDR36_TXTIME_MASK       GENMASK(23, 0)
-#define MT_MIB_SDR37(_band)            MT_WF_MIB(_band, 0x09c)
-#define MT_MIB_SDR37_RXTIME_MASK       GENMASK(23, 0)
-
 #define MT_MIB_DR8(_band)              MT_WF_MIB(_band, 0x0c0)
 #define MT_MIB_DR9(_band)              MT_WF_MIB(_band, 0x0c4)
 #define MT_MIB_DR11(_band)             MT_WF_MIB(_band, 0x0cc)
 #define MT_MIB_BA_MISS_COUNT_MASK      GENMASK(15, 0)
 #define MT_MIB_ACK_FAIL_COUNT_MASK     GENMASK(31, 16)
 
-#define MT_MIB_MB_SDR2(_band, n)       MT_WF_MIB(_band, 0x108 + ((n) << 4))
-#define MT_MIB_FRAME_RETRIES_COUNT_MASK        GENMASK(15, 0)
-
 #define MT_TX_AGG_CNT(_band, n)                MT_WF_MIB(_band, 0x0a8 + ((n) << 2))
 #define MT_TX_AGG_CNT2(_band, n)       MT_WF_MIB(_band, 0x164 + ((n) << 2))
 #define MT_MIB_ARNG(_band, n)          MT_WF_MIB(_band, 0x4b8 + ((n) << 2))
 #define MT_WF_RFCR1_DROP_CFEND         BIT(7)
 #define MT_WF_RFCR1_DROP_CFACK         BIT(8)
 
-#define MT_WF_RMAC_MIB_TIME0(_band)    MT_WF_RMAC(_band, 0x03c4)
+#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
 #define MT_WF_RMAC_MIB_RXTIME_CLR      BIT(31)
 #define MT_WF_RMAC_MIB_RXTIME_EN       BIT(30)
 
-#define MT_WF_RMAC_MIB_AIRTIME14(_band)        MT_WF_RMAC(_band, 0x03b8)
-#define MT_MIB_OBSSTIME_MASK           GENMASK(23, 0)
-#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
-
 /* WFDMA0 */
 #define MT_WFDMA0_BASE                 0xd4000
 #define MT_WFDMA0(ofs)                 (MT_WFDMA0_BASE + (ofs))
index f9d81e3..b220b33 100644 (file)
@@ -464,10 +464,17 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
 static void
 mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
 {
-       if (en)
+       mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
+
+       if (en) {
+               struct mt7915_dev *dev = phy->dev;
+
                mt7915_tm_update_channel(phy);
 
-       mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
+               /* read-clear */
+               mt76_rr(dev, MT_MIB_SDR3(phy != &dev->phy));
+               mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
+       }
 }
 
 static int
@@ -690,7 +697,11 @@ static int
 mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
 {
        struct mt7915_phy *phy = mphy->priv;
+       struct mt7915_dev *dev = phy->dev;
+       bool ext_phy = phy != &dev->phy;
+       enum mt76_rxq_id q;
        void *rx, *rssi;
+       u16 fcs_err;
        int i;
 
        rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX);
@@ -735,6 +746,12 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
 
        nla_nest_end(msg, rx);
 
+       fcs_err = mt76_get_field(dev, MT_MIB_SDR3(ext_phy),
+                                MT_MIB_SDR3_FCS_ERR_MASK);
+       q = ext_phy ? MT_RXQ_EXT : MT_RXQ_MAIN;
+       mphy->test.rx_stats.packets[q] += fcs_err;
+       mphy->test.rx_stats.fcs_error[q] += fcs_err;
+
        return 0;
 }
 
index 8f8533e..397a6b5 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: ISC
+/* SPDX-License-Identifier: ISC */
 /* Copyright (C) 2020 MediaTek Inc. */
 
 #ifndef __MT7915_TESTMODE_H
index e531666..0ebb599 100644 (file)
@@ -1,4 +1,4 @@
-#SPDX-License-Identifier: ISC
+# SPDX-License-Identifier: ISC
 
 obj-$(CONFIG_MT7921E) += mt7921e.o
 
index 6ee423d..77468bd 100644 (file)
@@ -184,7 +184,10 @@ mt7921_txpwr(struct seq_file *s, void *data)
        struct mt7921_txpwr txpwr;
        int ret;
 
+       mt7921_mutex_acquire(dev);
        ret = mt7921_get_txpwr_info(dev, &txpwr);
+       mt7921_mutex_release(dev);
+
        if (ret)
                return ret;
 
@@ -247,6 +250,9 @@ mt7921_pm_set(void *data, u64 val)
        ieee80211_iterate_active_interfaces(mphy->hw,
                                            IEEE80211_IFACE_ITER_RESUME_ALL,
                                            mt7921_pm_interface_iter, mphy->priv);
+
+       mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
+
        mt7921_mutex_release(dev);
 
        return 0;
@@ -264,6 +270,36 @@ mt7921_pm_get(void *data, u64 *val)
 
 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
 
+static int
+mt7921_deep_sleep_set(void *data, u64 val)
+{
+       struct mt7921_dev *dev = data;
+       struct mt76_connac_pm *pm = &dev->pm;
+       bool enable = !!val;
+
+       mt7921_mutex_acquire(dev);
+       if (pm->ds_enable != enable) {
+               mt76_connac_mcu_set_deep_sleep(&dev->mt76, enable);
+               pm->ds_enable = enable;
+       }
+       mt7921_mutex_release(dev);
+
+       return 0;
+}
+
+static int
+mt7921_deep_sleep_get(void *data, u64 *val)
+{
+       struct mt7921_dev *dev = data;
+
+       *val = dev->pm.ds_enable;
+
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get,
+                        mt7921_deep_sleep_set, "%lld\n");
+
 static int
 mt7921_pm_stats(struct seq_file *s, void *data)
 {
@@ -355,6 +391,7 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
        debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
        debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
                                    mt7921_pm_stats);
+       debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
 
        return 0;
 }
index 71e664e..7d7d43a 100644 (file)
@@ -74,7 +74,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
        mt7921_tx_cleanup(dev);
        if (napi_complete(napi))
                mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 
        return 0;
 }
@@ -92,7 +92,7 @@ static int mt7921_poll_rx(struct napi_struct *napi, int budget)
                return 0;
        }
        done = mt76_dma_rx_poll(napi, budget);
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 
        return done;
 }
@@ -313,9 +313,9 @@ static int mt7921_dma_reset(struct mt7921_dev *dev, bool force)
 
 int mt7921_wfsys_reset(struct mt7921_dev *dev)
 {
-       mt76_set(dev, 0x70002600, BIT(0));
-       msleep(200);
-       mt76_clear(dev, 0x70002600, BIT(0));
+       mt76_clear(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B);
+       msleep(50);
+       mt76_set(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B);
 
        if (!__mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B,
                              WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500))
@@ -380,9 +380,7 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
 
 int mt7921_dma_init(struct mt7921_dev *dev)
 {
-       /* Increase buffer size to receive large VHT/HE MPDUs */
        struct mt76_bus_ops *bus_ops;
-       int rx_buf_size = MT_RX_BUF_SIZE * 2;
        int ret;
 
        dev->bus_ops = dev->mt76.bus;
@@ -402,6 +400,10 @@ int mt7921_dma_init(struct mt7921_dev *dev)
        if (ret)
                return ret;
 
+       ret = mt7921_wfsys_reset(dev);
+       if (ret)
+               return ret;
+
        /* init tx queue */
        ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0,
                                    MT7921_TX_RING_SIZE);
@@ -426,7 +428,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
                               MT7921_RXQ_MCU_WM,
                               MT7921_RX_MCU_RING_SIZE,
-                              rx_buf_size, MT_RX_EVENT_RING_BASE);
+                              MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
        if (ret)
                return ret;
 
@@ -434,14 +436,14 @@ int mt7921_dma_init(struct mt7921_dev *dev)
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
                               MT7921_RXQ_MCU_WM,
                               MT7921_RX_MCU_RING_SIZE,
-                              rx_buf_size, MT_WFDMA0(0x540));
+                              MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
        if (ret)
                return ret;
 
        /* rx data */
        ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
                               MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
-                              rx_buf_size, MT_RX_DATA_RING_BASE);
+                              MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
        if (ret)
                return ret;
 
index 1763ea0..a9ce10b 100644 (file)
@@ -7,34 +7,6 @@
 #include "mcu.h"
 #include "eeprom.h"
 
-#define CCK_RATE(_idx, _rate) {                                                \
-       .bitrate = _rate,                                               \
-       .flags = IEEE80211_RATE_SHORT_PREAMBLE,                         \
-       .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx),                    \
-       .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)),        \
-}
-
-#define OFDM_RATE(_idx, _rate) {                                       \
-       .bitrate = _rate,                                               \
-       .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx),                   \
-       .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx),             \
-}
-
-static struct ieee80211_rate mt7921_rates[] = {
-       CCK_RATE(0, 10),
-       CCK_RATE(1, 20),
-       CCK_RATE(2, 55),
-       CCK_RATE(3, 110),
-       OFDM_RATE(11, 60),
-       OFDM_RATE(15, 90),
-       OFDM_RATE(10, 120),
-       OFDM_RATE(14, 180),
-       OFDM_RATE(9,  240),
-       OFDM_RATE(13, 360),
-       OFDM_RATE(8,  480),
-       OFDM_RATE(12, 540),
-};
-
 static const struct ieee80211_iface_limit if_limits[] = {
        {
                .max = MT7921_MAX_INTERFACES,
@@ -73,11 +45,13 @@ static void
 mt7921_init_wiphy(struct ieee80211_hw *hw)
 {
        struct mt7921_phy *phy = mt7921_hw_phy(hw);
+       struct mt7921_dev *dev = phy->dev;
        struct wiphy *wiphy = hw->wiphy;
 
        hw->queues = 4;
        hw->max_rx_aggregation_subframes = 64;
        hw->max_tx_aggregation_subframes = 128;
+       hw->netdev_features = NETIF_F_RXCSUM;
 
        hw->radiotap_timestamp.units_pos =
                IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
@@ -88,11 +62,13 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
        hw->vif_data_size = sizeof(struct mt7921_vif);
 
        wiphy->iface_combinations = if_comb;
+       wiphy->flags &= ~WIPHY_FLAG_IBSS_RSN;
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
        wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
        wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
        wiphy->max_scan_ssids = 4;
        wiphy->max_sched_scan_plan_interval =
-               MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL;
+               MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;
        wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
        wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
        wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
@@ -100,46 +76,33 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
        wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
        wiphy->reg_notifier = mt7921_regd_notifier;
 
-       wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+       wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
+                          NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
 
        ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
        ieee80211_hw_set(hw, HAS_RATE_CONTROL);
        ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
+       ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
        ieee80211_hw_set(hw, WANT_MONITOR_VIF);
        ieee80211_hw_set(hw, SUPPORTS_PS);
        ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 
+       if (dev->pm.enable)
+               ieee80211_hw_set(hw, CONNECTION_MONITOR);
+
        hw->max_tx_fragments = 4;
 }
 
 static void
 mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
 {
-       u32 mask, set;
-
        mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
                       MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
        mt76_set(dev, MT_TMAC_CTCR0(band),
                 MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
                 MT_TMAC_CTCR0_INS_DDLMT_EN);
 
-       mask = MT_MDP_RCFR0_MCU_RX_MGMT |
-              MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |
-              MT_MDP_RCFR0_MCU_RX_CTL_BAR;
-       set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |
-             FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |
-             FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);
-       mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);
-
-       mask = MT_MDP_RCFR1_MCU_RX_BYPASS |
-              MT_MDP_RCFR1_RX_DROPPED_UCAST |
-              MT_MDP_RCFR1_RX_DROPPED_MCAST;
-       set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |
-             FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |
-             FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
-       mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
-
        mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
        mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
 
@@ -148,14 +111,15 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
        mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
 }
 
-void mt7921_mac_init(struct mt7921_dev *dev)
+int mt7921_mac_init(struct mt7921_dev *dev)
 {
        int i;
 
        mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
-       /* disable hardware de-agg */
-       mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
-       mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
+       /* enable hardware de-agg */
+       mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
+       /* enable hardware rx header translation */
+       mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
 
        for (i = 0; i < MT7921_WTBL_SIZE; i++)
                mt7921_mac_wtbl_update(dev, i,
@@ -163,7 +127,7 @@ void mt7921_mac_init(struct mt7921_dev *dev)
        for (i = 0; i < 2; i++)
                mt7921_mac_init_band(dev, i);
 
-       mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
+       return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
 }
 
 static int mt7921_init_hardware(struct mt7921_dev *dev)
@@ -203,9 +167,7 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
        dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
        rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
 
-       mt7921_mac_init(dev);
-
-       return 0;
+       return mt7921_mac_init(dev);
 }
 
 int mt7921_register_device(struct mt7921_dev *dev)
@@ -224,7 +186,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
        mutex_init(&dev->pm.mutex);
        init_waitqueue_head(&dev->pm.wait);
        spin_lock_init(&dev->pm.txq_lock);
-       set_bit(MT76_STATE_PM, &dev->mphy.state);
        INIT_LIST_HEAD(&dev->phy.stats_list);
        INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
        INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
@@ -239,6 +200,8 @@ int mt7921_register_device(struct mt7921_dev *dev)
        dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
        dev->pm.stats.last_wake_event = jiffies;
        dev->pm.stats.last_doze_event = jiffies;
+       dev->pm.enable = true;
+       dev->pm.ds_enable = true;
 
        ret = mt7921_init_hardware(dev);
        if (ret)
@@ -253,19 +216,33 @@ int mt7921_register_device(struct mt7921_dev *dev)
                        IEEE80211_HT_CAP_MAX_AMSDU;
        dev->mphy.sband_5g.sband.vht_cap.cap |=
                        IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
-                       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+                       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
+                       IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+                       IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
+                       (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+
        dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
        dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
 
        mt76_set_stream_caps(&dev->mphy, true);
        mt7921_set_stream_he_caps(&dev->phy);
 
-       ret = mt76_register_device(&dev->mt76, true, mt7921_rates,
-                                  ARRAY_SIZE(mt7921_rates));
+       ret = mt76_register_device(&dev->mt76, true, mt76_rates,
+                                  ARRAY_SIZE(mt76_rates));
+       if (ret)
+               return ret;
+
+       ret = mt7921_init_debugfs(dev);
        if (ret)
                return ret;
 
-       return mt7921_init_debugfs(dev);
+       ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
+       if (ret)
+               return ret;
+
+       dev->hw_init_done = true;
+
+       return 0;
 }
 
 void mt7921_unregister_device(struct mt7921_dev *dev)
index decf2d5..7fe2e3a 100644 (file)
@@ -308,21 +308,24 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
 
 int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
 {
+       u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
        struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+       bool hdr_trans, unicast, insert_ccmp_hdr = false;
+       u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info;
+       __le32 *rxv = NULL, *rxd = (__le32 *)skb->data;
        struct mt76_phy *mphy = &dev->mt76.phy;
        struct mt7921_phy *phy = &dev->phy;
        struct ieee80211_supported_band *sband;
        struct ieee80211_hdr *hdr;
-       __le32 *rxd = (__le32 *)skb->data;
-       __le32 *rxv = NULL;
-       u32 mode = 0;
+       u32 rxd0 = le32_to_cpu(rxd[0]);
        u32 rxd1 = le32_to_cpu(rxd[1]);
        u32 rxd2 = le32_to_cpu(rxd[2]);
        u32 rxd3 = le32_to_cpu(rxd[3]);
-       bool unicast, insert_ccmp_hdr = false;
-       u8 remove_pad;
+       u32 rxd4 = le32_to_cpu(rxd[4]);
+       u16 seq_ctrl = 0;
+       __le16 fc = 0;
+       u32 mode = 0;
        int i, idx;
-       u8 chfreq;
 
        memset(status, 0, sizeof(*status));
 
@@ -332,9 +335,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (!test_bit(MT76_STATE_RUNNING, &mphy->state))
                return -EINVAL;
 
+       if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
+               return -EINVAL;
+
        chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
        unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
        idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
+       hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
        status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
 
        if (status->wcid) {
@@ -357,6 +364,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (!sband->channels)
                return -EINVAL;
 
+       if ((rxd0 & csum_mask) == csum_mask)
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+
        if (rxd1 & MT_RXD1_NORMAL_FCS_ERR)
                status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
@@ -377,6 +387,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
 
        rxd += 6;
        if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
+               u32 v0 = le32_to_cpu(rxd[0]);
+               u32 v2 = le32_to_cpu(rxd[2]);
+
+               fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0));
+               seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2);
+               qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2);
+
                rxd += 4;
                if ((u8 *)rxd - skb->data >= skb->len)
                        return -EINVAL;
@@ -386,14 +403,27 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
                u8 *data = (u8 *)rxd;
 
                if (status->flag & RX_FLAG_DECRYPTED) {
-                       status->iv[0] = data[5];
-                       status->iv[1] = data[4];
-                       status->iv[2] = data[3];
-                       status->iv[3] = data[2];
-                       status->iv[4] = data[1];
-                       status->iv[5] = data[0];
-
-                       insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                       switch (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1)) {
+                       case MT_CIPHER_AES_CCMP:
+                       case MT_CIPHER_CCMP_CCX:
+                       case MT_CIPHER_CCMP_256:
+                               insert_ccmp_hdr =
+                                       FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);
+                               fallthrough;
+                       case MT_CIPHER_TKIP:
+                       case MT_CIPHER_TKIP_NO_MIC:
+                       case MT_CIPHER_GCMP:
+                       case MT_CIPHER_GCMP_256:
+                               status->iv[0] = data[5];
+                               status->iv[1] = data[4];
+                               status->iv[2] = data[3];
+                               status->iv[3] = data[2];
+                               status->iv[4] = data[1];
+                               status->iv[5] = data[0];
+                               break;
+                       default:
+                               break;
+                       }
                }
                rxd += 4;
                if ((u8 *)rxd - skb->data >= skb->len)
@@ -444,16 +474,19 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
                status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1);
                status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1);
                status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
-               status->signal = status->chain_signal[0];
-
-               for (i = 1; i < hweight8(mphy->antenna_mask); i++) {
-                       if (!(status->chains & BIT(i)))
+               status->signal = -128;
+               for (i = 0; i < hweight8(mphy->antenna_mask); i++) {
+                       if (!(status->chains & BIT(i)) ||
+                           status->chain_signal[i] >= 0)
                                continue;
 
                        status->signal = max(status->signal,
                                             status->chain_signal[i]);
                }
 
+               if (status->signal == -128)
+                       status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
                stbc = FIELD_GET(MT_PRXV_STBC, v0);
                gi = FIELD_GET(MT_PRXV_SGI, v0);
                cck = false;
@@ -540,10 +573,35 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
 
        skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
 
-       if (insert_ccmp_hdr) {
-               u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
+       amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
+       status->amsdu = !!amsdu_info;
+       if (status->amsdu) {
+               status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
+               status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
+               if (!hdr_trans) {
+                       memmove(skb->data + 2, skb->data,
+                               ieee80211_get_hdrlen_from_skb(skb));
+                       skb_pull(skb, 2);
+               }
+       }
+
+       if (!hdr_trans) {
+               if (insert_ccmp_hdr) {
+                       u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
+
+                       mt76_insert_ccmp_hdr(skb, key_id);
+               }
 
-               mt76_insert_ccmp_hdr(skb, key_id);
+               hdr = mt76_skb_get_hdr(skb);
+               fc = hdr->frame_control;
+               if (ieee80211_is_data_qos(fc)) {
+                       seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
+                       qos_ctl = *ieee80211_get_qos_ctl(hdr);
+               }
+       } else {
+               status->flag &= ~(RX_FLAG_RADIOTAP_HE |
+                                 RX_FLAG_RADIOTAP_HE_MU);
+               status->flag |= RX_FLAG_8023;
        }
 
        mt7921_mac_assoc_rssi(dev, skb);
@@ -551,14 +609,12 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
                mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
 
-       hdr = mt76_skb_get_hdr(skb);
-       if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
+       if (!status->wcid || !ieee80211_is_data_qos(fc))
                return 0;
 
-       status->aggr = unicast &&
-                      !ieee80211_is_qos_nullfunc(hdr->frame_control);
-       status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
-       status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+       status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc);
+       status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
+       status->qos_ctl = qos_ctl;
 
        return 0;
 }
@@ -676,6 +732,23 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi,
        txwi[7] |= cpu_to_le32(val);
 }
 
+static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi)
+{
+       struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid);
+       u32 pid, frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, txwi[2]);
+
+       if (!(frame_type & (IEEE80211_FTYPE_DATA >> 2)))
+               return;
+
+       if (time_is_after_eq_jiffies(msta->next_txs_ts))
+               return;
+
+       msta->next_txs_ts = jiffies + msecs_to_jiffies(250);
+       pid = mt76_get_next_pkt_id(wcid);
+       txwi[5] |= cpu_to_le32(MT_TXD5_TX_STATUS_MCU |
+                              FIELD_PREP(MT_TXD5_PID, pid));
+}
+
 void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
                           struct sk_buff *skb, struct mt76_wcid *wcid,
                           struct ieee80211_key_conf *key, bool beacon)
@@ -752,6 +825,8 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
                txwi[6] |= cpu_to_le32(val);
                txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
        }
+
+       mt7921_update_txs(wcid, txwi);
 }
 
 static void
@@ -1154,18 +1229,18 @@ mt7921_phy_update_channel(struct mt76_phy *mphy, int idx)
        state->noise = -(phy->noise >> 4);
 }
 
-void mt7921_update_channel(struct mt76_dev *mdev)
+void mt7921_update_channel(struct mt76_phy *mphy)
 {
-       struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76);
 
-       if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
+       if (mt76_connac_pm_wake(mphy, &dev->pm))
                return;
 
-       mt7921_phy_update_channel(&mdev->phy, 0);
+       mt7921_phy_update_channel(mphy, 0);
        /* reset obss airtime */
        mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
 
-       mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
+       mt76_connac_power_save_sched(mphy, &dev->pm);
 }
 
 void mt7921_tx_token_put(struct mt7921_dev *dev)
@@ -1196,7 +1271,8 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
        struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
        struct mt7921_dev *dev = mvif->phy->dev;
 
-       ieee80211_disconnect(vif, true);
+       if (vif->type == NL80211_IFTYPE_STATION)
+               ieee80211_disconnect(vif, true);
 
        mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
        mt7921_mcu_set_tx(dev, vif);
@@ -1212,6 +1288,7 @@ mt7921_mac_reset(struct mt7921_dev *dev)
        mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
        mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
 
+       set_bit(MT76_RESET, &dev->mphy.state);
        set_bit(MT76_MCU_RESET, &dev->mphy.state);
        wake_up(&dev->mt76.mcu.wait);
        skb_queue_purge(&dev->mt76.mcu.res_q);
@@ -1227,56 +1304,64 @@ mt7921_mac_reset(struct mt7921_dev *dev)
        mt7921_tx_token_put(dev);
        idr_init(&dev->mt76.token);
 
-       err = mt7921_wpdma_reset(dev, true);
-       if (err)
-               return err;
+       mt7921_wpdma_reset(dev, true);
 
        mt76_for_each_q_rx(&dev->mt76, i) {
                napi_enable(&dev->mt76.napi[i]);
                napi_schedule(&dev->mt76.napi[i]);
        }
 
-       napi_enable(&dev->mt76.tx_napi);
-       napi_schedule(&dev->mt76.tx_napi);
-       mt76_worker_enable(&dev->mt76.tx_worker);
-
        clear_bit(MT76_MCU_RESET, &dev->mphy.state);
-       clear_bit(MT76_STATE_PM, &dev->mphy.state);
 
-       mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
+       mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA,
+               MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
+               MT_INT_MCU_CMD);
        mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
 
        err = mt7921_run_firmware(dev);
        if (err)
-               return err;
+               goto out;
 
        err = mt7921_mcu_set_eeprom(dev);
        if (err)
-               return err;
+               goto out;
 
-       mt7921_mac_init(dev);
-       return __mt7921_start(&dev->phy);
+       err = mt7921_mac_init(dev);
+       if (err)
+               goto out;
+
+       err = __mt7921_start(&dev->phy);
+out:
+       clear_bit(MT76_RESET, &dev->mphy.state);
+
+       napi_enable(&dev->mt76.tx_napi);
+       napi_schedule(&dev->mt76.tx_napi);
+       mt76_worker_enable(&dev->mt76.tx_worker);
+
+       return err;
 }
 
 /* system error recovery */
 void mt7921_mac_reset_work(struct work_struct *work)
 {
-       struct ieee80211_hw *hw;
-       struct mt7921_dev *dev;
+       struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
+                                             reset_work);
+       struct ieee80211_hw *hw = mt76_hw(dev);
+       struct mt76_connac_pm *pm = &dev->pm;
        int i;
 
-       dev = container_of(work, struct mt7921_dev, reset_work);
-       hw = mt76_hw(dev);
-
        dev_err(dev->mt76.dev, "chip reset\n");
+       dev->hw_full_reset = true;
        ieee80211_stop_queues(hw);
 
        cancel_delayed_work_sync(&dev->mphy.mac_work);
-       cancel_delayed_work_sync(&dev->pm.ps_work);
-       cancel_work_sync(&dev->pm.wake_work);
+       cancel_delayed_work_sync(&pm->ps_work);
+       cancel_work_sync(&pm->wake_work);
 
        mutex_lock(&dev->mt76.mutex);
        for (i = 0; i < 10; i++) {
+               __mt7921_mcu_drv_pmctrl(dev);
+
                if (!mt7921_mac_reset(dev))
                        break;
        }
@@ -1293,16 +1378,24 @@ void mt7921_mac_reset_work(struct work_struct *work)
                ieee80211_scan_completed(dev->mphy.hw, &info);
        }
 
+       dev->hw_full_reset = false;
        ieee80211_wake_queues(hw);
        ieee80211_iterate_active_interfaces(hw,
                                            IEEE80211_IFACE_ITER_RESUME_ALL,
                                            mt7921_vif_connect_iter, NULL);
+       mt76_connac_power_save_sched(&dev->mt76.phy, pm);
 }
 
 void mt7921_reset(struct mt76_dev *mdev)
 {
        struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
 
+       if (!dev->hw_init_done)
+               return;
+
+       if (dev->hw_full_reset)
+               return;
+
        queue_work(dev->mt76.wq, &dev->reset_work);
 }
 
@@ -1337,30 +1430,6 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
        }
 }
 
-static void
-mt7921_mac_sta_stats_work(struct mt7921_phy *phy)
-{
-       struct mt7921_dev *dev = phy->dev;
-       struct mt7921_sta *msta;
-       LIST_HEAD(list);
-
-       spin_lock_bh(&dev->sta_poll_lock);
-       list_splice_init(&phy->stats_list, &list);
-
-       while (!list_empty(&list)) {
-               msta = list_first_entry(&list, struct mt7921_sta, stats_list);
-               list_del_init(&msta->stats_list);
-               spin_unlock_bh(&dev->sta_poll_lock);
-
-               /* query wtbl info to report tx rate for further devices */
-               mt7921_get_wtbl_info(dev, msta->wcid.idx);
-
-               spin_lock_bh(&dev->sta_poll_lock);
-       }
-
-       spin_unlock_bh(&dev->sta_poll_lock);
-}
-
 void mt7921_mac_work(struct work_struct *work)
 {
        struct mt7921_phy *phy;
@@ -1372,16 +1441,12 @@ void mt7921_mac_work(struct work_struct *work)
 
        mt7921_mutex_acquire(phy->dev);
 
-       mt76_update_survey(mphy->dev);
+       mt76_update_survey(mphy);
        if (++mphy->mac_work_count == 2) {
                mphy->mac_work_count = 0;
 
                mt7921_mac_update_mib_stats(phy);
        }
-       if (++phy->sta_work_count == 4) {
-               phy->sta_work_count = 0;
-               mt7921_mac_sta_stats_work(phy);
-       }
 
        mt7921_mutex_release(phy->dev);
        ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
@@ -1417,13 +1482,15 @@ void mt7921_pm_power_save_work(struct work_struct *work)
 {
        struct mt7921_dev *dev;
        unsigned long delta;
+       struct mt76_phy *mphy;
 
        dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev,
                                                pm.ps_work.work);
+       mphy = dev->phy.mt76;
 
        delta = dev->pm.idle_timeout;
-       if (test_bit(MT76_HW_SCANNING, &dev->mphy.state) ||
-           test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state))
+       if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
+           test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
                goto out;
 
        if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
@@ -1431,8 +1498,10 @@ void mt7921_pm_power_save_work(struct work_struct *work)
                goto out;
        }
 
-       if (!mt7921_mcu_fw_pmctrl(dev))
+       if (!mt7921_mcu_fw_pmctrl(dev)) {
+               cancel_delayed_work_sync(&mphy->mac_work);
                return;
+       }
 out:
        queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
 }
@@ -1494,7 +1563,7 @@ void mt7921_coredump_work(struct work_struct *work)
                        break;
 
                skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
-               if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
+               if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
                        dev_kfree_skb(skb);
                        continue;
                }
@@ -1504,7 +1573,10 @@ void mt7921_coredump_work(struct work_struct *work)
 
                dev_kfree_skb(skb);
        }
-       dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
-                     GFP_KERNEL);
+
+       if (dump)
+               dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
+                             GFP_KERNEL);
+
        mt7921_reset(&dev->mt76);
 }
index 109c884..3af67fa 100644 (file)
@@ -88,6 +88,9 @@ enum rx_pkt_type {
 
 /* RXD DW4 */
 #define MT_RXD4_NORMAL_PAYLOAD_FORMAT  GENMASK(1, 0)
+#define MT_RXD4_FIRST_AMSDU_FRAME      GENMASK(1, 0)
+#define MT_RXD4_MID_AMSDU_FRAME                BIT(1)
+#define MT_RXD4_LAST_AMSDU_FRAME       BIT(0)
 #define MT_RXD4_NORMAL_PATTERN_DROP    BIT(9)
 #define MT_RXD4_NORMAL_CLS             BIT(10)
 #define MT_RXD4_NORMAL_OFLD            GENMASK(12, 11)
@@ -97,6 +100,17 @@ enum rx_pkt_type {
 #define MT_RXD3_NORMAL_PF_MODE         BIT(29)
 #define MT_RXD3_NORMAL_PF_STS          GENMASK(31, 30)
 
+/* RXD GROUP4 */
+#define MT_RXD6_FRAME_CONTROL          GENMASK(15, 0)
+#define MT_RXD6_TA_LO                  GENMASK(31, 16)
+
+#define MT_RXD7_TA_HI                  GENMASK(31, 0)
+
+#define MT_RXD8_SEQ_CTRL               GENMASK(15, 0)
+#define MT_RXD8_QOS_CTL                        GENMASK(31, 16)
+
+#define MT_RXD9_HT_CONTROL             GENMASK(31, 0)
+
 /* P-RXV DW0 */
 #define MT_PRXV_TX_RATE                        GENMASK(6, 0)
 #define MT_PRXV_TX_DCM                 BIT(4)
index 97a0ef3..7fd2104 100644 (file)
@@ -79,13 +79,14 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
                he_cap_elem->phy_cap_info[1] =
                        IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
                he_cap_elem->phy_cap_info[2] =
+                       IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
                        IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
-                       IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
+                       IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
+                       IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+                       IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
 
                switch (i) {
                case NL80211_IFTYPE_STATION:
-                       he_cap_elem->mac_cap_info[0] |=
-                               IEEE80211_HE_MAC_CAP0_TWT_REQ;
                        he_cap_elem->mac_cap_info[1] |=
                                IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
 
@@ -102,7 +103,15 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
                        he_cap_elem->phy_cap_info[3] |=
                                IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
                                IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
+                       he_cap_elem->phy_cap_info[4] |=
+                               IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
+                               IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
+                       he_cap_elem->phy_cap_info[5] |=
+                               IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
+                               IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
                        he_cap_elem->phy_cap_info[6] |=
+                               IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
+                               IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
                                IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
                                IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
                                IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
@@ -223,54 +232,6 @@ static void mt7921_stop(struct ieee80211_hw *hw)
        mt7921_mutex_release(dev);
 }
 
-static inline int get_free_idx(u32 mask, u8 start, u8 end)
-{
-       return ffs(~mask & GENMASK(end, start));
-}
-
-static int get_omac_idx(enum nl80211_iftype type, u64 mask)
-{
-       int i;
-
-       switch (type) {
-       case NL80211_IFTYPE_STATION:
-               /* prefer hw bssid slot 1-3 */
-               i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3);
-               if (i)
-                       return i - 1;
-
-               /* next, try to find a free repeater entry for the sta */
-               i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
-                                REPEATER_BSSID_MAX - REPEATER_BSSID_START);
-               if (i)
-                       return i + 32 - 1;
-
-               i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
-               if (i)
-                       return i - 1;
-
-               if (~mask & BIT(HW_BSSID_0))
-                       return HW_BSSID_0;
-
-               break;
-       case NL80211_IFTYPE_MONITOR:
-               /* ap uses hw bssid 0 and ext bssid */
-               if (~mask & BIT(HW_BSSID_0))
-                       return HW_BSSID_0;
-
-               i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
-               if (i)
-                       return i - 1;
-
-               break;
-       default:
-               WARN_ON(1);
-               break;
-       }
-
-       return -1;
-}
-
 static int mt7921_add_interface(struct ieee80211_hw *hw,
                                struct ieee80211_vif *vif)
 {
@@ -292,12 +253,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       idx = get_omac_idx(vif->type, phy->omac_mask);
-       if (idx < 0) {
-               ret = -ENOSPC;
-               goto out;
-       }
-       mvif->mt76.omac_idx = idx;
+       mvif->mt76.omac_idx = mvif->mt76.idx;
        mvif->phy = phy;
        mvif->mt76.band_idx = 0;
        mvif->mt76.wmm_idx = mvif->mt76.idx % MT7921_MAX_WMM_SETS;
@@ -369,7 +325,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
        spin_unlock_bh(&dev->sta_poll_lock);
 }
 
-int mt7921_set_channel(struct mt7921_phy *phy)
+static int mt7921_set_channel(struct mt7921_phy *phy)
 {
        struct mt7921_dev *dev = phy->dev;
        int ret;
@@ -429,6 +385,10 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
                wcid_keyidx = &wcid->hw_key_idx2;
                break;
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               if (!mvif->wep_sta)
+                       return -EOPNOTSUPP;
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
@@ -436,8 +396,6 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        case WLAN_CIPHER_SUITE_GCMP_256:
        case WLAN_CIPHER_SUITE_SMS4:
                break;
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
        default:
                return -EOPNOTSUPP;
        }
@@ -455,6 +413,12 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                            cmd == SET_KEY ? key : NULL);
 
        err = mt7921_mcu_add_key(dev, vif, msta, key, cmd);
+       if (err)
+               goto out;
+
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP104 ||
+           key->cipher == WLAN_CIPHER_SUITE_WEP40)
+               err = mt7921_mcu_add_key(dev, vif, mvif->wep_sta, key, cmd);
 out:
        mt7921_mutex_release(dev);
 
@@ -477,6 +441,9 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
 
        mt7921_mutex_acquire(dev);
 
+       if (changed & IEEE80211_CONF_CHANGE_POWER)
+               mt76_connac_mcu_set_rate_txpower(phy->mt76);
+
        if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
                bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
 
@@ -622,7 +589,8 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
                mt7921_mcu_uni_bss_ps(dev, vif);
 
        if (changed & BSS_CHANGED_ASSOC) {
-               mt7921_mcu_sta_add(dev, NULL, vif, true);
+               mt7921_mcu_sta_update(dev, NULL, vif, true,
+                                     MT76_STA_INFO_STATE_ASSOC);
                mt7921_bss_bcnft_apply(dev, vif, info->assoc);
        }
 
@@ -661,14 +629,14 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        if (ret)
                return ret;
 
-       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
-               mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
-                                           true);
+       if (vif->type == NL80211_IFTYPE_STATION)
+               mvif->wep_sta = msta;
 
        mt7921_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
-       ret = mt7921_mcu_sta_add(dev, sta, vif, true);
+       ret = mt7921_mcu_sta_update(dev, sta, vif, true,
+                                   MT76_STA_INFO_STATE_NONE);
        if (ret)
                return ret;
 
@@ -677,6 +645,27 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        return 0;
 }
 
+void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+                         struct ieee80211_sta *sta)
+{
+       struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
+       struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+
+       mt7921_mutex_acquire(dev);
+
+       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+               mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
+                                           true);
+
+       mt7921_mac_wtbl_update(dev, msta->wcid.idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+
+       mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC);
+
+       mt7921_mutex_release(dev);
+}
+
 void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta)
 {
@@ -686,13 +675,14 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
        mt76_connac_pm_wake(&dev->mphy, &dev->pm);
 
-       mt7921_mcu_sta_add(dev, sta, vif, false);
+       mt7921_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE);
        mt7921_mac_wtbl_update(dev, msta->wcid.idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
        if (vif->type == NL80211_IFTYPE_STATION) {
                struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
 
+               mvif->wep_sta = NULL;
                ewma_rssi_init(&mvif->rssi);
                if (!sta->tdls)
                        mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
@@ -720,7 +710,7 @@ void mt7921_tx_worker(struct mt76_worker *w)
        }
 
        mt76_txq_schedule_all(&dev->mphy);
-       mt76_connac_pm_unref(&dev->pm);
+       mt76_connac_pm_unref(&dev->mphy, &dev->pm);
 }
 
 static void mt7921_tx(struct ieee80211_hw *hw,
@@ -750,7 +740,7 @@ static void mt7921_tx(struct ieee80211_hw *hw,
 
        if (mt76_connac_pm_ref(mphy, &dev->pm)) {
                mt76_tx(mphy, control->sta, wcid, skb);
-               mt76_connac_pm_unref(&dev->pm);
+               mt76_connac_pm_unref(mphy, &dev->pm);
                return;
        }
 
@@ -831,20 +821,21 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        return ret;
 }
 
-static int
-mt7921_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-              struct ieee80211_sta *sta)
+static int mt7921_sta_state(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif,
+                           struct ieee80211_sta *sta,
+                           enum ieee80211_sta_state old_state,
+                           enum ieee80211_sta_state new_state)
 {
-       return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
-                             IEEE80211_STA_NONE);
-}
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
 
-static int
-mt7921_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                 struct ieee80211_sta *sta)
-{
-       return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
-                             IEEE80211_STA_NOTEXIST);
+       if (dev->pm.ds_enable) {
+               mt7921_mutex_acquire(dev);
+               mt76_connac_sta_state_dp(&dev->mt76, old_state, new_state);
+               mt7921_mutex_release(dev);
+       }
+
+       return mt76_sta_state(hw, vif, sta, old_state, new_state);
 }
 
 static int
@@ -1163,6 +1154,23 @@ static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                           HZ / 2);
 }
 
+static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
+                                        struct ieee80211_vif *vif,
+                                        struct ieee80211_sta *sta,
+                                        bool enabled)
+{
+       struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+       if (enabled)
+               set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
+       else
+               clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
+
+       mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid,
+                                            MCU_UNI_CMD_STA_REC_UPDATE);
+}
+
 const struct ieee80211_ops mt7921_ops = {
        .tx = mt7921_tx,
        .start = mt7921_start,
@@ -1173,10 +1181,10 @@ const struct ieee80211_ops mt7921_ops = {
        .conf_tx = mt7921_conf_tx,
        .configure_filter = mt7921_configure_filter,
        .bss_info_changed = mt7921_bss_info_changed,
-       .sta_add = mt7921_sta_add,
-       .sta_remove = mt7921_sta_remove,
+       .sta_state = mt7921_sta_state,
        .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
        .set_key = mt7921_set_key,
+       .sta_set_decap_offload = mt7921_sta_set_decap_offload,
        .ampdu_action = mt7921_ampdu_action,
        .set_rts_threshold = mt7921_set_rts_threshold,
        .wake_tx_queue = mt76_wake_tx_queue,
index 67dc4b4..c2c4dc1 100644 (file)
@@ -88,28 +88,28 @@ struct mt7921_fw_region {
 #define to_wcid_lo(id)                 FIELD_GET(GENMASK(7, 0), (u16)id)
 #define to_wcid_hi(id)                 FIELD_GET(GENMASK(9, 8), (u16)id)
 
-static enum mt7921_cipher_type
+static enum mcu_cipher_type
 mt7921_mcu_get_cipher(int cipher)
 {
        switch (cipher) {
        case WLAN_CIPHER_SUITE_WEP40:
-               return MT_CIPHER_WEP40;
+               return MCU_CIPHER_WEP40;
        case WLAN_CIPHER_SUITE_WEP104:
-               return MT_CIPHER_WEP104;
+               return MCU_CIPHER_WEP104;
        case WLAN_CIPHER_SUITE_TKIP:
-               return MT_CIPHER_TKIP;
+               return MCU_CIPHER_TKIP;
        case WLAN_CIPHER_SUITE_AES_CMAC:
-               return MT_CIPHER_BIP_CMAC_128;
+               return MCU_CIPHER_BIP_CMAC_128;
        case WLAN_CIPHER_SUITE_CCMP:
-               return MT_CIPHER_AES_CCMP;
+               return MCU_CIPHER_AES_CCMP;
        case WLAN_CIPHER_SUITE_CCMP_256:
-               return MT_CIPHER_CCMP_256;
+               return MCU_CIPHER_CCMP_256;
        case WLAN_CIPHER_SUITE_GCMP:
-               return MT_CIPHER_GCMP;
+               return MCU_CIPHER_GCMP;
        case WLAN_CIPHER_SUITE_GCMP_256:
-               return MT_CIPHER_GCMP_256;
+               return MCU_CIPHER_GCMP_256;
        case WLAN_CIPHER_SUITE_SMS4:
-               return MT_CIPHER_WAPI;
+               return MCU_CIPHER_WAPI;
        default:
                return MT_CIPHER_NONE;
        }
@@ -398,43 +398,6 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy,
        }
 }
 
-static void
-mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
-                         u16 wlan_idx)
-{
-       struct mt7921_mcu_wlan_info_event *wtbl_info;
-       struct mt76_phy *mphy = &dev->mphy;
-       struct mt7921_sta_stats *stats;
-       struct rate_info rate = {};
-       struct mt7921_sta *msta;
-       struct mt76_wcid *wcid;
-       u8 idx;
-
-       if (wlan_idx >= MT76_N_WCIDS)
-               return;
-
-       wtbl_info = (struct mt7921_mcu_wlan_info_event *)skb->data;
-       idx = wtbl_info->rate_info.rate_idx;
-       if (idx >= ARRAY_SIZE(wtbl_info->rate_info.rate))
-               return;
-
-       rcu_read_lock();
-
-       wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
-       if (!wcid)
-               goto out;
-
-       msta = container_of(wcid, struct mt7921_sta, wcid);
-       stats = &msta->stats;
-
-       /* current rate */
-       mt7921_mcu_tx_rate_parse(mphy, &wtbl_info->peer_cap, &rate,
-                                le16_to_cpu(wtbl_info->rate_info.rate[idx]));
-       stats->tx_rate = rate;
-out:
-       rcu_read_unlock();
-}
-
 static void
 mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
@@ -450,22 +413,33 @@ mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
 }
 
 static void
-mt7921_mcu_beacon_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
+mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,
+                               struct ieee80211_vif *vif)
+{
+       struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
+       struct mt76_connac_beacon_loss_event *event = priv;
+
+       if (mvif->idx != event->bss_idx)
+               return;
+
+       if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))
+               return;
+
+       ieee80211_connection_loss(vif);
+}
+
+static void
+mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
        struct mt76_connac_beacon_loss_event *event;
-       struct mt76_phy *mphy;
-       u8 band_idx = 0; /* DBDC support */
+       struct mt76_phy *mphy = &dev->mt76.phy;
 
        skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
        event = (struct mt76_connac_beacon_loss_event *)skb->data;
-       if (band_idx && dev->mt76.phy2)
-               mphy = dev->mt76.phy2;
-       else
-               mphy = &dev->mt76.phy;
 
        ieee80211_iterate_active_interfaces_atomic(mphy->hw,
                                        IEEE80211_IFACE_ITER_RESUME_ALL,
-                                       mt76_connac_mcu_beacon_loss_iter, event);
+                                       mt7921_mcu_connection_loss_iter, event);
 }
 
 static void
@@ -523,6 +497,49 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
        trace_lp_event(dev, event->state);
 }
 
+static void
+mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
+{
+       struct mt7921_mcu_tx_done_event *event;
+       struct mt7921_sta *msta;
+       struct mt7921_phy *mphy = &dev->phy;
+       struct mt7921_mcu_peer_cap peer;
+       struct ieee80211_sta *sta;
+       LIST_HEAD(list);
+
+       skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
+       event = (struct mt7921_mcu_tx_done_event *)skb->data;
+
+       spin_lock_bh(&dev->sta_poll_lock);
+       list_splice_init(&mphy->stats_list, &list);
+
+       while (!list_empty(&list)) {
+               msta = list_first_entry(&list, struct mt7921_sta, stats_list);
+               list_del_init(&msta->stats_list);
+
+               if (msta->wcid.idx != event->wlan_idx)
+                       continue;
+
+               spin_unlock_bh(&dev->sta_poll_lock);
+
+               sta = wcid_to_sta(&msta->wcid);
+
+               /* peer config based on IEEE SPEC */
+               memset(&peer, 0x0, sizeof(peer));
+               peer.bw = event->bw;
+               peer.g2 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
+               peer.g4 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
+               peer.g8 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
+               peer.g16 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
+               mt7921_mcu_tx_rate_parse(mphy->mt76, &peer,
+                                        &msta->stats.tx_rate, event->tx_rate);
+
+               spin_lock_bh(&dev->sta_poll_lock);
+               break;
+       }
+       spin_unlock_bh(&dev->sta_poll_lock);
+}
+
 static void
 mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
@@ -530,7 +547,7 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
 
        switch (rxd->eid) {
        case MCU_EVENT_BSS_BEACON_LOSS:
-               mt7921_mcu_beacon_loss_event(dev, skb);
+               mt7921_mcu_connection_loss_event(dev, skb);
                break;
        case MCU_EVENT_SCHED_SCAN_DONE:
        case MCU_EVENT_SCAN_DONE:
@@ -549,6 +566,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
        case MCU_EVENT_LP_INFO:
                mt7921_mcu_low_power_event(dev, skb);
                break;
+       case MCU_EVENT_TX_DONE:
+               mt7921_mcu_tx_done_event(dev, skb);
+               break;
        default:
                break;
        }
@@ -569,6 +589,7 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
            rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
            rxd->eid == MCU_EVENT_BSS_ABSENCE ||
            rxd->eid == MCU_EVENT_SCAN_DONE ||
+           rxd->eid == MCU_EVENT_TX_DONE ||
            rxd->eid == MCU_EVENT_DBG_MSG ||
            rxd->eid == MCU_EVENT_COREDUMP ||
            rxd->eid == MCU_EVENT_LP_INFO ||
@@ -604,14 +625,14 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb,
                sec_key = &sec->key[0];
                sec_key->cipher_len = sizeof(*sec_key);
 
-               if (cipher == MT_CIPHER_BIP_CMAC_128) {
-                       sec_key->cipher_id = MT_CIPHER_AES_CCMP;
+               if (cipher == MCU_CIPHER_BIP_CMAC_128) {
+                       sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
                        sec_key->key_id = bip->keyidx;
                        sec_key->key_len = 16;
                        memcpy(sec_key->key, bip->key, 16);
 
                        sec_key = &sec->key[1];
-                       sec_key->cipher_id = MT_CIPHER_BIP_CMAC_128;
+                       sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
                        sec_key->cipher_len = sizeof(*sec_key);
                        sec_key->key_len = 16;
                        memcpy(sec_key->key, key->key, 16);
@@ -623,14 +644,14 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb,
                        sec_key->key_len = key->keylen;
                        memcpy(sec_key->key, key->key, key->keylen);
 
-                       if (cipher == MT_CIPHER_TKIP) {
+                       if (cipher == MCU_CIPHER_TKIP) {
                                /* Rx/Tx MIC keys are swapped */
                                memcpy(sec_key->key + 16, key->key + 24, 8);
                                memcpy(sec_key->key + 24, key->key + 16, 8);
                        }
 
                        /* store key_conf for BIP batch update */
-                       if (cipher == MT_CIPHER_AES_CCMP) {
+                       if (cipher == MCU_CIPHER_AES_CCMP) {
                                memcpy(bip->key, key->key, key->keylen);
                                bip->keyidx = key->keyidx;
                        }
@@ -934,8 +955,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
        dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
 #endif /* CONFIG_PM */
 
-       clear_bit(MT76_STATE_PM, &dev->mphy.state);
-
        dev_err(dev->mt76.dev, "Firmware init done\n");
 
        return 0;
@@ -969,7 +988,7 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
        set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
        mt7921_mcu_fw_log_2_host(dev, 1);
 
-       return 0;
+       return mt76_connac_mcu_get_nic_capability(&dev->mphy);
 }
 
 int mt7921_mcu_init(struct mt7921_dev *dev)
@@ -1136,26 +1155,6 @@ int mt7921_mcu_get_eeprom(struct mt7921_dev *dev, u32 offset)
        return 0;
 }
 
-u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u32 wlan_idx)
-{
-       struct mt7921_mcu_wlan_info wtbl_info = {
-               .wlan_idx = cpu_to_le32(wlan_idx),
-       };
-       struct sk_buff *skb;
-       int ret;
-
-       ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CMD_GET_WTBL,
-                                       &wtbl_info, sizeof(wtbl_info), true,
-                                       &skb);
-       if (ret)
-               return ret;
-
-       mt7921_mcu_tx_rate_report(dev, skb, wlan_idx);
-       dev_kfree_skb(skb);
-
-       return 0;
-}
-
 int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)
 {
        struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
@@ -1268,8 +1267,9 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                                 sizeof(req), false);
 }
 
-int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-                      struct ieee80211_vif *vif, bool enable)
+int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
+                         struct ieee80211_vif *vif, bool enable,
+                         enum mt76_sta_info_state state)
 {
        struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
        int rssi = -ewma_rssi_read(&mvif->rssi);
@@ -1278,27 +1278,25 @@ int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
                .vif = vif,
                .enable = enable,
                .cmd = MCU_UNI_CMD_STA_REC_UPDATE,
+               .state = state,
+               .offload_fw = true,
                .rcpi = to_rcpi(rssi),
        };
        struct mt7921_sta *msta;
 
        msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL;
        info.wcid = msta ? &msta->wcid : &mvif->sta.wcid;
+       info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;
 
-       return mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
+       return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);
 }
 
-int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
+int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
 {
        struct mt76_phy *mphy = &dev->mt76.phy;
        struct mt76_connac_pm *pm = &dev->pm;
        int i, err = 0;
 
-       mutex_lock(&pm->mutex);
-
-       if (!test_bit(MT76_STATE_PM, &mphy->state))
-               goto out;
-
        for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
                mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
                if (mt76_poll_msec(dev, MT_CONN_ON_LPCTL,
@@ -1318,6 +1316,22 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
        pm->stats.last_wake_event = jiffies;
        pm->stats.doze_time += pm->stats.last_wake_event -
                               pm->stats.last_doze_event;
+out:
+       return err;
+}
+
+int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
+{
+       struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt76_connac_pm *pm = &dev->pm;
+       int err = 0;
+
+       mutex_lock(&pm->mutex);
+
+       if (!test_bit(MT76_STATE_PM, &mphy->state))
+               goto out;
+
+       err = __mt7921_mcu_drv_pmctrl(dev);
 out:
        mutex_unlock(&pm->mutex);
 
@@ -1368,6 +1382,7 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 {
        struct mt7921_phy *phy = priv;
        struct mt7921_dev *dev = phy->dev;
+       struct ieee80211_hw *hw = mt76_hw(dev);
        int ret;
 
        if (dev->pm.enable)
@@ -1380,9 +1395,11 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 
        if (dev->pm.enable) {
                vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+               ieee80211_hw_set(hw, CONNECTION_MONITOR);
                mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
        } else {
                vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
+               __clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags);
                mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
        }
 }
index 49823d0..d76cf8f 100644 (file)
@@ -81,6 +81,7 @@ enum {
        MCU_EVENT_REG_ACCESS = 0x05,
        MCU_EVENT_LP_INFO = 0x07,
        MCU_EVENT_SCAN_DONE = 0x0d,
+       MCU_EVENT_TX_DONE = 0x0f,
        MCU_EVENT_BSS_ABSENCE  = 0x11,
        MCU_EVENT_BSS_BEACON_LOSS = 0x13,
        MCU_EVENT_CH_PRIVILEGE = 0x18,
@@ -197,18 +198,17 @@ struct sta_rec_sec {
        struct sec_key key[2];
 } __packed;
 
-enum mt7921_cipher_type {
-       MT_CIPHER_NONE,
-       MT_CIPHER_WEP40,
-       MT_CIPHER_WEP104,
-       MT_CIPHER_WEP128,
-       MT_CIPHER_TKIP,
-       MT_CIPHER_AES_CCMP,
-       MT_CIPHER_CCMP_256,
-       MT_CIPHER_GCMP,
-       MT_CIPHER_GCMP_256,
-       MT_CIPHER_WAPI,
-       MT_CIPHER_BIP_CMAC_128,
+enum mcu_cipher_type {
+       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_WEP104,
+       MCU_CIPHER_WEP128,
+       MCU_CIPHER_TKIP,
+       MCU_CIPHER_AES_CCMP,
+       MCU_CIPHER_CCMP_256,
+       MCU_CIPHER_GCMP,
+       MCU_CIPHER_GCMP_256,
+       MCU_CIPHER_WAPI,
+       MCU_CIPHER_BIP_CMAC_128,
 };
 
 enum {
@@ -254,86 +254,6 @@ struct mt7921_mcu_reg_event {
        __le32 val;
 } __packed;
 
-struct mt7921_mcu_tx_config {
-       u8 peer_addr[ETH_ALEN];
-       u8 sw;
-       u8 dis_rx_hdr_tran;
-
-       u8 aad_om;
-       u8 pfmu_idx;
-       __le16 partial_aid;
-
-       u8 ibf;
-       u8 ebf;
-       u8 is_ht;
-       u8 is_vht;
-
-       u8 mesh;
-       u8 baf_en;
-       u8 cf_ack;
-       u8 rdg_ba;
-
-       u8 rdg;
-       u8 pm;
-       u8 rts;
-       u8 smps;
-
-       u8 txop_ps;
-       u8 not_update_ipsm;
-       u8 skip_tx;
-       u8 ldpc;
-
-       u8 qos;
-       u8 from_ds;
-       u8 to_ds;
-       u8 dyn_bw;
-
-       u8 amdsu_cross_lg;
-       u8 check_per;
-       u8 gid_63;
-       u8 he;
-
-       u8 vht_ibf;
-       u8 vht_ebf;
-       u8 vht_ldpc;
-       u8 he_ldpc;
-} __packed;
-
-struct mt7921_mcu_sec_config {
-       u8 wpi_flag;
-       u8 rv;
-       u8 ikv;
-       u8 rkv;
-
-       u8 rcid;
-       u8 rca1;
-       u8 rca2;
-       u8 even_pn;
-
-       u8 key_id;
-       u8 muar_idx;
-       u8 cipher_suit;
-       u8 rsv[1];
-} __packed;
-
-struct mt7921_mcu_key_config {
-       u8 key[32];
-} __packed;
-
-struct mt7921_mcu_rate_info {
-       u8 mpdu_fail;
-       u8 mpdu_tx;
-       u8 rate_idx;
-       u8 rsv[1];
-       __le16 rate[8];
-} __packed;
-
-struct mt7921_mcu_ba_config {
-       u8 ba_en;
-       u8 rsv[3];
-       __le32 ba_winsize;
-} __packed;
-
 struct mt7921_mcu_ant_id_config {
        u8 ant_id[4];
 } __packed;
@@ -357,41 +277,6 @@ struct mt7921_mcu_peer_cap {
        u8 rsv[1];
 } __packed;
 
-struct mt7921_mcu_rx_cnt {
-       u8 rx_rcpi[4];
-       u8 rx_cc[4];
-       u8 rx_cc_sel;
-       u8 ce_rmsd;
-       u8 rsv[2];
-} __packed;
-
-struct mt7921_mcu_tx_cnt {
-       __le16 rate1_cnt;
-       __le16 rate1_fail_cnt;
-       __le16 rate2_cnt;
-       __le16 rate3_cnt;
-       __le16 cur_bw_tx_cnt;
-       __le16 cur_bw_tx_fail_cnt;
-       __le16 other_bw_tx_cnt;
-       __le16 other_bw_tx_fail_cnt;
-} __packed;
-
-struct mt7921_mcu_wlan_info_event {
-       struct mt7921_mcu_tx_config tx_config;
-       struct mt7921_mcu_sec_config sec_config;
-       struct mt7921_mcu_key_config key_config;
-       struct mt7921_mcu_rate_info rate_info;
-       struct mt7921_mcu_ba_config ba_config;
-       struct mt7921_mcu_peer_cap peer_cap;
-       struct mt7921_mcu_rx_cnt rx_cnt;
-       struct mt7921_mcu_tx_cnt tx_cnt;
-} __packed;
-
-struct mt7921_mcu_wlan_info {
-       __le32 wlan_idx;
-       struct mt7921_mcu_wlan_info_event event;
-} __packed;
-
 struct mt7921_txpwr_req {
        u8 ver;
        u8 action;
@@ -407,4 +292,31 @@ struct mt7921_txpwr_event {
        struct mt7921_txpwr txpwr;
 } __packed;
 
+struct mt7921_mcu_tx_done_event {
+       u8 pid;
+       u8 status;
+       u16 seq;
+
+       u8 wlan_idx;
+       u8 tx_cnt;
+       u16 tx_rate;
+
+       u8 flag;
+       u8 tid;
+       u8 rsp_rate;
+       u8 mcs;
+
+       u8 bw;
+       u8 tx_pwr;
+       u8 reason;
+       u8 rsv0[1];
+
+       u32 delay;
+       u32 timestamp;
+       u32 applied_flag;
+
+       u8 txs[28];
+
+       u8 rsv1[32];
+} __packed;
 #endif
index 59862ea..2d8bd6b 100644 (file)
@@ -92,6 +92,8 @@ struct mt7921_sta {
        unsigned long ampdu_state;
 
        struct mt7921_sta_key_conf bip;
+
+       unsigned long next_txs_ts;
 };
 
 DECLARE_EWMA(rssi, 10, 8);
@@ -100,6 +102,8 @@ struct mt7921_vif {
        struct mt76_vif mt76; /* must be first */
 
        struct mt7921_sta sta;
+       struct mt7921_sta *wep_sta;
+
        struct mt7921_phy *phy;
 
        struct ewma_rssi rssi;
@@ -156,6 +160,8 @@ struct mt7921_dev {
        u16 chainmask;
 
        struct work_struct reset_work;
+       bool hw_full_reset:1;
+       bool hw_init_done:1;
 
        struct list_head sta_poll_list;
        spinlock_t sta_poll_lock;
@@ -256,9 +262,9 @@ int mt7921_mcu_init(struct mt7921_dev *dev);
 int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                       struct mt7921_sta *msta, struct ieee80211_key_conf *key,
                       enum set_key_cmd cmd);
-int mt7921_set_channel(struct mt7921_phy *phy);
-int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-                      struct ieee80211_vif *vif, bool enable);
+int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
+                         struct ieee80211_vif *vif, bool enable,
+                         enum mt76_sta_info_state state);
 int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd);
 int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif);
 int mt7921_mcu_set_eeprom(struct mt7921_dev *dev);
@@ -318,7 +324,7 @@ static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev)
        return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
 }
 
-void mt7921_mac_init(struct mt7921_dev *dev);
+int mt7921_mac_init(struct mt7921_dev *dev);
 bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
 void mt7921_mac_reset_counters(struct mt7921_phy *phy);
 void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
@@ -330,6 +336,8 @@ void mt7921_mac_fill_rx_vector(struct mt7921_dev *dev, struct sk_buff *skb);
 void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb);
 int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
+void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+                         struct ieee80211_sta *sta);
 void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta);
 void mt7921_mac_work(struct work_struct *work);
@@ -352,7 +360,7 @@ void mt7921_stats_work(struct work_struct *work);
 void mt7921_txp_skb_unmap(struct mt76_dev *dev,
                          struct mt76_txwi_cache *txwi);
 void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
-void mt7921_update_channel(struct mt76_dev *mdev);
+void mt7921_update_channel(struct mt76_phy *mphy);
 int mt7921_init_debugfs(struct mt7921_dev *dev);
 
 int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
@@ -362,12 +370,12 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
                         struct ieee80211_ampdu_params *params,
                         bool enable);
 void mt7921_scan_work(struct work_struct *work);
-u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u32 wlan_idx);
 int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
 int mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                             bool enable);
 int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
                          bool enable);
+int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
 int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
 int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
 void mt7921_pm_wake_work(struct work_struct *work);
index fa02d93..c3905bc 100644 (file)
@@ -106,6 +106,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
                .rx_poll_complete = mt7921_rx_poll_complete,
                .sta_ps = mt7921_sta_ps,
                .sta_add = mt7921_mac_sta_add,
+               .sta_assoc = mt7921_mac_sta_assoc,
                .sta_remove = mt7921_mac_sta_remove,
                .update_survey = mt7921_update_channel,
        };
@@ -188,22 +189,29 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct mt76_dev *mdev = pci_get_drvdata(pdev);
        struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       struct mt76_connac_pm *pm = &dev->pm;
        bool hif_suspend;
        int i, err;
 
-       err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
+       pm->suspended = true;
+       cancel_delayed_work_sync(&pm->ps_work);
+       cancel_work_sync(&pm->wake_work);
+
+       err = mt7921_mcu_drv_pmctrl(dev);
        if (err < 0)
-               return err;
+               goto restore_suspend;
 
        hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
        if (hif_suspend) {
                err = mt76_connac_mcu_set_hif_suspend(mdev, true);
                if (err)
-                       return err;
+                       goto restore_suspend;
        }
 
-       if (!dev->pm.enable)
-               mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
+       /* always enable deep sleep during suspend to reduce
+        * power consumption
+        */
+       mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
 
        napi_disable(&mdev->tx_napi);
        mt76_worker_disable(&mdev->tx_worker);
@@ -231,27 +239,30 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 
        err = mt7921_mcu_fw_pmctrl(dev);
        if (err)
-               goto restore;
+               goto restore_napi;
 
        pci_save_state(pdev);
        err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
        if (err)
-               goto restore;
+               goto restore_napi;
 
        return 0;
 
-restore:
+restore_napi:
        mt76_for_each_q_rx(mdev, i) {
                napi_enable(&mdev->napi[i]);
        }
        napi_enable(&mdev->tx_napi);
 
-       if (!dev->pm.enable)
+       if (!pm->ds_enable)
                mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
 
        if (hif_suspend)
                mt76_connac_mcu_set_hif_suspend(mdev, false);
 
+restore_suspend:
+       pm->suspended = false;
+
        return err;
 }
 
@@ -259,8 +270,10 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
 {
        struct mt76_dev *mdev = pci_get_drvdata(pdev);
        struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       struct mt76_connac_pm *pm = &dev->pm;
        int i, err;
 
+       pm->suspended = false;
        err = pci_set_power_state(pdev, PCI_D0);
        if (err)
                return err;
@@ -291,7 +304,8 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
        napi_enable(&mdev->tx_napi);
        napi_schedule(&mdev->tx_napi);
 
-       if (!dev->pm.enable)
+       /* restore previous ds setting */
+       if (!pm->ds_enable)
                mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
 
        if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state))
index a18d289..783a156 100644 (file)
@@ -184,9 +184,6 @@ static int mt76s_process_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
        if (!q->queued)
                wake_up(&dev->tx_wait);
 
-       if (!mcu)
-               mt76_txq_schedule(&dev->phy, q->qid);
-
        return nframes;
 }
 
@@ -195,19 +192,28 @@ static void mt76s_status_worker(struct mt76_worker *w)
        struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
                                              status_worker);
        struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
+       bool resched = false;
        int i, nframes;
 
        do {
+               int ndata_frames = 0;
+
                nframes = mt76s_process_tx_queue(dev, dev->q_mcu[MT_MCUQ_WM]);
 
                for (i = 0; i <= MT_TXQ_PSD; i++)
-                       nframes += mt76s_process_tx_queue(dev,
-                                                         dev->phy.q_tx[i]);
+                       ndata_frames += mt76s_process_tx_queue(dev,
+                                                              dev->phy.q_tx[i]);
+               nframes += ndata_frames;
+               if (ndata_frames > 0)
+                       resched = true;
 
                if (dev->drv->tx_status_data &&
                    !test_and_set_bit(MT76_READING_STATS, &dev->phy.state))
                        queue_work(dev->wq, &dev->sdio.stat_work);
        } while (nframes > 0);
+
+       if (resched)
+               mt76_worker_schedule(&dev->sdio.txrx_worker);
 }
 
 static void mt76s_tx_status_data(struct work_struct *work)
@@ -256,6 +262,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
 
        q->entry[q->head].skb = tx_info.skb;
        q->entry[q->head].buf_sz = len;
+       q->entry[q->head].wcid = 0xffff;
 
        smp_wmb();
 
index 001d0ba..f73ffbd 100644 (file)
@@ -88,17 +88,8 @@ static void
 mt76_testmode_free_skb(struct mt76_phy *phy)
 {
        struct mt76_testmode_data *td = &phy->test;
-       struct sk_buff *skb = td->tx_skb;
-
-       if (!skb)
-               return;
 
-       if (skb_has_frag_list(skb)) {
-               kfree_skb_list(skb_shinfo(skb)->frag_list);
-               skb_shinfo(skb)->frag_list = NULL;
-       }
-
-       dev_kfree_skb(skb);
+       dev_kfree_skb(td->tx_skb);
        td->tx_skb = NULL;
 }
 
@@ -158,19 +149,18 @@ int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len)
                        frag_len = MT_TXP_MAX_LEN;
 
                frag = alloc_skb(frag_len, GFP_KERNEL);
-               if (!frag)
+               if (!frag) {
+                       mt76_testmode_free_skb(phy);
+                       dev_kfree_skb(head);
                        return -ENOMEM;
+               }
 
                __skb_put_zero(frag, frag_len);
                head->len += frag->len;
                head->data_len += frag->len;
 
-               if (*frag_tail) {
-                       (*frag_tail)->next = frag;
-                       frag_tail = &frag;
-               } else {
-                       *frag_tail = frag;
-               }
+               *frag_tail = frag;
+               frag_tail = &(*frag_tail)->next;
        }
 
        mt76_testmode_free_skb(phy);
@@ -531,6 +521,14 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
        u64 rx_fcs_error = 0;
        int i;
 
+       if (dev->test_ops->dump_stats) {
+               int ret;
+
+               ret = dev->test_ops->dump_stats(phy, msg);
+               if (ret)
+                       return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(td->rx_stats.packets); i++) {
                rx_packets += td->rx_stats.packets[i];
                rx_fcs_error += td->rx_stats.fcs_error[i];
@@ -545,9 +543,6 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
                              MT76_TM_STATS_ATTR_PAD))
                return -EMSGSIZE;
 
-       if (dev->test_ops->dump_stats)
-               return dev->test_ops->dump_stats(phy, msg);
-
        return 0;
 }
 
index 53ea8de..f0f7a91 100644 (file)
@@ -54,11 +54,23 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
 
        spin_unlock_bh(&dev->status_list.lock);
 
+       rcu_read_lock();
        while ((skb = __skb_dequeue(list)) != NULL) {
+               struct ieee80211_tx_status status = {
+                       .skb = skb,
+                       .info = IEEE80211_SKB_CB(skb),
+               };
+               struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
+               struct mt76_wcid *wcid;
+
+               wcid = rcu_dereference(dev->wcid[cb->wcid]);
+               if (wcid)
+                       status.sta = wcid_to_sta(wcid);
+
                hw = mt76_tx_status_get_hw(dev, skb);
-               ieee80211_tx_status(hw, skb);
+               ieee80211_tx_status_ext(hw, &status);
        }
-
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(mt76_tx_status_unlock);
 
@@ -80,7 +92,7 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
 
        /* Tx status can be unreliable. if it fails, mark the frame as ACKed */
        if (flags & MT_TX_CB_TXS_FAILED) {
-               ieee80211_tx_info_clear_status(info);
+               info->status.rates[0].count = 0;
                info->status.rates[0].idx = -1;
                info->flags |= IEEE80211_TX_STAT_ACK;
        }
@@ -117,12 +129,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
        spin_lock_bh(&dev->status_list.lock);
 
        memset(cb, 0, sizeof(*cb));
-       wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
-       if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
-           wcid->packet_id == MT_PACKET_ID_NO_SKB)
-               wcid->packet_id = MT_PACKET_ID_FIRST;
-
-       pid = wcid->packet_id;
+       pid = mt76_get_next_pkt_id(wcid);
        cb->wcid = wcid->idx;
        cb->pktid = pid;
        cb->jiffies = jiffies;
@@ -173,36 +180,37 @@ mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid, bool flush)
 EXPORT_SYMBOL_GPL(mt76_tx_status_check);
 
 static void
-mt76_tx_check_non_aql(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb)
+mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
+                     struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct mt76_wcid *wcid;
        int pending;
 
-       if (info->tx_time_est)
-               return;
-
-       if (wcid_idx >= ARRAY_SIZE(dev->wcid))
+       if (!wcid || info->tx_time_est)
                return;
 
-       rcu_read_lock();
-
-       wcid = rcu_dereference(dev->wcid[wcid_idx]);
-       if (wcid) {
-               pending = atomic_dec_return(&wcid->non_aql_packets);
-               if (pending < 0)
-                       atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
-       }
-
-       rcu_read_unlock();
+       pending = atomic_dec_return(&wcid->non_aql_packets);
+       if (pending < 0)
+               atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
 }
 
-void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb)
+void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
+                           struct list_head *free_list)
 {
+       struct ieee80211_tx_status status = {
+               .skb = skb,
+               .free_list = free_list,
+       };
+       struct mt76_wcid *wcid = NULL;
        struct ieee80211_hw *hw;
        struct sk_buff_head list;
 
-       mt76_tx_check_non_aql(dev, wcid_idx, skb);
+       rcu_read_lock();
+
+       if (wcid_idx < ARRAY_SIZE(dev->wcid))
+               wcid = rcu_dereference(dev->wcid[wcid_idx]);
+
+       mt76_tx_check_non_aql(dev, wcid, skb);
 
 #ifdef CONFIG_NL80211_TESTMODE
        if (mt76_is_testmode_skb(dev, skb, &hw)) {
@@ -214,21 +222,25 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *sk
                        wake_up(&dev->tx_wait);
 
                dev_kfree_skb_any(skb);
-               return;
+               goto out;
        }
 #endif
 
        if (!skb->prev) {
                hw = mt76_tx_status_get_hw(dev, skb);
-               ieee80211_free_txskb(hw, skb);
-               return;
+               status.sta = wcid_to_sta(wcid);
+               ieee80211_tx_status_ext(hw, &status);
+               goto out;
        }
 
        mt76_tx_status_lock(dev, &list);
        __mt76_tx_status_skb_done(dev, skb, MT_TX_CB_DMA_DONE, &list);
        mt76_tx_status_unlock(dev, &list);
+
+out:
+       rcu_read_unlock();
 }
-EXPORT_SYMBOL_GPL(mt76_tx_complete_skb);
+EXPORT_SYMBOL_GPL(__mt76_tx_complete_skb);
 
 static int
 __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
@@ -244,11 +256,15 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
 
        non_aql = !info->tx_time_est;
        idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
-       if (idx < 0 || !sta || !non_aql)
+       if (idx < 0 || !sta)
                return idx;
 
        wcid = (struct mt76_wcid *)sta->drv_priv;
        q->entry[idx].wcid = wcid->idx;
+
+       if (!non_aql)
+               return idx;
+
        pending = atomic_inc_return(&wcid->non_aql_packets);
        if (stop && pending >= MT_MAX_NON_AQL_PKT)
                *stop = true;
@@ -285,7 +301,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
                skb_set_queue_mapping(skb, qid);
        }
 
-       if (!(wcid->tx_info & MT_WCID_TX_INFO_SET))
+       if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
                ieee80211_get_tx_rates(info->control.vif, sta, skb,
                                       info->control.rates, 1);
 
index 30bc54e..1e9f60b 100644 (file)
@@ -925,6 +925,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
 
        q->head = (q->head + 1) % q->ndesc;
        q->entry[idx].skb = tx_info.skb;
+       q->entry[idx].wcid = 0xffff;
        q->queued++;
 
        return idx;