16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc. */
36c92544dSBjoern A. Zeeb
46c92544dSBjoern A. Zeeb #include <linux/fs.h>
56c92544dSBjoern A. Zeeb #include "mt7915.h"
66c92544dSBjoern A. Zeeb #include "mcu.h"
76c92544dSBjoern A. Zeeb #include "mac.h"
86c92544dSBjoern A. Zeeb #include "eeprom.h"
96c92544dSBjoern A. Zeeb
106c92544dSBjoern A. Zeeb #define fw_name(_dev, name, ...) ({ \
116c92544dSBjoern A. Zeeb char *_fw; \
126c92544dSBjoern A. Zeeb switch (mt76_chip(&(_dev)->mt76)) { \
136c92544dSBjoern A. Zeeb case 0x7915: \
146c92544dSBjoern A. Zeeb _fw = MT7915_##name; \
156c92544dSBjoern A. Zeeb break; \
16cbb3ec25SBjoern A. Zeeb case 0x7981: \
17cbb3ec25SBjoern A. Zeeb _fw = MT7981_##name; \
18cbb3ec25SBjoern A. Zeeb break; \
196c92544dSBjoern A. Zeeb case 0x7986: \
206c92544dSBjoern A. Zeeb _fw = MT7986_##name##__VA_ARGS__; \
216c92544dSBjoern A. Zeeb break; \
226c92544dSBjoern A. Zeeb default: \
236c92544dSBjoern A. Zeeb _fw = MT7916_##name; \
246c92544dSBjoern A. Zeeb break; \
256c92544dSBjoern A. Zeeb } \
266c92544dSBjoern A. Zeeb _fw; \
276c92544dSBjoern A. Zeeb })
286c92544dSBjoern A. Zeeb
296c92544dSBjoern A. Zeeb #define fw_name_var(_dev, name) (mt7915_check_adie(dev, false) ? \
306c92544dSBjoern A. Zeeb fw_name(_dev, name) : \
316c92544dSBjoern A. Zeeb fw_name(_dev, name, _MT7975))
326c92544dSBjoern A. Zeeb
336c92544dSBjoern A. Zeeb #define MCU_PATCH_ADDRESS 0x200000
346c92544dSBjoern A. Zeeb
356c92544dSBjoern A. Zeeb #define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p)
366c92544dSBjoern A. Zeeb #define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m)
376c92544dSBjoern A. Zeeb
38cbb3ec25SBjoern A. Zeeb static bool sr_scene_detect = true;
39cbb3ec25SBjoern A. Zeeb module_param(sr_scene_detect, bool, 0644);
40cbb3ec25SBjoern A. Zeeb MODULE_PARM_DESC(sr_scene_detect, "Enable firmware scene detection algorithm");
41cbb3ec25SBjoern A. Zeeb
426c92544dSBjoern A. Zeeb static u8
mt7915_mcu_get_sta_nss(u16 mcs_map)436c92544dSBjoern A. Zeeb mt7915_mcu_get_sta_nss(u16 mcs_map)
446c92544dSBjoern A. Zeeb {
456c92544dSBjoern A. Zeeb u8 nss;
466c92544dSBjoern A. Zeeb
476c92544dSBjoern A. Zeeb for (nss = 8; nss > 0; nss--) {
486c92544dSBjoern A. Zeeb u8 nss_mcs = (mcs_map >> (2 * (nss - 1))) & 3;
496c92544dSBjoern A. Zeeb
506c92544dSBjoern A. Zeeb if (nss_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED)
516c92544dSBjoern A. Zeeb break;
526c92544dSBjoern A. Zeeb }
536c92544dSBjoern A. Zeeb
546c92544dSBjoern A. Zeeb return nss - 1;
556c92544dSBjoern A. Zeeb }
566c92544dSBjoern A. Zeeb
576c92544dSBjoern A. Zeeb static void
mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta * sta,__le16 * he_mcs,u16 mcs_map)586c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
596c92544dSBjoern A. Zeeb u16 mcs_map)
606c92544dSBjoern A. Zeeb {
616c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
626c92544dSBjoern A. Zeeb struct mt7915_dev *dev = msta->vif->phy->dev;
636c92544dSBjoern A. Zeeb enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band;
646c92544dSBjoern A. Zeeb const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs;
656c92544dSBjoern A. Zeeb int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
666c92544dSBjoern A. Zeeb
676c92544dSBjoern A. Zeeb for (nss = 0; nss < max_nss; nss++) {
686c92544dSBjoern A. Zeeb int mcs;
696c92544dSBjoern A. Zeeb
706c92544dSBjoern A. Zeeb switch ((mcs_map >> (2 * nss)) & 0x3) {
716c92544dSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_11:
726c92544dSBjoern A. Zeeb mcs = GENMASK(11, 0);
736c92544dSBjoern A. Zeeb break;
746c92544dSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_9:
756c92544dSBjoern A. Zeeb mcs = GENMASK(9, 0);
766c92544dSBjoern A. Zeeb break;
776c92544dSBjoern A. Zeeb case IEEE80211_HE_MCS_SUPPORT_0_7:
786c92544dSBjoern A. Zeeb mcs = GENMASK(7, 0);
796c92544dSBjoern A. Zeeb break;
806c92544dSBjoern A. Zeeb default:
816c92544dSBjoern A. Zeeb mcs = 0;
826c92544dSBjoern A. Zeeb }
836c92544dSBjoern A. Zeeb
846c92544dSBjoern A. Zeeb mcs = mcs ? fls(mcs & mask[nss]) - 1 : -1;
856c92544dSBjoern A. Zeeb
866c92544dSBjoern A. Zeeb switch (mcs) {
876c92544dSBjoern A. Zeeb case 0 ... 7:
886c92544dSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
896c92544dSBjoern A. Zeeb break;
906c92544dSBjoern A. Zeeb case 8 ... 9:
916c92544dSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
926c92544dSBjoern A. Zeeb break;
936c92544dSBjoern A. Zeeb case 10 ... 11:
946c92544dSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
956c92544dSBjoern A. Zeeb break;
966c92544dSBjoern A. Zeeb default:
976c92544dSBjoern A. Zeeb mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
986c92544dSBjoern A. Zeeb break;
996c92544dSBjoern A. Zeeb }
1006c92544dSBjoern A. Zeeb mcs_map &= ~(0x3 << (nss * 2));
1016c92544dSBjoern A. Zeeb mcs_map |= mcs << (nss * 2);
1026c92544dSBjoern A. Zeeb
1036c92544dSBjoern A. Zeeb /* only support 2ss on 160MHz for mt7915 */
1046c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76) && nss > 1 &&
1056c92544dSBjoern A. Zeeb sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
1066c92544dSBjoern A. Zeeb break;
1076c92544dSBjoern A. Zeeb }
1086c92544dSBjoern A. Zeeb
1096c92544dSBjoern A. Zeeb *he_mcs = cpu_to_le16(mcs_map);
1106c92544dSBjoern A. Zeeb }
1116c92544dSBjoern A. Zeeb
1126c92544dSBjoern A. Zeeb static void
mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta * sta,__le16 * vht_mcs,const u16 * mask)1136c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
1146c92544dSBjoern A. Zeeb const u16 *mask)
1156c92544dSBjoern A. Zeeb {
1166c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
1176c92544dSBjoern A. Zeeb struct mt7915_dev *dev = msta->vif->phy->dev;
1186c92544dSBjoern A. Zeeb u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
1196c92544dSBjoern A. Zeeb int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
1206c92544dSBjoern A. Zeeb u16 mcs;
1216c92544dSBjoern A. Zeeb
1226c92544dSBjoern A. Zeeb for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {
1236c92544dSBjoern A. Zeeb switch (mcs_map & 0x3) {
1246c92544dSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_9:
1256c92544dSBjoern A. Zeeb mcs = GENMASK(9, 0);
1266c92544dSBjoern A. Zeeb break;
1276c92544dSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_8:
1286c92544dSBjoern A. Zeeb mcs = GENMASK(8, 0);
1296c92544dSBjoern A. Zeeb break;
1306c92544dSBjoern A. Zeeb case IEEE80211_VHT_MCS_SUPPORT_0_7:
1316c92544dSBjoern A. Zeeb mcs = GENMASK(7, 0);
1326c92544dSBjoern A. Zeeb break;
1336c92544dSBjoern A. Zeeb default:
1346c92544dSBjoern A. Zeeb mcs = 0;
1356c92544dSBjoern A. Zeeb }
1366c92544dSBjoern A. Zeeb
1376c92544dSBjoern A. Zeeb vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]);
1386c92544dSBjoern A. Zeeb
1396c92544dSBjoern A. Zeeb /* only support 2ss on 160MHz for mt7915 */
1406c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76) && nss > 1 &&
1416c92544dSBjoern A. Zeeb sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
1426c92544dSBjoern A. Zeeb break;
1436c92544dSBjoern A. Zeeb }
1446c92544dSBjoern A. Zeeb }
1456c92544dSBjoern A. Zeeb
1466c92544dSBjoern A. Zeeb static void
mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta * sta,u8 * ht_mcs,const u8 * mask)1476c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
1486c92544dSBjoern A. Zeeb const u8 *mask)
1496c92544dSBjoern A. Zeeb {
1506c92544dSBjoern A. Zeeb int nss, max_nss = sta->deflink.rx_nss > 3 ? 4 : sta->deflink.rx_nss;
1516c92544dSBjoern A. Zeeb
1526c92544dSBjoern A. Zeeb for (nss = 0; nss < max_nss; nss++)
1536c92544dSBjoern A. Zeeb ht_mcs[nss] = sta->deflink.ht_cap.mcs.rx_mask[nss] & mask[nss];
1546c92544dSBjoern A. Zeeb }
1556c92544dSBjoern A. Zeeb
1566c92544dSBjoern A. Zeeb static int
mt7915_mcu_parse_response(struct mt76_dev * mdev,int cmd,struct sk_buff * skb,int seq)1576c92544dSBjoern A. Zeeb mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
1586c92544dSBjoern A. Zeeb struct sk_buff *skb, int seq)
1596c92544dSBjoern A. Zeeb {
160*8ba4d145SBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
1616c92544dSBjoern A. Zeeb struct mt76_connac2_mcu_rxd *rxd;
1626c92544dSBjoern A. Zeeb int ret = 0;
1636c92544dSBjoern A. Zeeb
1646c92544dSBjoern A. Zeeb if (!skb) {
1656c92544dSBjoern A. Zeeb dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
1666c92544dSBjoern A. Zeeb cmd, seq);
167*8ba4d145SBjoern A. Zeeb
168*8ba4d145SBjoern A. Zeeb if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) {
169*8ba4d145SBjoern A. Zeeb dev->recovery.restart = true;
170*8ba4d145SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
171*8ba4d145SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->reset_work);
172*8ba4d145SBjoern A. Zeeb wake_up(&dev->reset_wait);
173*8ba4d145SBjoern A. Zeeb }
174*8ba4d145SBjoern A. Zeeb
1756c92544dSBjoern A. Zeeb return -ETIMEDOUT;
1766c92544dSBjoern A. Zeeb }
1776c92544dSBjoern A. Zeeb
1786c92544dSBjoern A. Zeeb rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
179cbb3ec25SBjoern A. Zeeb if (seq != rxd->seq &&
180cbb3ec25SBjoern A. Zeeb !(rxd->eid == MCU_CMD_EXT_CID &&
181cbb3ec25SBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
1826c92544dSBjoern A. Zeeb return -EAGAIN;
1836c92544dSBjoern A. Zeeb
1846c92544dSBjoern A. Zeeb if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
1856c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd) - 4);
1866c92544dSBjoern A. Zeeb ret = *skb->data;
1876c92544dSBjoern A. Zeeb } else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
1886c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd) + 4);
1896c92544dSBjoern A. Zeeb ret = le32_to_cpu(*(__le32 *)skb->data);
1906c92544dSBjoern A. Zeeb } else {
1916c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
1926c92544dSBjoern A. Zeeb }
1936c92544dSBjoern A. Zeeb
1946c92544dSBjoern A. Zeeb return ret;
1956c92544dSBjoern A. Zeeb }
1966c92544dSBjoern A. Zeeb
197*8ba4d145SBjoern A. Zeeb static void
mt7915_mcu_set_timeout(struct mt76_dev * mdev,int cmd)198*8ba4d145SBjoern A. Zeeb mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
199*8ba4d145SBjoern A. Zeeb {
200*8ba4d145SBjoern A. Zeeb if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID)
201*8ba4d145SBjoern A. Zeeb return;
202*8ba4d145SBjoern A. Zeeb
203*8ba4d145SBjoern A. Zeeb switch (FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd)) {
204*8ba4d145SBjoern A. Zeeb case MCU_EXT_CMD_THERMAL_CTRL:
205*8ba4d145SBjoern A. Zeeb case MCU_EXT_CMD_GET_MIB_INFO:
206*8ba4d145SBjoern A. Zeeb case MCU_EXT_CMD_PHY_STAT_INFO:
207*8ba4d145SBjoern A. Zeeb case MCU_EXT_CMD_STA_REC_UPDATE:
208*8ba4d145SBjoern A. Zeeb case MCU_EXT_CMD_BSS_INFO_UPDATE:
209*8ba4d145SBjoern A. Zeeb mdev->mcu.timeout = 2 * HZ;
210*8ba4d145SBjoern A. Zeeb return;
211*8ba4d145SBjoern A. Zeeb default:
212*8ba4d145SBjoern A. Zeeb break;
213*8ba4d145SBjoern A. Zeeb }
214*8ba4d145SBjoern A. Zeeb }
215*8ba4d145SBjoern A. Zeeb
2166c92544dSBjoern A. Zeeb static int
mt7915_mcu_send_message(struct mt76_dev * mdev,struct sk_buff * skb,int cmd,int * wait_seq)2176c92544dSBjoern A. Zeeb mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
2186c92544dSBjoern A. Zeeb int cmd, int *wait_seq)
2196c92544dSBjoern A. Zeeb {
2206c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
2216c92544dSBjoern A. Zeeb enum mt76_mcuq_id qid;
2226c92544dSBjoern A. Zeeb
2236c92544dSBjoern A. Zeeb if (cmd == MCU_CMD(FW_SCATTER))
2246c92544dSBjoern A. Zeeb qid = MT_MCUQ_FWDL;
2256c92544dSBjoern A. Zeeb else if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
2266c92544dSBjoern A. Zeeb qid = MT_MCUQ_WA;
2276c92544dSBjoern A. Zeeb else
2286c92544dSBjoern A. Zeeb qid = MT_MCUQ_WM;
2296c92544dSBjoern A. Zeeb
230*8ba4d145SBjoern A. Zeeb mt7915_mcu_set_timeout(mdev, cmd);
231*8ba4d145SBjoern A. Zeeb
2326c92544dSBjoern A. Zeeb return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);
2336c92544dSBjoern A. Zeeb }
2346c92544dSBjoern A. Zeeb
mt7915_mcu_wa_cmd(struct mt7915_dev * dev,int cmd,u32 a1,u32 a2,u32 a3)2356c92544dSBjoern A. Zeeb int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
2366c92544dSBjoern A. Zeeb {
2376c92544dSBjoern A. Zeeb struct {
2386c92544dSBjoern A. Zeeb __le32 args[3];
2396c92544dSBjoern A. Zeeb } req = {
2406c92544dSBjoern A. Zeeb .args = {
2416c92544dSBjoern A. Zeeb cpu_to_le32(a1),
2426c92544dSBjoern A. Zeeb cpu_to_le32(a2),
2436c92544dSBjoern A. Zeeb cpu_to_le32(a3),
2446c92544dSBjoern A. Zeeb },
2456c92544dSBjoern A. Zeeb };
2466c92544dSBjoern A. Zeeb
2476c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), false);
2486c92544dSBjoern A. Zeeb }
2496c92544dSBjoern A. Zeeb
2506c92544dSBjoern A. Zeeb static void
mt7915_mcu_csa_finish(void * priv,u8 * mac,struct ieee80211_vif * vif)2516c92544dSBjoern A. Zeeb mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
2526c92544dSBjoern A. Zeeb {
253*8ba4d145SBjoern A. Zeeb if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
254*8ba4d145SBjoern A. Zeeb return;
255*8ba4d145SBjoern A. Zeeb
256*8ba4d145SBjoern A. Zeeb ieee80211_csa_finish(vif, 0);
2576c92544dSBjoern A. Zeeb }
2586c92544dSBjoern A. Zeeb
2596c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_csa_notify(struct mt7915_dev * dev,struct sk_buff * skb)2606c92544dSBjoern A. Zeeb mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
2616c92544dSBjoern A. Zeeb {
2626c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
2636c92544dSBjoern A. Zeeb struct mt7915_mcu_csa_notify *c;
2646c92544dSBjoern A. Zeeb
2656c92544dSBjoern A. Zeeb c = (struct mt7915_mcu_csa_notify *)skb->data;
2666c92544dSBjoern A. Zeeb
267cbb3ec25SBjoern A. Zeeb if (c->band_idx > MT_BAND1)
268cbb3ec25SBjoern A. Zeeb return;
269cbb3ec25SBjoern A. Zeeb
270cbb3ec25SBjoern A. Zeeb if ((c->band_idx && !dev->phy.mt76->band_idx) &&
271cbb3ec25SBjoern A. Zeeb dev->mt76.phys[MT_BAND1])
2726c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
2736c92544dSBjoern A. Zeeb
2746c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(mphy->hw,
2756c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
2766c92544dSBjoern A. Zeeb mt7915_mcu_csa_finish, mphy->hw);
2776c92544dSBjoern A. Zeeb }
2786c92544dSBjoern A. Zeeb
2796c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_thermal_notify(struct mt7915_dev * dev,struct sk_buff * skb)2806c92544dSBjoern A. Zeeb mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
2816c92544dSBjoern A. Zeeb {
2826c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
2836c92544dSBjoern A. Zeeb struct mt7915_mcu_thermal_notify *t;
2846c92544dSBjoern A. Zeeb struct mt7915_phy *phy;
2856c92544dSBjoern A. Zeeb
2866c92544dSBjoern A. Zeeb t = (struct mt7915_mcu_thermal_notify *)skb->data;
2876c92544dSBjoern A. Zeeb if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
2886c92544dSBjoern A. Zeeb return;
2896c92544dSBjoern A. Zeeb
290cbb3ec25SBjoern A. Zeeb if (t->ctrl.band_idx > MT_BAND1)
291cbb3ec25SBjoern A. Zeeb return;
292cbb3ec25SBjoern A. Zeeb
293cbb3ec25SBjoern A. Zeeb if ((t->ctrl.band_idx && !dev->phy.mt76->band_idx) &&
294cbb3ec25SBjoern A. Zeeb dev->mt76.phys[MT_BAND1])
2956c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
2966c92544dSBjoern A. Zeeb
297*8ba4d145SBjoern A. Zeeb phy = mphy->priv;
2986c92544dSBjoern A. Zeeb phy->throttle_state = t->ctrl.duty.duty_cycle;
2996c92544dSBjoern A. Zeeb }
3006c92544dSBjoern A. Zeeb
3016c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_radar_detected(struct mt7915_dev * dev,struct sk_buff * skb)3026c92544dSBjoern A. Zeeb mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
3036c92544dSBjoern A. Zeeb {
3046c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
3056c92544dSBjoern A. Zeeb struct mt7915_mcu_rdd_report *r;
3066c92544dSBjoern A. Zeeb
3076c92544dSBjoern A. Zeeb r = (struct mt7915_mcu_rdd_report *)skb->data;
3086c92544dSBjoern A. Zeeb
309cbb3ec25SBjoern A. Zeeb if (r->band_idx > MT_RX_SEL2)
310cbb3ec25SBjoern A. Zeeb return;
311cbb3ec25SBjoern A. Zeeb
312cbb3ec25SBjoern A. Zeeb if ((r->band_idx && !dev->phy.mt76->band_idx) &&
313cbb3ec25SBjoern A. Zeeb dev->mt76.phys[MT_BAND1])
3146c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
3156c92544dSBjoern A. Zeeb
3166c92544dSBjoern A. Zeeb if (r->band_idx == MT_RX_SEL2)
3176c92544dSBjoern A. Zeeb cfg80211_background_radar_event(mphy->hw->wiphy,
3186c92544dSBjoern A. Zeeb &dev->rdd2_chandef,
3196c92544dSBjoern A. Zeeb GFP_ATOMIC);
3206c92544dSBjoern A. Zeeb else
321*8ba4d145SBjoern A. Zeeb ieee80211_radar_detected(mphy->hw, NULL);
3226c92544dSBjoern A. Zeeb dev->hw_pattern++;
3236c92544dSBjoern A. Zeeb }
3246c92544dSBjoern A. Zeeb
3256c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_log_message(struct mt7915_dev * dev,struct sk_buff * skb)3266c92544dSBjoern A. Zeeb mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
3276c92544dSBjoern A. Zeeb {
3286c92544dSBjoern A. Zeeb struct mt76_connac2_mcu_rxd *rxd;
3296c92544dSBjoern A. Zeeb int len = skb->len - sizeof(*rxd);
3306c92544dSBjoern A. Zeeb const char *data, *type;
3316c92544dSBjoern A. Zeeb
3326c92544dSBjoern A. Zeeb rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
3336c92544dSBjoern A. Zeeb data = (char *)&rxd[1];
3346c92544dSBjoern A. Zeeb
3356c92544dSBjoern A. Zeeb switch (rxd->s2d_index) {
3366c92544dSBjoern A. Zeeb case 0:
3376c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS)
3386c92544dSBjoern A. Zeeb if (mt7915_debugfs_rx_log(dev, data, len))
3396c92544dSBjoern A. Zeeb return;
3406c92544dSBjoern A. Zeeb #endif
3416c92544dSBjoern A. Zeeb
3426c92544dSBjoern A. Zeeb type = "WM";
3436c92544dSBjoern A. Zeeb break;
3446c92544dSBjoern A. Zeeb case 2:
3456c92544dSBjoern A. Zeeb type = "WA";
3466c92544dSBjoern A. Zeeb break;
3476c92544dSBjoern A. Zeeb default:
3486c92544dSBjoern A. Zeeb type = "unknown";
3496c92544dSBjoern A. Zeeb break;
3506c92544dSBjoern A. Zeeb }
3516c92544dSBjoern A. Zeeb
3526c92544dSBjoern A. Zeeb wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data);
3536c92544dSBjoern A. Zeeb }
3546c92544dSBjoern A. Zeeb
3556c92544dSBjoern A. Zeeb static void
mt7915_mcu_cca_finish(void * priv,u8 * mac,struct ieee80211_vif * vif)3566c92544dSBjoern A. Zeeb mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
3576c92544dSBjoern A. Zeeb {
358*8ba4d145SBjoern A. Zeeb if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
3596c92544dSBjoern A. Zeeb return;
3606c92544dSBjoern A. Zeeb
361*8ba4d145SBjoern A. Zeeb ieee80211_color_change_finish(vif, 0);
3626c92544dSBjoern A. Zeeb }
3636c92544dSBjoern A. Zeeb
3646c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_bcc_notify(struct mt7915_dev * dev,struct sk_buff * skb)3656c92544dSBjoern A. Zeeb mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
3666c92544dSBjoern A. Zeeb {
3676c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
3686c92544dSBjoern A. Zeeb struct mt7915_mcu_bcc_notify *b;
3696c92544dSBjoern A. Zeeb
3706c92544dSBjoern A. Zeeb b = (struct mt7915_mcu_bcc_notify *)skb->data;
3716c92544dSBjoern A. Zeeb
372cbb3ec25SBjoern A. Zeeb if (b->band_idx > MT_BAND1)
373cbb3ec25SBjoern A. Zeeb return;
374cbb3ec25SBjoern A. Zeeb
375cbb3ec25SBjoern A. Zeeb if ((b->band_idx && !dev->phy.mt76->band_idx) &&
376cbb3ec25SBjoern A. Zeeb dev->mt76.phys[MT_BAND1])
3776c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
3786c92544dSBjoern A. Zeeb
3796c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(mphy->hw,
3806c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
3816c92544dSBjoern A. Zeeb mt7915_mcu_cca_finish, mphy->hw);
3826c92544dSBjoern A. Zeeb }
3836c92544dSBjoern A. Zeeb
3846c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_ext_event(struct mt7915_dev * dev,struct sk_buff * skb)3856c92544dSBjoern A. Zeeb mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
3866c92544dSBjoern A. Zeeb {
3876c92544dSBjoern A. Zeeb struct mt76_connac2_mcu_rxd *rxd;
3886c92544dSBjoern A. Zeeb
3896c92544dSBjoern A. Zeeb rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
3906c92544dSBjoern A. Zeeb switch (rxd->ext_eid) {
3916c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_THERMAL_PROTECT:
3926c92544dSBjoern A. Zeeb mt7915_mcu_rx_thermal_notify(dev, skb);
3936c92544dSBjoern A. Zeeb break;
3946c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_RDD_REPORT:
3956c92544dSBjoern A. Zeeb mt7915_mcu_rx_radar_detected(dev, skb);
3966c92544dSBjoern A. Zeeb break;
3976c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_CSA_NOTIFY:
3986c92544dSBjoern A. Zeeb mt7915_mcu_rx_csa_notify(dev, skb);
3996c92544dSBjoern A. Zeeb break;
4006c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_FW_LOG_2_HOST:
4016c92544dSBjoern A. Zeeb mt7915_mcu_rx_log_message(dev, skb);
4026c92544dSBjoern A. Zeeb break;
4036c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_BCC_NOTIFY:
4046c92544dSBjoern A. Zeeb mt7915_mcu_rx_bcc_notify(dev, skb);
4056c92544dSBjoern A. Zeeb break;
4066c92544dSBjoern A. Zeeb default:
4076c92544dSBjoern A. Zeeb break;
4086c92544dSBjoern A. Zeeb }
4096c92544dSBjoern A. Zeeb }
4106c92544dSBjoern A. Zeeb
4116c92544dSBjoern A. Zeeb static void
mt7915_mcu_rx_unsolicited_event(struct mt7915_dev * dev,struct sk_buff * skb)4126c92544dSBjoern A. Zeeb mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb)
4136c92544dSBjoern A. Zeeb {
4146c92544dSBjoern A. Zeeb struct mt76_connac2_mcu_rxd *rxd;
4156c92544dSBjoern A. Zeeb
4166c92544dSBjoern A. Zeeb rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
4176c92544dSBjoern A. Zeeb switch (rxd->eid) {
4186c92544dSBjoern A. Zeeb case MCU_EVENT_EXT:
4196c92544dSBjoern A. Zeeb mt7915_mcu_rx_ext_event(dev, skb);
4206c92544dSBjoern A. Zeeb break;
4216c92544dSBjoern A. Zeeb default:
4226c92544dSBjoern A. Zeeb break;
4236c92544dSBjoern A. Zeeb }
4246c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
4256c92544dSBjoern A. Zeeb }
4266c92544dSBjoern A. Zeeb
mt7915_mcu_rx_event(struct mt7915_dev * dev,struct sk_buff * skb)4276c92544dSBjoern A. Zeeb void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
4286c92544dSBjoern A. Zeeb {
4296c92544dSBjoern A. Zeeb struct mt76_connac2_mcu_rxd *rxd;
4306c92544dSBjoern A. Zeeb
4316c92544dSBjoern A. Zeeb rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
432cbb3ec25SBjoern A. Zeeb if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
4336c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
4346c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
4356c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
4366c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
437cbb3ec25SBjoern A. Zeeb !rxd->seq) &&
438cbb3ec25SBjoern A. Zeeb !(rxd->eid == MCU_CMD_EXT_CID &&
439cbb3ec25SBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
4406c92544dSBjoern A. Zeeb mt7915_mcu_rx_unsolicited_event(dev, skb);
4416c92544dSBjoern A. Zeeb else
4426c92544dSBjoern A. Zeeb mt76_mcu_rx_event(&dev->mt76, skb);
4436c92544dSBjoern A. Zeeb }
4446c92544dSBjoern A. Zeeb
4456c92544dSBjoern A. Zeeb static struct tlv *
mt7915_mcu_add_nested_subtlv(struct sk_buff * skb,int sub_tag,int sub_len,__le16 * sub_ntlv,__le16 * len)4466c92544dSBjoern A. Zeeb mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len,
4476c92544dSBjoern A. Zeeb __le16 *sub_ntlv, __le16 *len)
4486c92544dSBjoern A. Zeeb {
4496c92544dSBjoern A. Zeeb struct tlv *ptlv, tlv = {
4506c92544dSBjoern A. Zeeb .tag = cpu_to_le16(sub_tag),
4516c92544dSBjoern A. Zeeb .len = cpu_to_le16(sub_len),
4526c92544dSBjoern A. Zeeb };
4536c92544dSBjoern A. Zeeb
454*8ba4d145SBjoern A. Zeeb ptlv = skb_put_zero(skb, sub_len);
4556c92544dSBjoern A. Zeeb memcpy(ptlv, &tlv, sizeof(tlv));
4566c92544dSBjoern A. Zeeb
4576c92544dSBjoern A. Zeeb le16_add_cpu(sub_ntlv, 1);
4586c92544dSBjoern A. Zeeb le16_add_cpu(len, sub_len);
4596c92544dSBjoern A. Zeeb
4606c92544dSBjoern A. Zeeb return ptlv;
4616c92544dSBjoern A. Zeeb }
4626c92544dSBjoern A. Zeeb
4636c92544dSBjoern A. Zeeb /** bss info **/
4646c92544dSBjoern A. Zeeb struct mt7915_he_obss_narrow_bw_ru_data {
4656c92544dSBjoern A. Zeeb bool tolerated;
4666c92544dSBjoern A. Zeeb };
4676c92544dSBjoern A. Zeeb
mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy * wiphy,struct cfg80211_bss * bss,void * _data)4686c92544dSBjoern A. Zeeb static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
4696c92544dSBjoern A. Zeeb struct cfg80211_bss *bss,
4706c92544dSBjoern A. Zeeb void *_data)
4716c92544dSBjoern A. Zeeb {
4726c92544dSBjoern A. Zeeb struct mt7915_he_obss_narrow_bw_ru_data *data = _data;
4736c92544dSBjoern A. Zeeb const struct element *elem;
4746c92544dSBjoern A. Zeeb
4756c92544dSBjoern A. Zeeb rcu_read_lock();
4766c92544dSBjoern A. Zeeb elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY);
4776c92544dSBjoern A. Zeeb
4786c92544dSBjoern A. Zeeb if (!elem || elem->datalen <= 10 ||
4796c92544dSBjoern A. Zeeb !(elem->data[10] &
4806c92544dSBjoern A. Zeeb WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT))
4816c92544dSBjoern A. Zeeb data->tolerated = false;
4826c92544dSBjoern A. Zeeb
4836c92544dSBjoern A. Zeeb rcu_read_unlock();
4846c92544dSBjoern A. Zeeb }
4856c92544dSBjoern A. Zeeb
mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw * hw,struct ieee80211_vif * vif)4866c92544dSBjoern A. Zeeb static bool mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
4876c92544dSBjoern A. Zeeb struct ieee80211_vif *vif)
4886c92544dSBjoern A. Zeeb {
4896c92544dSBjoern A. Zeeb struct mt7915_he_obss_narrow_bw_ru_data iter_data = {
4906c92544dSBjoern A. Zeeb .tolerated = true,
4916c92544dSBjoern A. Zeeb };
4926c92544dSBjoern A. Zeeb
493*8ba4d145SBjoern A. Zeeb if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR))
4946c92544dSBjoern A. Zeeb return false;
4956c92544dSBjoern A. Zeeb
496*8ba4d145SBjoern A. Zeeb cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper,
4976c92544dSBjoern A. Zeeb mt7915_check_he_obss_narrow_bw_ru_iter,
4986c92544dSBjoern A. Zeeb &iter_data);
4996c92544dSBjoern A. Zeeb
5006c92544dSBjoern A. Zeeb /*
5016c92544dSBjoern A. Zeeb * If there is at least one AP on radar channel that cannot
5026c92544dSBjoern A. Zeeb * tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
5036c92544dSBjoern A. Zeeb */
5046c92544dSBjoern A. Zeeb return !iter_data.tolerated;
5056c92544dSBjoern A. Zeeb }
5066c92544dSBjoern A. Zeeb
5076c92544dSBjoern A. Zeeb static void
mt7915_mcu_bss_rfch_tlv(struct sk_buff * skb,struct ieee80211_vif * vif,struct mt7915_phy * phy)5086c92544dSBjoern A. Zeeb mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
5096c92544dSBjoern A. Zeeb struct mt7915_phy *phy)
5106c92544dSBjoern A. Zeeb {
5116c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
5126c92544dSBjoern A. Zeeb struct bss_info_rf_ch *ch;
5136c92544dSBjoern A. Zeeb struct tlv *tlv;
5146c92544dSBjoern A. Zeeb int freq1 = chandef->center_freq1;
5156c92544dSBjoern A. Zeeb
5166c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch));
5176c92544dSBjoern A. Zeeb
5186c92544dSBjoern A. Zeeb ch = (struct bss_info_rf_ch *)tlv;
5196c92544dSBjoern A. Zeeb ch->pri_ch = chandef->chan->hw_value;
5206c92544dSBjoern A. Zeeb ch->center_ch0 = ieee80211_frequency_to_channel(freq1);
5216c92544dSBjoern A. Zeeb ch->bw = mt76_connac_chan_bw(chandef);
5226c92544dSBjoern A. Zeeb
5236c92544dSBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_80P80) {
5246c92544dSBjoern A. Zeeb int freq2 = chandef->center_freq2;
5256c92544dSBjoern A. Zeeb
5266c92544dSBjoern A. Zeeb ch->center_ch1 = ieee80211_frequency_to_channel(freq2);
5276c92544dSBjoern A. Zeeb }
5286c92544dSBjoern A. Zeeb
5296c92544dSBjoern A. Zeeb if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) {
5306c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
5316c92544dSBjoern A. Zeeb
5326c92544dSBjoern A. Zeeb ch->he_ru26_block =
5336c92544dSBjoern A. Zeeb mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif);
5346c92544dSBjoern A. Zeeb ch->he_all_disable = false;
5356c92544dSBjoern A. Zeeb } else {
5366c92544dSBjoern A. Zeeb ch->he_all_disable = true;
5376c92544dSBjoern A. Zeeb }
5386c92544dSBjoern A. Zeeb }
5396c92544dSBjoern A. Zeeb
5406c92544dSBjoern A. Zeeb static void
mt7915_mcu_bss_ra_tlv(struct sk_buff * skb,struct ieee80211_vif * vif,struct mt7915_phy * phy)5416c92544dSBjoern A. Zeeb mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
5426c92544dSBjoern A. Zeeb struct mt7915_phy *phy)
5436c92544dSBjoern A. Zeeb {
544cbb3ec25SBjoern A. Zeeb int max_nss = hweight8(phy->mt76->antenna_mask);
5456c92544dSBjoern A. Zeeb struct bss_info_ra *ra;
5466c92544dSBjoern A. Zeeb struct tlv *tlv;
5476c92544dSBjoern A. Zeeb
5486c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra));
5496c92544dSBjoern A. Zeeb
5506c92544dSBjoern A. Zeeb ra = (struct bss_info_ra *)tlv;
5516c92544dSBjoern A. Zeeb ra->op_mode = vif->type == NL80211_IFTYPE_AP;
5526c92544dSBjoern A. Zeeb ra->adhoc_en = vif->type == NL80211_IFTYPE_ADHOC;
5536c92544dSBjoern A. Zeeb ra->short_preamble = true;
5546c92544dSBjoern A. Zeeb ra->tx_streams = max_nss;
5556c92544dSBjoern A. Zeeb ra->rx_streams = max_nss;
5566c92544dSBjoern A. Zeeb ra->algo = 4;
5576c92544dSBjoern A. Zeeb ra->train_up_rule = 2;
5586c92544dSBjoern A. Zeeb ra->train_up_high_thres = 110;
5596c92544dSBjoern A. Zeeb ra->train_up_rule_rssi = -70;
5606c92544dSBjoern A. Zeeb ra->low_traffic_thres = 2;
5616c92544dSBjoern A. Zeeb ra->phy_cap = cpu_to_le32(0xfdf);
5626c92544dSBjoern A. Zeeb ra->interval = cpu_to_le32(500);
5636c92544dSBjoern A. Zeeb ra->fast_interval = cpu_to_le32(100);
5646c92544dSBjoern A. Zeeb }
5656c92544dSBjoern A. Zeeb
5666c92544dSBjoern A. Zeeb static void
mt7915_mcu_bss_he_tlv(struct sk_buff * skb,struct ieee80211_vif * vif,struct mt7915_phy * phy)5676c92544dSBjoern A. Zeeb mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
5686c92544dSBjoern A. Zeeb struct mt7915_phy *phy)
5696c92544dSBjoern A. Zeeb {
5706c92544dSBjoern A. Zeeb #define DEFAULT_HE_PE_DURATION 4
5716c92544dSBjoern A. Zeeb #define DEFAULT_HE_DURATION_RTS_THRES 1023
5726c92544dSBjoern A. Zeeb const struct ieee80211_sta_he_cap *cap;
5736c92544dSBjoern A. Zeeb struct bss_info_he *he;
5746c92544dSBjoern A. Zeeb struct tlv *tlv;
5756c92544dSBjoern A. Zeeb
5766c92544dSBjoern A. Zeeb cap = mt76_connac_get_he_phy_cap(phy->mt76, vif);
5776c92544dSBjoern A. Zeeb
5786c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he));
5796c92544dSBjoern A. Zeeb
5806c92544dSBjoern A. Zeeb he = (struct bss_info_he *)tlv;
5816c92544dSBjoern A. Zeeb he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;
5826c92544dSBjoern A. Zeeb if (!he->he_pe_duration)
5836c92544dSBjoern A. Zeeb he->he_pe_duration = DEFAULT_HE_PE_DURATION;
5846c92544dSBjoern A. Zeeb
5856c92544dSBjoern A. Zeeb he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);
5866c92544dSBjoern A. Zeeb if (!he->he_rts_thres)
5876c92544dSBjoern A. Zeeb he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);
5886c92544dSBjoern A. Zeeb
5896c92544dSBjoern A. Zeeb he->max_nss_mcs[CMD_HE_MCS_BW80] = cap->he_mcs_nss_supp.tx_mcs_80;
5906c92544dSBjoern A. Zeeb he->max_nss_mcs[CMD_HE_MCS_BW160] = cap->he_mcs_nss_supp.tx_mcs_160;
5916c92544dSBjoern A. Zeeb he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
5926c92544dSBjoern A. Zeeb }
5936c92544dSBjoern A. Zeeb
5946c92544dSBjoern A. Zeeb static void
mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff * skb)5956c92544dSBjoern A. Zeeb mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb)
5966c92544dSBjoern A. Zeeb {
5976c92544dSBjoern A. Zeeb #define TXD_CMP_MAP1 GENMASK(15, 0)
5986c92544dSBjoern A. Zeeb #define TXD_CMP_MAP2 (GENMASK(31, 0) & ~BIT(23))
5996c92544dSBjoern A. Zeeb struct bss_info_hw_amsdu *amsdu;
6006c92544dSBjoern A. Zeeb struct tlv *tlv;
6016c92544dSBjoern A. Zeeb
6026c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu));
6036c92544dSBjoern A. Zeeb
6046c92544dSBjoern A. Zeeb amsdu = (struct bss_info_hw_amsdu *)tlv;
6056c92544dSBjoern A. Zeeb amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1);
6066c92544dSBjoern A. Zeeb amsdu->cmp_bitmap_1 = cpu_to_le32(TXD_CMP_MAP2);
6076c92544dSBjoern A. Zeeb amsdu->trig_thres = cpu_to_le16(2);
6086c92544dSBjoern A. Zeeb amsdu->enable = true;
6096c92544dSBjoern A. Zeeb }
6106c92544dSBjoern A. Zeeb
6116c92544dSBjoern A. Zeeb static void
mt7915_mcu_bss_bmc_tlv(struct sk_buff * skb,struct mt7915_phy * phy)6126c92544dSBjoern A. Zeeb mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy)
6136c92544dSBjoern A. Zeeb {
6146c92544dSBjoern A. Zeeb struct bss_info_bmc_rate *bmc;
6156c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
6166c92544dSBjoern A. Zeeb enum nl80211_band band = chandef->chan->band;
6176c92544dSBjoern A. Zeeb struct tlv *tlv;
6186c92544dSBjoern A. Zeeb
6196c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc));
6206c92544dSBjoern A. Zeeb
6216c92544dSBjoern A. Zeeb bmc = (struct bss_info_bmc_rate *)tlv;
6226c92544dSBjoern A. Zeeb if (band == NL80211_BAND_2GHZ) {
6236c92544dSBjoern A. Zeeb bmc->short_preamble = true;
6246c92544dSBjoern A. Zeeb } else {
6256c92544dSBjoern A. Zeeb bmc->bc_trans = cpu_to_le16(0x2000);
6266c92544dSBjoern A. Zeeb bmc->mc_trans = cpu_to_le16(0x2080);
6276c92544dSBjoern A. Zeeb }
6286c92544dSBjoern A. Zeeb }
6296c92544dSBjoern A. Zeeb
6306c92544dSBjoern A. Zeeb static int
mt7915_mcu_muar_config(struct mt7915_phy * phy,struct ieee80211_vif * vif,bool bssid,bool enable)6316c92544dSBjoern A. Zeeb mt7915_mcu_muar_config(struct mt7915_phy *phy, struct ieee80211_vif *vif,
6326c92544dSBjoern A. Zeeb bool bssid, bool enable)
6336c92544dSBjoern A. Zeeb {
6346c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
6356c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
6366c92544dSBjoern A. Zeeb u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START;
6376c92544dSBjoern A. Zeeb u32 mask = phy->omac_mask >> 32 & ~BIT(idx);
6386c92544dSBjoern A. Zeeb const u8 *addr = vif->addr;
6396c92544dSBjoern A. Zeeb struct {
6406c92544dSBjoern A. Zeeb u8 mode;
6416c92544dSBjoern A. Zeeb u8 force_clear;
6426c92544dSBjoern A. Zeeb u8 clear_bitmap[8];
6436c92544dSBjoern A. Zeeb u8 entry_count;
6446c92544dSBjoern A. Zeeb u8 write;
6456c92544dSBjoern A. Zeeb u8 band;
6466c92544dSBjoern A. Zeeb
6476c92544dSBjoern A. Zeeb u8 index;
6486c92544dSBjoern A. Zeeb u8 bssid;
6496c92544dSBjoern A. Zeeb u8 addr[ETH_ALEN];
6506c92544dSBjoern A. Zeeb } __packed req = {
6516c92544dSBjoern A. Zeeb .mode = !!mask || enable,
6526c92544dSBjoern A. Zeeb .entry_count = 1,
6536c92544dSBjoern A. Zeeb .write = 1,
654cbb3ec25SBjoern A. Zeeb .band = phy->mt76->band_idx,
6556c92544dSBjoern A. Zeeb .index = idx * 2 + bssid,
6566c92544dSBjoern A. Zeeb };
6576c92544dSBjoern A. Zeeb
6586c92544dSBjoern A. Zeeb if (bssid)
6596c92544dSBjoern A. Zeeb addr = vif->bss_conf.bssid;
6606c92544dSBjoern A. Zeeb
6616c92544dSBjoern A. Zeeb if (enable)
6626c92544dSBjoern A. Zeeb ether_addr_copy(req.addr, addr);
6636c92544dSBjoern A. Zeeb
6646c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE), &req,
6656c92544dSBjoern A. Zeeb sizeof(req), true);
6666c92544dSBjoern A. Zeeb }
6676c92544dSBjoern A. Zeeb
mt7915_mcu_add_bss_info(struct mt7915_phy * phy,struct ieee80211_vif * vif,int enable)6686c92544dSBjoern A. Zeeb int mt7915_mcu_add_bss_info(struct mt7915_phy *phy,
6696c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, int enable)
6706c92544dSBjoern A. Zeeb {
6716c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
6726c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
6736c92544dSBjoern A. Zeeb struct sk_buff *skb;
6746c92544dSBjoern A. Zeeb
6756c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) {
6766c92544dSBjoern A. Zeeb mt7915_mcu_muar_config(phy, vif, false, enable);
6776c92544dSBjoern A. Zeeb mt7915_mcu_muar_config(phy, vif, true, enable);
6786c92544dSBjoern A. Zeeb }
6796c92544dSBjoern A. Zeeb
6806c92544dSBjoern A. Zeeb skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,
6816c92544dSBjoern A. Zeeb MT7915_BSS_UPDATE_MAX_SIZE);
6826c92544dSBjoern A. Zeeb if (IS_ERR(skb))
6836c92544dSBjoern A. Zeeb return PTR_ERR(skb);
6846c92544dSBjoern A. Zeeb
6856c92544dSBjoern A. Zeeb /* bss_omac must be first */
6866c92544dSBjoern A. Zeeb if (enable)
6876c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_omac_tlv(skb, vif);
6886c92544dSBjoern A. Zeeb
6896c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_basic_tlv(skb, vif, NULL, phy->mt76,
6906c92544dSBjoern A. Zeeb mvif->sta.wcid.idx, enable);
6916c92544dSBjoern A. Zeeb
6926c92544dSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_MONITOR)
6936c92544dSBjoern A. Zeeb goto out;
6946c92544dSBjoern A. Zeeb
6956c92544dSBjoern A. Zeeb if (enable) {
6966c92544dSBjoern A. Zeeb mt7915_mcu_bss_rfch_tlv(skb, vif, phy);
6976c92544dSBjoern A. Zeeb mt7915_mcu_bss_bmc_tlv(skb, phy);
6986c92544dSBjoern A. Zeeb mt7915_mcu_bss_ra_tlv(skb, vif, phy);
6996c92544dSBjoern A. Zeeb mt7915_mcu_bss_hw_amsdu_tlv(skb);
7006c92544dSBjoern A. Zeeb
7016c92544dSBjoern A. Zeeb if (vif->bss_conf.he_support)
7026c92544dSBjoern A. Zeeb mt7915_mcu_bss_he_tlv(skb, vif, phy);
7036c92544dSBjoern A. Zeeb
7046c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx >= EXT_BSSID_START &&
7056c92544dSBjoern A. Zeeb mvif->mt76.omac_idx < REPEATER_BSSID_START)
7066c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76);
7076c92544dSBjoern A. Zeeb }
7086c92544dSBjoern A. Zeeb out:
7096c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
7106c92544dSBjoern A. Zeeb MCU_EXT_CMD(BSS_INFO_UPDATE), true);
7116c92544dSBjoern A. Zeeb }
7126c92544dSBjoern A. Zeeb
7136c92544dSBjoern A. Zeeb /** starec & wtbl **/
mt7915_mcu_add_tx_ba(struct mt7915_dev * dev,struct ieee80211_ampdu_params * params,bool enable)7146c92544dSBjoern A. Zeeb int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,
7156c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
7166c92544dSBjoern A. Zeeb bool enable)
7176c92544dSBjoern A. Zeeb {
7186c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;
7196c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = msta->vif;
720*8ba4d145SBjoern A. Zeeb int ret;
7216c92544dSBjoern A. Zeeb
722*8ba4d145SBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker);
7236c92544dSBjoern A. Zeeb if (enable && !params->amsdu)
7246c92544dSBjoern A. Zeeb msta->wcid.amsdu = false;
725*8ba4d145SBjoern A. Zeeb ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
7266c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE),
7276c92544dSBjoern A. Zeeb enable, true);
728*8ba4d145SBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker);
729*8ba4d145SBjoern A. Zeeb
730*8ba4d145SBjoern A. Zeeb return ret;
7316c92544dSBjoern A. Zeeb }
7326c92544dSBjoern A. Zeeb
mt7915_mcu_add_rx_ba(struct mt7915_dev * dev,struct ieee80211_ampdu_params * params,bool enable)7336c92544dSBjoern A. Zeeb int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
7346c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
7356c92544dSBjoern A. Zeeb bool enable)
7366c92544dSBjoern A. Zeeb {
7376c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv;
7386c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = msta->vif;
7396c92544dSBjoern A. Zeeb
7406c92544dSBjoern A. Zeeb return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
7416c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE),
7426c92544dSBjoern A. Zeeb enable, false);
7436c92544dSBjoern A. Zeeb }
7446c92544dSBjoern A. Zeeb
7456c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_he_tlv(struct sk_buff * skb,struct ieee80211_sta * sta,struct ieee80211_vif * vif)7466c92544dSBjoern A. Zeeb mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
7476c92544dSBjoern A. Zeeb struct ieee80211_vif *vif)
7486c92544dSBjoern A. Zeeb {
7496c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
7506c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
7516c92544dSBjoern A. Zeeb struct ieee80211_he_mcs_nss_supp mcs_map;
7526c92544dSBjoern A. Zeeb struct sta_rec_he *he;
7536c92544dSBjoern A. Zeeb struct tlv *tlv;
7546c92544dSBjoern A. Zeeb u32 cap = 0;
7556c92544dSBjoern A. Zeeb
7566c92544dSBjoern A. Zeeb if (!sta->deflink.he_cap.has_he)
7576c92544dSBjoern A. Zeeb return;
7586c92544dSBjoern A. Zeeb
7596c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he));
7606c92544dSBjoern A. Zeeb
7616c92544dSBjoern A. Zeeb he = (struct sta_rec_he *)tlv;
7626c92544dSBjoern A. Zeeb
7636c92544dSBjoern A. Zeeb if (elem->mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)
7646c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_HTC;
7656c92544dSBjoern A. Zeeb
7666c92544dSBjoern A. Zeeb if (elem->mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)
7676c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_BSR;
7686c92544dSBjoern A. Zeeb
7696c92544dSBjoern A. Zeeb if (elem->mac_cap_info[3] & IEEE80211_HE_MAC_CAP3_OMI_CONTROL)
7706c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_OM;
7716c92544dSBjoern A. Zeeb
7726c92544dSBjoern A. Zeeb if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU)
7736c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_AMSDU_IN_AMPDU;
7746c92544dSBjoern A. Zeeb
7756c92544dSBjoern A. Zeeb if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)
7766c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_BQR;
7776c92544dSBjoern A. Zeeb
7786c92544dSBjoern A. Zeeb if (elem->phy_cap_info[0] &
7796c92544dSBjoern A. Zeeb (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G |
7806c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
7816c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
7826c92544dSBjoern A. Zeeb
7836c92544dSBjoern A. Zeeb if (mvif->cap.he_ldpc &&
7846c92544dSBjoern A. Zeeb (elem->phy_cap_info[1] &
7856c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
7866c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_LDPC;
7876c92544dSBjoern A. Zeeb
7886c92544dSBjoern A. Zeeb if (elem->phy_cap_info[1] &
7896c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US)
7906c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI;
7916c92544dSBjoern A. Zeeb
7926c92544dSBjoern A. Zeeb if (elem->phy_cap_info[2] &
7936c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US)
7946c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI;
7956c92544dSBjoern A. Zeeb
7966c92544dSBjoern A. Zeeb if (elem->phy_cap_info[2] &
7976c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ)
7986c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_LE_EQ_80M_TX_STBC;
7996c92544dSBjoern A. Zeeb
8006c92544dSBjoern A. Zeeb if (elem->phy_cap_info[2] &
8016c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
8026c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_LE_EQ_80M_RX_STBC;
8036c92544dSBjoern A. Zeeb
8046c92544dSBjoern A. Zeeb if (elem->phy_cap_info[6] &
8056c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB)
8066c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_TRIG_CQI_FK;
8076c92544dSBjoern A. Zeeb
8086c92544dSBjoern A. Zeeb if (elem->phy_cap_info[6] &
8096c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE)
8106c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE;
8116c92544dSBjoern A. Zeeb
8126c92544dSBjoern A. Zeeb if (elem->phy_cap_info[7] &
8136c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI)
8146c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI;
8156c92544dSBjoern A. Zeeb
8166c92544dSBjoern A. Zeeb if (elem->phy_cap_info[7] &
8176c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ)
8186c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_GT_80M_TX_STBC;
8196c92544dSBjoern A. Zeeb
8206c92544dSBjoern A. Zeeb if (elem->phy_cap_info[7] &
8216c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
8226c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_GT_80M_RX_STBC;
8236c92544dSBjoern A. Zeeb
8246c92544dSBjoern A. Zeeb if (elem->phy_cap_info[8] &
8256c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI)
8266c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI;
8276c92544dSBjoern A. Zeeb
8286c92544dSBjoern A. Zeeb if (elem->phy_cap_info[8] &
8296c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI)
8306c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI;
8316c92544dSBjoern A. Zeeb
8326c92544dSBjoern A. Zeeb if (elem->phy_cap_info[9] &
8336c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU)
8346c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242;
8356c92544dSBjoern A. Zeeb
8366c92544dSBjoern A. Zeeb if (elem->phy_cap_info[9] &
8376c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU)
8386c92544dSBjoern A. Zeeb cap |= STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242;
8396c92544dSBjoern A. Zeeb
8406c92544dSBjoern A. Zeeb he->he_cap = cpu_to_le32(cap);
8416c92544dSBjoern A. Zeeb
8426c92544dSBjoern A. Zeeb mcs_map = sta->deflink.he_cap.he_mcs_nss_supp;
8436c92544dSBjoern A. Zeeb switch (sta->deflink.bandwidth) {
8446c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
8456c92544dSBjoern A. Zeeb if (elem->phy_cap_info[0] &
8466c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
8476c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_he_mcs(sta,
8486c92544dSBjoern A. Zeeb &he->max_nss_mcs[CMD_HE_MCS_BW8080],
8496c92544dSBjoern A. Zeeb le16_to_cpu(mcs_map.rx_mcs_80p80));
8506c92544dSBjoern A. Zeeb
8516c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_he_mcs(sta,
8526c92544dSBjoern A. Zeeb &he->max_nss_mcs[CMD_HE_MCS_BW160],
8536c92544dSBjoern A. Zeeb le16_to_cpu(mcs_map.rx_mcs_160));
8546c92544dSBjoern A. Zeeb fallthrough;
8556c92544dSBjoern A. Zeeb default:
8566c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_he_mcs(sta,
8576c92544dSBjoern A. Zeeb &he->max_nss_mcs[CMD_HE_MCS_BW80],
8586c92544dSBjoern A. Zeeb le16_to_cpu(mcs_map.rx_mcs_80));
8596c92544dSBjoern A. Zeeb break;
8606c92544dSBjoern A. Zeeb }
8616c92544dSBjoern A. Zeeb
8626c92544dSBjoern A. Zeeb he->t_frame_dur =
8636c92544dSBjoern A. Zeeb HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
8646c92544dSBjoern A. Zeeb he->max_ampdu_exp =
8656c92544dSBjoern A. Zeeb HE_MAC(CAP3_MAX_AMPDU_LEN_EXP_MASK, elem->mac_cap_info[3]);
8666c92544dSBjoern A. Zeeb
8676c92544dSBjoern A. Zeeb he->bw_set =
8686c92544dSBjoern A. Zeeb HE_PHY(CAP0_CHANNEL_WIDTH_SET_MASK, elem->phy_cap_info[0]);
8696c92544dSBjoern A. Zeeb he->device_class =
8706c92544dSBjoern A. Zeeb HE_PHY(CAP1_DEVICE_CLASS_A, elem->phy_cap_info[1]);
8716c92544dSBjoern A. Zeeb he->punc_pream_rx =
8726c92544dSBjoern A. Zeeb HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
8736c92544dSBjoern A. Zeeb
8746c92544dSBjoern A. Zeeb he->dcm_tx_mode =
8756c92544dSBjoern A. Zeeb HE_PHY(CAP3_DCM_MAX_CONST_TX_MASK, elem->phy_cap_info[3]);
8766c92544dSBjoern A. Zeeb he->dcm_tx_max_nss =
8776c92544dSBjoern A. Zeeb HE_PHY(CAP3_DCM_MAX_TX_NSS_2, elem->phy_cap_info[3]);
8786c92544dSBjoern A. Zeeb he->dcm_rx_mode =
8796c92544dSBjoern A. Zeeb HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);
8806c92544dSBjoern A. Zeeb he->dcm_rx_max_nss =
8816c92544dSBjoern A. Zeeb HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);
8826c92544dSBjoern A. Zeeb he->dcm_rx_max_nss =
8836c92544dSBjoern A. Zeeb HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);
8846c92544dSBjoern A. Zeeb
8856c92544dSBjoern A. Zeeb he->pkt_ext = 2;
8866c92544dSBjoern A. Zeeb }
8876c92544dSBjoern A. Zeeb
8886c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_muru_tlv(struct mt7915_dev * dev,struct sk_buff * skb,struct ieee80211_sta * sta,struct ieee80211_vif * vif)8896c92544dSBjoern A. Zeeb mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
8906c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, struct ieee80211_vif *vif)
8916c92544dSBjoern A. Zeeb {
8926c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
8936c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
8946c92544dSBjoern A. Zeeb struct sta_rec_muru *muru;
8956c92544dSBjoern A. Zeeb struct tlv *tlv;
8966c92544dSBjoern A. Zeeb
8976c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION &&
8986c92544dSBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP)
8996c92544dSBjoern A. Zeeb return;
9006c92544dSBjoern A. Zeeb
9016c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
9026c92544dSBjoern A. Zeeb
9036c92544dSBjoern A. Zeeb muru = (struct sta_rec_muru *)tlv;
9046c92544dSBjoern A. Zeeb
9056c92544dSBjoern A. Zeeb muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
9066c92544dSBjoern A. Zeeb mvif->cap.vht_mu_ebfer ||
9076c92544dSBjoern A. Zeeb mvif->cap.vht_mu_ebfee;
9086c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
9096c92544dSBjoern A. Zeeb muru->cfg.mimo_ul_en = true;
9106c92544dSBjoern A. Zeeb muru->cfg.ofdma_dl_en = true;
9116c92544dSBjoern A. Zeeb
9126c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported)
9136c92544dSBjoern A. Zeeb muru->mimo_dl.vht_mu_bfee =
9146c92544dSBjoern A. Zeeb !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
9156c92544dSBjoern A. Zeeb
9166c92544dSBjoern A. Zeeb if (!sta->deflink.he_cap.has_he)
9176c92544dSBjoern A. Zeeb return;
9186c92544dSBjoern A. Zeeb
9196c92544dSBjoern A. Zeeb muru->mimo_dl.partial_bw_dl_mimo =
9206c92544dSBjoern A. Zeeb HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);
9216c92544dSBjoern A. Zeeb
9226c92544dSBjoern A. Zeeb muru->mimo_ul.full_ul_mimo =
9236c92544dSBjoern A. Zeeb HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);
9246c92544dSBjoern A. Zeeb muru->mimo_ul.partial_ul_mimo =
9256c92544dSBjoern A. Zeeb HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
9266c92544dSBjoern A. Zeeb
9276c92544dSBjoern A. Zeeb muru->ofdma_dl.punc_pream_rx =
9286c92544dSBjoern A. Zeeb HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
9296c92544dSBjoern A. Zeeb muru->ofdma_dl.he_20m_in_40m_2g =
9306c92544dSBjoern A. Zeeb HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]);
9316c92544dSBjoern A. Zeeb muru->ofdma_dl.he_20m_in_160m =
9326c92544dSBjoern A. Zeeb HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
9336c92544dSBjoern A. Zeeb muru->ofdma_dl.he_80m_in_160m =
9346c92544dSBjoern A. Zeeb HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
9356c92544dSBjoern A. Zeeb
9366c92544dSBjoern A. Zeeb muru->ofdma_ul.t_frame_dur =
9376c92544dSBjoern A. Zeeb HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
9386c92544dSBjoern A. Zeeb muru->ofdma_ul.mu_cascading =
9396c92544dSBjoern A. Zeeb HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
9406c92544dSBjoern A. Zeeb muru->ofdma_ul.uo_ra =
9416c92544dSBjoern A. Zeeb HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
942*8ba4d145SBjoern A. Zeeb muru->ofdma_ul.rx_ctrl_frame_to_mbss =
943*8ba4d145SBjoern A. Zeeb HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
9446c92544dSBjoern A. Zeeb }
9456c92544dSBjoern A. Zeeb
9466c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_ht_tlv(struct sk_buff * skb,struct ieee80211_sta * sta)9476c92544dSBjoern A. Zeeb mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
9486c92544dSBjoern A. Zeeb {
9496c92544dSBjoern A. Zeeb struct sta_rec_ht *ht;
9506c92544dSBjoern A. Zeeb struct tlv *tlv;
9516c92544dSBjoern A. Zeeb
9526c92544dSBjoern A. Zeeb if (!sta->deflink.ht_cap.ht_supported)
9536c92544dSBjoern A. Zeeb return;
9546c92544dSBjoern A. Zeeb
9556c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
9566c92544dSBjoern A. Zeeb
9576c92544dSBjoern A. Zeeb ht = (struct sta_rec_ht *)tlv;
9586c92544dSBjoern A. Zeeb ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);
9596c92544dSBjoern A. Zeeb }
9606c92544dSBjoern A. Zeeb
9616c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_vht_tlv(struct sk_buff * skb,struct ieee80211_sta * sta)9626c92544dSBjoern A. Zeeb mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
9636c92544dSBjoern A. Zeeb {
9646c92544dSBjoern A. Zeeb struct sta_rec_vht *vht;
9656c92544dSBjoern A. Zeeb struct tlv *tlv;
9666c92544dSBjoern A. Zeeb
9676c92544dSBjoern A. Zeeb if (!sta->deflink.vht_cap.vht_supported)
9686c92544dSBjoern A. Zeeb return;
9696c92544dSBjoern A. Zeeb
9706c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
9716c92544dSBjoern A. Zeeb
9726c92544dSBjoern A. Zeeb vht = (struct sta_rec_vht *)tlv;
9736c92544dSBjoern A. Zeeb vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);
9746c92544dSBjoern A. Zeeb vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
9756c92544dSBjoern A. Zeeb vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
9766c92544dSBjoern A. Zeeb }
9776c92544dSBjoern A. Zeeb
9786c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev * dev,struct sk_buff * skb,struct ieee80211_vif * vif,struct ieee80211_sta * sta)9796c92544dSBjoern A. Zeeb mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
9806c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta)
9816c92544dSBjoern A. Zeeb {
9826c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
9836c92544dSBjoern A. Zeeb struct sta_rec_amsdu *amsdu;
9846c92544dSBjoern A. Zeeb struct tlv *tlv;
9856c92544dSBjoern A. Zeeb
9866c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION &&
9876c92544dSBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP)
9886c92544dSBjoern A. Zeeb return;
9896c92544dSBjoern A. Zeeb
9906c92544dSBjoern A. Zeeb if (!sta->deflink.agg.max_amsdu_len)
9916c92544dSBjoern A. Zeeb return;
9926c92544dSBjoern A. Zeeb
9936c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));
9946c92544dSBjoern A. Zeeb amsdu = (struct sta_rec_amsdu *)tlv;
9956c92544dSBjoern A. Zeeb amsdu->max_amsdu_num = 8;
9966c92544dSBjoern A. Zeeb amsdu->amsdu_en = true;
9976c92544dSBjoern A. Zeeb msta->wcid.amsdu = true;
9986c92544dSBjoern A. Zeeb
9996c92544dSBjoern A. Zeeb switch (sta->deflink.agg.max_amsdu_len) {
10006c92544dSBjoern A. Zeeb case IEEE80211_MAX_MPDU_LEN_VHT_11454:
10016c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76)) {
10026c92544dSBjoern A. Zeeb amsdu->max_mpdu_size =
10036c92544dSBjoern A. Zeeb IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
10046c92544dSBjoern A. Zeeb return;
10056c92544dSBjoern A. Zeeb }
10066c92544dSBjoern A. Zeeb fallthrough;
10076c92544dSBjoern A. Zeeb case IEEE80211_MAX_MPDU_LEN_HT_7935:
10086c92544dSBjoern A. Zeeb case IEEE80211_MAX_MPDU_LEN_VHT_7991:
10096c92544dSBjoern A. Zeeb amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
10106c92544dSBjoern A. Zeeb return;
10116c92544dSBjoern A. Zeeb default:
10126c92544dSBjoern A. Zeeb amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
10136c92544dSBjoern A. Zeeb return;
10146c92544dSBjoern A. Zeeb }
10156c92544dSBjoern A. Zeeb }
10166c92544dSBjoern A. Zeeb
10176c92544dSBjoern A. Zeeb static int
mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev * dev,struct sk_buff * skb,struct ieee80211_vif * vif,struct ieee80211_sta * sta)10186c92544dSBjoern A. Zeeb mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
10196c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta)
10206c92544dSBjoern A. Zeeb {
10216c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
10226c92544dSBjoern A. Zeeb struct mt7915_sta *msta;
10236c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
10246c92544dSBjoern A. Zeeb struct mt76_wcid *wcid;
10256c92544dSBjoern A. Zeeb struct tlv *tlv;
10266c92544dSBjoern A. Zeeb
10276c92544dSBjoern A. Zeeb msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;
10286c92544dSBjoern A. Zeeb wcid = sta ? &msta->wcid : NULL;
10296c92544dSBjoern A. Zeeb
10306c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));
10316c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
10326c92544dSBjoern A. Zeeb WTBL_RESET_AND_SET, tlv,
10336c92544dSBjoern A. Zeeb &skb);
10346c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
10356c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
10366c92544dSBjoern A. Zeeb
10376c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, skb, vif, sta, tlv,
10386c92544dSBjoern A. Zeeb wtbl_hdr);
10396c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
10406c92544dSBjoern A. Zeeb if (sta)
10416c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
10426c92544dSBjoern A. Zeeb wtbl_hdr, mvif->cap.ht_ldpc,
10436c92544dSBjoern A. Zeeb mvif->cap.vht_ldpc);
10446c92544dSBjoern A. Zeeb
10456c92544dSBjoern A. Zeeb return 0;
10466c92544dSBjoern A. Zeeb }
10476c92544dSBjoern A. Zeeb
10486c92544dSBjoern A. Zeeb static inline bool
mt7915_is_ebf_supported(struct mt7915_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool bfee)10496c92544dSBjoern A. Zeeb mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
10506c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool bfee)
10516c92544dSBjoern A. Zeeb {
10526c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1053*8ba4d145SBjoern A. Zeeb int sts = hweight16(phy->mt76->chainmask);
10546c92544dSBjoern A. Zeeb
10556c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION &&
10566c92544dSBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP)
10576c92544dSBjoern A. Zeeb return false;
10586c92544dSBjoern A. Zeeb
1059*8ba4d145SBjoern A. Zeeb if (!bfee && sts < 2)
10606c92544dSBjoern A. Zeeb return false;
10616c92544dSBjoern A. Zeeb
10626c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he) {
10636c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
10646c92544dSBjoern A. Zeeb
10656c92544dSBjoern A. Zeeb if (bfee)
10666c92544dSBjoern A. Zeeb return mvif->cap.he_su_ebfee &&
10676c92544dSBjoern A. Zeeb HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
10686c92544dSBjoern A. Zeeb else
10696c92544dSBjoern A. Zeeb return mvif->cap.he_su_ebfer &&
10706c92544dSBjoern A. Zeeb HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
10716c92544dSBjoern A. Zeeb }
10726c92544dSBjoern A. Zeeb
10736c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported) {
10746c92544dSBjoern A. Zeeb u32 cap = sta->deflink.vht_cap.cap;
10756c92544dSBjoern A. Zeeb
10766c92544dSBjoern A. Zeeb if (bfee)
10776c92544dSBjoern A. Zeeb return mvif->cap.vht_su_ebfee &&
10786c92544dSBjoern A. Zeeb (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
10796c92544dSBjoern A. Zeeb else
10806c92544dSBjoern A. Zeeb return mvif->cap.vht_su_ebfer &&
10816c92544dSBjoern A. Zeeb (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
10826c92544dSBjoern A. Zeeb }
10836c92544dSBjoern A. Zeeb
10846c92544dSBjoern A. Zeeb return false;
10856c92544dSBjoern A. Zeeb }
10866c92544dSBjoern A. Zeeb
10876c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_sounding_rate(struct sta_rec_bf * bf)10886c92544dSBjoern A. Zeeb mt7915_mcu_sta_sounding_rate(struct sta_rec_bf *bf)
10896c92544dSBjoern A. Zeeb {
10906c92544dSBjoern A. Zeeb bf->sounding_phy = MT_PHY_TYPE_OFDM;
10916c92544dSBjoern A. Zeeb bf->ndp_rate = 0; /* mcs0 */
10926c92544dSBjoern A. Zeeb bf->ndpa_rate = MT7915_CFEND_RATE_DEFAULT; /* ofdm 24m */
10936c92544dSBjoern A. Zeeb bf->rept_poll_rate = MT7915_CFEND_RATE_DEFAULT; /* ofdm 24m */
10946c92544dSBjoern A. Zeeb }
10956c92544dSBjoern A. Zeeb
10966c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_bfer_ht(struct ieee80211_sta * sta,struct mt7915_phy * phy,struct sta_rec_bf * bf)10976c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7915_phy *phy,
10986c92544dSBjoern A. Zeeb struct sta_rec_bf *bf)
10996c92544dSBjoern A. Zeeb {
11006c92544dSBjoern A. Zeeb struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs;
11016c92544dSBjoern A. Zeeb u8 n = 0;
11026c92544dSBjoern A. Zeeb
11036c92544dSBjoern A. Zeeb bf->tx_mode = MT_PHY_TYPE_HT;
11046c92544dSBjoern A. Zeeb
11056c92544dSBjoern A. Zeeb if ((mcs->tx_params & IEEE80211_HT_MCS_TX_RX_DIFF) &&
11066c92544dSBjoern A. Zeeb (mcs->tx_params & IEEE80211_HT_MCS_TX_DEFINED))
11076c92544dSBjoern A. Zeeb n = FIELD_GET(IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK,
11086c92544dSBjoern A. Zeeb mcs->tx_params);
11096c92544dSBjoern A. Zeeb else if (mcs->rx_mask[3])
11106c92544dSBjoern A. Zeeb n = 3;
11116c92544dSBjoern A. Zeeb else if (mcs->rx_mask[2])
11126c92544dSBjoern A. Zeeb n = 2;
11136c92544dSBjoern A. Zeeb else if (mcs->rx_mask[1])
11146c92544dSBjoern A. Zeeb n = 1;
11156c92544dSBjoern A. Zeeb
11166c92544dSBjoern A. Zeeb bf->nrow = hweight8(phy->mt76->chainmask) - 1;
11176c92544dSBjoern A. Zeeb bf->ncol = min_t(u8, bf->nrow, n);
11186c92544dSBjoern A. Zeeb bf->ibf_ncol = n;
11196c92544dSBjoern A. Zeeb }
11206c92544dSBjoern A. Zeeb
11216c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_bfer_vht(struct ieee80211_sta * sta,struct mt7915_phy * phy,struct sta_rec_bf * bf,bool explicit)11226c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy,
11236c92544dSBjoern A. Zeeb struct sta_rec_bf *bf, bool explicit)
11246c92544dSBjoern A. Zeeb {
11256c92544dSBjoern A. Zeeb struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;
11266c92544dSBjoern A. Zeeb struct ieee80211_sta_vht_cap *vc = &phy->mt76->sband_5g.sband.vht_cap;
11276c92544dSBjoern A. Zeeb u16 mcs_map = le16_to_cpu(pc->vht_mcs.rx_mcs_map);
11286c92544dSBjoern A. Zeeb u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
11296c92544dSBjoern A. Zeeb u8 tx_ant = hweight8(phy->mt76->chainmask) - 1;
11306c92544dSBjoern A. Zeeb
11316c92544dSBjoern A. Zeeb bf->tx_mode = MT_PHY_TYPE_VHT;
11326c92544dSBjoern A. Zeeb
11336c92544dSBjoern A. Zeeb if (explicit) {
11346c92544dSBjoern A. Zeeb u8 sts, snd_dim;
11356c92544dSBjoern A. Zeeb
11366c92544dSBjoern A. Zeeb mt7915_mcu_sta_sounding_rate(bf);
11376c92544dSBjoern A. Zeeb
11386c92544dSBjoern A. Zeeb sts = FIELD_GET(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK,
11396c92544dSBjoern A. Zeeb pc->cap);
11406c92544dSBjoern A. Zeeb snd_dim = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
11416c92544dSBjoern A. Zeeb vc->cap);
11426c92544dSBjoern A. Zeeb bf->nrow = min_t(u8, min_t(u8, snd_dim, sts), tx_ant);
11436c92544dSBjoern A. Zeeb bf->ncol = min_t(u8, nss_mcs, bf->nrow);
11446c92544dSBjoern A. Zeeb bf->ibf_ncol = bf->ncol;
11456c92544dSBjoern A. Zeeb
11466c92544dSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
11476c92544dSBjoern A. Zeeb bf->nrow = 1;
11486c92544dSBjoern A. Zeeb } else {
11496c92544dSBjoern A. Zeeb bf->nrow = tx_ant;
11506c92544dSBjoern A. Zeeb bf->ncol = min_t(u8, nss_mcs, bf->nrow);
11516c92544dSBjoern A. Zeeb bf->ibf_ncol = nss_mcs;
11526c92544dSBjoern A. Zeeb
11536c92544dSBjoern A. Zeeb if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
11546c92544dSBjoern A. Zeeb bf->ibf_nrow = 1;
11556c92544dSBjoern A. Zeeb }
11566c92544dSBjoern A. Zeeb }
11576c92544dSBjoern A. Zeeb
11586c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_bfer_he(struct ieee80211_sta * sta,struct ieee80211_vif * vif,struct mt7915_phy * phy,struct sta_rec_bf * bf)11596c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
11606c92544dSBjoern A. Zeeb struct mt7915_phy *phy, struct sta_rec_bf *bf)
11616c92544dSBjoern A. Zeeb {
11626c92544dSBjoern A. Zeeb struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;
11636c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
11646c92544dSBjoern A. Zeeb const struct ieee80211_sta_he_cap *vc =
11656c92544dSBjoern A. Zeeb mt76_connac_get_he_phy_cap(phy->mt76, vif);
11666c92544dSBjoern A. Zeeb const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;
11676c92544dSBjoern A. Zeeb u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80);
11686c92544dSBjoern A. Zeeb u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
11696c92544dSBjoern A. Zeeb u8 snd_dim, sts;
11706c92544dSBjoern A. Zeeb
11716c92544dSBjoern A. Zeeb bf->tx_mode = MT_PHY_TYPE_HE_SU;
11726c92544dSBjoern A. Zeeb
11736c92544dSBjoern A. Zeeb mt7915_mcu_sta_sounding_rate(bf);
11746c92544dSBjoern A. Zeeb
11756c92544dSBjoern A. Zeeb bf->trigger_su = HE_PHY(CAP6_TRIG_SU_BEAMFORMING_FB,
11766c92544dSBjoern A. Zeeb pe->phy_cap_info[6]);
11776c92544dSBjoern A. Zeeb bf->trigger_mu = HE_PHY(CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB,
11786c92544dSBjoern A. Zeeb pe->phy_cap_info[6]);
11796c92544dSBjoern A. Zeeb snd_dim = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
11806c92544dSBjoern A. Zeeb ve->phy_cap_info[5]);
11816c92544dSBjoern A. Zeeb sts = HE_PHY(CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK,
11826c92544dSBjoern A. Zeeb pe->phy_cap_info[4]);
11836c92544dSBjoern A. Zeeb bf->nrow = min_t(u8, snd_dim, sts);
11846c92544dSBjoern A. Zeeb bf->ncol = min_t(u8, nss_mcs, bf->nrow);
11856c92544dSBjoern A. Zeeb bf->ibf_ncol = bf->ncol;
11866c92544dSBjoern A. Zeeb
11876c92544dSBjoern A. Zeeb if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160)
11886c92544dSBjoern A. Zeeb return;
11896c92544dSBjoern A. Zeeb
11906c92544dSBjoern A. Zeeb /* go over for 160MHz and 80p80 */
11916c92544dSBjoern A. Zeeb if (pe->phy_cap_info[0] &
11926c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) {
11936c92544dSBjoern A. Zeeb mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_160);
11946c92544dSBjoern A. Zeeb nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
11956c92544dSBjoern A. Zeeb
1196cbb3ec25SBjoern A. Zeeb bf->ncol_gt_bw80 = nss_mcs;
11976c92544dSBjoern A. Zeeb }
11986c92544dSBjoern A. Zeeb
11996c92544dSBjoern A. Zeeb if (pe->phy_cap_info[0] &
12006c92544dSBjoern A. Zeeb IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
12016c92544dSBjoern A. Zeeb mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80p80);
12026c92544dSBjoern A. Zeeb nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
12036c92544dSBjoern A. Zeeb
1204cbb3ec25SBjoern A. Zeeb if (bf->ncol_gt_bw80)
1205cbb3ec25SBjoern A. Zeeb bf->ncol_gt_bw80 = min_t(u8, bf->ncol_gt_bw80, nss_mcs);
12066c92544dSBjoern A. Zeeb else
1207cbb3ec25SBjoern A. Zeeb bf->ncol_gt_bw80 = nss_mcs;
12086c92544dSBjoern A. Zeeb }
12096c92544dSBjoern A. Zeeb
12106c92544dSBjoern A. Zeeb snd_dim = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
12116c92544dSBjoern A. Zeeb ve->phy_cap_info[5]);
12126c92544dSBjoern A. Zeeb sts = HE_PHY(CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK,
12136c92544dSBjoern A. Zeeb pe->phy_cap_info[4]);
12146c92544dSBjoern A. Zeeb
1215cbb3ec25SBjoern A. Zeeb bf->nrow_gt_bw80 = min_t(int, snd_dim, sts);
12166c92544dSBjoern A. Zeeb }
12176c92544dSBjoern A. Zeeb
12186c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_bfer_tlv(struct mt7915_dev * dev,struct sk_buff * skb,struct ieee80211_vif * vif,struct ieee80211_sta * sta)12196c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
12206c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta)
12216c92544dSBjoern A. Zeeb {
12226c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
12236c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mvif->phy;
12246c92544dSBjoern A. Zeeb int tx_ant = hweight8(phy->mt76->chainmask) - 1;
12256c92544dSBjoern A. Zeeb struct sta_rec_bf *bf;
12266c92544dSBjoern A. Zeeb struct tlv *tlv;
1227*8ba4d145SBjoern A. Zeeb static const u8 matrix[4][4] = {
12286c92544dSBjoern A. Zeeb {0, 0, 0, 0},
12296c92544dSBjoern A. Zeeb {1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */
12306c92544dSBjoern A. Zeeb {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
12316c92544dSBjoern A. Zeeb {3, 5, 6, 0} /* 4x1, 4x2, 4x3, 4x4 */
12326c92544dSBjoern A. Zeeb };
12336c92544dSBjoern A. Zeeb bool ebf;
12346c92544dSBjoern A. Zeeb
12356c92544dSBjoern A. Zeeb if (!(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
12366c92544dSBjoern A. Zeeb return;
12376c92544dSBjoern A. Zeeb
12386c92544dSBjoern A. Zeeb ebf = mt7915_is_ebf_supported(phy, vif, sta, false);
12396c92544dSBjoern A. Zeeb if (!ebf && !dev->ibf)
12406c92544dSBjoern A. Zeeb return;
12416c92544dSBjoern A. Zeeb
12426c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
12436c92544dSBjoern A. Zeeb bf = (struct sta_rec_bf *)tlv;
12446c92544dSBjoern A. Zeeb
12456c92544dSBjoern A. Zeeb /* he: eBF only, in accordance with spec
12466c92544dSBjoern A. Zeeb * vht: support eBF and iBF
12476c92544dSBjoern A. Zeeb * ht: iBF only, since mac80211 lacks of eBF support
12486c92544dSBjoern A. Zeeb */
12496c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he && ebf)
12506c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_he(sta, vif, phy, bf);
12516c92544dSBjoern A. Zeeb else if (sta->deflink.vht_cap.vht_supported)
12526c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf);
12536c92544dSBjoern A. Zeeb else if (sta->deflink.ht_cap.ht_supported)
12546c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_ht(sta, phy, bf);
12556c92544dSBjoern A. Zeeb else
12566c92544dSBjoern A. Zeeb return;
12576c92544dSBjoern A. Zeeb
12586c92544dSBjoern A. Zeeb bf->bf_cap = ebf ? ebf : dev->ibf << 1;
12596c92544dSBjoern A. Zeeb bf->bw = sta->deflink.bandwidth;
12606c92544dSBjoern A. Zeeb bf->ibf_dbw = sta->deflink.bandwidth;
12616c92544dSBjoern A. Zeeb bf->ibf_nrow = tx_ant;
12626c92544dSBjoern A. Zeeb
12636c92544dSBjoern A. Zeeb if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol)
12646c92544dSBjoern A. Zeeb bf->ibf_timeout = 0x48;
12656c92544dSBjoern A. Zeeb else
12666c92544dSBjoern A. Zeeb bf->ibf_timeout = 0x18;
12676c92544dSBjoern A. Zeeb
12686c92544dSBjoern A. Zeeb if (ebf && bf->nrow != tx_ant)
12696c92544dSBjoern A. Zeeb bf->mem_20m = matrix[tx_ant][bf->ncol];
12706c92544dSBjoern A. Zeeb else
12716c92544dSBjoern A. Zeeb bf->mem_20m = matrix[bf->nrow][bf->ncol];
12726c92544dSBjoern A. Zeeb
12736c92544dSBjoern A. Zeeb switch (sta->deflink.bandwidth) {
12746c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
12756c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
12766c92544dSBjoern A. Zeeb bf->mem_total = bf->mem_20m * 2;
12776c92544dSBjoern A. Zeeb break;
12786c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
12796c92544dSBjoern A. Zeeb bf->mem_total = bf->mem_20m;
12806c92544dSBjoern A. Zeeb break;
12816c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_20:
12826c92544dSBjoern A. Zeeb default:
12836c92544dSBjoern A. Zeeb break;
12846c92544dSBjoern A. Zeeb }
12856c92544dSBjoern A. Zeeb }
12866c92544dSBjoern A. Zeeb
12876c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_bfee_tlv(struct mt7915_dev * dev,struct sk_buff * skb,struct ieee80211_vif * vif,struct ieee80211_sta * sta)12886c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
12896c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta)
12906c92544dSBjoern A. Zeeb {
12916c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
12926c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mvif->phy;
12936c92544dSBjoern A. Zeeb int tx_ant = hweight8(phy->mt76->chainmask) - 1;
12946c92544dSBjoern A. Zeeb struct sta_rec_bfee *bfee;
12956c92544dSBjoern A. Zeeb struct tlv *tlv;
12966c92544dSBjoern A. Zeeb u8 nrow = 0;
12976c92544dSBjoern A. Zeeb
12986c92544dSBjoern A. Zeeb if (!(sta->deflink.vht_cap.vht_supported || sta->deflink.he_cap.has_he))
12996c92544dSBjoern A. Zeeb return;
13006c92544dSBjoern A. Zeeb
13016c92544dSBjoern A. Zeeb if (!mt7915_is_ebf_supported(phy, vif, sta, true))
13026c92544dSBjoern A. Zeeb return;
13036c92544dSBjoern A. Zeeb
13046c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee));
13056c92544dSBjoern A. Zeeb bfee = (struct sta_rec_bfee *)tlv;
13066c92544dSBjoern A. Zeeb
13076c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he) {
13086c92544dSBjoern A. Zeeb struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
13096c92544dSBjoern A. Zeeb
13106c92544dSBjoern A. Zeeb nrow = HE_PHY(CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
13116c92544dSBjoern A. Zeeb pe->phy_cap_info[5]);
13126c92544dSBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported) {
13136c92544dSBjoern A. Zeeb struct ieee80211_sta_vht_cap *pc = &sta->deflink.vht_cap;
13146c92544dSBjoern A. Zeeb
13156c92544dSBjoern A. Zeeb nrow = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
13166c92544dSBjoern A. Zeeb pc->cap);
13176c92544dSBjoern A. Zeeb }
13186c92544dSBjoern A. Zeeb
13196c92544dSBjoern A. Zeeb /* reply with identity matrix to avoid 2x2 BF negative gain */
13206c92544dSBjoern A. Zeeb bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
13216c92544dSBjoern A. Zeeb }
13226c92544dSBjoern A. Zeeb
13236c92544dSBjoern A. Zeeb static enum mcu_mmps_mode
mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode smps)13246c92544dSBjoern A. Zeeb mt7915_mcu_get_mmps_mode(enum ieee80211_smps_mode smps)
13256c92544dSBjoern A. Zeeb {
13266c92544dSBjoern A. Zeeb switch (smps) {
13276c92544dSBjoern A. Zeeb case IEEE80211_SMPS_OFF:
13286c92544dSBjoern A. Zeeb return MCU_MMPS_DISABLE;
13296c92544dSBjoern A. Zeeb case IEEE80211_SMPS_STATIC:
13306c92544dSBjoern A. Zeeb return MCU_MMPS_STATIC;
13316c92544dSBjoern A. Zeeb case IEEE80211_SMPS_DYNAMIC:
13326c92544dSBjoern A. Zeeb return MCU_MMPS_DYNAMIC;
13336c92544dSBjoern A. Zeeb default:
13346c92544dSBjoern A. Zeeb return MCU_MMPS_DISABLE;
13356c92544dSBjoern A. Zeeb }
13366c92544dSBjoern A. Zeeb }
13376c92544dSBjoern A. Zeeb
mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta,void * data,u32 field)13386c92544dSBjoern A. Zeeb int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
13396c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
13406c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
13416c92544dSBjoern A. Zeeb void *data, u32 field)
13426c92544dSBjoern A. Zeeb {
13436c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
13446c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
13456c92544dSBjoern A. Zeeb struct sta_phy *phy = data;
13466c92544dSBjoern A. Zeeb struct sta_rec_ra_fixed *ra;
13476c92544dSBjoern A. Zeeb struct sk_buff *skb;
13486c92544dSBjoern A. Zeeb struct tlv *tlv;
13496c92544dSBjoern A. Zeeb
13506c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
13516c92544dSBjoern A. Zeeb &msta->wcid);
13526c92544dSBjoern A. Zeeb if (IS_ERR(skb))
13536c92544dSBjoern A. Zeeb return PTR_ERR(skb);
13546c92544dSBjoern A. Zeeb
13556c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
13566c92544dSBjoern A. Zeeb ra = (struct sta_rec_ra_fixed *)tlv;
13576c92544dSBjoern A. Zeeb
13586c92544dSBjoern A. Zeeb switch (field) {
13596c92544dSBjoern A. Zeeb case RATE_PARAM_AUTO:
13606c92544dSBjoern A. Zeeb break;
13616c92544dSBjoern A. Zeeb case RATE_PARAM_FIXED:
13626c92544dSBjoern A. Zeeb case RATE_PARAM_FIXED_MCS:
13636c92544dSBjoern A. Zeeb case RATE_PARAM_FIXED_GI:
13646c92544dSBjoern A. Zeeb case RATE_PARAM_FIXED_HE_LTF:
13656c92544dSBjoern A. Zeeb if (phy)
13666c92544dSBjoern A. Zeeb ra->phy = *phy;
13676c92544dSBjoern A. Zeeb break;
13686c92544dSBjoern A. Zeeb case RATE_PARAM_MMPS_UPDATE:
13696c92544dSBjoern A. Zeeb ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode);
13706c92544dSBjoern A. Zeeb break;
1371cbb3ec25SBjoern A. Zeeb case RATE_PARAM_SPE_UPDATE:
1372cbb3ec25SBjoern A. Zeeb ra->spe_idx = *(u8 *)data;
1373cbb3ec25SBjoern A. Zeeb break;
13746c92544dSBjoern A. Zeeb default:
13756c92544dSBjoern A. Zeeb break;
13766c92544dSBjoern A. Zeeb }
13776c92544dSBjoern A. Zeeb ra->field = cpu_to_le32(field);
13786c92544dSBjoern A. Zeeb
13796c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
13806c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
13816c92544dSBjoern A. Zeeb }
13826c92544dSBjoern A. Zeeb
mt7915_mcu_add_smps(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)13836c92544dSBjoern A. Zeeb int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
13846c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
13856c92544dSBjoern A. Zeeb {
13866c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
13876c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
13886c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
13896c92544dSBjoern A. Zeeb struct tlv *sta_wtbl;
13906c92544dSBjoern A. Zeeb struct sk_buff *skb;
13916c92544dSBjoern A. Zeeb int ret;
13926c92544dSBjoern A. Zeeb
13936c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
13946c92544dSBjoern A. Zeeb &msta->wcid);
13956c92544dSBjoern A. Zeeb if (IS_ERR(skb))
13966c92544dSBjoern A. Zeeb return PTR_ERR(skb);
13976c92544dSBjoern A. Zeeb
13986c92544dSBjoern A. Zeeb sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
13996c92544dSBjoern A. Zeeb sizeof(struct tlv));
14006c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
14016c92544dSBjoern A. Zeeb WTBL_SET, sta_wtbl, &skb);
14026c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
14036c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
14046c92544dSBjoern A. Zeeb
14056c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr);
14066c92544dSBjoern A. Zeeb
14076c92544dSBjoern A. Zeeb ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
14086c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
14096c92544dSBjoern A. Zeeb if (ret)
14106c92544dSBjoern A. Zeeb return ret;
14116c92544dSBjoern A. Zeeb
14126c92544dSBjoern A. Zeeb return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, NULL,
14136c92544dSBjoern A. Zeeb RATE_PARAM_MMPS_UPDATE);
14146c92544dSBjoern A. Zeeb }
14156c92544dSBjoern A. Zeeb
14166c92544dSBjoern A. Zeeb static int
mt7915_mcu_set_spe_idx(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)1417cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_spe_idx(struct mt7915_dev *dev, struct ieee80211_vif *vif,
1418cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta)
1419cbb3ec25SBjoern A. Zeeb {
1420cbb3ec25SBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1421cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = mvif->phy->mt76;
1422cbb3ec25SBjoern A. Zeeb u8 spe_idx = mt76_connac_spe_idx(mphy->antenna_mask);
1423cbb3ec25SBjoern A. Zeeb
1424cbb3ec25SBjoern A. Zeeb return mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &spe_idx,
1425cbb3ec25SBjoern A. Zeeb RATE_PARAM_SPE_UPDATE);
1426cbb3ec25SBjoern A. Zeeb }
1427cbb3ec25SBjoern A. Zeeb
1428cbb3ec25SBjoern A. Zeeb static int
mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)14296c92544dSBjoern A. Zeeb mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,
14306c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
14316c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
14326c92544dSBjoern A. Zeeb {
14336c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
14346c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
14356c92544dSBjoern A. Zeeb struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
14366c92544dSBjoern A. Zeeb enum nl80211_band band = chandef->chan->band;
14376c92544dSBjoern A. Zeeb struct sta_phy phy = {};
14386c92544dSBjoern A. Zeeb int ret, nrates = 0;
14396c92544dSBjoern A. Zeeb
14406c92544dSBjoern A. Zeeb #define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
14416c92544dSBjoern A. Zeeb do { \
14426c92544dSBjoern A. Zeeb u8 i, gi = mask->control[band]._gi; \
14436c92544dSBjoern A. Zeeb gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
14446c92544dSBjoern A. Zeeb for (i = 0; i <= sta->deflink.bandwidth; i++) { \
14456c92544dSBjoern A. Zeeb phy.sgi |= gi << (i << (_he)); \
14466c92544dSBjoern A. Zeeb phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\
14476c92544dSBjoern A. Zeeb } \
14486c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
14496c92544dSBjoern A. Zeeb if (!mask->control[band]._mcs[i]) \
14506c92544dSBjoern A. Zeeb continue; \
14516c92544dSBjoern A. Zeeb nrates += hweight16(mask->control[band]._mcs[i]); \
14526c92544dSBjoern A. Zeeb phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
14536c92544dSBjoern A. Zeeb if (_ht) \
14546c92544dSBjoern A. Zeeb phy.mcs += 8 * i; \
14556c92544dSBjoern A. Zeeb } \
14566c92544dSBjoern A. Zeeb } while (0)
14576c92544dSBjoern A. Zeeb
14586c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he) {
14596c92544dSBjoern A. Zeeb __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
14606c92544dSBjoern A. Zeeb } else if (sta->deflink.vht_cap.vht_supported) {
14616c92544dSBjoern A. Zeeb __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
14626c92544dSBjoern A. Zeeb } else if (sta->deflink.ht_cap.ht_supported) {
14636c92544dSBjoern A. Zeeb __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
14646c92544dSBjoern A. Zeeb } else {
14656c92544dSBjoern A. Zeeb nrates = hweight32(mask->control[band].legacy);
14666c92544dSBjoern A. Zeeb phy.mcs = ffs(mask->control[band].legacy) - 1;
14676c92544dSBjoern A. Zeeb }
14686c92544dSBjoern A. Zeeb #undef __sta_phy_bitrate_mask_check
14696c92544dSBjoern A. Zeeb
14706c92544dSBjoern A. Zeeb /* fall back to auto rate control */
14716c92544dSBjoern A. Zeeb if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
14726c92544dSBjoern A. Zeeb mask->control[band].he_gi == GENMASK(7, 0) &&
14736c92544dSBjoern A. Zeeb mask->control[band].he_ltf == GENMASK(7, 0) &&
14746c92544dSBjoern A. Zeeb nrates != 1)
14756c92544dSBjoern A. Zeeb return 0;
14766c92544dSBjoern A. Zeeb
14776c92544dSBjoern A. Zeeb /* fixed single rate */
14786c92544dSBjoern A. Zeeb if (nrates == 1) {
14796c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
14806c92544dSBjoern A. Zeeb RATE_PARAM_FIXED_MCS);
14816c92544dSBjoern A. Zeeb if (ret)
14826c92544dSBjoern A. Zeeb return ret;
14836c92544dSBjoern A. Zeeb }
14846c92544dSBjoern A. Zeeb
14856c92544dSBjoern A. Zeeb /* fixed GI */
14866c92544dSBjoern A. Zeeb if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
14876c92544dSBjoern A. Zeeb mask->control[band].he_gi != GENMASK(7, 0)) {
14886c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
14896c92544dSBjoern A. Zeeb u32 addr;
14906c92544dSBjoern A. Zeeb
14916c92544dSBjoern A. Zeeb /* firmware updates only TXCMD but doesn't take WTBL into
14926c92544dSBjoern A. Zeeb * account, so driver should update here to reflect the
14936c92544dSBjoern A. Zeeb * actual txrate hardware sends out.
14946c92544dSBjoern A. Zeeb */
14956c92544dSBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
14966c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he)
14976c92544dSBjoern A. Zeeb mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
14986c92544dSBjoern A. Zeeb else
14996c92544dSBjoern A. Zeeb mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
15006c92544dSBjoern A. Zeeb
15016c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
15026c92544dSBjoern A. Zeeb RATE_PARAM_FIXED_GI);
15036c92544dSBjoern A. Zeeb if (ret)
15046c92544dSBjoern A. Zeeb return ret;
15056c92544dSBjoern A. Zeeb }
15066c92544dSBjoern A. Zeeb
15076c92544dSBjoern A. Zeeb /* fixed HE_LTF */
15086c92544dSBjoern A. Zeeb if (mask->control[band].he_ltf != GENMASK(7, 0)) {
15096c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
15106c92544dSBjoern A. Zeeb RATE_PARAM_FIXED_HE_LTF);
15116c92544dSBjoern A. Zeeb if (ret)
15126c92544dSBjoern A. Zeeb return ret;
15136c92544dSBjoern A. Zeeb }
15146c92544dSBjoern A. Zeeb
1515cbb3ec25SBjoern A. Zeeb return mt7915_mcu_set_spe_idx(dev, vif, sta);
15166c92544dSBjoern A. Zeeb }
15176c92544dSBjoern A. Zeeb
15186c92544dSBjoern A. Zeeb static void
mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff * skb,struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)15196c92544dSBjoern A. Zeeb mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
15206c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta)
15216c92544dSBjoern A. Zeeb {
15226c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
15236c92544dSBjoern A. Zeeb struct mt76_phy *mphy = mvif->phy->mt76;
15246c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &mphy->chandef;
15256c92544dSBjoern A. Zeeb struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
15266c92544dSBjoern A. Zeeb enum nl80211_band band = chandef->chan->band;
15276c92544dSBjoern A. Zeeb struct sta_rec_ra *ra;
15286c92544dSBjoern A. Zeeb struct tlv *tlv;
15296c92544dSBjoern A. Zeeb u32 supp_rate = sta->deflink.supp_rates[band];
15306c92544dSBjoern A. Zeeb u32 cap = sta->wme ? STA_CAP_WMM : 0;
15316c92544dSBjoern A. Zeeb
15326c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
15336c92544dSBjoern A. Zeeb ra = (struct sta_rec_ra *)tlv;
15346c92544dSBjoern A. Zeeb
15356c92544dSBjoern A. Zeeb ra->valid = true;
15366c92544dSBjoern A. Zeeb ra->auto_rate = true;
1537*8ba4d145SBjoern A. Zeeb ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, &sta->deflink);
15386c92544dSBjoern A. Zeeb ra->channel = chandef->chan->hw_value;
15396c92544dSBjoern A. Zeeb ra->bw = sta->deflink.bandwidth;
15406c92544dSBjoern A. Zeeb ra->phy.bw = sta->deflink.bandwidth;
15416c92544dSBjoern A. Zeeb ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->deflink.smps_mode);
15426c92544dSBjoern A. Zeeb
15436c92544dSBjoern A. Zeeb if (supp_rate) {
15446c92544dSBjoern A. Zeeb supp_rate &= mask->control[band].legacy;
15456c92544dSBjoern A. Zeeb ra->rate_len = hweight32(supp_rate);
15466c92544dSBjoern A. Zeeb
15476c92544dSBjoern A. Zeeb if (band == NL80211_BAND_2GHZ) {
15486c92544dSBjoern A. Zeeb ra->supp_mode = MODE_CCK;
15496c92544dSBjoern A. Zeeb ra->supp_cck_rate = supp_rate & GENMASK(3, 0);
15506c92544dSBjoern A. Zeeb
15516c92544dSBjoern A. Zeeb if (ra->rate_len > 4) {
15526c92544dSBjoern A. Zeeb ra->supp_mode |= MODE_OFDM;
15536c92544dSBjoern A. Zeeb ra->supp_ofdm_rate = supp_rate >> 4;
15546c92544dSBjoern A. Zeeb }
15556c92544dSBjoern A. Zeeb } else {
15566c92544dSBjoern A. Zeeb ra->supp_mode = MODE_OFDM;
15576c92544dSBjoern A. Zeeb ra->supp_ofdm_rate = supp_rate;
15586c92544dSBjoern A. Zeeb }
15596c92544dSBjoern A. Zeeb }
15606c92544dSBjoern A. Zeeb
15616c92544dSBjoern A. Zeeb if (sta->deflink.ht_cap.ht_supported) {
15626c92544dSBjoern A. Zeeb ra->supp_mode |= MODE_HT;
15636c92544dSBjoern A. Zeeb ra->af = sta->deflink.ht_cap.ampdu_factor;
15646c92544dSBjoern A. Zeeb ra->ht_gf = !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
15656c92544dSBjoern A. Zeeb
15666c92544dSBjoern A. Zeeb cap |= STA_CAP_HT;
15676c92544dSBjoern A. Zeeb if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
15686c92544dSBjoern A. Zeeb cap |= STA_CAP_SGI_20;
15696c92544dSBjoern A. Zeeb if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
15706c92544dSBjoern A. Zeeb cap |= STA_CAP_SGI_40;
15716c92544dSBjoern A. Zeeb if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)
15726c92544dSBjoern A. Zeeb cap |= STA_CAP_TX_STBC;
15736c92544dSBjoern A. Zeeb if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
15746c92544dSBjoern A. Zeeb cap |= STA_CAP_RX_STBC;
15756c92544dSBjoern A. Zeeb if (mvif->cap.ht_ldpc &&
15766c92544dSBjoern A. Zeeb (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
15776c92544dSBjoern A. Zeeb cap |= STA_CAP_LDPC;
15786c92544dSBjoern A. Zeeb
15796c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,
15806c92544dSBjoern A. Zeeb mask->control[band].ht_mcs);
15816c92544dSBjoern A. Zeeb ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
15826c92544dSBjoern A. Zeeb }
15836c92544dSBjoern A. Zeeb
15846c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported) {
15856c92544dSBjoern A. Zeeb u8 af;
15866c92544dSBjoern A. Zeeb
15876c92544dSBjoern A. Zeeb ra->supp_mode |= MODE_VHT;
15886c92544dSBjoern A. Zeeb af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
15896c92544dSBjoern A. Zeeb sta->deflink.vht_cap.cap);
15906c92544dSBjoern A. Zeeb ra->af = max_t(u8, ra->af, af);
15916c92544dSBjoern A. Zeeb
15926c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT;
15936c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
15946c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT_SGI_80;
15956c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)
15966c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT_SGI_160;
15976c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
15986c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT_TX_STBC;
15996c92544dSBjoern A. Zeeb if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
16006c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT_RX_STBC;
16016c92544dSBjoern A. Zeeb if (mvif->cap.vht_ldpc &&
16026c92544dSBjoern A. Zeeb (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
16036c92544dSBjoern A. Zeeb cap |= STA_CAP_VHT_LDPC;
16046c92544dSBjoern A. Zeeb
16056c92544dSBjoern A. Zeeb mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,
16066c92544dSBjoern A. Zeeb mask->control[band].vht_mcs);
16076c92544dSBjoern A. Zeeb }
16086c92544dSBjoern A. Zeeb
16096c92544dSBjoern A. Zeeb if (sta->deflink.he_cap.has_he) {
16106c92544dSBjoern A. Zeeb ra->supp_mode |= MODE_HE;
16116c92544dSBjoern A. Zeeb cap |= STA_CAP_HE;
16126c92544dSBjoern A. Zeeb
16136c92544dSBjoern A. Zeeb if (sta->deflink.he_6ghz_capa.capa)
16146c92544dSBjoern A. Zeeb ra->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
16156c92544dSBjoern A. Zeeb IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
16166c92544dSBjoern A. Zeeb }
16176c92544dSBjoern A. Zeeb
16186c92544dSBjoern A. Zeeb ra->sta_cap = cpu_to_le32(cap);
16196c92544dSBjoern A. Zeeb }
16206c92544dSBjoern A. Zeeb
mt7915_mcu_add_rate_ctrl(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool changed)16216c92544dSBjoern A. Zeeb int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
16226c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool changed)
16236c92544dSBjoern A. Zeeb {
16246c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
16256c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
16266c92544dSBjoern A. Zeeb struct sk_buff *skb;
16276c92544dSBjoern A. Zeeb int ret;
16286c92544dSBjoern A. Zeeb
16296c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
16306c92544dSBjoern A. Zeeb &msta->wcid);
16316c92544dSBjoern A. Zeeb if (IS_ERR(skb))
16326c92544dSBjoern A. Zeeb return PTR_ERR(skb);
16336c92544dSBjoern A. Zeeb
16346c92544dSBjoern A. Zeeb /* firmware rc algorithm refers to sta_rec_he for HE control.
16356c92544dSBjoern A. Zeeb * once dev->rc_work changes the settings driver should also
16366c92544dSBjoern A. Zeeb * update sta_rec_he here.
16376c92544dSBjoern A. Zeeb */
16386c92544dSBjoern A. Zeeb if (changed)
16396c92544dSBjoern A. Zeeb mt7915_mcu_sta_he_tlv(skb, sta, vif);
16406c92544dSBjoern A. Zeeb
16416c92544dSBjoern A. Zeeb /* sta_rec_ra accommodates BW, NSS and only MCS range format
16426c92544dSBjoern A. Zeeb * i.e 0-{7,8,9} for VHT.
16436c92544dSBjoern A. Zeeb */
16446c92544dSBjoern A. Zeeb mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
16456c92544dSBjoern A. Zeeb
16466c92544dSBjoern A. Zeeb ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
16476c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
16486c92544dSBjoern A. Zeeb if (ret)
16496c92544dSBjoern A. Zeeb return ret;
16506c92544dSBjoern A. Zeeb
16516c92544dSBjoern A. Zeeb /* sta_rec_ra_fixed accommodates single rate, (HE)GI and HE_LTE,
16526c92544dSBjoern A. Zeeb * and updates as peer fixed rate parameters, which overrides
16536c92544dSBjoern A. Zeeb * sta_rec_ra and firmware rate control algorithm.
16546c92544dSBjoern A. Zeeb */
16556c92544dSBjoern A. Zeeb return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta);
16566c92544dSBjoern A. Zeeb }
16576c92544dSBjoern A. Zeeb
16586c92544dSBjoern A. Zeeb static int
mt7915_mcu_add_group(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)16596c92544dSBjoern A. Zeeb mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,
16606c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
16616c92544dSBjoern A. Zeeb {
16626c92544dSBjoern A. Zeeb #define MT_STA_BSS_GROUP 1
16636c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
16646c92544dSBjoern A. Zeeb struct mt7915_sta *msta;
16656c92544dSBjoern A. Zeeb struct {
16666c92544dSBjoern A. Zeeb __le32 action;
16676c92544dSBjoern A. Zeeb u8 wlan_idx_lo;
16686c92544dSBjoern A. Zeeb u8 status;
16696c92544dSBjoern A. Zeeb u8 wlan_idx_hi;
16706c92544dSBjoern A. Zeeb u8 rsv0[5];
16716c92544dSBjoern A. Zeeb __le32 val;
16726c92544dSBjoern A. Zeeb u8 rsv1[8];
16736c92544dSBjoern A. Zeeb } __packed req = {
16746c92544dSBjoern A. Zeeb .action = cpu_to_le32(MT_STA_BSS_GROUP),
16756c92544dSBjoern A. Zeeb .val = cpu_to_le32(mvif->mt76.idx % 16),
16766c92544dSBjoern A. Zeeb };
16776c92544dSBjoern A. Zeeb
16786c92544dSBjoern A. Zeeb msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;
16796c92544dSBjoern A. Zeeb req.wlan_idx_lo = to_wcid_lo(msta->wcid.idx);
16806c92544dSBjoern A. Zeeb req.wlan_idx_hi = to_wcid_hi(msta->wcid.idx);
16816c92544dSBjoern A. Zeeb
16826c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_DRR_CTRL), &req,
16836c92544dSBjoern A. Zeeb sizeof(req), true);
16846c92544dSBjoern A. Zeeb }
16856c92544dSBjoern A. Zeeb
mt7915_mcu_add_sta(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta,int conn_state,bool newly)16866c92544dSBjoern A. Zeeb int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
1687*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta, int conn_state, bool newly)
16886c92544dSBjoern A. Zeeb {
16896c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1690*8ba4d145SBjoern A. Zeeb struct ieee80211_link_sta *link_sta;
16916c92544dSBjoern A. Zeeb struct mt7915_sta *msta;
16926c92544dSBjoern A. Zeeb struct sk_buff *skb;
16936c92544dSBjoern A. Zeeb int ret;
16946c92544dSBjoern A. Zeeb
16956c92544dSBjoern A. Zeeb msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta;
1696*8ba4d145SBjoern A. Zeeb link_sta = sta ? &sta->deflink : NULL;
16976c92544dSBjoern A. Zeeb
16986c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
16996c92544dSBjoern A. Zeeb &msta->wcid);
17006c92544dSBjoern A. Zeeb if (IS_ERR(skb))
17016c92544dSBjoern A. Zeeb return PTR_ERR(skb);
17026c92544dSBjoern A. Zeeb
17036c92544dSBjoern A. Zeeb /* starec basic */
1704*8ba4d145SBjoern A. Zeeb mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, &vif->bss_conf, link_sta,
1705*8ba4d145SBjoern A. Zeeb conn_state, newly);
17066c92544dSBjoern A. Zeeb /* tag order is in accordance with firmware dependency. */
1707*8ba4d145SBjoern A. Zeeb if (sta && conn_state != CONN_STATE_DISCONNECT) {
17086c92544dSBjoern A. Zeeb /* starec bfer */
17096c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta);
17106c92544dSBjoern A. Zeeb /* starec ht */
17116c92544dSBjoern A. Zeeb mt7915_mcu_sta_ht_tlv(skb, sta);
17126c92544dSBjoern A. Zeeb /* starec vht */
17136c92544dSBjoern A. Zeeb mt7915_mcu_sta_vht_tlv(skb, sta);
17146c92544dSBjoern A. Zeeb /* starec uapsd */
17156c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_uapsd(skb, vif, sta);
17166c92544dSBjoern A. Zeeb }
17176c92544dSBjoern A. Zeeb
1718*8ba4d145SBjoern A. Zeeb if (newly || conn_state != CONN_STATE_DISCONNECT) {
17196c92544dSBjoern A. Zeeb ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta);
17206c92544dSBjoern A. Zeeb if (ret) {
17216c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
17226c92544dSBjoern A. Zeeb return ret;
17236c92544dSBjoern A. Zeeb }
1724*8ba4d145SBjoern A. Zeeb }
1725*8ba4d145SBjoern A. Zeeb
1726*8ba4d145SBjoern A. Zeeb if (conn_state == CONN_STATE_DISCONNECT)
1727*8ba4d145SBjoern A. Zeeb goto out;
17286c92544dSBjoern A. Zeeb
17296c92544dSBjoern A. Zeeb if (sta) {
17306c92544dSBjoern A. Zeeb /* starec amsdu */
17316c92544dSBjoern A. Zeeb mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
17326c92544dSBjoern A. Zeeb /* starec he */
17336c92544dSBjoern A. Zeeb mt7915_mcu_sta_he_tlv(skb, sta, vif);
17346c92544dSBjoern A. Zeeb /* starec muru */
17356c92544dSBjoern A. Zeeb mt7915_mcu_sta_muru_tlv(dev, skb, sta, vif);
17366c92544dSBjoern A. Zeeb /* starec bfee */
17376c92544dSBjoern A. Zeeb mt7915_mcu_sta_bfee_tlv(dev, skb, vif, sta);
17386c92544dSBjoern A. Zeeb }
17396c92544dSBjoern A. Zeeb
17406c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_group(dev, vif, sta);
17416c92544dSBjoern A. Zeeb if (ret) {
17426c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
17436c92544dSBjoern A. Zeeb return ret;
17446c92544dSBjoern A. Zeeb }
17456c92544dSBjoern A. Zeeb out:
1746cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_sta_wed_update(&dev->mt76, skb);
1747cbb3ec25SBjoern A. Zeeb if (ret)
1748cbb3ec25SBjoern A. Zeeb return ret;
1749cbb3ec25SBjoern A. Zeeb
17506c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
17516c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
17526c92544dSBjoern A. Zeeb }
17536c92544dSBjoern A. Zeeb
mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev * dev)1754cbb3ec25SBjoern A. Zeeb int mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev *dev)
1755cbb3ec25SBjoern A. Zeeb {
1756cbb3ec25SBjoern A. Zeeb #ifdef CONFIG_NET_MEDIATEK_SOC_WED
1757cbb3ec25SBjoern A. Zeeb struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
1758cbb3ec25SBjoern A. Zeeb struct {
1759cbb3ec25SBjoern A. Zeeb __le32 args[2];
1760cbb3ec25SBjoern A. Zeeb } req = {
1761cbb3ec25SBjoern A. Zeeb .args[0] = cpu_to_le32(1),
1762cbb3ec25SBjoern A. Zeeb .args[1] = cpu_to_le32(6),
1763cbb3ec25SBjoern A. Zeeb };
1764cbb3ec25SBjoern A. Zeeb
1765cbb3ec25SBjoern A. Zeeb return mtk_wed_device_update_msg(wed, MTK_WED_WO_CMD_RXCNT_CTRL,
1766cbb3ec25SBjoern A. Zeeb &req, sizeof(req));
1767cbb3ec25SBjoern A. Zeeb #else
1768cbb3ec25SBjoern A. Zeeb return 0;
1769cbb3ec25SBjoern A. Zeeb #endif
1770cbb3ec25SBjoern A. Zeeb }
1771cbb3ec25SBjoern A. Zeeb
mt7915_mcu_add_dev_info(struct mt7915_phy * phy,struct ieee80211_vif * vif,bool enable)17726c92544dSBjoern A. Zeeb int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,
17736c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, bool enable)
17746c92544dSBjoern A. Zeeb {
17756c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
17766c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
17776c92544dSBjoern A. Zeeb struct {
17786c92544dSBjoern A. Zeeb struct req_hdr {
17796c92544dSBjoern A. Zeeb u8 omac_idx;
1780cbb3ec25SBjoern A. Zeeb u8 band_idx;
17816c92544dSBjoern A. Zeeb __le16 tlv_num;
17826c92544dSBjoern A. Zeeb u8 is_tlv_append;
17836c92544dSBjoern A. Zeeb u8 rsv[3];
17846c92544dSBjoern A. Zeeb } __packed hdr;
17856c92544dSBjoern A. Zeeb struct req_tlv {
17866c92544dSBjoern A. Zeeb __le16 tag;
17876c92544dSBjoern A. Zeeb __le16 len;
17886c92544dSBjoern A. Zeeb u8 active;
1789cbb3ec25SBjoern A. Zeeb u8 band_idx;
17906c92544dSBjoern A. Zeeb u8 omac_addr[ETH_ALEN];
17916c92544dSBjoern A. Zeeb } __packed tlv;
17926c92544dSBjoern A. Zeeb } data = {
17936c92544dSBjoern A. Zeeb .hdr = {
17946c92544dSBjoern A. Zeeb .omac_idx = mvif->mt76.omac_idx,
1795cbb3ec25SBjoern A. Zeeb .band_idx = mvif->mt76.band_idx,
17966c92544dSBjoern A. Zeeb .tlv_num = cpu_to_le16(1),
17976c92544dSBjoern A. Zeeb .is_tlv_append = 1,
17986c92544dSBjoern A. Zeeb },
17996c92544dSBjoern A. Zeeb .tlv = {
18006c92544dSBjoern A. Zeeb .tag = cpu_to_le16(DEV_INFO_ACTIVE),
18016c92544dSBjoern A. Zeeb .len = cpu_to_le16(sizeof(struct req_tlv)),
18026c92544dSBjoern A. Zeeb .active = enable,
1803cbb3ec25SBjoern A. Zeeb .band_idx = mvif->mt76.band_idx,
18046c92544dSBjoern A. Zeeb },
18056c92544dSBjoern A. Zeeb };
18066c92544dSBjoern A. Zeeb
18076c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)
18086c92544dSBjoern A. Zeeb return mt7915_mcu_muar_config(phy, vif, false, enable);
18096c92544dSBjoern A. Zeeb
18106c92544dSBjoern A. Zeeb memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN);
18116c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DEV_INFO_UPDATE),
18126c92544dSBjoern A. Zeeb &data, sizeof(data), true);
18136c92544dSBjoern A. Zeeb }
18146c92544dSBjoern A. Zeeb
18156c92544dSBjoern A. Zeeb static void
mt7915_mcu_beacon_cntdwn(struct ieee80211_vif * vif,struct sk_buff * rskb,struct sk_buff * skb,struct bss_info_bcn * bcn,struct ieee80211_mutable_offsets * offs)18166c92544dSBjoern A. Zeeb mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
18176c92544dSBjoern A. Zeeb struct sk_buff *skb, struct bss_info_bcn *bcn,
18186c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets *offs)
18196c92544dSBjoern A. Zeeb {
18206c92544dSBjoern A. Zeeb struct bss_info_bcn_cntdwn *info;
18216c92544dSBjoern A. Zeeb struct tlv *tlv;
18226c92544dSBjoern A. Zeeb int sub_tag;
18236c92544dSBjoern A. Zeeb
18246c92544dSBjoern A. Zeeb if (!offs->cntdwn_counter_offs[0])
18256c92544dSBjoern A. Zeeb return;
18266c92544dSBjoern A. Zeeb
18276c92544dSBjoern A. Zeeb sub_tag = vif->bss_conf.csa_active ? BSS_INFO_BCN_CSA : BSS_INFO_BCN_BCC;
18286c92544dSBjoern A. Zeeb tlv = mt7915_mcu_add_nested_subtlv(rskb, sub_tag, sizeof(*info),
18296c92544dSBjoern A. Zeeb &bcn->sub_ntlv, &bcn->len);
18306c92544dSBjoern A. Zeeb info = (struct bss_info_bcn_cntdwn *)tlv;
18316c92544dSBjoern A. Zeeb info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
18326c92544dSBjoern A. Zeeb }
18336c92544dSBjoern A. Zeeb
18346c92544dSBjoern A. Zeeb static void
mt7915_mcu_beacon_mbss(struct sk_buff * rskb,struct sk_buff * skb,struct ieee80211_vif * vif,struct bss_info_bcn * bcn,struct ieee80211_mutable_offsets * offs)18356c92544dSBjoern A. Zeeb mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
18366c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct bss_info_bcn *bcn,
18376c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets *offs)
18386c92544dSBjoern A. Zeeb {
18396c92544dSBjoern A. Zeeb struct bss_info_bcn_mbss *mbss;
18406c92544dSBjoern A. Zeeb const struct element *elem;
18416c92544dSBjoern A. Zeeb struct tlv *tlv;
18426c92544dSBjoern A. Zeeb
18436c92544dSBjoern A. Zeeb if (!vif->bss_conf.bssid_indicator)
18446c92544dSBjoern A. Zeeb return;
18456c92544dSBjoern A. Zeeb
18466c92544dSBjoern A. Zeeb tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID,
18476c92544dSBjoern A. Zeeb sizeof(*mbss), &bcn->sub_ntlv,
18486c92544dSBjoern A. Zeeb &bcn->len);
18496c92544dSBjoern A. Zeeb
18506c92544dSBjoern A. Zeeb mbss = (struct bss_info_bcn_mbss *)tlv;
18516c92544dSBjoern A. Zeeb mbss->offset[0] = cpu_to_le16(offs->tim_offset);
18526c92544dSBjoern A. Zeeb mbss->bitmap = cpu_to_le32(1);
18536c92544dSBjoern A. Zeeb
18546c92544dSBjoern A. Zeeb for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
18556c92544dSBjoern A. Zeeb &skb->data[offs->mbssid_off],
18566c92544dSBjoern A. Zeeb skb->len - offs->mbssid_off) {
18576c92544dSBjoern A. Zeeb const struct element *sub_elem;
18586c92544dSBjoern A. Zeeb
18596c92544dSBjoern A. Zeeb if (elem->datalen < 2)
18606c92544dSBjoern A. Zeeb continue;
18616c92544dSBjoern A. Zeeb
18626c92544dSBjoern A. Zeeb for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
18636c92544dSBjoern A. Zeeb const struct ieee80211_bssid_index *idx;
18646c92544dSBjoern A. Zeeb const u8 *idx_ie;
18656c92544dSBjoern A. Zeeb
18666c92544dSBjoern A. Zeeb if (sub_elem->id || sub_elem->datalen < 4)
18676c92544dSBjoern A. Zeeb continue; /* not a valid BSS profile */
18686c92544dSBjoern A. Zeeb
18696c92544dSBjoern A. Zeeb /* Find WLAN_EID_MULTI_BSSID_IDX
18706c92544dSBjoern A. Zeeb * in the merged nontransmitted profile
18716c92544dSBjoern A. Zeeb */
18726c92544dSBjoern A. Zeeb idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
18736c92544dSBjoern A. Zeeb sub_elem->data,
18746c92544dSBjoern A. Zeeb sub_elem->datalen);
18756c92544dSBjoern A. Zeeb if (!idx_ie || idx_ie[1] < sizeof(*idx))
18766c92544dSBjoern A. Zeeb continue;
18776c92544dSBjoern A. Zeeb
18786c92544dSBjoern A. Zeeb #if defined(__linux__)
18796c92544dSBjoern A. Zeeb idx = (void *)(idx_ie + 2);
18806c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__)
18816c92544dSBjoern A. Zeeb idx = (const void *)(idx_ie + 2);
18826c92544dSBjoern A. Zeeb #endif
18836c92544dSBjoern A. Zeeb if (!idx->bssid_index || idx->bssid_index > 31)
18846c92544dSBjoern A. Zeeb continue;
18856c92544dSBjoern A. Zeeb
18866c92544dSBjoern A. Zeeb mbss->offset[idx->bssid_index] =
18876c92544dSBjoern A. Zeeb cpu_to_le16(idx_ie - skb->data);
18886c92544dSBjoern A. Zeeb mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
18896c92544dSBjoern A. Zeeb }
18906c92544dSBjoern A. Zeeb }
18916c92544dSBjoern A. Zeeb }
18926c92544dSBjoern A. Zeeb
18936c92544dSBjoern A. Zeeb static void
mt7915_mcu_beacon_cont(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct sk_buff * rskb,struct sk_buff * skb,struct bss_info_bcn * bcn,struct ieee80211_mutable_offsets * offs)18946c92544dSBjoern A. Zeeb mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
18956c92544dSBjoern A. Zeeb struct sk_buff *rskb, struct sk_buff *skb,
18966c92544dSBjoern A. Zeeb struct bss_info_bcn *bcn,
18976c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets *offs)
18986c92544dSBjoern A. Zeeb {
18996c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid;
19006c92544dSBjoern A. Zeeb struct bss_info_bcn_cont *cont;
19016c92544dSBjoern A. Zeeb struct tlv *tlv;
19026c92544dSBjoern A. Zeeb u8 *buf;
19036c92544dSBjoern A. Zeeb int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;
19046c92544dSBjoern A. Zeeb
19056c92544dSBjoern A. Zeeb len = (len & 0x3) ? ((len | 0x3) + 1) : len;
19066c92544dSBjoern A. Zeeb tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,
19076c92544dSBjoern A. Zeeb len, &bcn->sub_ntlv, &bcn->len);
19086c92544dSBjoern A. Zeeb
19096c92544dSBjoern A. Zeeb cont = (struct bss_info_bcn_cont *)tlv;
19106c92544dSBjoern A. Zeeb cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
19116c92544dSBjoern A. Zeeb cont->tim_ofs = cpu_to_le16(offs->tim_offset);
19126c92544dSBjoern A. Zeeb
19136c92544dSBjoern A. Zeeb if (offs->cntdwn_counter_offs[0]) {
19146c92544dSBjoern A. Zeeb u16 offset = offs->cntdwn_counter_offs[0];
19156c92544dSBjoern A. Zeeb
19166c92544dSBjoern A. Zeeb if (vif->bss_conf.csa_active)
19176c92544dSBjoern A. Zeeb cont->csa_ofs = cpu_to_le16(offset - 4);
19186c92544dSBjoern A. Zeeb if (vif->bss_conf.color_change_active)
19196c92544dSBjoern A. Zeeb cont->bcc_ofs = cpu_to_le16(offset - 3);
19206c92544dSBjoern A. Zeeb }
19216c92544dSBjoern A. Zeeb
19226c92544dSBjoern A. Zeeb buf = (u8 *)tlv + sizeof(*cont);
19236c92544dSBjoern A. Zeeb mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
19246c92544dSBjoern A. Zeeb 0, BSS_CHANGED_BEACON);
19256c92544dSBjoern A. Zeeb memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
19266c92544dSBjoern A. Zeeb }
19276c92544dSBjoern A. Zeeb
1928*8ba4d145SBjoern A. Zeeb int
mt7915_mcu_add_inband_discov(struct mt7915_dev * dev,struct ieee80211_vif * vif,u32 changed)1929*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
19306c92544dSBjoern A. Zeeb u32 changed)
19316c92544dSBjoern A. Zeeb {
19326c92544dSBjoern A. Zeeb #define OFFLOAD_TX_MODE_SU BIT(0)
19336c92544dSBjoern A. Zeeb #define OFFLOAD_TX_MODE_MU BIT(1)
19346c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mt76_hw(dev);
19356c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
19366c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
19376c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
19386c92544dSBjoern A. Zeeb enum nl80211_band band = chandef->chan->band;
19396c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid;
1940*8ba4d145SBjoern A. Zeeb struct bss_info_bcn *bcn;
19416c92544dSBjoern A. Zeeb struct bss_info_inband_discovery *discov;
19426c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info;
1943*8ba4d145SBjoern A. Zeeb struct sk_buff *rskb, *skb = NULL;
1944*8ba4d145SBjoern A. Zeeb struct tlv *tlv, *sub_tlv;
19456c92544dSBjoern A. Zeeb bool ext_phy = phy != &dev->phy;
19466c92544dSBjoern A. Zeeb u8 *buf, interval;
19476c92544dSBjoern A. Zeeb int len;
19486c92544dSBjoern A. Zeeb
1949*8ba4d145SBjoern A. Zeeb if (vif->bss_conf.nontransmitted)
1950*8ba4d145SBjoern A. Zeeb return 0;
1951*8ba4d145SBjoern A. Zeeb
1952*8ba4d145SBjoern A. Zeeb rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,
1953*8ba4d145SBjoern A. Zeeb MT7915_MAX_BSS_OFFLOAD_SIZE);
1954*8ba4d145SBjoern A. Zeeb if (IS_ERR(rskb))
1955*8ba4d145SBjoern A. Zeeb return PTR_ERR(rskb);
1956*8ba4d145SBjoern A. Zeeb
1957*8ba4d145SBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
1958*8ba4d145SBjoern A. Zeeb bcn = (struct bss_info_bcn *)tlv;
1959*8ba4d145SBjoern A. Zeeb bcn->enable = true;
1960*8ba4d145SBjoern A. Zeeb
1961*8ba4d145SBjoern A. Zeeb if (changed & BSS_CHANGED_FILS_DISCOVERY) {
19626c92544dSBjoern A. Zeeb interval = vif->bss_conf.fils_discovery.max_interval;
19636c92544dSBjoern A. Zeeb skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
19646c92544dSBjoern A. Zeeb } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
19656c92544dSBjoern A. Zeeb vif->bss_conf.unsol_bcast_probe_resp_interval) {
19666c92544dSBjoern A. Zeeb interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
19676c92544dSBjoern A. Zeeb skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
19686c92544dSBjoern A. Zeeb }
19696c92544dSBjoern A. Zeeb
1970*8ba4d145SBjoern A. Zeeb if (!skb) {
1971*8ba4d145SBjoern A. Zeeb dev_kfree_skb(rskb);
1972*8ba4d145SBjoern A. Zeeb return -EINVAL;
1973*8ba4d145SBjoern A. Zeeb }
19746c92544dSBjoern A. Zeeb
19756c92544dSBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
19766c92544dSBjoern A. Zeeb info->control.vif = vif;
19776c92544dSBjoern A. Zeeb info->band = band;
19786c92544dSBjoern A. Zeeb info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
19796c92544dSBjoern A. Zeeb
19806c92544dSBjoern A. Zeeb len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
19816c92544dSBjoern A. Zeeb len = (len & 0x3) ? ((len | 0x3) + 1) : len;
19826c92544dSBjoern A. Zeeb
1983*8ba4d145SBjoern A. Zeeb if (skb->len > MT7915_MAX_BEACON_SIZE) {
19846c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
1985*8ba4d145SBjoern A. Zeeb dev_kfree_skb(rskb);
19866c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
1987*8ba4d145SBjoern A. Zeeb return -EINVAL;
19886c92544dSBjoern A. Zeeb }
19896c92544dSBjoern A. Zeeb
1990*8ba4d145SBjoern A. Zeeb sub_tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
19916c92544dSBjoern A. Zeeb len, &bcn->sub_ntlv, &bcn->len);
1992*8ba4d145SBjoern A. Zeeb discov = (struct bss_info_inband_discovery *)sub_tlv;
19936c92544dSBjoern A. Zeeb discov->tx_mode = OFFLOAD_TX_MODE_SU;
19946c92544dSBjoern A. Zeeb /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
19956c92544dSBjoern A. Zeeb discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
19966c92544dSBjoern A. Zeeb discov->tx_interval = interval;
19976c92544dSBjoern A. Zeeb discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
1998*8ba4d145SBjoern A. Zeeb discov->enable = !!interval;
19996c92544dSBjoern A. Zeeb
2000*8ba4d145SBjoern A. Zeeb buf = (u8 *)sub_tlv + sizeof(*discov);
20016c92544dSBjoern A. Zeeb
20026c92544dSBjoern A. Zeeb mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
20036c92544dSBjoern A. Zeeb 0, changed);
20046c92544dSBjoern A. Zeeb memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
20056c92544dSBjoern A. Zeeb
20066c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
2007*8ba4d145SBjoern A. Zeeb
2008*8ba4d145SBjoern A. Zeeb return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
2009*8ba4d145SBjoern A. Zeeb MCU_EXT_CMD(BSS_INFO_UPDATE), true);
20106c92544dSBjoern A. Zeeb }
20116c92544dSBjoern A. Zeeb
mt7915_mcu_add_beacon(struct ieee80211_hw * hw,struct ieee80211_vif * vif,int en,u32 changed)20126c92544dSBjoern A. Zeeb int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
20136c92544dSBjoern A. Zeeb int en, u32 changed)
20146c92544dSBjoern A. Zeeb {
20156c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
20166c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
20176c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
20186c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets offs;
20196c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info;
20206c92544dSBjoern A. Zeeb struct sk_buff *skb, *rskb;
20216c92544dSBjoern A. Zeeb struct tlv *tlv;
20226c92544dSBjoern A. Zeeb struct bss_info_bcn *bcn;
20236c92544dSBjoern A. Zeeb int len = MT7915_MAX_BSS_OFFLOAD_SIZE;
20246c92544dSBjoern A. Zeeb bool ext_phy = phy != &dev->phy;
20256c92544dSBjoern A. Zeeb
20266c92544dSBjoern A. Zeeb if (vif->bss_conf.nontransmitted)
20276c92544dSBjoern A. Zeeb return 0;
20286c92544dSBjoern A. Zeeb
20296c92544dSBjoern A. Zeeb rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
20306c92544dSBjoern A. Zeeb NULL, len);
20316c92544dSBjoern A. Zeeb if (IS_ERR(rskb))
20326c92544dSBjoern A. Zeeb return PTR_ERR(rskb);
20336c92544dSBjoern A. Zeeb
20346c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
20356c92544dSBjoern A. Zeeb bcn = (struct bss_info_bcn *)tlv;
20366c92544dSBjoern A. Zeeb bcn->enable = en;
20376c92544dSBjoern A. Zeeb
20386c92544dSBjoern A. Zeeb if (!en)
20396c92544dSBjoern A. Zeeb goto out;
20406c92544dSBjoern A. Zeeb
20416c92544dSBjoern A. Zeeb skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
2042*8ba4d145SBjoern A. Zeeb if (!skb) {
2043*8ba4d145SBjoern A. Zeeb dev_kfree_skb(rskb);
20446c92544dSBjoern A. Zeeb return -EINVAL;
2045*8ba4d145SBjoern A. Zeeb }
20466c92544dSBjoern A. Zeeb
2047*8ba4d145SBjoern A. Zeeb if (skb->len > MT7915_MAX_BEACON_SIZE) {
20486c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
2049*8ba4d145SBjoern A. Zeeb dev_kfree_skb(rskb);
20506c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
20516c92544dSBjoern A. Zeeb return -EINVAL;
20526c92544dSBjoern A. Zeeb }
20536c92544dSBjoern A. Zeeb
20546c92544dSBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
20556c92544dSBjoern A. Zeeb info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
20566c92544dSBjoern A. Zeeb
20576c92544dSBjoern A. Zeeb mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
20586c92544dSBjoern A. Zeeb mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
20596c92544dSBjoern A. Zeeb mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
20606c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
20616c92544dSBjoern A. Zeeb
20626c92544dSBjoern A. Zeeb out:
20636c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
20646c92544dSBjoern A. Zeeb MCU_EXT_CMD(BSS_INFO_UPDATE), true);
20656c92544dSBjoern A. Zeeb }
20666c92544dSBjoern A. Zeeb
mt7915_driver_own(struct mt7915_dev * dev,u8 band)20676c92544dSBjoern A. Zeeb static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)
20686c92544dSBjoern A. Zeeb {
20696c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(band), MT_TOP_LPCR_HOST_DRV_OWN);
20706c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND(band),
20716c92544dSBjoern A. Zeeb MT_TOP_LPCR_HOST_FW_OWN_STAT, 0, 500)) {
20726c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for driver own\n");
20736c92544dSBjoern A. Zeeb return -EIO;
20746c92544dSBjoern A. Zeeb }
20756c92544dSBjoern A. Zeeb
20766c92544dSBjoern A. Zeeb /* clear irq when the driver own success */
20776c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_LPCR_HOST_BAND_IRQ_STAT(band),
20786c92544dSBjoern A. Zeeb MT_TOP_LPCR_HOST_BAND_STAT);
20796c92544dSBjoern A. Zeeb
20806c92544dSBjoern A. Zeeb return 0;
20816c92544dSBjoern A. Zeeb }
20826c92544dSBjoern A. Zeeb
20836c92544dSBjoern A. Zeeb static int
mt7915_firmware_state(struct mt7915_dev * dev,bool wa)20846c92544dSBjoern A. Zeeb mt7915_firmware_state(struct mt7915_dev *dev, bool wa)
20856c92544dSBjoern A. Zeeb {
20866c92544dSBjoern A. Zeeb u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE,
20876c92544dSBjoern A. Zeeb wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD);
20886c92544dSBjoern A. Zeeb
20896c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
20906c92544dSBjoern A. Zeeb state, 1000)) {
20916c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
20926c92544dSBjoern A. Zeeb return -EIO;
20936c92544dSBjoern A. Zeeb }
20946c92544dSBjoern A. Zeeb return 0;
20956c92544dSBjoern A. Zeeb }
20966c92544dSBjoern A. Zeeb
mt7915_load_firmware(struct mt7915_dev * dev)20976c92544dSBjoern A. Zeeb static int mt7915_load_firmware(struct mt7915_dev *dev)
20986c92544dSBjoern A. Zeeb {
20996c92544dSBjoern A. Zeeb int ret;
21006c92544dSBjoern A. Zeeb
21016c92544dSBjoern A. Zeeb /* make sure fw is download state */
21026c92544dSBjoern A. Zeeb if (mt7915_firmware_state(dev, false)) {
21036c92544dSBjoern A. Zeeb /* restart firmware once */
2104cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_restart(&dev->mt76);
21056c92544dSBjoern A. Zeeb ret = mt7915_firmware_state(dev, false);
21066c92544dSBjoern A. Zeeb if (ret) {
21076c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev,
21086c92544dSBjoern A. Zeeb "Firmware is not ready for download\n");
21096c92544dSBjoern A. Zeeb return ret;
21106c92544dSBjoern A. Zeeb }
21116c92544dSBjoern A. Zeeb }
21126c92544dSBjoern A. Zeeb
21136c92544dSBjoern A. Zeeb ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));
21146c92544dSBjoern A. Zeeb if (ret)
21156c92544dSBjoern A. Zeeb return ret;
21166c92544dSBjoern A. Zeeb
21176c92544dSBjoern A. Zeeb ret = mt76_connac2_load_ram(&dev->mt76, fw_name_var(dev, FIRMWARE_WM),
21186c92544dSBjoern A. Zeeb fw_name(dev, FIRMWARE_WA));
21196c92544dSBjoern A. Zeeb if (ret)
21206c92544dSBjoern A. Zeeb return ret;
21216c92544dSBjoern A. Zeeb
21226c92544dSBjoern A. Zeeb ret = mt7915_firmware_state(dev, true);
21236c92544dSBjoern A. Zeeb if (ret)
21246c92544dSBjoern A. Zeeb return ret;
21256c92544dSBjoern A. Zeeb
21266c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
21276c92544dSBjoern A. Zeeb
21286c92544dSBjoern A. Zeeb dev_dbg(dev->mt76.dev, "Firmware init done\n");
21296c92544dSBjoern A. Zeeb
21306c92544dSBjoern A. Zeeb return 0;
21316c92544dSBjoern A. Zeeb }
21326c92544dSBjoern A. Zeeb
mt7915_mcu_fw_log_2_host(struct mt7915_dev * dev,u8 type,u8 ctrl)21336c92544dSBjoern A. Zeeb int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl)
21346c92544dSBjoern A. Zeeb {
21356c92544dSBjoern A. Zeeb struct {
21366c92544dSBjoern A. Zeeb u8 ctrl_val;
21376c92544dSBjoern A. Zeeb u8 pad[3];
21386c92544dSBjoern A. Zeeb } data = {
21396c92544dSBjoern A. Zeeb .ctrl_val = ctrl
21406c92544dSBjoern A. Zeeb };
21416c92544dSBjoern A. Zeeb
21426c92544dSBjoern A. Zeeb if (type == MCU_FW_LOG_WA)
21436c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(FW_LOG_2_HOST),
21446c92544dSBjoern A. Zeeb &data, sizeof(data), true);
21456c92544dSBjoern A. Zeeb
21466c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST), &data,
21476c92544dSBjoern A. Zeeb sizeof(data), true);
21486c92544dSBjoern A. Zeeb }
21496c92544dSBjoern A. Zeeb
mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev * dev,u32 module,u8 level)21506c92544dSBjoern A. Zeeb int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)
21516c92544dSBjoern A. Zeeb {
21526c92544dSBjoern A. Zeeb struct {
21536c92544dSBjoern A. Zeeb u8 ver;
21546c92544dSBjoern A. Zeeb u8 pad;
21556c92544dSBjoern A. Zeeb __le16 len;
21566c92544dSBjoern A. Zeeb u8 level;
21576c92544dSBjoern A. Zeeb u8 rsv[3];
21586c92544dSBjoern A. Zeeb __le32 module_idx;
21596c92544dSBjoern A. Zeeb } data = {
21606c92544dSBjoern A. Zeeb .module_idx = cpu_to_le32(module),
21616c92544dSBjoern A. Zeeb .level = level,
21626c92544dSBjoern A. Zeeb };
21636c92544dSBjoern A. Zeeb
21646c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_DBG_CTRL), &data,
21656c92544dSBjoern A. Zeeb sizeof(data), false);
21666c92544dSBjoern A. Zeeb }
21676c92544dSBjoern A. Zeeb
mt7915_mcu_muru_debug_set(struct mt7915_dev * dev,bool enabled)21686c92544dSBjoern A. Zeeb int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled)
21696c92544dSBjoern A. Zeeb {
21706c92544dSBjoern A. Zeeb struct {
21716c92544dSBjoern A. Zeeb __le32 cmd;
21726c92544dSBjoern A. Zeeb u8 enable;
21736c92544dSBjoern A. Zeeb } data = {
21746c92544dSBjoern A. Zeeb .cmd = cpu_to_le32(MURU_SET_TXC_TX_STATS_EN),
21756c92544dSBjoern A. Zeeb .enable = enabled,
21766c92544dSBjoern A. Zeeb };
21776c92544dSBjoern A. Zeeb
21786c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &data,
21796c92544dSBjoern A. Zeeb sizeof(data), false);
21806c92544dSBjoern A. Zeeb }
21816c92544dSBjoern A. Zeeb
mt7915_mcu_muru_debug_get(struct mt7915_phy * phy)2182cbb3ec25SBjoern A. Zeeb int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy)
21836c92544dSBjoern A. Zeeb {
21846c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
21856c92544dSBjoern A. Zeeb struct sk_buff *skb;
2186cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_muru_stats *mu_stats;
21876c92544dSBjoern A. Zeeb int ret;
21886c92544dSBjoern A. Zeeb
21896c92544dSBjoern A. Zeeb struct {
21906c92544dSBjoern A. Zeeb __le32 cmd;
21916c92544dSBjoern A. Zeeb u8 band_idx;
21926c92544dSBjoern A. Zeeb } req = {
21936c92544dSBjoern A. Zeeb .cmd = cpu_to_le32(MURU_GET_TXC_TX_STATS),
2194cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
21956c92544dSBjoern A. Zeeb };
21966c92544dSBjoern A. Zeeb
21976c92544dSBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL),
21986c92544dSBjoern A. Zeeb &req, sizeof(req), true, &skb);
21996c92544dSBjoern A. Zeeb if (ret)
22006c92544dSBjoern A. Zeeb return ret;
22016c92544dSBjoern A. Zeeb
2202cbb3ec25SBjoern A. Zeeb mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data);
2203cbb3ec25SBjoern A. Zeeb
2204cbb3ec25SBjoern A. Zeeb /* accumulate stats, these are clear-on-read */
2205cbb3ec25SBjoern A. Zeeb #define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s)
2206cbb3ec25SBjoern A. Zeeb #define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s)
2207cbb3ec25SBjoern A. Zeeb __dl_u32(cck_cnt);
2208cbb3ec25SBjoern A. Zeeb __dl_u32(ofdm_cnt);
2209cbb3ec25SBjoern A. Zeeb __dl_u32(htmix_cnt);
2210cbb3ec25SBjoern A. Zeeb __dl_u32(htgf_cnt);
2211cbb3ec25SBjoern A. Zeeb __dl_u32(vht_su_cnt);
2212cbb3ec25SBjoern A. Zeeb __dl_u32(vht_2mu_cnt);
2213cbb3ec25SBjoern A. Zeeb __dl_u32(vht_3mu_cnt);
2214cbb3ec25SBjoern A. Zeeb __dl_u32(vht_4mu_cnt);
2215cbb3ec25SBjoern A. Zeeb __dl_u32(he_su_cnt);
2216cbb3ec25SBjoern A. Zeeb __dl_u32(he_2ru_cnt);
2217cbb3ec25SBjoern A. Zeeb __dl_u32(he_2mu_cnt);
2218cbb3ec25SBjoern A. Zeeb __dl_u32(he_3ru_cnt);
2219cbb3ec25SBjoern A. Zeeb __dl_u32(he_3mu_cnt);
2220cbb3ec25SBjoern A. Zeeb __dl_u32(he_4ru_cnt);
2221cbb3ec25SBjoern A. Zeeb __dl_u32(he_4mu_cnt);
2222cbb3ec25SBjoern A. Zeeb __dl_u32(he_5to8ru_cnt);
2223cbb3ec25SBjoern A. Zeeb __dl_u32(he_9to16ru_cnt);
2224cbb3ec25SBjoern A. Zeeb __dl_u32(he_gtr16ru_cnt);
2225cbb3ec25SBjoern A. Zeeb
2226cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_su_cnt);
2227cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_2ru_cnt);
2228cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_3ru_cnt);
2229cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_4ru_cnt);
2230cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_5to8ru_cnt);
2231cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_9to16ru_cnt);
2232cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_gtr16ru_cnt);
2233cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_2mu_cnt);
2234cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_3mu_cnt);
2235cbb3ec25SBjoern A. Zeeb __ul_u32(hetrig_4mu_cnt);
2236cbb3ec25SBjoern A. Zeeb #undef __dl_u32
2237cbb3ec25SBjoern A. Zeeb #undef __ul_u32
2238cbb3ec25SBjoern A. Zeeb
22396c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
22406c92544dSBjoern A. Zeeb
22416c92544dSBjoern A. Zeeb return 0;
22426c92544dSBjoern A. Zeeb }
22436c92544dSBjoern A. Zeeb
mt7915_mcu_set_mwds(struct mt7915_dev * dev,bool enabled)22446c92544dSBjoern A. Zeeb static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled)
22456c92544dSBjoern A. Zeeb {
22466c92544dSBjoern A. Zeeb struct {
22476c92544dSBjoern A. Zeeb u8 enable;
22486c92544dSBjoern A. Zeeb u8 _rsv[3];
22496c92544dSBjoern A. Zeeb } __packed req = {
22506c92544dSBjoern A. Zeeb .enable = enabled
22516c92544dSBjoern A. Zeeb };
22526c92544dSBjoern A. Zeeb
22536c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(MWDS_SUPPORT), &req,
22546c92544dSBjoern A. Zeeb sizeof(req), false);
22556c92544dSBjoern A. Zeeb }
22566c92544dSBjoern A. Zeeb
mt7915_mcu_set_muru_ctrl(struct mt7915_dev * dev,u32 cmd,u32 val)22576c92544dSBjoern A. Zeeb int mt7915_mcu_set_muru_ctrl(struct mt7915_dev *dev, u32 cmd, u32 val)
22586c92544dSBjoern A. Zeeb {
22596c92544dSBjoern A. Zeeb struct {
22606c92544dSBjoern A. Zeeb __le32 cmd;
22616c92544dSBjoern A. Zeeb u8 val[4];
22626c92544dSBjoern A. Zeeb } __packed req = {
22636c92544dSBjoern A. Zeeb .cmd = cpu_to_le32(cmd),
22646c92544dSBjoern A. Zeeb };
22656c92544dSBjoern A. Zeeb
22666c92544dSBjoern A. Zeeb put_unaligned_le32(val, req.val);
22676c92544dSBjoern A. Zeeb
22686c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), &req,
22696c92544dSBjoern A. Zeeb sizeof(req), false);
22706c92544dSBjoern A. Zeeb }
22716c92544dSBjoern A. Zeeb
22726c92544dSBjoern A. Zeeb static int
mt7915_mcu_init_rx_airtime(struct mt7915_dev * dev)22736c92544dSBjoern A. Zeeb mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
22746c92544dSBjoern A. Zeeb {
22756c92544dSBjoern A. Zeeb #define RX_AIRTIME_FEATURE_CTRL 1
22766c92544dSBjoern A. Zeeb #define RX_AIRTIME_BITWISE_CTRL 2
22776c92544dSBjoern A. Zeeb #define RX_AIRTIME_CLEAR_EN 1
22786c92544dSBjoern A. Zeeb struct {
22796c92544dSBjoern A. Zeeb __le16 field;
22806c92544dSBjoern A. Zeeb __le16 sub_field;
22816c92544dSBjoern A. Zeeb __le32 set_status;
22826c92544dSBjoern A. Zeeb __le32 get_status;
22836c92544dSBjoern A. Zeeb u8 _rsv[12];
22846c92544dSBjoern A. Zeeb
22856c92544dSBjoern A. Zeeb bool airtime_en;
22866c92544dSBjoern A. Zeeb bool mibtime_en;
22876c92544dSBjoern A. Zeeb bool earlyend_en;
22886c92544dSBjoern A. Zeeb u8 _rsv1[9];
22896c92544dSBjoern A. Zeeb
22906c92544dSBjoern A. Zeeb bool airtime_clear;
22916c92544dSBjoern A. Zeeb bool mibtime_clear;
22926c92544dSBjoern A. Zeeb u8 _rsv2[98];
22936c92544dSBjoern A. Zeeb } __packed req = {
22946c92544dSBjoern A. Zeeb .field = cpu_to_le16(RX_AIRTIME_BITWISE_CTRL),
22956c92544dSBjoern A. Zeeb .sub_field = cpu_to_le16(RX_AIRTIME_CLEAR_EN),
22966c92544dSBjoern A. Zeeb .airtime_clear = true,
22976c92544dSBjoern A. Zeeb };
22986c92544dSBjoern A. Zeeb int ret;
22996c92544dSBjoern A. Zeeb
23006c92544dSBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_AIRTIME_CTRL), &req,
23016c92544dSBjoern A. Zeeb sizeof(req), true);
23026c92544dSBjoern A. Zeeb if (ret)
23036c92544dSBjoern A. Zeeb return ret;
23046c92544dSBjoern A. Zeeb
23056c92544dSBjoern A. Zeeb req.field = cpu_to_le16(RX_AIRTIME_FEATURE_CTRL);
23066c92544dSBjoern A. Zeeb req.sub_field = cpu_to_le16(RX_AIRTIME_CLEAR_EN);
23076c92544dSBjoern A. Zeeb req.airtime_en = true;
23086c92544dSBjoern A. Zeeb
23096c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_AIRTIME_CTRL), &req,
23106c92544dSBjoern A. Zeeb sizeof(req), true);
23116c92544dSBjoern A. Zeeb }
23126c92544dSBjoern A. Zeeb
mt7915_red_set_watermark(struct mt7915_dev * dev)2313cbb3ec25SBjoern A. Zeeb static int mt7915_red_set_watermark(struct mt7915_dev *dev)
23146c92544dSBjoern A. Zeeb {
2315cbb3ec25SBjoern A. Zeeb #define RED_GLOBAL_TOKEN_WATERMARK 2
2316cbb3ec25SBjoern A. Zeeb struct {
2317cbb3ec25SBjoern A. Zeeb __le32 args[3];
2318cbb3ec25SBjoern A. Zeeb u8 cmd;
2319cbb3ec25SBjoern A. Zeeb u8 version;
2320cbb3ec25SBjoern A. Zeeb u8 __rsv1[4];
2321cbb3ec25SBjoern A. Zeeb __le16 len;
2322cbb3ec25SBjoern A. Zeeb __le16 high_mark;
2323cbb3ec25SBjoern A. Zeeb __le16 low_mark;
2324cbb3ec25SBjoern A. Zeeb u8 __rsv2[12];
2325cbb3ec25SBjoern A. Zeeb } __packed req = {
2326cbb3ec25SBjoern A. Zeeb .args[0] = cpu_to_le32(MCU_WA_PARAM_RED_SETTING),
2327cbb3ec25SBjoern A. Zeeb .cmd = RED_GLOBAL_TOKEN_WATERMARK,
2328cbb3ec25SBjoern A. Zeeb .len = cpu_to_le16(sizeof(req) - sizeof(req.args)),
2329cbb3ec25SBjoern A. Zeeb .high_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256),
2330cbb3ec25SBjoern A. Zeeb .low_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256 - 1536),
23316c92544dSBjoern A. Zeeb };
23326c92544dSBjoern A. Zeeb
2333cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET), &req,
2334cbb3ec25SBjoern A. Zeeb sizeof(req), false);
2335cbb3ec25SBjoern A. Zeeb }
2336cbb3ec25SBjoern A. Zeeb
mt7915_mcu_set_red(struct mt7915_dev * dev,bool enabled)2337cbb3ec25SBjoern A. Zeeb static int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled)
2338cbb3ec25SBjoern A. Zeeb {
2339cbb3ec25SBjoern A. Zeeb #define RED_DISABLE 0
2340cbb3ec25SBjoern A. Zeeb #define RED_BY_WA_ENABLE 2
2341cbb3ec25SBjoern A. Zeeb int ret;
2342cbb3ec25SBjoern A. Zeeb u32 red_type = enabled ? RED_BY_WA_ENABLE : RED_DISABLE;
2343cbb3ec25SBjoern A. Zeeb __le32 req = cpu_to_le32(red_type);
2344cbb3ec25SBjoern A. Zeeb
2345cbb3ec25SBjoern A. Zeeb if (enabled) {
2346cbb3ec25SBjoern A. Zeeb ret = mt7915_red_set_watermark(dev);
2347cbb3ec25SBjoern A. Zeeb if (ret < 0)
2348cbb3ec25SBjoern A. Zeeb return ret;
2349cbb3ec25SBjoern A. Zeeb }
2350cbb3ec25SBjoern A. Zeeb
2351cbb3ec25SBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RED_ENABLE), &req,
2352cbb3ec25SBjoern A. Zeeb sizeof(req), false);
2353cbb3ec25SBjoern A. Zeeb if (ret < 0)
2354cbb3ec25SBjoern A. Zeeb return ret;
2355cbb3ec25SBjoern A. Zeeb
2356cbb3ec25SBjoern A. Zeeb return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
2357cbb3ec25SBjoern A. Zeeb MCU_WA_PARAM_RED, enabled, 0);
2358cbb3ec25SBjoern A. Zeeb }
2359cbb3ec25SBjoern A. Zeeb
mt7915_mcu_init_firmware(struct mt7915_dev * dev)2360cbb3ec25SBjoern A. Zeeb int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
2361cbb3ec25SBjoern A. Zeeb {
2362cbb3ec25SBjoern A. Zeeb int ret;
23636c92544dSBjoern A. Zeeb
23646c92544dSBjoern A. Zeeb /* force firmware operation mode into normal state,
23656c92544dSBjoern A. Zeeb * which should be set before firmware download stage.
23666c92544dSBjoern A. Zeeb */
23676c92544dSBjoern A. Zeeb mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
23686c92544dSBjoern A. Zeeb
23696c92544dSBjoern A. Zeeb ret = mt7915_driver_own(dev, 0);
23706c92544dSBjoern A. Zeeb if (ret)
23716c92544dSBjoern A. Zeeb return ret;
23726c92544dSBjoern A. Zeeb /* set driver own for band1 when two hif exist */
23736c92544dSBjoern A. Zeeb if (dev->hif2) {
23746c92544dSBjoern A. Zeeb ret = mt7915_driver_own(dev, 1);
23756c92544dSBjoern A. Zeeb if (ret)
23766c92544dSBjoern A. Zeeb return ret;
23776c92544dSBjoern A. Zeeb }
23786c92544dSBjoern A. Zeeb
23796c92544dSBjoern A. Zeeb ret = mt7915_load_firmware(dev);
23806c92544dSBjoern A. Zeeb if (ret)
23816c92544dSBjoern A. Zeeb return ret;
23826c92544dSBjoern A. Zeeb
23836c92544dSBjoern A. Zeeb set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
23846c92544dSBjoern A. Zeeb ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);
23856c92544dSBjoern A. Zeeb if (ret)
23866c92544dSBjoern A. Zeeb return ret;
23876c92544dSBjoern A. Zeeb
23886c92544dSBjoern A. Zeeb ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, 0);
23896c92544dSBjoern A. Zeeb if (ret)
23906c92544dSBjoern A. Zeeb return ret;
23916c92544dSBjoern A. Zeeb
2392*8ba4d145SBjoern A. Zeeb mt76_connac_mcu_del_wtbl_all(&dev->mt76);
2393*8ba4d145SBjoern A. Zeeb
2394cbb3ec25SBjoern A. Zeeb if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
2395cbb3ec25SBjoern A. Zeeb is_mt7915(&dev->mt76)) ||
2396cbb3ec25SBjoern A. Zeeb !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
23976c92544dSBjoern A. Zeeb mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
23986c92544dSBjoern A. Zeeb
23996c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_mwds(dev, 1);
24006c92544dSBjoern A. Zeeb if (ret)
24016c92544dSBjoern A. Zeeb return ret;
24026c92544dSBjoern A. Zeeb
24036c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_muru_ctrl(dev, MURU_SET_PLATFORM_TYPE,
24046c92544dSBjoern A. Zeeb MURU_PLATFORM_TYPE_PERF_LEVEL_2);
24056c92544dSBjoern A. Zeeb if (ret)
24066c92544dSBjoern A. Zeeb return ret;
24076c92544dSBjoern A. Zeeb
24086c92544dSBjoern A. Zeeb ret = mt7915_mcu_init_rx_airtime(dev);
24096c92544dSBjoern A. Zeeb if (ret)
24106c92544dSBjoern A. Zeeb return ret;
24116c92544dSBjoern A. Zeeb
2412cbb3ec25SBjoern A. Zeeb return mt7915_mcu_set_red(dev, mtk_wed_device_active(&dev->mt76.mmio.wed));
2413cbb3ec25SBjoern A. Zeeb }
2414cbb3ec25SBjoern A. Zeeb
mt7915_mcu_init(struct mt7915_dev * dev)2415cbb3ec25SBjoern A. Zeeb int mt7915_mcu_init(struct mt7915_dev *dev)
2416cbb3ec25SBjoern A. Zeeb {
2417cbb3ec25SBjoern A. Zeeb static const struct mt76_mcu_ops mt7915_mcu_ops = {
2418*8ba4d145SBjoern A. Zeeb .max_retry = 1,
2419cbb3ec25SBjoern A. Zeeb .headroom = sizeof(struct mt76_connac2_mcu_txd),
2420*8ba4d145SBjoern A. Zeeb .mcu_skb_prepare_msg = mt76_connac2_mcu_fill_message,
2421cbb3ec25SBjoern A. Zeeb .mcu_skb_send_msg = mt7915_mcu_send_message,
2422cbb3ec25SBjoern A. Zeeb .mcu_parse_response = mt7915_mcu_parse_response,
2423cbb3ec25SBjoern A. Zeeb };
2424cbb3ec25SBjoern A. Zeeb
2425cbb3ec25SBjoern A. Zeeb dev->mt76.mcu_ops = &mt7915_mcu_ops;
2426cbb3ec25SBjoern A. Zeeb
2427cbb3ec25SBjoern A. Zeeb return mt7915_mcu_init_firmware(dev);
24286c92544dSBjoern A. Zeeb }
24296c92544dSBjoern A. Zeeb
mt7915_mcu_exit(struct mt7915_dev * dev)24306c92544dSBjoern A. Zeeb void mt7915_mcu_exit(struct mt7915_dev *dev)
24316c92544dSBjoern A. Zeeb {
2432cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_restart(&dev->mt76);
24336c92544dSBjoern A. Zeeb if (mt7915_firmware_state(dev, false)) {
24346c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to exit mcu\n");
2435cbb3ec25SBjoern A. Zeeb goto out;
24366c92544dSBjoern A. Zeeb }
24376c92544dSBjoern A. Zeeb
24386c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN);
24396c92544dSBjoern A. Zeeb if (dev->hif2)
24406c92544dSBjoern A. Zeeb mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1),
24416c92544dSBjoern A. Zeeb MT_TOP_LPCR_HOST_FW_OWN);
2442cbb3ec25SBjoern A. Zeeb out:
24436c92544dSBjoern A. Zeeb skb_queue_purge(&dev->mt76.mcu.res_q);
24446c92544dSBjoern A. Zeeb }
24456c92544dSBjoern A. Zeeb
24466c92544dSBjoern A. Zeeb static int
mt7915_mcu_set_rx_hdr_trans_blacklist(struct mt7915_dev * dev,int band)24476c92544dSBjoern A. Zeeb mt7915_mcu_set_rx_hdr_trans_blacklist(struct mt7915_dev *dev, int band)
24486c92544dSBjoern A. Zeeb {
24496c92544dSBjoern A. Zeeb struct {
24506c92544dSBjoern A. Zeeb u8 operation;
24516c92544dSBjoern A. Zeeb u8 count;
24526c92544dSBjoern A. Zeeb u8 _rsv[2];
24536c92544dSBjoern A. Zeeb u8 index;
24546c92544dSBjoern A. Zeeb u8 enable;
24556c92544dSBjoern A. Zeeb __le16 etype;
24566c92544dSBjoern A. Zeeb } req = {
24576c92544dSBjoern A. Zeeb .operation = 1,
24586c92544dSBjoern A. Zeeb .count = 1,
24596c92544dSBjoern A. Zeeb .enable = 1,
24606c92544dSBjoern A. Zeeb .etype = cpu_to_le16(ETH_P_PAE),
24616c92544dSBjoern A. Zeeb };
24626c92544dSBjoern A. Zeeb
24636c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),
24646c92544dSBjoern A. Zeeb &req, sizeof(req), false);
24656c92544dSBjoern A. Zeeb }
24666c92544dSBjoern A. Zeeb
mt7915_mcu_set_mac(struct mt7915_dev * dev,int band,bool enable,bool hdr_trans)24676c92544dSBjoern A. Zeeb int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,
24686c92544dSBjoern A. Zeeb bool enable, bool hdr_trans)
24696c92544dSBjoern A. Zeeb {
24706c92544dSBjoern A. Zeeb struct {
24716c92544dSBjoern A. Zeeb u8 operation;
24726c92544dSBjoern A. Zeeb u8 enable;
24736c92544dSBjoern A. Zeeb u8 check_bssid;
24746c92544dSBjoern A. Zeeb u8 insert_vlan;
24756c92544dSBjoern A. Zeeb u8 remove_vlan;
24766c92544dSBjoern A. Zeeb u8 tid;
24776c92544dSBjoern A. Zeeb u8 mode;
24786c92544dSBjoern A. Zeeb u8 rsv;
24796c92544dSBjoern A. Zeeb } __packed req_trans = {
24806c92544dSBjoern A. Zeeb .enable = hdr_trans,
24816c92544dSBjoern A. Zeeb };
24826c92544dSBjoern A. Zeeb struct {
24836c92544dSBjoern A. Zeeb u8 enable;
24846c92544dSBjoern A. Zeeb u8 band;
24856c92544dSBjoern A. Zeeb u8 rsv[2];
24866c92544dSBjoern A. Zeeb } __packed req_mac = {
24876c92544dSBjoern A. Zeeb .enable = enable,
24886c92544dSBjoern A. Zeeb .band = band,
24896c92544dSBjoern A. Zeeb };
24906c92544dSBjoern A. Zeeb int ret;
24916c92544dSBjoern A. Zeeb
24926c92544dSBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),
24936c92544dSBjoern A. Zeeb &req_trans, sizeof(req_trans), false);
24946c92544dSBjoern A. Zeeb if (ret)
24956c92544dSBjoern A. Zeeb return ret;
24966c92544dSBjoern A. Zeeb
24976c92544dSBjoern A. Zeeb if (hdr_trans)
24986c92544dSBjoern A. Zeeb mt7915_mcu_set_rx_hdr_trans_blacklist(dev, band);
24996c92544dSBjoern A. Zeeb
25006c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MAC_INIT_CTRL),
25016c92544dSBjoern A. Zeeb &req_mac, sizeof(req_mac), true);
25026c92544dSBjoern A. Zeeb }
25036c92544dSBjoern A. Zeeb
mt7915_mcu_update_edca(struct mt7915_dev * dev,void * param)25046c92544dSBjoern A. Zeeb int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param)
25056c92544dSBjoern A. Zeeb {
25066c92544dSBjoern A. Zeeb struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param;
25076c92544dSBjoern A. Zeeb u8 num = req->total;
25086c92544dSBjoern A. Zeeb size_t len = sizeof(*req) -
25096c92544dSBjoern A. Zeeb (IEEE80211_NUM_ACS - num) * sizeof(struct edca);
25106c92544dSBjoern A. Zeeb
25116c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE), req,
25126c92544dSBjoern A. Zeeb len, true);
25136c92544dSBjoern A. Zeeb }
25146c92544dSBjoern A. Zeeb
mt7915_mcu_set_tx(struct mt7915_dev * dev,struct ieee80211_vif * vif)25156c92544dSBjoern A. Zeeb int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif)
25166c92544dSBjoern A. Zeeb {
25176c92544dSBjoern A. Zeeb #define TX_CMD_MODE 1
25186c92544dSBjoern A. Zeeb struct mt7915_mcu_tx req = {
25196c92544dSBjoern A. Zeeb .valid = true,
25206c92544dSBjoern A. Zeeb .mode = TX_CMD_MODE,
25216c92544dSBjoern A. Zeeb .total = IEEE80211_NUM_ACS,
25226c92544dSBjoern A. Zeeb };
25236c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
25246c92544dSBjoern A. Zeeb int ac;
25256c92544dSBjoern A. Zeeb
25266c92544dSBjoern A. Zeeb for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
25276c92544dSBjoern A. Zeeb struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac];
25286c92544dSBjoern A. Zeeb struct edca *e = &req.edca[ac];
25296c92544dSBjoern A. Zeeb
25306c92544dSBjoern A. Zeeb e->set = WMM_PARAM_SET;
25316c92544dSBjoern A. Zeeb e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
25326c92544dSBjoern A. Zeeb e->aifs = q->aifs;
25336c92544dSBjoern A. Zeeb e->txop = cpu_to_le16(q->txop);
25346c92544dSBjoern A. Zeeb
25356c92544dSBjoern A. Zeeb if (q->cw_min)
25366c92544dSBjoern A. Zeeb e->cw_min = fls(q->cw_min);
25376c92544dSBjoern A. Zeeb else
25386c92544dSBjoern A. Zeeb e->cw_min = 5;
25396c92544dSBjoern A. Zeeb
25406c92544dSBjoern A. Zeeb if (q->cw_max)
25416c92544dSBjoern A. Zeeb e->cw_max = cpu_to_le16(fls(q->cw_max));
25426c92544dSBjoern A. Zeeb else
25436c92544dSBjoern A. Zeeb e->cw_max = cpu_to_le16(10);
25446c92544dSBjoern A. Zeeb }
25456c92544dSBjoern A. Zeeb
25466c92544dSBjoern A. Zeeb return mt7915_mcu_update_edca(dev, &req);
25476c92544dSBjoern A. Zeeb }
25486c92544dSBjoern A. Zeeb
mt7915_mcu_set_fcc5_lpn(struct mt7915_dev * dev,int val)25496c92544dSBjoern A. Zeeb int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val)
25506c92544dSBjoern A. Zeeb {
25516c92544dSBjoern A. Zeeb struct {
25526c92544dSBjoern A. Zeeb __le32 tag;
25536c92544dSBjoern A. Zeeb __le16 min_lpn;
25546c92544dSBjoern A. Zeeb u8 rsv[2];
25556c92544dSBjoern A. Zeeb } __packed req = {
25566c92544dSBjoern A. Zeeb .tag = cpu_to_le32(0x1),
25576c92544dSBjoern A. Zeeb .min_lpn = cpu_to_le16(val),
25586c92544dSBjoern A. Zeeb };
25596c92544dSBjoern A. Zeeb
25606c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,
25616c92544dSBjoern A. Zeeb sizeof(req), true);
25626c92544dSBjoern A. Zeeb }
25636c92544dSBjoern A. Zeeb
mt7915_mcu_set_pulse_th(struct mt7915_dev * dev,const struct mt7915_dfs_pulse * pulse)25646c92544dSBjoern A. Zeeb int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,
25656c92544dSBjoern A. Zeeb const struct mt7915_dfs_pulse *pulse)
25666c92544dSBjoern A. Zeeb {
25676c92544dSBjoern A. Zeeb struct {
25686c92544dSBjoern A. Zeeb __le32 tag;
25696c92544dSBjoern A. Zeeb
25706c92544dSBjoern A. Zeeb __le32 max_width; /* us */
25716c92544dSBjoern A. Zeeb __le32 max_pwr; /* dbm */
25726c92544dSBjoern A. Zeeb __le32 min_pwr; /* dbm */
25736c92544dSBjoern A. Zeeb __le32 min_stgr_pri; /* us */
25746c92544dSBjoern A. Zeeb __le32 max_stgr_pri; /* us */
25756c92544dSBjoern A. Zeeb __le32 min_cr_pri; /* us */
25766c92544dSBjoern A. Zeeb __le32 max_cr_pri; /* us */
25776c92544dSBjoern A. Zeeb } __packed req = {
25786c92544dSBjoern A. Zeeb .tag = cpu_to_le32(0x3),
25796c92544dSBjoern A. Zeeb
25806c92544dSBjoern A. Zeeb #define __req_field(field) .field = cpu_to_le32(pulse->field)
25816c92544dSBjoern A. Zeeb __req_field(max_width),
25826c92544dSBjoern A. Zeeb __req_field(max_pwr),
25836c92544dSBjoern A. Zeeb __req_field(min_pwr),
25846c92544dSBjoern A. Zeeb __req_field(min_stgr_pri),
25856c92544dSBjoern A. Zeeb __req_field(max_stgr_pri),
25866c92544dSBjoern A. Zeeb __req_field(min_cr_pri),
25876c92544dSBjoern A. Zeeb __req_field(max_cr_pri),
25886c92544dSBjoern A. Zeeb #undef __req_field
25896c92544dSBjoern A. Zeeb };
25906c92544dSBjoern A. Zeeb
25916c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,
25926c92544dSBjoern A. Zeeb sizeof(req), true);
25936c92544dSBjoern A. Zeeb }
25946c92544dSBjoern A. Zeeb
mt7915_mcu_set_radar_th(struct mt7915_dev * dev,int index,const struct mt7915_dfs_pattern * pattern)25956c92544dSBjoern A. Zeeb int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
25966c92544dSBjoern A. Zeeb const struct mt7915_dfs_pattern *pattern)
25976c92544dSBjoern A. Zeeb {
25986c92544dSBjoern A. Zeeb struct {
25996c92544dSBjoern A. Zeeb __le32 tag;
26006c92544dSBjoern A. Zeeb __le16 radar_type;
26016c92544dSBjoern A. Zeeb
26026c92544dSBjoern A. Zeeb u8 enb;
26036c92544dSBjoern A. Zeeb u8 stgr;
26046c92544dSBjoern A. Zeeb u8 min_crpn;
26056c92544dSBjoern A. Zeeb u8 max_crpn;
26066c92544dSBjoern A. Zeeb u8 min_crpr;
26076c92544dSBjoern A. Zeeb u8 min_pw;
26086c92544dSBjoern A. Zeeb __le32 min_pri;
26096c92544dSBjoern A. Zeeb __le32 max_pri;
26106c92544dSBjoern A. Zeeb u8 max_pw;
26116c92544dSBjoern A. Zeeb u8 min_crbn;
26126c92544dSBjoern A. Zeeb u8 max_crbn;
26136c92544dSBjoern A. Zeeb u8 min_stgpn;
26146c92544dSBjoern A. Zeeb u8 max_stgpn;
26156c92544dSBjoern A. Zeeb u8 min_stgpr;
26166c92544dSBjoern A. Zeeb u8 rsv[2];
26176c92544dSBjoern A. Zeeb __le32 min_stgpr_diff;
26186c92544dSBjoern A. Zeeb } __packed req = {
26196c92544dSBjoern A. Zeeb .tag = cpu_to_le32(0x2),
26206c92544dSBjoern A. Zeeb .radar_type = cpu_to_le16(index),
26216c92544dSBjoern A. Zeeb
26226c92544dSBjoern A. Zeeb #define __req_field_u8(field) .field = pattern->field
26236c92544dSBjoern A. Zeeb #define __req_field_u32(field) .field = cpu_to_le32(pattern->field)
26246c92544dSBjoern A. Zeeb __req_field_u8(enb),
26256c92544dSBjoern A. Zeeb __req_field_u8(stgr),
26266c92544dSBjoern A. Zeeb __req_field_u8(min_crpn),
26276c92544dSBjoern A. Zeeb __req_field_u8(max_crpn),
26286c92544dSBjoern A. Zeeb __req_field_u8(min_crpr),
26296c92544dSBjoern A. Zeeb __req_field_u8(min_pw),
26306c92544dSBjoern A. Zeeb __req_field_u32(min_pri),
26316c92544dSBjoern A. Zeeb __req_field_u32(max_pri),
26326c92544dSBjoern A. Zeeb __req_field_u8(max_pw),
26336c92544dSBjoern A. Zeeb __req_field_u8(min_crbn),
26346c92544dSBjoern A. Zeeb __req_field_u8(max_crbn),
26356c92544dSBjoern A. Zeeb __req_field_u8(min_stgpn),
26366c92544dSBjoern A. Zeeb __req_field_u8(max_stgpn),
26376c92544dSBjoern A. Zeeb __req_field_u8(min_stgpr),
26386c92544dSBjoern A. Zeeb __req_field_u32(min_stgpr_diff),
26396c92544dSBjoern A. Zeeb #undef __req_field_u8
26406c92544dSBjoern A. Zeeb #undef __req_field_u32
26416c92544dSBjoern A. Zeeb };
26426c92544dSBjoern A. Zeeb
26436c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_TH), &req,
26446c92544dSBjoern A. Zeeb sizeof(req), true);
26456c92544dSBjoern A. Zeeb }
26466c92544dSBjoern A. Zeeb
26476c92544dSBjoern A. Zeeb static int
mt7915_mcu_background_chain_ctrl(struct mt7915_phy * phy,struct cfg80211_chan_def * chandef,int cmd)26486c92544dSBjoern A. Zeeb mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
26496c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef,
26506c92544dSBjoern A. Zeeb int cmd)
26516c92544dSBjoern A. Zeeb {
26526c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
26536c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
26546c92544dSBjoern A. Zeeb struct ieee80211_channel *chan = mphy->chandef.chan;
26556c92544dSBjoern A. Zeeb int freq = mphy->chandef.center_freq1;
26566c92544dSBjoern A. Zeeb struct mt7915_mcu_background_chain_ctrl req = {
26576c92544dSBjoern A. Zeeb .monitor_scan_type = 2, /* simple rx */
26586c92544dSBjoern A. Zeeb };
26596c92544dSBjoern A. Zeeb
26606c92544dSBjoern A. Zeeb if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP)
26616c92544dSBjoern A. Zeeb return -EINVAL;
26626c92544dSBjoern A. Zeeb
26636c92544dSBjoern A. Zeeb if (!cfg80211_chandef_valid(&mphy->chandef))
26646c92544dSBjoern A. Zeeb return -EINVAL;
26656c92544dSBjoern A. Zeeb
26666c92544dSBjoern A. Zeeb switch (cmd) {
26676c92544dSBjoern A. Zeeb case CH_SWITCH_BACKGROUND_SCAN_START: {
26686c92544dSBjoern A. Zeeb req.chan = chan->hw_value;
26696c92544dSBjoern A. Zeeb req.central_chan = ieee80211_frequency_to_channel(freq);
26706c92544dSBjoern A. Zeeb req.bw = mt76_connac_chan_bw(&mphy->chandef);
26716c92544dSBjoern A. Zeeb req.monitor_chan = chandef->chan->hw_value;
26726c92544dSBjoern A. Zeeb req.monitor_central_chan =
26736c92544dSBjoern A. Zeeb ieee80211_frequency_to_channel(chandef->center_freq1);
26746c92544dSBjoern A. Zeeb req.monitor_bw = mt76_connac_chan_bw(chandef);
2675cbb3ec25SBjoern A. Zeeb req.band_idx = phy->mt76->band_idx;
26766c92544dSBjoern A. Zeeb req.scan_mode = 1;
26776c92544dSBjoern A. Zeeb break;
26786c92544dSBjoern A. Zeeb }
26796c92544dSBjoern A. Zeeb case CH_SWITCH_BACKGROUND_SCAN_RUNNING:
26806c92544dSBjoern A. Zeeb req.monitor_chan = chandef->chan->hw_value;
26816c92544dSBjoern A. Zeeb req.monitor_central_chan =
26826c92544dSBjoern A. Zeeb ieee80211_frequency_to_channel(chandef->center_freq1);
2683cbb3ec25SBjoern A. Zeeb req.band_idx = phy->mt76->band_idx;
26846c92544dSBjoern A. Zeeb req.scan_mode = 2;
26856c92544dSBjoern A. Zeeb break;
26866c92544dSBjoern A. Zeeb case CH_SWITCH_BACKGROUND_SCAN_STOP:
26876c92544dSBjoern A. Zeeb req.chan = chan->hw_value;
26886c92544dSBjoern A. Zeeb req.central_chan = ieee80211_frequency_to_channel(freq);
26896c92544dSBjoern A. Zeeb req.bw = mt76_connac_chan_bw(&mphy->chandef);
26906c92544dSBjoern A. Zeeb req.tx_stream = hweight8(mphy->antenna_mask);
26916c92544dSBjoern A. Zeeb req.rx_stream = mphy->antenna_mask;
26926c92544dSBjoern A. Zeeb break;
26936c92544dSBjoern A. Zeeb default:
26946c92544dSBjoern A. Zeeb return -EINVAL;
26956c92544dSBjoern A. Zeeb }
26966c92544dSBjoern A. Zeeb req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1;
26976c92544dSBjoern A. Zeeb
26986c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL),
26996c92544dSBjoern A. Zeeb &req, sizeof(req), false);
27006c92544dSBjoern A. Zeeb }
27016c92544dSBjoern A. Zeeb
mt7915_mcu_rdd_background_enable(struct mt7915_phy * phy,struct cfg80211_chan_def * chandef)27026c92544dSBjoern A. Zeeb int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
27036c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef)
27046c92544dSBjoern A. Zeeb {
27056c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
27066c92544dSBjoern A. Zeeb int err, region;
27076c92544dSBjoern A. Zeeb
27086c92544dSBjoern A. Zeeb if (!chandef) { /* disable offchain */
27096c92544dSBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2,
27106c92544dSBjoern A. Zeeb 0, 0);
27116c92544dSBjoern A. Zeeb if (err)
27126c92544dSBjoern A. Zeeb return err;
27136c92544dSBjoern A. Zeeb
27146c92544dSBjoern A. Zeeb return mt7915_mcu_background_chain_ctrl(phy, NULL,
27156c92544dSBjoern A. Zeeb CH_SWITCH_BACKGROUND_SCAN_STOP);
27166c92544dSBjoern A. Zeeb }
27176c92544dSBjoern A. Zeeb
27186c92544dSBjoern A. Zeeb err = mt7915_mcu_background_chain_ctrl(phy, chandef,
27196c92544dSBjoern A. Zeeb CH_SWITCH_BACKGROUND_SCAN_START);
27206c92544dSBjoern A. Zeeb if (err)
27216c92544dSBjoern A. Zeeb return err;
27226c92544dSBjoern A. Zeeb
27236c92544dSBjoern A. Zeeb switch (dev->mt76.region) {
27246c92544dSBjoern A. Zeeb case NL80211_DFS_ETSI:
27256c92544dSBjoern A. Zeeb region = 0;
27266c92544dSBjoern A. Zeeb break;
27276c92544dSBjoern A. Zeeb case NL80211_DFS_JP:
27286c92544dSBjoern A. Zeeb region = 2;
27296c92544dSBjoern A. Zeeb break;
27306c92544dSBjoern A. Zeeb case NL80211_DFS_FCC:
27316c92544dSBjoern A. Zeeb default:
27326c92544dSBjoern A. Zeeb region = 1;
27336c92544dSBjoern A. Zeeb break;
27346c92544dSBjoern A. Zeeb }
27356c92544dSBjoern A. Zeeb
27366c92544dSBjoern A. Zeeb return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2,
27376c92544dSBjoern A. Zeeb 0, region);
27386c92544dSBjoern A. Zeeb }
27396c92544dSBjoern A. Zeeb
mt7915_mcu_set_chan_info(struct mt7915_phy * phy,int cmd)27406c92544dSBjoern A. Zeeb int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
27416c92544dSBjoern A. Zeeb {
27426c92544dSBjoern A. Zeeb static const u8 ch_band[] = {
27436c92544dSBjoern A. Zeeb [NL80211_BAND_2GHZ] = 0,
27446c92544dSBjoern A. Zeeb [NL80211_BAND_5GHZ] = 1,
27456c92544dSBjoern A. Zeeb [NL80211_BAND_6GHZ] = 2,
27466c92544dSBjoern A. Zeeb };
27476c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
27486c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
27496c92544dSBjoern A. Zeeb int freq1 = chandef->center_freq1;
2750cbb3ec25SBjoern A. Zeeb u8 band = phy->mt76->band_idx;
27516c92544dSBjoern A. Zeeb struct {
27526c92544dSBjoern A. Zeeb u8 control_ch;
27536c92544dSBjoern A. Zeeb u8 center_ch;
27546c92544dSBjoern A. Zeeb u8 bw;
2755cbb3ec25SBjoern A. Zeeb u8 tx_path_num;
2756cbb3ec25SBjoern A. Zeeb u8 rx_path; /* mask or num */
27576c92544dSBjoern A. Zeeb u8 switch_reason;
27586c92544dSBjoern A. Zeeb u8 band_idx;
27596c92544dSBjoern A. Zeeb u8 center_ch2; /* for 80+80 only */
27606c92544dSBjoern A. Zeeb __le16 cac_case;
27616c92544dSBjoern A. Zeeb u8 channel_band;
27626c92544dSBjoern A. Zeeb u8 rsv0;
27636c92544dSBjoern A. Zeeb __le32 outband_freq;
27646c92544dSBjoern A. Zeeb u8 txpower_drop;
27656c92544dSBjoern A. Zeeb u8 ap_bw;
27666c92544dSBjoern A. Zeeb u8 ap_center_ch;
27676c92544dSBjoern A. Zeeb u8 rsv1[57];
27686c92544dSBjoern A. Zeeb } __packed req = {
27696c92544dSBjoern A. Zeeb .control_ch = chandef->chan->hw_value,
27706c92544dSBjoern A. Zeeb .center_ch = ieee80211_frequency_to_channel(freq1),
27716c92544dSBjoern A. Zeeb .bw = mt76_connac_chan_bw(chandef),
2772cbb3ec25SBjoern A. Zeeb .tx_path_num = hweight16(phy->mt76->chainmask),
2773cbb3ec25SBjoern A. Zeeb .rx_path = phy->mt76->chainmask >> (dev->chainshift * band),
2774cbb3ec25SBjoern A. Zeeb .band_idx = band,
27756c92544dSBjoern A. Zeeb .channel_band = ch_band[chandef->chan->band],
27766c92544dSBjoern A. Zeeb };
27776c92544dSBjoern A. Zeeb
27786c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE
27796c92544dSBjoern A. Zeeb if (phy->mt76->test.tx_antenna_mask &&
2780cbb3ec25SBjoern A. Zeeb mt76_testmode_enabled(phy->mt76)) {
2781cbb3ec25SBjoern A. Zeeb req.tx_path_num = fls(phy->mt76->test.tx_antenna_mask);
2782cbb3ec25SBjoern A. Zeeb req.rx_path = phy->mt76->test.tx_antenna_mask;
27836c92544dSBjoern A. Zeeb }
27846c92544dSBjoern A. Zeeb #endif
27856c92544dSBjoern A. Zeeb
2786cbb3ec25SBjoern A. Zeeb if (mt76_connac_spe_idx(phy->mt76->antenna_mask))
2787cbb3ec25SBjoern A. Zeeb req.tx_path_num = fls(phy->mt76->antenna_mask);
2788cbb3ec25SBjoern A. Zeeb
2789*8ba4d145SBjoern A. Zeeb if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
27906c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_NORMAL;
2791*8ba4d145SBjoern A. Zeeb else if (phy->mt76->offchannel ||
2792*8ba4d145SBjoern A. Zeeb phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
27936c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
27946c92544dSBjoern A. Zeeb else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
27956c92544dSBjoern A. Zeeb NL80211_IFTYPE_AP))
27966c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_DFS;
27976c92544dSBjoern A. Zeeb else
27986c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_NORMAL;
27996c92544dSBjoern A. Zeeb
28006c92544dSBjoern A. Zeeb if (cmd == MCU_EXT_CMD(CHANNEL_SWITCH))
2801cbb3ec25SBjoern A. Zeeb req.rx_path = hweight8(req.rx_path);
28026c92544dSBjoern A. Zeeb
28036c92544dSBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_80P80) {
28046c92544dSBjoern A. Zeeb int freq2 = chandef->center_freq2;
28056c92544dSBjoern A. Zeeb
28066c92544dSBjoern A. Zeeb req.center_ch2 = ieee80211_frequency_to_channel(freq2);
28076c92544dSBjoern A. Zeeb }
28086c92544dSBjoern A. Zeeb
28096c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
28106c92544dSBjoern A. Zeeb }
28116c92544dSBjoern A. Zeeb
mt7915_mcu_set_eeprom_flash(struct mt7915_dev * dev)28126c92544dSBjoern A. Zeeb static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
28136c92544dSBjoern A. Zeeb {
28146c92544dSBjoern A. Zeeb #define MAX_PAGE_IDX_MASK GENMASK(7, 5)
28156c92544dSBjoern A. Zeeb #define PAGE_IDX_MASK GENMASK(4, 2)
28166c92544dSBjoern A. Zeeb #define PER_PAGE_SIZE 0x400
28176c92544dSBjoern A. Zeeb struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER };
28186c92544dSBjoern A. Zeeb u16 eeprom_size = mt7915_eeprom_size(dev);
28196c92544dSBjoern A. Zeeb u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);
28206c92544dSBjoern A. Zeeb u8 *eep = (u8 *)dev->mt76.eeprom.data;
28216c92544dSBjoern A. Zeeb int eep_len;
28226c92544dSBjoern A. Zeeb int i;
28236c92544dSBjoern A. Zeeb
28246c92544dSBjoern A. Zeeb for (i = 0; i < total; i++, eep += eep_len) {
28256c92544dSBjoern A. Zeeb struct sk_buff *skb;
28266c92544dSBjoern A. Zeeb int ret;
28276c92544dSBjoern A. Zeeb
28286c92544dSBjoern A. Zeeb if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))
28296c92544dSBjoern A. Zeeb eep_len = eeprom_size % PER_PAGE_SIZE;
28306c92544dSBjoern A. Zeeb else
28316c92544dSBjoern A. Zeeb eep_len = PER_PAGE_SIZE;
28326c92544dSBjoern A. Zeeb
28336c92544dSBjoern A. Zeeb skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
28346c92544dSBjoern A. Zeeb sizeof(req) + eep_len);
28356c92544dSBjoern A. Zeeb if (!skb)
28366c92544dSBjoern A. Zeeb return -ENOMEM;
28376c92544dSBjoern A. Zeeb
28386c92544dSBjoern A. Zeeb req.format = FIELD_PREP(MAX_PAGE_IDX_MASK, total - 1) |
28396c92544dSBjoern A. Zeeb FIELD_PREP(PAGE_IDX_MASK, i) | EE_FORMAT_WHOLE;
28406c92544dSBjoern A. Zeeb req.len = cpu_to_le16(eep_len);
28416c92544dSBjoern A. Zeeb
28426c92544dSBjoern A. Zeeb skb_put_data(skb, &req, sizeof(req));
28436c92544dSBjoern A. Zeeb skb_put_data(skb, eep, eep_len);
28446c92544dSBjoern A. Zeeb
28456c92544dSBjoern A. Zeeb ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
28466c92544dSBjoern A. Zeeb MCU_EXT_CMD(EFUSE_BUFFER_MODE), true);
28476c92544dSBjoern A. Zeeb if (ret)
28486c92544dSBjoern A. Zeeb return ret;
28496c92544dSBjoern A. Zeeb }
28506c92544dSBjoern A. Zeeb
28516c92544dSBjoern A. Zeeb return 0;
28526c92544dSBjoern A. Zeeb }
28536c92544dSBjoern A. Zeeb
mt7915_mcu_set_eeprom(struct mt7915_dev * dev)28546c92544dSBjoern A. Zeeb int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
28556c92544dSBjoern A. Zeeb {
28566c92544dSBjoern A. Zeeb struct mt7915_mcu_eeprom req = {
28576c92544dSBjoern A. Zeeb .buffer_mode = EE_MODE_EFUSE,
28586c92544dSBjoern A. Zeeb .format = EE_FORMAT_WHOLE,
28596c92544dSBjoern A. Zeeb };
28606c92544dSBjoern A. Zeeb
28616c92544dSBjoern A. Zeeb if (dev->flash_mode)
28626c92544dSBjoern A. Zeeb return mt7915_mcu_set_eeprom_flash(dev);
28636c92544dSBjoern A. Zeeb
28646c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
28656c92544dSBjoern A. Zeeb &req, sizeof(req), true);
28666c92544dSBjoern A. Zeeb }
28676c92544dSBjoern A. Zeeb
mt7915_mcu_get_eeprom(struct mt7915_dev * dev,u32 offset)28686c92544dSBjoern A. Zeeb int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
28696c92544dSBjoern A. Zeeb {
28706c92544dSBjoern A. Zeeb struct mt7915_mcu_eeprom_info req = {
28716c92544dSBjoern A. Zeeb .addr = cpu_to_le32(round_down(offset,
28726c92544dSBjoern A. Zeeb MT7915_EEPROM_BLOCK_SIZE)),
28736c92544dSBjoern A. Zeeb };
28746c92544dSBjoern A. Zeeb struct mt7915_mcu_eeprom_info *res;
28756c92544dSBjoern A. Zeeb struct sk_buff *skb;
28766c92544dSBjoern A. Zeeb int ret;
28776c92544dSBjoern A. Zeeb u8 *buf;
28786c92544dSBjoern A. Zeeb
2879cbb3ec25SBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76,
2880cbb3ec25SBjoern A. Zeeb MCU_EXT_QUERY(EFUSE_ACCESS),
2881cbb3ec25SBjoern A. Zeeb &req, sizeof(req), true, &skb);
28826c92544dSBjoern A. Zeeb if (ret)
28836c92544dSBjoern A. Zeeb return ret;
28846c92544dSBjoern A. Zeeb
28856c92544dSBjoern A. Zeeb res = (struct mt7915_mcu_eeprom_info *)skb->data;
28866c92544dSBjoern A. Zeeb #if defined(__linux__)
28876c92544dSBjoern A. Zeeb buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
28886c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__)
28896c92544dSBjoern A. Zeeb buf = (u8 *)dev->mt76.eeprom.data + le32_to_cpu(res->addr);
28906c92544dSBjoern A. Zeeb #endif
28916c92544dSBjoern A. Zeeb memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
28926c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
28936c92544dSBjoern A. Zeeb
28946c92544dSBjoern A. Zeeb return 0;
28956c92544dSBjoern A. Zeeb }
28966c92544dSBjoern A. Zeeb
mt7915_mcu_get_eeprom_free_block(struct mt7915_dev * dev,u8 * block_num)28976c92544dSBjoern A. Zeeb int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num)
28986c92544dSBjoern A. Zeeb {
28996c92544dSBjoern A. Zeeb struct {
29006c92544dSBjoern A. Zeeb u8 _rsv;
29016c92544dSBjoern A. Zeeb u8 version;
29026c92544dSBjoern A. Zeeb u8 die_idx;
29036c92544dSBjoern A. Zeeb u8 _rsv2;
29046c92544dSBjoern A. Zeeb } __packed req = {
29056c92544dSBjoern A. Zeeb .version = 1,
29066c92544dSBjoern A. Zeeb };
29076c92544dSBjoern A. Zeeb struct sk_buff *skb;
29086c92544dSBjoern A. Zeeb int ret;
29096c92544dSBjoern A. Zeeb
2910cbb3ec25SBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76,
2911cbb3ec25SBjoern A. Zeeb MCU_EXT_QUERY(EFUSE_FREE_BLOCK),
2912cbb3ec25SBjoern A. Zeeb &req, sizeof(req), true, &skb);
29136c92544dSBjoern A. Zeeb if (ret)
29146c92544dSBjoern A. Zeeb return ret;
29156c92544dSBjoern A. Zeeb
29166c92544dSBjoern A. Zeeb *block_num = *(u8 *)skb->data;
29176c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
29186c92544dSBjoern A. Zeeb
29196c92544dSBjoern A. Zeeb return 0;
29206c92544dSBjoern A. Zeeb }
29216c92544dSBjoern A. Zeeb
mt7915_mcu_set_pre_cal(struct mt7915_dev * dev,u8 idx,u8 * data,u32 len,int cmd)29226c92544dSBjoern A. Zeeb static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
29236c92544dSBjoern A. Zeeb u8 *data, u32 len, int cmd)
29246c92544dSBjoern A. Zeeb {
29256c92544dSBjoern A. Zeeb struct {
29266c92544dSBjoern A. Zeeb u8 dir;
29276c92544dSBjoern A. Zeeb u8 valid;
29286c92544dSBjoern A. Zeeb __le16 bitmap;
29296c92544dSBjoern A. Zeeb s8 precal;
29306c92544dSBjoern A. Zeeb u8 action;
29316c92544dSBjoern A. Zeeb u8 band;
29326c92544dSBjoern A. Zeeb u8 idx;
29336c92544dSBjoern A. Zeeb u8 rsv[4];
29346c92544dSBjoern A. Zeeb __le32 len;
29356c92544dSBjoern A. Zeeb } req = {};
29366c92544dSBjoern A. Zeeb struct sk_buff *skb;
29376c92544dSBjoern A. Zeeb
29386c92544dSBjoern A. Zeeb skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len);
29396c92544dSBjoern A. Zeeb if (!skb)
29406c92544dSBjoern A. Zeeb return -ENOMEM;
29416c92544dSBjoern A. Zeeb
29426c92544dSBjoern A. Zeeb req.idx = idx;
29436c92544dSBjoern A. Zeeb req.len = cpu_to_le32(len);
29446c92544dSBjoern A. Zeeb skb_put_data(skb, &req, sizeof(req));
29456c92544dSBjoern A. Zeeb skb_put_data(skb, data, len);
29466c92544dSBjoern A. Zeeb
29476c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, false);
29486c92544dSBjoern A. Zeeb }
29496c92544dSBjoern A. Zeeb
mt7915_mcu_apply_group_cal(struct mt7915_dev * dev)29506c92544dSBjoern A. Zeeb int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
29516c92544dSBjoern A. Zeeb {
29526c92544dSBjoern A. Zeeb u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
2953*8ba4d145SBjoern A. Zeeb u32 total = mt7915_get_cal_group_size(dev);
2954*8ba4d145SBjoern A. Zeeb u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
29556c92544dSBjoern A. Zeeb
2956*8ba4d145SBjoern A. Zeeb if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
29576c92544dSBjoern A. Zeeb return 0;
29586c92544dSBjoern A. Zeeb
29596c92544dSBjoern A. Zeeb /*
29606c92544dSBjoern A. Zeeb * Items: Rx DCOC, RSSI DCOC, Tx TSSI DCOC, Tx LPFG
29616c92544dSBjoern A. Zeeb * Tx FDIQ, Tx DCIQ, Rx FDIQ, Rx FIIQ, ADCDCOC
29626c92544dSBjoern A. Zeeb */
29636c92544dSBjoern A. Zeeb while (total > 0) {
29646c92544dSBjoern A. Zeeb int ret, len;
29656c92544dSBjoern A. Zeeb
29666c92544dSBjoern A. Zeeb len = min_t(u32, total, MT_EE_CAL_UNIT);
29676c92544dSBjoern A. Zeeb
29686c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_pre_cal(dev, idx, cal, len,
29696c92544dSBjoern A. Zeeb MCU_EXT_CMD(GROUP_PRE_CAL_INFO));
29706c92544dSBjoern A. Zeeb if (ret)
29716c92544dSBjoern A. Zeeb return ret;
29726c92544dSBjoern A. Zeeb
29736c92544dSBjoern A. Zeeb total -= len;
29746c92544dSBjoern A. Zeeb cal += len;
29756c92544dSBjoern A. Zeeb idx++;
29766c92544dSBjoern A. Zeeb }
29776c92544dSBjoern A. Zeeb
29786c92544dSBjoern A. Zeeb return 0;
29796c92544dSBjoern A. Zeeb }
29806c92544dSBjoern A. Zeeb
mt7915_find_freq_idx(const u16 * freqs,int n_freqs,u16 cur)29816c92544dSBjoern A. Zeeb static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
29826c92544dSBjoern A. Zeeb {
29836c92544dSBjoern A. Zeeb int i;
29846c92544dSBjoern A. Zeeb
29856c92544dSBjoern A. Zeeb for (i = 0; i < n_freqs; i++)
29866c92544dSBjoern A. Zeeb if (cur == freqs[i])
29876c92544dSBjoern A. Zeeb return i;
29886c92544dSBjoern A. Zeeb
29896c92544dSBjoern A. Zeeb return -1;
29906c92544dSBjoern A. Zeeb }
29916c92544dSBjoern A. Zeeb
mt7915_dpd_freq_idx(struct mt7915_dev * dev,u16 freq,u8 bw)2992*8ba4d145SBjoern A. Zeeb static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw)
29936c92544dSBjoern A. Zeeb {
2994*8ba4d145SBjoern A. Zeeb static const u16 freq_list_v1[] = {
29956c92544dSBjoern A. Zeeb 5180, 5200, 5220, 5240,
29966c92544dSBjoern A. Zeeb 5260, 5280, 5300, 5320,
29976c92544dSBjoern A. Zeeb 5500, 5520, 5540, 5560,
29986c92544dSBjoern A. Zeeb 5580, 5600, 5620, 5640,
29996c92544dSBjoern A. Zeeb 5660, 5680, 5700, 5745,
30006c92544dSBjoern A. Zeeb 5765, 5785, 5805, 5825
30016c92544dSBjoern A. Zeeb };
3002*8ba4d145SBjoern A. Zeeb static const u16 freq_list_v2[] = {
3003*8ba4d145SBjoern A. Zeeb /* 6G BW20*/
3004*8ba4d145SBjoern A. Zeeb 5955, 5975, 5995, 6015,
3005*8ba4d145SBjoern A. Zeeb 6035, 6055, 6075, 6095,
3006*8ba4d145SBjoern A. Zeeb 6115, 6135, 6155, 6175,
3007*8ba4d145SBjoern A. Zeeb 6195, 6215, 6235, 6255,
3008*8ba4d145SBjoern A. Zeeb 6275, 6295, 6315, 6335,
3009*8ba4d145SBjoern A. Zeeb 6355, 6375, 6395, 6415,
3010*8ba4d145SBjoern A. Zeeb 6435, 6455, 6475, 6495,
3011*8ba4d145SBjoern A. Zeeb 6515, 6535, 6555, 6575,
3012*8ba4d145SBjoern A. Zeeb 6595, 6615, 6635, 6655,
3013*8ba4d145SBjoern A. Zeeb 6675, 6695, 6715, 6735,
3014*8ba4d145SBjoern A. Zeeb 6755, 6775, 6795, 6815,
3015*8ba4d145SBjoern A. Zeeb 6835, 6855, 6875, 6895,
3016*8ba4d145SBjoern A. Zeeb 6915, 6935, 6955, 6975,
3017*8ba4d145SBjoern A. Zeeb 6995, 7015, 7035, 7055,
3018*8ba4d145SBjoern A. Zeeb 7075, 7095, 7115,
3019*8ba4d145SBjoern A. Zeeb /* 6G BW160 */
3020*8ba4d145SBjoern A. Zeeb 6025, 6185, 6345, 6505,
3021*8ba4d145SBjoern A. Zeeb 6665, 6825, 6985,
3022*8ba4d145SBjoern A. Zeeb /* 5G BW20 */
3023*8ba4d145SBjoern A. Zeeb 5180, 5200, 5220, 5240,
3024*8ba4d145SBjoern A. Zeeb 5260, 5280, 5300, 5320,
3025*8ba4d145SBjoern A. Zeeb 5500, 5520, 5540, 5560,
3026*8ba4d145SBjoern A. Zeeb 5580, 5600, 5620, 5640,
3027*8ba4d145SBjoern A. Zeeb 5660, 5680, 5700, 5720,
3028*8ba4d145SBjoern A. Zeeb 5745, 5765, 5785, 5805,
3029*8ba4d145SBjoern A. Zeeb 5825, 5845, 5865, 5885,
3030*8ba4d145SBjoern A. Zeeb /* 5G BW160 */
3031*8ba4d145SBjoern A. Zeeb 5250, 5570, 5815
3032*8ba4d145SBjoern A. Zeeb };
3033*8ba4d145SBjoern A. Zeeb static const u16 freq_list_v2_7981[] = {
3034*8ba4d145SBjoern A. Zeeb /* 5G BW20 */
3035*8ba4d145SBjoern A. Zeeb 5180, 5200, 5220, 5240,
3036*8ba4d145SBjoern A. Zeeb 5260, 5280, 5300, 5320,
3037*8ba4d145SBjoern A. Zeeb 5500, 5520, 5540, 5560,
3038*8ba4d145SBjoern A. Zeeb 5580, 5600, 5620, 5640,
3039*8ba4d145SBjoern A. Zeeb 5660, 5680, 5700, 5720,
3040*8ba4d145SBjoern A. Zeeb 5745, 5765, 5785, 5805,
3041*8ba4d145SBjoern A. Zeeb 5825, 5845, 5865, 5885,
3042*8ba4d145SBjoern A. Zeeb /* 5G BW160 */
3043*8ba4d145SBjoern A. Zeeb 5250, 5570, 5815
3044*8ba4d145SBjoern A. Zeeb };
3045*8ba4d145SBjoern A. Zeeb const u16 *freq_list = freq_list_v1;
3046*8ba4d145SBjoern A. Zeeb int n_freqs = ARRAY_SIZE(freq_list_v1);
30476c92544dSBjoern A. Zeeb int idx;
30486c92544dSBjoern A. Zeeb
3049*8ba4d145SBjoern A. Zeeb if (!is_mt7915(&dev->mt76)) {
3050*8ba4d145SBjoern A. Zeeb if (is_mt7981(&dev->mt76)) {
3051*8ba4d145SBjoern A. Zeeb freq_list = freq_list_v2_7981;
3052*8ba4d145SBjoern A. Zeeb n_freqs = ARRAY_SIZE(freq_list_v2_7981);
3053*8ba4d145SBjoern A. Zeeb } else {
3054*8ba4d145SBjoern A. Zeeb freq_list = freq_list_v2;
3055*8ba4d145SBjoern A. Zeeb n_freqs = ARRAY_SIZE(freq_list_v2);
3056*8ba4d145SBjoern A. Zeeb }
3057*8ba4d145SBjoern A. Zeeb }
3058*8ba4d145SBjoern A. Zeeb
30596c92544dSBjoern A. Zeeb if (freq < 4000) {
30606c92544dSBjoern A. Zeeb if (freq < 2432)
3061*8ba4d145SBjoern A. Zeeb return n_freqs;
30626c92544dSBjoern A. Zeeb if (freq < 2457)
3063*8ba4d145SBjoern A. Zeeb return n_freqs + 1;
30646c92544dSBjoern A. Zeeb
3065*8ba4d145SBjoern A. Zeeb return n_freqs + 2;
30666c92544dSBjoern A. Zeeb }
30676c92544dSBjoern A. Zeeb
3068*8ba4d145SBjoern A. Zeeb if (bw == NL80211_CHAN_WIDTH_80P80)
30696c92544dSBjoern A. Zeeb return -1;
30706c92544dSBjoern A. Zeeb
30716c92544dSBjoern A. Zeeb if (bw != NL80211_CHAN_WIDTH_20) {
3072*8ba4d145SBjoern A. Zeeb idx = mt7915_find_freq_idx(freq_list, n_freqs, freq + 10);
30736c92544dSBjoern A. Zeeb if (idx >= 0)
30746c92544dSBjoern A. Zeeb return idx;
30756c92544dSBjoern A. Zeeb
3076*8ba4d145SBjoern A. Zeeb idx = mt7915_find_freq_idx(freq_list, n_freqs, freq - 10);
30776c92544dSBjoern A. Zeeb if (idx >= 0)
30786c92544dSBjoern A. Zeeb return idx;
30796c92544dSBjoern A. Zeeb }
30806c92544dSBjoern A. Zeeb
3081*8ba4d145SBjoern A. Zeeb return mt7915_find_freq_idx(freq_list, n_freqs, freq);
30826c92544dSBjoern A. Zeeb }
30836c92544dSBjoern A. Zeeb
mt7915_mcu_apply_tx_dpd(struct mt7915_phy * phy)30846c92544dSBjoern A. Zeeb int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
30856c92544dSBjoern A. Zeeb {
30866c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
30876c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
3088*8ba4d145SBjoern A. Zeeb enum nl80211_band band = chandef->chan->band;
3089*8ba4d145SBjoern A. Zeeb u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
3090*8ba4d145SBjoern A. Zeeb u16 center_freq = chandef->center_freq1;
30916c92544dSBjoern A. Zeeb u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
3092*8ba4d145SBjoern A. Zeeb u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;
30936c92544dSBjoern A. Zeeb int idx;
30946c92544dSBjoern A. Zeeb
3095*8ba4d145SBjoern A. Zeeb switch (band) {
3096*8ba4d145SBjoern A. Zeeb case NL80211_BAND_2GHZ:
3097*8ba4d145SBjoern A. Zeeb dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
3098*8ba4d145SBjoern A. Zeeb break;
3099*8ba4d145SBjoern A. Zeeb case NL80211_BAND_5GHZ:
3100*8ba4d145SBjoern A. Zeeb dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
3101*8ba4d145SBjoern A. Zeeb break;
3102*8ba4d145SBjoern A. Zeeb case NL80211_BAND_6GHZ:
3103*8ba4d145SBjoern A. Zeeb dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
3104*8ba4d145SBjoern A. Zeeb break;
3105*8ba4d145SBjoern A. Zeeb default:
3106*8ba4d145SBjoern A. Zeeb dpd_mask = 0;
3107*8ba4d145SBjoern A. Zeeb break;
3108*8ba4d145SBjoern A. Zeeb }
3109*8ba4d145SBjoern A. Zeeb
3110*8ba4d145SBjoern A. Zeeb if (!(eep[offs] & dpd_mask))
31116c92544dSBjoern A. Zeeb return 0;
31126c92544dSBjoern A. Zeeb
3113*8ba4d145SBjoern A. Zeeb idx = mt7915_dpd_freq_idx(dev, center_freq, chandef->width);
31146c92544dSBjoern A. Zeeb if (idx < 0)
31156c92544dSBjoern A. Zeeb return -EINVAL;
31166c92544dSBjoern A. Zeeb
31176c92544dSBjoern A. Zeeb /* Items: Tx DPD, Tx Flatness */
3118*8ba4d145SBjoern A. Zeeb idx = idx * cal_num;
3119*8ba4d145SBjoern A. Zeeb cal += mt7915_get_cal_group_size(dev) + (idx * MT_EE_CAL_UNIT);
31206c92544dSBjoern A. Zeeb
3121*8ba4d145SBjoern A. Zeeb while (cal_num--) {
31226c92544dSBjoern A. Zeeb int ret;
31236c92544dSBjoern A. Zeeb
31246c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT,
31256c92544dSBjoern A. Zeeb MCU_EXT_CMD(DPD_PRE_CAL_INFO));
31266c92544dSBjoern A. Zeeb if (ret)
31276c92544dSBjoern A. Zeeb return ret;
31286c92544dSBjoern A. Zeeb
31296c92544dSBjoern A. Zeeb idx++;
3130*8ba4d145SBjoern A. Zeeb cal += MT_EE_CAL_UNIT;
31316c92544dSBjoern A. Zeeb }
31326c92544dSBjoern A. Zeeb
31336c92544dSBjoern A. Zeeb return 0;
31346c92544dSBjoern A. Zeeb }
31356c92544dSBjoern A. Zeeb
mt7915_mcu_get_chan_mib_info(struct mt7915_phy * phy,bool chan_switch)31366c92544dSBjoern A. Zeeb int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
31376c92544dSBjoern A. Zeeb {
31386c92544dSBjoern A. Zeeb struct mt76_channel_state *state = phy->mt76->chan_state;
31396c92544dSBjoern A. Zeeb struct mt76_channel_state *state_ts = &phy->state_ts;
31406c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3141cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_mib *res, req[5];
31426c92544dSBjoern A. Zeeb struct sk_buff *skb;
3143cbb3ec25SBjoern A. Zeeb static const u32 *offs;
3144cbb3ec25SBjoern A. Zeeb int i, ret, len, offs_cc;
3145cbb3ec25SBjoern A. Zeeb u64 cc_tx;
31466c92544dSBjoern A. Zeeb
3147cbb3ec25SBjoern A. Zeeb /* strict order */
3148cbb3ec25SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
3149cbb3ec25SBjoern A. Zeeb static const u32 chip_offs[] = {
3150cbb3ec25SBjoern A. Zeeb MIB_NON_WIFI_TIME,
3151cbb3ec25SBjoern A. Zeeb MIB_TX_TIME,
3152cbb3ec25SBjoern A. Zeeb MIB_RX_TIME,
3153cbb3ec25SBjoern A. Zeeb MIB_OBSS_AIRTIME,
3154cbb3ec25SBjoern A. Zeeb MIB_TXOP_INIT_COUNT,
3155cbb3ec25SBjoern A. Zeeb };
3156cbb3ec25SBjoern A. Zeeb len = ARRAY_SIZE(chip_offs);
3157cbb3ec25SBjoern A. Zeeb offs = chip_offs;
3158cbb3ec25SBjoern A. Zeeb offs_cc = 20;
3159cbb3ec25SBjoern A. Zeeb } else {
3160cbb3ec25SBjoern A. Zeeb static const u32 chip_offs[] = {
3161cbb3ec25SBjoern A. Zeeb MIB_NON_WIFI_TIME_V2,
3162cbb3ec25SBjoern A. Zeeb MIB_TX_TIME_V2,
3163cbb3ec25SBjoern A. Zeeb MIB_RX_TIME_V2,
3164cbb3ec25SBjoern A. Zeeb MIB_OBSS_AIRTIME_V2
3165cbb3ec25SBjoern A. Zeeb };
3166cbb3ec25SBjoern A. Zeeb len = ARRAY_SIZE(chip_offs);
3167cbb3ec25SBjoern A. Zeeb offs = chip_offs;
3168cbb3ec25SBjoern A. Zeeb offs_cc = 0;
31696c92544dSBjoern A. Zeeb }
31706c92544dSBjoern A. Zeeb
3171cbb3ec25SBjoern A. Zeeb for (i = 0; i < len; i++) {
3172cbb3ec25SBjoern A. Zeeb req[i].band = cpu_to_le32(phy->mt76->band_idx);
3173cbb3ec25SBjoern A. Zeeb req[i].offs = cpu_to_le32(offs[i]);
31746c92544dSBjoern A. Zeeb }
31756c92544dSBjoern A. Zeeb
31766c92544dSBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
3177cbb3ec25SBjoern A. Zeeb req, len * sizeof(req[0]), true, &skb);
31786c92544dSBjoern A. Zeeb if (ret)
31796c92544dSBjoern A. Zeeb return ret;
31806c92544dSBjoern A. Zeeb
3181cbb3ec25SBjoern A. Zeeb res = (struct mt7915_mcu_mib *)(skb->data + offs_cc);
3182cbb3ec25SBjoern A. Zeeb
3183cbb3ec25SBjoern A. Zeeb #define __res_u64(s) le64_to_cpu(res[s].data)
3184*8ba4d145SBjoern A. Zeeb /* subtract Tx backoff time from Tx duration for MT7915 */
3185*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
3186*8ba4d145SBjoern A. Zeeb u64 backoff = (__res_u64(4) & 0xffff) * 79; /* 16us + 9us * 7 */
3187*8ba4d145SBjoern A. Zeeb cc_tx = __res_u64(1) - backoff;
3188*8ba4d145SBjoern A. Zeeb } else {
3189*8ba4d145SBjoern A. Zeeb cc_tx = __res_u64(1);
3190*8ba4d145SBjoern A. Zeeb }
31916c92544dSBjoern A. Zeeb
31926c92544dSBjoern A. Zeeb if (chan_switch)
31936c92544dSBjoern A. Zeeb goto out;
31946c92544dSBjoern A. Zeeb
3195cbb3ec25SBjoern A. Zeeb state->cc_tx += cc_tx - state_ts->cc_tx;
31966c92544dSBjoern A. Zeeb state->cc_bss_rx += __res_u64(2) - state_ts->cc_bss_rx;
31976c92544dSBjoern A. Zeeb state->cc_rx += __res_u64(2) + __res_u64(3) - state_ts->cc_rx;
3198cbb3ec25SBjoern A. Zeeb state->cc_busy += __res_u64(0) + cc_tx + __res_u64(2) + __res_u64(3) -
3199cbb3ec25SBjoern A. Zeeb state_ts->cc_busy;
32006c92544dSBjoern A. Zeeb
32016c92544dSBjoern A. Zeeb out:
3202cbb3ec25SBjoern A. Zeeb state_ts->cc_tx = cc_tx;
32036c92544dSBjoern A. Zeeb state_ts->cc_bss_rx = __res_u64(2);
32046c92544dSBjoern A. Zeeb state_ts->cc_rx = __res_u64(2) + __res_u64(3);
3205cbb3ec25SBjoern A. Zeeb state_ts->cc_busy = __res_u64(0) + cc_tx + __res_u64(2) + __res_u64(3);
32066c92544dSBjoern A. Zeeb #undef __res_u64
32076c92544dSBjoern A. Zeeb
32086c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
32096c92544dSBjoern A. Zeeb
32106c92544dSBjoern A. Zeeb return 0;
32116c92544dSBjoern A. Zeeb }
32126c92544dSBjoern A. Zeeb
mt7915_mcu_get_temperature(struct mt7915_phy * phy)32136c92544dSBjoern A. Zeeb int mt7915_mcu_get_temperature(struct mt7915_phy *phy)
32146c92544dSBjoern A. Zeeb {
32156c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
32166c92544dSBjoern A. Zeeb struct {
32176c92544dSBjoern A. Zeeb u8 ctrl_id;
32186c92544dSBjoern A. Zeeb u8 action;
3219cbb3ec25SBjoern A. Zeeb u8 band_idx;
32206c92544dSBjoern A. Zeeb u8 rsv[5];
32216c92544dSBjoern A. Zeeb } req = {
32226c92544dSBjoern A. Zeeb .ctrl_id = THERMAL_SENSOR_TEMP_QUERY,
3223cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
32246c92544dSBjoern A. Zeeb };
32256c92544dSBjoern A. Zeeb
32266c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,
32276c92544dSBjoern A. Zeeb sizeof(req), true);
32286c92544dSBjoern A. Zeeb }
32296c92544dSBjoern A. Zeeb
mt7915_mcu_set_thermal_throttling(struct mt7915_phy * phy,u8 state)32306c92544dSBjoern A. Zeeb int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
32316c92544dSBjoern A. Zeeb {
32326c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3233cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_thermal_ctrl req = {
3234cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3235cbb3ec25SBjoern A. Zeeb .ctrl_id = THERMAL_PROTECT_DUTY_CONFIG,
3236cbb3ec25SBjoern A. Zeeb };
3237cbb3ec25SBjoern A. Zeeb int level, ret;
3238cbb3ec25SBjoern A. Zeeb
3239cbb3ec25SBjoern A. Zeeb /* set duty cycle and level */
3240cbb3ec25SBjoern A. Zeeb for (level = 0; level < 4; level++) {
3241cbb3ec25SBjoern A. Zeeb req.duty.duty_level = level;
3242cbb3ec25SBjoern A. Zeeb req.duty.duty_cycle = state;
3243cbb3ec25SBjoern A. Zeeb state /= 2;
3244cbb3ec25SBjoern A. Zeeb
3245cbb3ec25SBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
3246cbb3ec25SBjoern A. Zeeb &req, sizeof(req), false);
3247cbb3ec25SBjoern A. Zeeb if (ret)
3248cbb3ec25SBjoern A. Zeeb return ret;
3249cbb3ec25SBjoern A. Zeeb }
3250cbb3ec25SBjoern A. Zeeb return 0;
3251cbb3ec25SBjoern A. Zeeb }
3252cbb3ec25SBjoern A. Zeeb
mt7915_mcu_set_thermal_protect(struct mt7915_phy * phy)3253cbb3ec25SBjoern A. Zeeb int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy)
3254cbb3ec25SBjoern A. Zeeb {
3255cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
32566c92544dSBjoern A. Zeeb struct {
32576c92544dSBjoern A. Zeeb struct mt7915_mcu_thermal_ctrl ctrl;
32586c92544dSBjoern A. Zeeb
32596c92544dSBjoern A. Zeeb __le32 trigger_temp;
32606c92544dSBjoern A. Zeeb __le32 restore_temp;
32616c92544dSBjoern A. Zeeb __le16 sustain_time;
32626c92544dSBjoern A. Zeeb u8 rsv[2];
32636c92544dSBjoern A. Zeeb } __packed req = {
32646c92544dSBjoern A. Zeeb .ctrl = {
3265cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3266cbb3ec25SBjoern A. Zeeb .type.protect_type = 1,
3267cbb3ec25SBjoern A. Zeeb .type.trigger_type = 1,
32686c92544dSBjoern A. Zeeb },
32696c92544dSBjoern A. Zeeb };
32706c92544dSBjoern A. Zeeb int ret;
32716c92544dSBjoern A. Zeeb
3272cbb3ec25SBjoern A. Zeeb req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;
32736c92544dSBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
32746c92544dSBjoern A. Zeeb &req, sizeof(req.ctrl), false);
3275cbb3ec25SBjoern A. Zeeb
32766c92544dSBjoern A. Zeeb if (ret)
32776c92544dSBjoern A. Zeeb return ret;
32786c92544dSBjoern A. Zeeb
32796c92544dSBjoern A. Zeeb /* set high-temperature trigger threshold */
32806c92544dSBjoern A. Zeeb req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE;
32816c92544dSBjoern A. Zeeb /* add a safety margin ~10 */
32826c92544dSBjoern A. Zeeb req.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10);
32836c92544dSBjoern A. Zeeb req.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
32846c92544dSBjoern A. Zeeb req.sustain_time = cpu_to_le16(10);
32856c92544dSBjoern A. Zeeb
32866c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
32876c92544dSBjoern A. Zeeb &req, sizeof(req), false);
32886c92544dSBjoern A. Zeeb }
32896c92544dSBjoern A. Zeeb
mt7915_mcu_set_txpower_frame_min(struct mt7915_phy * phy,s8 txpower)3290cbb3ec25SBjoern A. Zeeb int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower)
3291cbb3ec25SBjoern A. Zeeb {
3292cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3293cbb3ec25SBjoern A. Zeeb struct {
3294cbb3ec25SBjoern A. Zeeb u8 format_id;
3295cbb3ec25SBjoern A. Zeeb u8 rsv;
3296cbb3ec25SBjoern A. Zeeb u8 band_idx;
3297cbb3ec25SBjoern A. Zeeb s8 txpower_min;
3298cbb3ec25SBjoern A. Zeeb } __packed req = {
3299cbb3ec25SBjoern A. Zeeb .format_id = TX_POWER_LIMIT_FRAME_MIN,
3300cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3301cbb3ec25SBjoern A. Zeeb .txpower_min = txpower * 2, /* 0.5db */
3302cbb3ec25SBjoern A. Zeeb };
3303cbb3ec25SBjoern A. Zeeb
3304cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76,
3305cbb3ec25SBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
3306cbb3ec25SBjoern A. Zeeb sizeof(req), true);
3307cbb3ec25SBjoern A. Zeeb }
3308cbb3ec25SBjoern A. Zeeb
mt7915_mcu_set_txpower_frame(struct mt7915_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,s8 txpower)3309cbb3ec25SBjoern A. Zeeb int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
3310cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif,
3311cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, s8 txpower)
3312cbb3ec25SBjoern A. Zeeb {
3313cbb3ec25SBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
3314cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3315cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
3316cbb3ec25SBjoern A. Zeeb struct {
3317cbb3ec25SBjoern A. Zeeb u8 format_id;
3318cbb3ec25SBjoern A. Zeeb u8 rsv[3];
3319cbb3ec25SBjoern A. Zeeb u8 band_idx;
3320cbb3ec25SBjoern A. Zeeb s8 txpower_max;
3321cbb3ec25SBjoern A. Zeeb __le16 wcid;
3322cbb3ec25SBjoern A. Zeeb s8 txpower_offs[48];
3323cbb3ec25SBjoern A. Zeeb } __packed req = {
3324cbb3ec25SBjoern A. Zeeb .format_id = TX_POWER_LIMIT_FRAME,
3325cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3326cbb3ec25SBjoern A. Zeeb .txpower_max = DIV_ROUND_UP(mphy->txpower_cur, 2),
3327cbb3ec25SBjoern A. Zeeb .wcid = cpu_to_le16(msta->wcid.idx),
3328cbb3ec25SBjoern A. Zeeb };
3329cbb3ec25SBjoern A. Zeeb int ret;
3330cbb3ec25SBjoern A. Zeeb s8 txpower_sku[MT7915_SKU_RATE_NUM];
3331cbb3ec25SBjoern A. Zeeb
3332cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
3333cbb3ec25SBjoern A. Zeeb if (ret)
3334cbb3ec25SBjoern A. Zeeb return ret;
3335cbb3ec25SBjoern A. Zeeb
3336cbb3ec25SBjoern A. Zeeb txpower = mt7915_get_power_bound(phy, txpower);
3337cbb3ec25SBjoern A. Zeeb if (txpower > mphy->txpower_cur || txpower < 0)
3338cbb3ec25SBjoern A. Zeeb return -EINVAL;
3339cbb3ec25SBjoern A. Zeeb
3340cbb3ec25SBjoern A. Zeeb if (txpower) {
3341cbb3ec25SBjoern A. Zeeb u32 offs, len, i;
3342cbb3ec25SBjoern A. Zeeb
3343cbb3ec25SBjoern A. Zeeb if (sta->deflink.ht_cap.ht_supported) {
3344cbb3ec25SBjoern A. Zeeb const u8 *sku_len = mt7915_sku_group_len;
3345cbb3ec25SBjoern A. Zeeb
3346cbb3ec25SBjoern A. Zeeb offs = sku_len[SKU_CCK] + sku_len[SKU_OFDM];
3347cbb3ec25SBjoern A. Zeeb len = sku_len[SKU_HT_BW20] + sku_len[SKU_HT_BW40];
3348cbb3ec25SBjoern A. Zeeb
3349cbb3ec25SBjoern A. Zeeb if (sta->deflink.vht_cap.vht_supported) {
3350cbb3ec25SBjoern A. Zeeb offs += len;
3351cbb3ec25SBjoern A. Zeeb len = sku_len[SKU_VHT_BW20] * 4;
3352cbb3ec25SBjoern A. Zeeb
3353cbb3ec25SBjoern A. Zeeb if (sta->deflink.he_cap.has_he) {
3354cbb3ec25SBjoern A. Zeeb offs += len + sku_len[SKU_HE_RU26] * 3;
3355cbb3ec25SBjoern A. Zeeb len = sku_len[SKU_HE_RU242] * 4;
3356cbb3ec25SBjoern A. Zeeb }
3357cbb3ec25SBjoern A. Zeeb }
3358cbb3ec25SBjoern A. Zeeb } else {
3359cbb3ec25SBjoern A. Zeeb return -EINVAL;
3360cbb3ec25SBjoern A. Zeeb }
3361cbb3ec25SBjoern A. Zeeb
3362cbb3ec25SBjoern A. Zeeb for (i = 0; i < len; i++, offs++)
3363cbb3ec25SBjoern A. Zeeb req.txpower_offs[i] =
3364cbb3ec25SBjoern A. Zeeb DIV_ROUND_UP(txpower - txpower_sku[offs], 2);
3365cbb3ec25SBjoern A. Zeeb }
3366cbb3ec25SBjoern A. Zeeb
3367cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76,
3368cbb3ec25SBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
3369cbb3ec25SBjoern A. Zeeb sizeof(req), true);
3370cbb3ec25SBjoern A. Zeeb }
3371cbb3ec25SBjoern A. Zeeb
mt7915_mcu_set_txpower_sku(struct mt7915_phy * phy)33726c92544dSBjoern A. Zeeb int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
33736c92544dSBjoern A. Zeeb {
33746c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
33756c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
33766c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mphy->hw;
3377cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_txpower_sku req = {
3378cbb3ec25SBjoern A. Zeeb .format_id = TX_POWER_LIMIT_TABLE,
3379cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
33806c92544dSBjoern A. Zeeb };
33816c92544dSBjoern A. Zeeb struct mt76_power_limits limits_array;
33826c92544dSBjoern A. Zeeb s8 *la = (s8 *)&limits_array;
3383cbb3ec25SBjoern A. Zeeb int i, idx;
3384cbb3ec25SBjoern A. Zeeb int tx_power;
33856c92544dSBjoern A. Zeeb
3386cbb3ec25SBjoern A. Zeeb tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
33876c92544dSBjoern A. Zeeb tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
33886c92544dSBjoern A. Zeeb &limits_array, tx_power);
33896c92544dSBjoern A. Zeeb mphy->txpower_cur = tx_power;
33906c92544dSBjoern A. Zeeb
33916c92544dSBjoern A. Zeeb for (i = 0, idx = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
33926c92544dSBjoern A. Zeeb u8 mcs_num, len = mt7915_sku_group_len[i];
33936c92544dSBjoern A. Zeeb int j;
33946c92544dSBjoern A. Zeeb
33956c92544dSBjoern A. Zeeb if (i >= SKU_HT_BW20 && i <= SKU_VHT_BW160) {
33966c92544dSBjoern A. Zeeb mcs_num = 10;
33976c92544dSBjoern A. Zeeb
33986c92544dSBjoern A. Zeeb if (i == SKU_HT_BW20 || i == SKU_VHT_BW20)
33996c92544dSBjoern A. Zeeb la = (s8 *)&limits_array + 12;
34006c92544dSBjoern A. Zeeb } else {
34016c92544dSBjoern A. Zeeb mcs_num = len;
34026c92544dSBjoern A. Zeeb }
34036c92544dSBjoern A. Zeeb
34046c92544dSBjoern A. Zeeb for (j = 0; j < min_t(u8, mcs_num, len); j++)
3405cbb3ec25SBjoern A. Zeeb req.txpower_sku[idx + j] = la[j];
34066c92544dSBjoern A. Zeeb
34076c92544dSBjoern A. Zeeb la += mcs_num;
34086c92544dSBjoern A. Zeeb idx += len;
34096c92544dSBjoern A. Zeeb }
34106c92544dSBjoern A. Zeeb
34116c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76,
34126c92544dSBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
34136c92544dSBjoern A. Zeeb sizeof(req), true);
34146c92544dSBjoern A. Zeeb }
34156c92544dSBjoern A. Zeeb
mt7915_mcu_get_txpower_sku(struct mt7915_phy * phy,s8 * txpower,int len)34166c92544dSBjoern A. Zeeb int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
34176c92544dSBjoern A. Zeeb {
34186c92544dSBjoern A. Zeeb #define RATE_POWER_INFO 2
34196c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
34206c92544dSBjoern A. Zeeb struct {
34216c92544dSBjoern A. Zeeb u8 format_id;
34226c92544dSBjoern A. Zeeb u8 category;
3423cbb3ec25SBjoern A. Zeeb u8 band_idx;
34246c92544dSBjoern A. Zeeb u8 _rsv;
34256c92544dSBjoern A. Zeeb } __packed req = {
3426cbb3ec25SBjoern A. Zeeb .format_id = TX_POWER_LIMIT_INFO,
34276c92544dSBjoern A. Zeeb .category = RATE_POWER_INFO,
3428cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
34296c92544dSBjoern A. Zeeb };
3430cbb3ec25SBjoern A. Zeeb s8 txpower_sku[MT7915_SKU_RATE_NUM][2];
34316c92544dSBjoern A. Zeeb struct sk_buff *skb;
34326c92544dSBjoern A. Zeeb int ret, i;
34336c92544dSBjoern A. Zeeb
34346c92544dSBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76,
34356c92544dSBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
34366c92544dSBjoern A. Zeeb &req, sizeof(req), true, &skb);
34376c92544dSBjoern A. Zeeb if (ret)
34386c92544dSBjoern A. Zeeb return ret;
34396c92544dSBjoern A. Zeeb
3440cbb3ec25SBjoern A. Zeeb memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku));
34416c92544dSBjoern A. Zeeb for (i = 0; i < len; i++)
3442cbb3ec25SBjoern A. Zeeb txpower[i] = txpower_sku[i][req.band_idx];
34436c92544dSBjoern A. Zeeb
34446c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
34456c92544dSBjoern A. Zeeb
34466c92544dSBjoern A. Zeeb return 0;
34476c92544dSBjoern A. Zeeb }
34486c92544dSBjoern A. Zeeb
mt7915_mcu_set_test_param(struct mt7915_dev * dev,u8 param,bool test_mode,u8 en)34496c92544dSBjoern A. Zeeb int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
34506c92544dSBjoern A. Zeeb u8 en)
34516c92544dSBjoern A. Zeeb {
34526c92544dSBjoern A. Zeeb struct {
34536c92544dSBjoern A. Zeeb u8 test_mode_en;
34546c92544dSBjoern A. Zeeb u8 param_idx;
34556c92544dSBjoern A. Zeeb u8 _rsv[2];
34566c92544dSBjoern A. Zeeb
34576c92544dSBjoern A. Zeeb u8 enable;
34586c92544dSBjoern A. Zeeb u8 _rsv2[3];
34596c92544dSBjoern A. Zeeb
34606c92544dSBjoern A. Zeeb u8 pad[8];
34616c92544dSBjoern A. Zeeb } __packed req = {
34626c92544dSBjoern A. Zeeb .test_mode_en = test_mode,
34636c92544dSBjoern A. Zeeb .param_idx = param,
34646c92544dSBjoern A. Zeeb .enable = en,
34656c92544dSBjoern A. Zeeb };
34666c92544dSBjoern A. Zeeb
34676c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
34686c92544dSBjoern A. Zeeb sizeof(req), false);
34696c92544dSBjoern A. Zeeb }
34706c92544dSBjoern A. Zeeb
mt7915_mcu_set_sku_en(struct mt7915_phy * phy,bool enable)34716c92544dSBjoern A. Zeeb int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
34726c92544dSBjoern A. Zeeb {
34736c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
34746c92544dSBjoern A. Zeeb struct mt7915_sku {
34756c92544dSBjoern A. Zeeb u8 format_id;
34766c92544dSBjoern A. Zeeb u8 sku_enable;
3477cbb3ec25SBjoern A. Zeeb u8 band_idx;
34786c92544dSBjoern A. Zeeb u8 rsv;
34796c92544dSBjoern A. Zeeb } __packed req = {
3480cbb3ec25SBjoern A. Zeeb .format_id = TX_POWER_LIMIT_ENABLE,
3481cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
34826c92544dSBjoern A. Zeeb .sku_enable = enable,
34836c92544dSBjoern A. Zeeb };
34846c92544dSBjoern A. Zeeb
34856c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76,
34866c92544dSBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
34876c92544dSBjoern A. Zeeb sizeof(req), true);
34886c92544dSBjoern A. Zeeb }
34896c92544dSBjoern A. Zeeb
mt7915_mcu_set_ser(struct mt7915_dev * dev,u8 action,u8 set,u8 band)34906c92544dSBjoern A. Zeeb int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
34916c92544dSBjoern A. Zeeb {
34926c92544dSBjoern A. Zeeb struct {
34936c92544dSBjoern A. Zeeb u8 action;
34946c92544dSBjoern A. Zeeb u8 set;
34956c92544dSBjoern A. Zeeb u8 band;
34966c92544dSBjoern A. Zeeb u8 rsv;
34976c92544dSBjoern A. Zeeb } req = {
34986c92544dSBjoern A. Zeeb .action = action,
34996c92544dSBjoern A. Zeeb .set = set,
35006c92544dSBjoern A. Zeeb .band = band,
35016c92544dSBjoern A. Zeeb };
35026c92544dSBjoern A. Zeeb
35036c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SER_TRIGGER),
35046c92544dSBjoern A. Zeeb &req, sizeof(req), false);
35056c92544dSBjoern A. Zeeb }
35066c92544dSBjoern A. Zeeb
mt7915_mcu_set_txbf(struct mt7915_dev * dev,u8 action)35076c92544dSBjoern A. Zeeb int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
35086c92544dSBjoern A. Zeeb {
35096c92544dSBjoern A. Zeeb struct {
35106c92544dSBjoern A. Zeeb u8 action;
35116c92544dSBjoern A. Zeeb union {
35126c92544dSBjoern A. Zeeb struct {
35136c92544dSBjoern A. Zeeb u8 snd_mode;
35146c92544dSBjoern A. Zeeb u8 sta_num;
35156c92544dSBjoern A. Zeeb u8 rsv;
35166c92544dSBjoern A. Zeeb u8 wlan_idx[4];
35176c92544dSBjoern A. Zeeb __le32 snd_period; /* ms */
35186c92544dSBjoern A. Zeeb } __packed snd;
35196c92544dSBjoern A. Zeeb struct {
35206c92544dSBjoern A. Zeeb bool ebf;
35216c92544dSBjoern A. Zeeb bool ibf;
35226c92544dSBjoern A. Zeeb u8 rsv;
35236c92544dSBjoern A. Zeeb } __packed type;
35246c92544dSBjoern A. Zeeb struct {
35256c92544dSBjoern A. Zeeb u8 bf_num;
35266c92544dSBjoern A. Zeeb u8 bf_bitmap;
35276c92544dSBjoern A. Zeeb u8 bf_sel[8];
35286c92544dSBjoern A. Zeeb u8 rsv[5];
35296c92544dSBjoern A. Zeeb } __packed mod;
35306c92544dSBjoern A. Zeeb };
35316c92544dSBjoern A. Zeeb } __packed req = {
35326c92544dSBjoern A. Zeeb .action = action,
35336c92544dSBjoern A. Zeeb };
35346c92544dSBjoern A. Zeeb
35356c92544dSBjoern A. Zeeb #define MT_BF_PROCESSING 4
35366c92544dSBjoern A. Zeeb switch (action) {
35376c92544dSBjoern A. Zeeb case MT_BF_SOUNDING_ON:
35386c92544dSBjoern A. Zeeb req.snd.snd_mode = MT_BF_PROCESSING;
35396c92544dSBjoern A. Zeeb break;
35406c92544dSBjoern A. Zeeb case MT_BF_TYPE_UPDATE:
35416c92544dSBjoern A. Zeeb req.type.ebf = true;
35426c92544dSBjoern A. Zeeb req.type.ibf = dev->ibf;
35436c92544dSBjoern A. Zeeb break;
35446c92544dSBjoern A. Zeeb case MT_BF_MODULE_UPDATE:
35456c92544dSBjoern A. Zeeb req.mod.bf_num = 2;
35466c92544dSBjoern A. Zeeb req.mod.bf_bitmap = GENMASK(1, 0);
35476c92544dSBjoern A. Zeeb break;
35486c92544dSBjoern A. Zeeb default:
35496c92544dSBjoern A. Zeeb return -EINVAL;
35506c92544dSBjoern A. Zeeb }
35516c92544dSBjoern A. Zeeb
35526c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
35536c92544dSBjoern A. Zeeb sizeof(req), true);
35546c92544dSBjoern A. Zeeb }
35556c92544dSBjoern A. Zeeb
3556cbb3ec25SBjoern A. Zeeb static int
mt7915_mcu_enable_obss_spr(struct mt7915_phy * phy,u8 action,u8 val)3557cbb3ec25SBjoern A. Zeeb mt7915_mcu_enable_obss_spr(struct mt7915_phy *phy, u8 action, u8 val)
35586c92544dSBjoern A. Zeeb {
3559cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3560cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_sr_ctrl req = {
3561cbb3ec25SBjoern A. Zeeb .action = action,
3562cbb3ec25SBjoern A. Zeeb .argnum = 1,
3563cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3564cbb3ec25SBjoern A. Zeeb .val = cpu_to_le32(val),
35656c92544dSBjoern A. Zeeb };
35666c92544dSBjoern A. Zeeb
35676c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
35686c92544dSBjoern A. Zeeb sizeof(req), true);
35696c92544dSBjoern A. Zeeb }
35706c92544dSBjoern A. Zeeb
3571cbb3ec25SBjoern A. Zeeb static int
mt7915_mcu_set_obss_spr_pd(struct mt7915_phy * phy,struct ieee80211_he_obss_pd * he_obss_pd)3572cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_obss_spr_pd(struct mt7915_phy *phy,
3573cbb3ec25SBjoern A. Zeeb struct ieee80211_he_obss_pd *he_obss_pd)
3574cbb3ec25SBjoern A. Zeeb {
3575cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3576cbb3ec25SBjoern A. Zeeb struct {
3577cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_sr_ctrl ctrl;
3578cbb3ec25SBjoern A. Zeeb struct {
3579cbb3ec25SBjoern A. Zeeb u8 pd_th_non_srg;
3580cbb3ec25SBjoern A. Zeeb u8 pd_th_srg;
3581cbb3ec25SBjoern A. Zeeb u8 period_offs;
3582cbb3ec25SBjoern A. Zeeb u8 rcpi_src;
3583cbb3ec25SBjoern A. Zeeb __le16 obss_pd_min;
3584cbb3ec25SBjoern A. Zeeb __le16 obss_pd_min_srg;
3585cbb3ec25SBjoern A. Zeeb u8 resp_txpwr_mode;
3586cbb3ec25SBjoern A. Zeeb u8 txpwr_restrict_mode;
3587cbb3ec25SBjoern A. Zeeb u8 txpwr_ref;
3588cbb3ec25SBjoern A. Zeeb u8 rsv[3];
3589cbb3ec25SBjoern A. Zeeb } __packed param;
3590cbb3ec25SBjoern A. Zeeb } __packed req = {
3591cbb3ec25SBjoern A. Zeeb .ctrl = {
3592cbb3ec25SBjoern A. Zeeb .action = SPR_SET_PARAM,
3593cbb3ec25SBjoern A. Zeeb .argnum = 9,
3594cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3595cbb3ec25SBjoern A. Zeeb },
3596cbb3ec25SBjoern A. Zeeb };
3597cbb3ec25SBjoern A. Zeeb int ret;
3598cbb3ec25SBjoern A. Zeeb u8 max_th = 82, non_srg_max_th = 62;
3599cbb3ec25SBjoern A. Zeeb
3600cbb3ec25SBjoern A. Zeeb /* disable firmware dynamical PD asjustment */
3601cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_DPD, false);
3602cbb3ec25SBjoern A. Zeeb if (ret)
3603cbb3ec25SBjoern A. Zeeb return ret;
3604cbb3ec25SBjoern A. Zeeb
3605cbb3ec25SBjoern A. Zeeb if (he_obss_pd->sr_ctrl &
3606cbb3ec25SBjoern A. Zeeb IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED)
3607cbb3ec25SBjoern A. Zeeb req.param.pd_th_non_srg = max_th;
3608cbb3ec25SBjoern A. Zeeb else if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
3609cbb3ec25SBjoern A. Zeeb req.param.pd_th_non_srg = max_th - he_obss_pd->non_srg_max_offset;
3610cbb3ec25SBjoern A. Zeeb else
3611cbb3ec25SBjoern A. Zeeb req.param.pd_th_non_srg = non_srg_max_th;
3612cbb3ec25SBjoern A. Zeeb
3613cbb3ec25SBjoern A. Zeeb if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT)
3614cbb3ec25SBjoern A. Zeeb req.param.pd_th_srg = max_th - he_obss_pd->max_offset;
3615cbb3ec25SBjoern A. Zeeb
3616cbb3ec25SBjoern A. Zeeb req.param.obss_pd_min = cpu_to_le16(82);
3617cbb3ec25SBjoern A. Zeeb req.param.obss_pd_min_srg = cpu_to_le16(82);
3618cbb3ec25SBjoern A. Zeeb req.param.txpwr_restrict_mode = 2;
3619cbb3ec25SBjoern A. Zeeb req.param.txpwr_ref = 21;
3620cbb3ec25SBjoern A. Zeeb
3621cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
3622cbb3ec25SBjoern A. Zeeb sizeof(req), true);
3623cbb3ec25SBjoern A. Zeeb }
3624cbb3ec25SBjoern A. Zeeb
3625cbb3ec25SBjoern A. Zeeb static int
mt7915_mcu_set_obss_spr_siga(struct mt7915_phy * phy,struct ieee80211_vif * vif,struct ieee80211_he_obss_pd * he_obss_pd)3626cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_obss_spr_siga(struct mt7915_phy *phy, struct ieee80211_vif *vif,
3627cbb3ec25SBjoern A. Zeeb struct ieee80211_he_obss_pd *he_obss_pd)
3628cbb3ec25SBjoern A. Zeeb {
3629cbb3ec25SBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
3630cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3631cbb3ec25SBjoern A. Zeeb u8 omac = mvif->mt76.omac_idx;
3632cbb3ec25SBjoern A. Zeeb struct {
3633cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_sr_ctrl ctrl;
3634cbb3ec25SBjoern A. Zeeb struct {
3635cbb3ec25SBjoern A. Zeeb u8 omac;
3636cbb3ec25SBjoern A. Zeeb u8 rsv[3];
3637cbb3ec25SBjoern A. Zeeb u8 flag[20];
3638cbb3ec25SBjoern A. Zeeb } __packed siga;
3639cbb3ec25SBjoern A. Zeeb } __packed req = {
3640cbb3ec25SBjoern A. Zeeb .ctrl = {
3641cbb3ec25SBjoern A. Zeeb .action = SPR_SET_SIGA,
3642cbb3ec25SBjoern A. Zeeb .argnum = 1,
3643cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3644cbb3ec25SBjoern A. Zeeb },
3645cbb3ec25SBjoern A. Zeeb .siga = {
3646cbb3ec25SBjoern A. Zeeb .omac = omac > HW_BSSID_MAX ? omac - 12 : omac,
3647cbb3ec25SBjoern A. Zeeb },
3648cbb3ec25SBjoern A. Zeeb };
3649cbb3ec25SBjoern A. Zeeb int ret;
3650cbb3ec25SBjoern A. Zeeb
3651cbb3ec25SBjoern A. Zeeb if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED)
3652cbb3ec25SBjoern A. Zeeb req.siga.flag[req.siga.omac] = 0xf;
3653cbb3ec25SBjoern A. Zeeb else
3654cbb3ec25SBjoern A. Zeeb return 0;
3655cbb3ec25SBjoern A. Zeeb
3656cbb3ec25SBjoern A. Zeeb /* switch to normal AP mode */
3657cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_MODE, 0);
3658cbb3ec25SBjoern A. Zeeb if (ret)
3659cbb3ec25SBjoern A. Zeeb return ret;
3660cbb3ec25SBjoern A. Zeeb
3661cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
3662cbb3ec25SBjoern A. Zeeb sizeof(req), true);
3663cbb3ec25SBjoern A. Zeeb }
3664cbb3ec25SBjoern A. Zeeb
3665cbb3ec25SBjoern A. Zeeb static int
mt7915_mcu_set_obss_spr_bitmap(struct mt7915_phy * phy,struct ieee80211_he_obss_pd * he_obss_pd)3666cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_obss_spr_bitmap(struct mt7915_phy *phy,
3667cbb3ec25SBjoern A. Zeeb struct ieee80211_he_obss_pd *he_obss_pd)
3668cbb3ec25SBjoern A. Zeeb {
3669cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3670cbb3ec25SBjoern A. Zeeb struct {
3671cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_sr_ctrl ctrl;
3672cbb3ec25SBjoern A. Zeeb struct {
3673cbb3ec25SBjoern A. Zeeb __le32 color_l[2];
3674cbb3ec25SBjoern A. Zeeb __le32 color_h[2];
3675cbb3ec25SBjoern A. Zeeb __le32 bssid_l[2];
3676cbb3ec25SBjoern A. Zeeb __le32 bssid_h[2];
3677cbb3ec25SBjoern A. Zeeb } __packed bitmap;
3678cbb3ec25SBjoern A. Zeeb } __packed req = {
3679cbb3ec25SBjoern A. Zeeb .ctrl = {
3680cbb3ec25SBjoern A. Zeeb .action = SPR_SET_SRG_BITMAP,
3681cbb3ec25SBjoern A. Zeeb .argnum = 4,
3682cbb3ec25SBjoern A. Zeeb .band_idx = phy->mt76->band_idx,
3683cbb3ec25SBjoern A. Zeeb },
3684cbb3ec25SBjoern A. Zeeb };
3685cbb3ec25SBjoern A. Zeeb u32 bitmap;
3686cbb3ec25SBjoern A. Zeeb
3687cbb3ec25SBjoern A. Zeeb memcpy(&bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));
3688cbb3ec25SBjoern A. Zeeb req.bitmap.color_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);
3689cbb3ec25SBjoern A. Zeeb
3690cbb3ec25SBjoern A. Zeeb memcpy(&bitmap, he_obss_pd->bss_color_bitmap + 4, sizeof(bitmap));
3691cbb3ec25SBjoern A. Zeeb req.bitmap.color_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);
3692cbb3ec25SBjoern A. Zeeb
3693cbb3ec25SBjoern A. Zeeb memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));
3694cbb3ec25SBjoern A. Zeeb req.bitmap.bssid_l[req.ctrl.band_idx] = cpu_to_le32(bitmap);
3695cbb3ec25SBjoern A. Zeeb
3696cbb3ec25SBjoern A. Zeeb memcpy(&bitmap, he_obss_pd->partial_bssid_bitmap + 4, sizeof(bitmap));
3697cbb3ec25SBjoern A. Zeeb req.bitmap.bssid_h[req.ctrl.band_idx] = cpu_to_le32(bitmap);
3698cbb3ec25SBjoern A. Zeeb
3699cbb3ec25SBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_SPR), &req,
3700cbb3ec25SBjoern A. Zeeb sizeof(req), true);
3701cbb3ec25SBjoern A. Zeeb }
3702cbb3ec25SBjoern A. Zeeb
mt7915_mcu_add_obss_spr(struct mt7915_phy * phy,struct ieee80211_vif * vif,struct ieee80211_he_obss_pd * he_obss_pd)3703cbb3ec25SBjoern A. Zeeb int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
3704cbb3ec25SBjoern A. Zeeb struct ieee80211_he_obss_pd *he_obss_pd)
3705cbb3ec25SBjoern A. Zeeb {
3706cbb3ec25SBjoern A. Zeeb int ret;
3707cbb3ec25SBjoern A. Zeeb
3708cbb3ec25SBjoern A. Zeeb /* enable firmware scene detection algorithms */
3709cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_SD, sr_scene_detect);
3710cbb3ec25SBjoern A. Zeeb if (ret)
3711cbb3ec25SBjoern A. Zeeb return ret;
3712cbb3ec25SBjoern A. Zeeb
3713cbb3ec25SBjoern A. Zeeb /* firmware dynamically adjusts PD threshold so skip manual control */
3714cbb3ec25SBjoern A. Zeeb if (sr_scene_detect && !he_obss_pd->enable)
3715cbb3ec25SBjoern A. Zeeb return 0;
3716cbb3ec25SBjoern A. Zeeb
3717cbb3ec25SBjoern A. Zeeb /* enable spatial reuse */
3718cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE, he_obss_pd->enable);
3719cbb3ec25SBjoern A. Zeeb if (ret)
3720cbb3ec25SBjoern A. Zeeb return ret;
3721cbb3ec25SBjoern A. Zeeb
3722cbb3ec25SBjoern A. Zeeb if (sr_scene_detect || !he_obss_pd->enable)
3723cbb3ec25SBjoern A. Zeeb return 0;
3724cbb3ec25SBjoern A. Zeeb
3725cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_enable_obss_spr(phy, SPR_ENABLE_TX, true);
3726cbb3ec25SBjoern A. Zeeb if (ret)
3727cbb3ec25SBjoern A. Zeeb return ret;
3728cbb3ec25SBjoern A. Zeeb
3729cbb3ec25SBjoern A. Zeeb /* set SRG/non-SRG OBSS PD threshold */
3730cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_obss_spr_pd(phy, he_obss_pd);
3731cbb3ec25SBjoern A. Zeeb if (ret)
3732cbb3ec25SBjoern A. Zeeb return ret;
3733cbb3ec25SBjoern A. Zeeb
3734cbb3ec25SBjoern A. Zeeb /* Set SR prohibit */
3735cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_obss_spr_siga(phy, vif, he_obss_pd);
3736cbb3ec25SBjoern A. Zeeb if (ret)
3737cbb3ec25SBjoern A. Zeeb return ret;
3738cbb3ec25SBjoern A. Zeeb
3739cbb3ec25SBjoern A. Zeeb /* set SRG BSS color/BSSID bitmap */
3740cbb3ec25SBjoern A. Zeeb return mt7915_mcu_set_obss_spr_bitmap(phy, he_obss_pd);
3741cbb3ec25SBjoern A. Zeeb }
3742cbb3ec25SBjoern A. Zeeb
mt7915_mcu_get_rx_rate(struct mt7915_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct rate_info * rate)37436c92544dSBjoern A. Zeeb int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
37446c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, struct rate_info *rate)
37456c92544dSBjoern A. Zeeb {
37466c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
37476c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
37486c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
37496c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
37506c92544dSBjoern A. Zeeb struct {
37516c92544dSBjoern A. Zeeb u8 category;
37526c92544dSBjoern A. Zeeb u8 band;
37536c92544dSBjoern A. Zeeb __le16 wcid;
37546c92544dSBjoern A. Zeeb } __packed req = {
37556c92544dSBjoern A. Zeeb .category = MCU_PHY_STATE_CONTENTION_RX_RATE,
37566c92544dSBjoern A. Zeeb .band = mvif->mt76.band_idx,
37576c92544dSBjoern A. Zeeb .wcid = cpu_to_le16(msta->wcid.idx),
37586c92544dSBjoern A. Zeeb };
37596c92544dSBjoern A. Zeeb struct ieee80211_supported_band *sband;
37606c92544dSBjoern A. Zeeb struct mt7915_mcu_phy_rx_info *res;
37616c92544dSBjoern A. Zeeb struct sk_buff *skb;
37626c92544dSBjoern A. Zeeb int ret;
37636c92544dSBjoern A. Zeeb bool cck = false;
37646c92544dSBjoern A. Zeeb
37656c92544dSBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(PHY_STAT_INFO),
37666c92544dSBjoern A. Zeeb &req, sizeof(req), true, &skb);
37676c92544dSBjoern A. Zeeb if (ret)
37686c92544dSBjoern A. Zeeb return ret;
37696c92544dSBjoern A. Zeeb
37706c92544dSBjoern A. Zeeb res = (struct mt7915_mcu_phy_rx_info *)skb->data;
37716c92544dSBjoern A. Zeeb
37726c92544dSBjoern A. Zeeb rate->mcs = res->rate;
37736c92544dSBjoern A. Zeeb rate->nss = res->nsts + 1;
37746c92544dSBjoern A. Zeeb
37756c92544dSBjoern A. Zeeb switch (res->mode) {
37766c92544dSBjoern A. Zeeb case MT_PHY_TYPE_CCK:
37776c92544dSBjoern A. Zeeb cck = true;
37786c92544dSBjoern A. Zeeb fallthrough;
37796c92544dSBjoern A. Zeeb case MT_PHY_TYPE_OFDM:
37806c92544dSBjoern A. Zeeb if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
37816c92544dSBjoern A. Zeeb sband = &mphy->sband_5g.sband;
37826c92544dSBjoern A. Zeeb else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
37836c92544dSBjoern A. Zeeb sband = &mphy->sband_6g.sband;
37846c92544dSBjoern A. Zeeb else
37856c92544dSBjoern A. Zeeb sband = &mphy->sband_2g.sband;
37866c92544dSBjoern A. Zeeb
37876c92544dSBjoern A. Zeeb rate->mcs = mt76_get_rate(&dev->mt76, sband, rate->mcs, cck);
37886c92544dSBjoern A. Zeeb rate->legacy = sband->bitrates[rate->mcs].bitrate;
37896c92544dSBjoern A. Zeeb break;
37906c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HT:
37916c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HT_GF:
37926c92544dSBjoern A. Zeeb if (rate->mcs > 31) {
37936c92544dSBjoern A. Zeeb ret = -EINVAL;
37946c92544dSBjoern A. Zeeb goto out;
37956c92544dSBjoern A. Zeeb }
37966c92544dSBjoern A. Zeeb
37976c92544dSBjoern A. Zeeb rate->flags = RATE_INFO_FLAGS_MCS;
37986c92544dSBjoern A. Zeeb if (res->gi)
37996c92544dSBjoern A. Zeeb rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
38006c92544dSBjoern A. Zeeb break;
38016c92544dSBjoern A. Zeeb case MT_PHY_TYPE_VHT:
38026c92544dSBjoern A. Zeeb if (rate->mcs > 9) {
38036c92544dSBjoern A. Zeeb ret = -EINVAL;
38046c92544dSBjoern A. Zeeb goto out;
38056c92544dSBjoern A. Zeeb }
38066c92544dSBjoern A. Zeeb
38076c92544dSBjoern A. Zeeb rate->flags = RATE_INFO_FLAGS_VHT_MCS;
38086c92544dSBjoern A. Zeeb if (res->gi)
38096c92544dSBjoern A. Zeeb rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
38106c92544dSBjoern A. Zeeb break;
38116c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HE_SU:
38126c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HE_EXT_SU:
38136c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HE_TB:
38146c92544dSBjoern A. Zeeb case MT_PHY_TYPE_HE_MU:
38156c92544dSBjoern A. Zeeb if (res->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) {
38166c92544dSBjoern A. Zeeb ret = -EINVAL;
38176c92544dSBjoern A. Zeeb goto out;
38186c92544dSBjoern A. Zeeb }
38196c92544dSBjoern A. Zeeb rate->he_gi = res->gi;
38206c92544dSBjoern A. Zeeb rate->flags = RATE_INFO_FLAGS_HE_MCS;
38216c92544dSBjoern A. Zeeb break;
38226c92544dSBjoern A. Zeeb default:
38236c92544dSBjoern A. Zeeb ret = -EINVAL;
38246c92544dSBjoern A. Zeeb goto out;
38256c92544dSBjoern A. Zeeb }
38266c92544dSBjoern A. Zeeb
38276c92544dSBjoern A. Zeeb switch (res->bw) {
38286c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_160:
38296c92544dSBjoern A. Zeeb rate->bw = RATE_INFO_BW_160;
38306c92544dSBjoern A. Zeeb break;
38316c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_80:
38326c92544dSBjoern A. Zeeb rate->bw = RATE_INFO_BW_80;
38336c92544dSBjoern A. Zeeb break;
38346c92544dSBjoern A. Zeeb case IEEE80211_STA_RX_BW_40:
38356c92544dSBjoern A. Zeeb rate->bw = RATE_INFO_BW_40;
38366c92544dSBjoern A. Zeeb break;
38376c92544dSBjoern A. Zeeb default:
38386c92544dSBjoern A. Zeeb rate->bw = RATE_INFO_BW_20;
38396c92544dSBjoern A. Zeeb break;
38406c92544dSBjoern A. Zeeb }
38416c92544dSBjoern A. Zeeb
38426c92544dSBjoern A. Zeeb out:
38436c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
38446c92544dSBjoern A. Zeeb
38456c92544dSBjoern A. Zeeb return ret;
38466c92544dSBjoern A. Zeeb }
38476c92544dSBjoern A. Zeeb
mt7915_mcu_update_bss_color(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct cfg80211_he_bss_color * he_bss_color)38486c92544dSBjoern A. Zeeb int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
38496c92544dSBjoern A. Zeeb struct cfg80211_he_bss_color *he_bss_color)
38506c92544dSBjoern A. Zeeb {
38516c92544dSBjoern A. Zeeb int len = sizeof(struct sta_req_hdr) + sizeof(struct bss_info_color);
38526c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
38536c92544dSBjoern A. Zeeb struct bss_info_color *bss_color;
38546c92544dSBjoern A. Zeeb struct sk_buff *skb;
38556c92544dSBjoern A. Zeeb struct tlv *tlv;
38566c92544dSBjoern A. Zeeb
38576c92544dSBjoern A. Zeeb skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
38586c92544dSBjoern A. Zeeb NULL, len);
38596c92544dSBjoern A. Zeeb if (IS_ERR(skb))
38606c92544dSBjoern A. Zeeb return PTR_ERR(skb);
38616c92544dSBjoern A. Zeeb
38626c92544dSBjoern A. Zeeb tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR,
38636c92544dSBjoern A. Zeeb sizeof(*bss_color));
38646c92544dSBjoern A. Zeeb bss_color = (struct bss_info_color *)tlv;
38656c92544dSBjoern A. Zeeb bss_color->disable = !he_bss_color->enabled;
38666c92544dSBjoern A. Zeeb bss_color->color = he_bss_color->color;
38676c92544dSBjoern A. Zeeb
38686c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
38696c92544dSBjoern A. Zeeb MCU_EXT_CMD(BSS_INFO_UPDATE), true);
38706c92544dSBjoern A. Zeeb }
38716c92544dSBjoern A. Zeeb
38726c92544dSBjoern A. Zeeb #define TWT_AGRT_TRIGGER BIT(0)
38736c92544dSBjoern A. Zeeb #define TWT_AGRT_ANNOUNCE BIT(1)
38746c92544dSBjoern A. Zeeb #define TWT_AGRT_PROTECT BIT(2)
38756c92544dSBjoern A. Zeeb
mt7915_mcu_twt_agrt_update(struct mt7915_dev * dev,struct mt7915_vif * mvif,struct mt7915_twt_flow * flow,int cmd)38766c92544dSBjoern A. Zeeb int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
38776c92544dSBjoern A. Zeeb struct mt7915_vif *mvif,
38786c92544dSBjoern A. Zeeb struct mt7915_twt_flow *flow,
38796c92544dSBjoern A. Zeeb int cmd)
38806c92544dSBjoern A. Zeeb {
38816c92544dSBjoern A. Zeeb struct {
38826c92544dSBjoern A. Zeeb u8 tbl_idx;
38836c92544dSBjoern A. Zeeb u8 cmd;
38846c92544dSBjoern A. Zeeb u8 own_mac_idx;
38856c92544dSBjoern A. Zeeb u8 flowid; /* 0xff for group id */
38866c92544dSBjoern A. Zeeb __le16 peer_id; /* specify the peer_id (msb=0)
38876c92544dSBjoern A. Zeeb * or group_id (msb=1)
38886c92544dSBjoern A. Zeeb */
38896c92544dSBjoern A. Zeeb u8 duration; /* 256 us */
38906c92544dSBjoern A. Zeeb u8 bss_idx;
38916c92544dSBjoern A. Zeeb __le64 start_tsf;
38926c92544dSBjoern A. Zeeb __le16 mantissa;
38936c92544dSBjoern A. Zeeb u8 exponent;
38946c92544dSBjoern A. Zeeb u8 is_ap;
38956c92544dSBjoern A. Zeeb u8 agrt_params;
38966c92544dSBjoern A. Zeeb u8 rsv[23];
38976c92544dSBjoern A. Zeeb } __packed req = {
38986c92544dSBjoern A. Zeeb .tbl_idx = flow->table_id,
38996c92544dSBjoern A. Zeeb .cmd = cmd,
39006c92544dSBjoern A. Zeeb .own_mac_idx = mvif->mt76.omac_idx,
39016c92544dSBjoern A. Zeeb .flowid = flow->id,
39026c92544dSBjoern A. Zeeb .peer_id = cpu_to_le16(flow->wcid),
39036c92544dSBjoern A. Zeeb .duration = flow->duration,
39046c92544dSBjoern A. Zeeb .bss_idx = mvif->mt76.idx,
39056c92544dSBjoern A. Zeeb .start_tsf = cpu_to_le64(flow->tsf),
39066c92544dSBjoern A. Zeeb .mantissa = flow->mantissa,
39076c92544dSBjoern A. Zeeb .exponent = flow->exp,
39086c92544dSBjoern A. Zeeb .is_ap = true,
39096c92544dSBjoern A. Zeeb };
39106c92544dSBjoern A. Zeeb
39116c92544dSBjoern A. Zeeb if (flow->protection)
39126c92544dSBjoern A. Zeeb req.agrt_params |= TWT_AGRT_PROTECT;
39136c92544dSBjoern A. Zeeb if (!flow->flowtype)
39146c92544dSBjoern A. Zeeb req.agrt_params |= TWT_AGRT_ANNOUNCE;
39156c92544dSBjoern A. Zeeb if (flow->trigger)
39166c92544dSBjoern A. Zeeb req.agrt_params |= TWT_AGRT_TRIGGER;
39176c92544dSBjoern A. Zeeb
39186c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE),
39196c92544dSBjoern A. Zeeb &req, sizeof(req), true);
39206c92544dSBjoern A. Zeeb }
39216c92544dSBjoern A. Zeeb
mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev * dev,u16 wlan_idx)3922cbb3ec25SBjoern A. Zeeb int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
3923cbb3ec25SBjoern A. Zeeb {
3924cbb3ec25SBjoern A. Zeeb struct {
3925cbb3ec25SBjoern A. Zeeb __le32 cmd;
3926*8ba4d145SBjoern A. Zeeb __le32 arg0;
3927*8ba4d145SBjoern A. Zeeb __le32 arg1;
3928*8ba4d145SBjoern A. Zeeb __le16 arg2;
3929*8ba4d145SBjoern A. Zeeb } __packed req = {
3930cbb3ec25SBjoern A. Zeeb .cmd = cpu_to_le32(0x15),
3931cbb3ec25SBjoern A. Zeeb };
3932cbb3ec25SBjoern A. Zeeb struct mt7915_mcu_wa_tx_stat {
3933*8ba4d145SBjoern A. Zeeb __le16 wcid;
3934*8ba4d145SBjoern A. Zeeb u8 __rsv2[2];
3935cbb3ec25SBjoern A. Zeeb
3936cbb3ec25SBjoern A. Zeeb /* tx_bytes is deprecated since WA byte counter uses u32,
3937cbb3ec25SBjoern A. Zeeb * which easily leads to overflow.
3938cbb3ec25SBjoern A. Zeeb */
3939cbb3ec25SBjoern A. Zeeb __le32 tx_bytes;
3940cbb3ec25SBjoern A. Zeeb __le32 tx_packets;
3941*8ba4d145SBjoern A. Zeeb } __packed *res;
3942cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid;
3943cbb3ec25SBjoern A. Zeeb struct sk_buff *skb;
3944*8ba4d145SBjoern A. Zeeb int ret, len;
3945*8ba4d145SBjoern A. Zeeb u16 ret_wcid;
3946*8ba4d145SBjoern A. Zeeb
3947*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) {
3948*8ba4d145SBjoern A. Zeeb req.arg0 = cpu_to_le32(wlan_idx);
3949*8ba4d145SBjoern A. Zeeb len = sizeof(req) - sizeof(req.arg2);
3950*8ba4d145SBjoern A. Zeeb } else {
3951*8ba4d145SBjoern A. Zeeb req.arg0 = cpu_to_le32(1);
3952*8ba4d145SBjoern A. Zeeb req.arg2 = cpu_to_le16(wlan_idx);
3953*8ba4d145SBjoern A. Zeeb len = sizeof(req);
3954*8ba4d145SBjoern A. Zeeb }
3955cbb3ec25SBjoern A. Zeeb
3956cbb3ec25SBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
3957*8ba4d145SBjoern A. Zeeb &req, len, true, &skb);
3958cbb3ec25SBjoern A. Zeeb if (ret)
3959cbb3ec25SBjoern A. Zeeb return ret;
3960cbb3ec25SBjoern A. Zeeb
3961cbb3ec25SBjoern A. Zeeb if (!is_mt7915(&dev->mt76))
3962cbb3ec25SBjoern A. Zeeb skb_pull(skb, 4);
3963cbb3ec25SBjoern A. Zeeb
3964cbb3ec25SBjoern A. Zeeb res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
3965cbb3ec25SBjoern A. Zeeb
3966*8ba4d145SBjoern A. Zeeb ret_wcid = le16_to_cpu(res->wcid);
3967*8ba4d145SBjoern A. Zeeb if (is_mt7915(&dev->mt76))
3968*8ba4d145SBjoern A. Zeeb ret_wcid &= 0xff;
3969*8ba4d145SBjoern A. Zeeb
3970*8ba4d145SBjoern A. Zeeb if (ret_wcid != wlan_idx) {
3971cbb3ec25SBjoern A. Zeeb ret = -EINVAL;
3972cbb3ec25SBjoern A. Zeeb goto out;
3973cbb3ec25SBjoern A. Zeeb }
3974cbb3ec25SBjoern A. Zeeb
3975cbb3ec25SBjoern A. Zeeb rcu_read_lock();
3976cbb3ec25SBjoern A. Zeeb
3977cbb3ec25SBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
3978cbb3ec25SBjoern A. Zeeb if (wcid)
3979cbb3ec25SBjoern A. Zeeb wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
3980cbb3ec25SBjoern A. Zeeb else
3981cbb3ec25SBjoern A. Zeeb ret = -EINVAL;
3982cbb3ec25SBjoern A. Zeeb
3983cbb3ec25SBjoern A. Zeeb rcu_read_unlock();
3984cbb3ec25SBjoern A. Zeeb out:
3985cbb3ec25SBjoern A. Zeeb dev_kfree_skb(skb);
3986cbb3ec25SBjoern A. Zeeb
3987cbb3ec25SBjoern A. Zeeb return ret;
3988cbb3ec25SBjoern A. Zeeb }
3989cbb3ec25SBjoern A. Zeeb
mt7915_mcu_rf_regval(struct mt7915_dev * dev,u32 regidx,u32 * val,bool set)39906c92544dSBjoern A. Zeeb int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
39916c92544dSBjoern A. Zeeb {
39926c92544dSBjoern A. Zeeb struct {
39936c92544dSBjoern A. Zeeb __le32 idx;
39946c92544dSBjoern A. Zeeb __le32 ofs;
39956c92544dSBjoern A. Zeeb __le32 data;
39966c92544dSBjoern A. Zeeb } __packed req = {
3997cbb3ec25SBjoern A. Zeeb .idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 24))),
3998cbb3ec25SBjoern A. Zeeb .ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(23, 0))),
39996c92544dSBjoern A. Zeeb .data = set ? cpu_to_le32(*val) : 0,
40006c92544dSBjoern A. Zeeb };
40016c92544dSBjoern A. Zeeb struct sk_buff *skb;
40026c92544dSBjoern A. Zeeb int ret;
40036c92544dSBjoern A. Zeeb
40046c92544dSBjoern A. Zeeb if (set)
40056c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),
40066c92544dSBjoern A. Zeeb &req, sizeof(req), false);
40076c92544dSBjoern A. Zeeb
40086c92544dSBjoern A. Zeeb ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),
40096c92544dSBjoern A. Zeeb &req, sizeof(req), true, &skb);
40106c92544dSBjoern A. Zeeb if (ret)
40116c92544dSBjoern A. Zeeb return ret;
40126c92544dSBjoern A. Zeeb
40136c92544dSBjoern A. Zeeb *val = le32_to_cpu(*(__le32 *)(skb->data + 8));
40146c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
40156c92544dSBjoern A. Zeeb
40166c92544dSBjoern A. Zeeb return 0;
40176c92544dSBjoern A. Zeeb }
4018