16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2019 MediaTek Inc.
36c92544dSBjoern A. Zeeb *
46c92544dSBjoern A. Zeeb * Author: Roy Luo <royluo@google.com>
56c92544dSBjoern A. Zeeb * Ryder Lee <ryder.lee@mediatek.com>
66c92544dSBjoern A. Zeeb */
76c92544dSBjoern A. Zeeb
86c92544dSBjoern A. Zeeb #include <linux/firmware.h>
96c92544dSBjoern A. Zeeb #include "mt7615.h"
106c92544dSBjoern A. Zeeb #include "mcu.h"
116c92544dSBjoern A. Zeeb #include "mac.h"
126c92544dSBjoern A. Zeeb #include "eeprom.h"
136c92544dSBjoern A. Zeeb
146c92544dSBjoern A. Zeeb static bool prefer_offload_fw = true;
156c92544dSBjoern A. Zeeb module_param(prefer_offload_fw, bool, 0644);
166c92544dSBjoern A. Zeeb MODULE_PARM_DESC(prefer_offload_fw,
176c92544dSBjoern A. Zeeb "Prefer client mode offload firmware (MT7663)");
186c92544dSBjoern A. Zeeb
196c92544dSBjoern A. Zeeb struct mt7615_patch_hdr {
206c92544dSBjoern A. Zeeb char build_date[16];
216c92544dSBjoern A. Zeeb char platform[4];
226c92544dSBjoern A. Zeeb __be32 hw_sw_ver;
236c92544dSBjoern A. Zeeb __be32 patch_ver;
246c92544dSBjoern A. Zeeb __be16 checksum;
256c92544dSBjoern A. Zeeb } __packed;
266c92544dSBjoern A. Zeeb
276c92544dSBjoern A. Zeeb struct mt7615_fw_trailer {
286c92544dSBjoern A. Zeeb __le32 addr;
296c92544dSBjoern A. Zeeb u8 chip_id;
306c92544dSBjoern A. Zeeb u8 feature_set;
316c92544dSBjoern A. Zeeb u8 eco_code;
326c92544dSBjoern A. Zeeb char fw_ver[10];
336c92544dSBjoern A. Zeeb char build_date[15];
346c92544dSBjoern A. Zeeb __le32 len;
356c92544dSBjoern A. Zeeb } __packed;
366c92544dSBjoern A. Zeeb
376c92544dSBjoern A. Zeeb #define FW_V3_COMMON_TAILER_SIZE 36
386c92544dSBjoern A. Zeeb #define FW_V3_REGION_TAILER_SIZE 40
396c92544dSBjoern A. Zeeb #define FW_START_OVERRIDE BIT(0)
406c92544dSBjoern A. Zeeb #define FW_START_DLYCAL BIT(1)
416c92544dSBjoern A. Zeeb #define FW_START_WORKING_PDA_CR4 BIT(2)
426c92544dSBjoern A. Zeeb
436c92544dSBjoern A. Zeeb struct mt7663_fw_buf {
446c92544dSBjoern A. Zeeb __le32 crc;
456c92544dSBjoern A. Zeeb __le32 d_img_size;
466c92544dSBjoern A. Zeeb __le32 block_size;
476c92544dSBjoern A. Zeeb u8 rsv[4];
486c92544dSBjoern A. Zeeb __le32 img_dest_addr;
496c92544dSBjoern A. Zeeb __le32 img_size;
506c92544dSBjoern A. Zeeb u8 feature_set;
516c92544dSBjoern A. Zeeb };
526c92544dSBjoern A. Zeeb
536c92544dSBjoern A. Zeeb #define MT7615_PATCH_ADDRESS 0x80000
546c92544dSBjoern A. Zeeb #define MT7622_PATCH_ADDRESS 0x9c000
556c92544dSBjoern A. Zeeb #define MT7663_PATCH_ADDRESS 0xdc000
566c92544dSBjoern A. Zeeb
576c92544dSBjoern A. Zeeb #define N9_REGION_NUM 2
586c92544dSBjoern A. Zeeb #define CR4_REGION_NUM 1
596c92544dSBjoern A. Zeeb
606c92544dSBjoern A. Zeeb #define IMG_CRC_LEN 4
616c92544dSBjoern A. Zeeb
mt7615_mcu_fill_msg(struct mt7615_dev * dev,struct sk_buff * skb,int cmd,int * wait_seq)626c92544dSBjoern A. Zeeb void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
636c92544dSBjoern A. Zeeb int cmd, int *wait_seq)
646c92544dSBjoern A. Zeeb {
656c92544dSBjoern A. Zeeb int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);
666c92544dSBjoern A. Zeeb struct mt7615_uni_txd *uni_txd;
676c92544dSBjoern A. Zeeb struct mt7615_mcu_txd *mcu_txd;
686c92544dSBjoern A. Zeeb u8 seq, q_idx, pkt_fmt;
696c92544dSBjoern A. Zeeb __le32 *txd;
706c92544dSBjoern A. Zeeb u32 val;
716c92544dSBjoern A. Zeeb
726c92544dSBjoern A. Zeeb /* TODO: make dynamic based on msg type */
736c92544dSBjoern A. Zeeb dev->mt76.mcu.timeout = 20 * HZ;
746c92544dSBjoern A. Zeeb
756c92544dSBjoern A. Zeeb seq = ++dev->mt76.mcu.msg_seq & 0xf;
766c92544dSBjoern A. Zeeb if (!seq)
776c92544dSBjoern A. Zeeb seq = ++dev->mt76.mcu.msg_seq & 0xf;
786c92544dSBjoern A. Zeeb if (wait_seq)
796c92544dSBjoern A. Zeeb *wait_seq = seq;
806c92544dSBjoern A. Zeeb
816c92544dSBjoern A. Zeeb txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
826c92544dSBjoern A. Zeeb txd = (__le32 *)skb_push(skb, txd_len);
836c92544dSBjoern A. Zeeb
846c92544dSBjoern A. Zeeb if (cmd != MCU_CMD(FW_SCATTER)) {
856c92544dSBjoern A. Zeeb q_idx = MT_TX_MCU_PORT_RX_Q0;
866c92544dSBjoern A. Zeeb pkt_fmt = MT_TX_TYPE_CMD;
876c92544dSBjoern A. Zeeb } else {
886c92544dSBjoern A. Zeeb q_idx = MT_TX_MCU_PORT_RX_FWDL;
896c92544dSBjoern A. Zeeb pkt_fmt = MT_TX_TYPE_FW;
906c92544dSBjoern A. Zeeb }
916c92544dSBjoern A. Zeeb
926c92544dSBjoern A. Zeeb val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
936c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) |
946c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
956c92544dSBjoern A. Zeeb txd[0] = cpu_to_le32(val);
966c92544dSBjoern A. Zeeb
976c92544dSBjoern A. Zeeb val = MT_TXD1_LONG_FORMAT |
986c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD) |
996c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt);
1006c92544dSBjoern A. Zeeb txd[1] = cpu_to_le32(val);
1016c92544dSBjoern A. Zeeb
1026c92544dSBjoern A. Zeeb if (cmd & __MCU_CMD_FIELD_UNI) {
1036c92544dSBjoern A. Zeeb uni_txd = (struct mt7615_uni_txd *)txd;
1046c92544dSBjoern A. Zeeb uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
1056c92544dSBjoern A. Zeeb uni_txd->option = MCU_CMD_UNI_EXT_ACK;
1066c92544dSBjoern A. Zeeb uni_txd->cid = cpu_to_le16(mcu_cmd);
1076c92544dSBjoern A. Zeeb uni_txd->s2d_index = MCU_S2D_H2N;
1086c92544dSBjoern A. Zeeb uni_txd->pkt_type = MCU_PKT_ID;
1096c92544dSBjoern A. Zeeb uni_txd->seq = seq;
1106c92544dSBjoern A. Zeeb
1116c92544dSBjoern A. Zeeb return;
1126c92544dSBjoern A. Zeeb }
1136c92544dSBjoern A. Zeeb
1146c92544dSBjoern A. Zeeb mcu_txd = (struct mt7615_mcu_txd *)txd;
1156c92544dSBjoern A. Zeeb mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));
1166c92544dSBjoern A. Zeeb mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, q_idx));
1176c92544dSBjoern A. Zeeb mcu_txd->s2d_index = MCU_S2D_H2N;
1186c92544dSBjoern A. Zeeb mcu_txd->pkt_type = MCU_PKT_ID;
1196c92544dSBjoern A. Zeeb mcu_txd->seq = seq;
1206c92544dSBjoern A. Zeeb mcu_txd->cid = mcu_cmd;
1216c92544dSBjoern A. Zeeb mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);
1226c92544dSBjoern A. Zeeb
1236c92544dSBjoern A. Zeeb if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {
1246c92544dSBjoern A. Zeeb if (cmd & __MCU_CMD_FIELD_QUERY)
1256c92544dSBjoern A. Zeeb mcu_txd->set_query = MCU_Q_QUERY;
1266c92544dSBjoern A. Zeeb else
1276c92544dSBjoern A. Zeeb mcu_txd->set_query = MCU_Q_SET;
1286c92544dSBjoern A. Zeeb mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;
1296c92544dSBjoern A. Zeeb } else {
1306c92544dSBjoern A. Zeeb mcu_txd->set_query = MCU_Q_NA;
1316c92544dSBjoern A. Zeeb }
1326c92544dSBjoern A. Zeeb }
1336c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_mcu_fill_msg);
1346c92544dSBjoern A. Zeeb
mt7615_mcu_parse_response(struct mt76_dev * mdev,int cmd,struct sk_buff * skb,int seq)1356c92544dSBjoern A. Zeeb int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
1366c92544dSBjoern A. Zeeb struct sk_buff *skb, int seq)
1376c92544dSBjoern A. Zeeb {
1386c92544dSBjoern A. Zeeb struct mt7615_mcu_rxd *rxd;
1396c92544dSBjoern A. Zeeb int ret = 0;
1406c92544dSBjoern A. Zeeb
1416c92544dSBjoern A. Zeeb if (!skb) {
1426c92544dSBjoern A. Zeeb dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
1436c92544dSBjoern A. Zeeb cmd, seq);
1446c92544dSBjoern A. Zeeb return -ETIMEDOUT;
1456c92544dSBjoern A. Zeeb }
1466c92544dSBjoern A. Zeeb
1476c92544dSBjoern A. Zeeb rxd = (struct mt7615_mcu_rxd *)skb->data;
1486c92544dSBjoern A. Zeeb if (seq != rxd->seq)
1496c92544dSBjoern A. Zeeb return -EAGAIN;
1506c92544dSBjoern A. Zeeb
1516c92544dSBjoern A. Zeeb if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
1526c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd) - 4);
1536c92544dSBjoern A. Zeeb ret = *skb->data;
1546c92544dSBjoern A. Zeeb } else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
1556c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd));
1566c92544dSBjoern A. Zeeb ret = le32_to_cpu(*(__le32 *)skb->data);
1576c92544dSBjoern A. Zeeb } else if (cmd == MCU_EXT_QUERY(RF_REG_ACCESS)) {
1586c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd));
1596c92544dSBjoern A. Zeeb ret = le32_to_cpu(*(__le32 *)&skb->data[8]);
1606c92544dSBjoern A. Zeeb } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||
1616c92544dSBjoern A. Zeeb cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||
1626c92544dSBjoern A. Zeeb cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||
1636c92544dSBjoern A. Zeeb cmd == MCU_UNI_CMD(HIF_CTRL) ||
1646c92544dSBjoern A. Zeeb cmd == MCU_UNI_CMD(OFFLOAD) ||
1656c92544dSBjoern A. Zeeb cmd == MCU_UNI_CMD(SUSPEND)) {
166cbb3ec25SBjoern A. Zeeb struct mt76_connac_mcu_uni_event *event;
1676c92544dSBjoern A. Zeeb
1686c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd));
169cbb3ec25SBjoern A. Zeeb event = (struct mt76_connac_mcu_uni_event *)skb->data;
1706c92544dSBjoern A. Zeeb ret = le32_to_cpu(event->status);
1716c92544dSBjoern A. Zeeb } else if (cmd == MCU_CE_QUERY(REG_READ)) {
172cbb3ec25SBjoern A. Zeeb struct mt76_connac_mcu_reg_event *event;
1736c92544dSBjoern A. Zeeb
1746c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(*rxd));
175cbb3ec25SBjoern A. Zeeb event = (struct mt76_connac_mcu_reg_event *)skb->data;
1766c92544dSBjoern A. Zeeb ret = (int)le32_to_cpu(event->val);
1776c92544dSBjoern A. Zeeb }
1786c92544dSBjoern A. Zeeb
1796c92544dSBjoern A. Zeeb return ret;
1806c92544dSBjoern A. Zeeb }
1816c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_mcu_parse_response);
1826c92544dSBjoern A. Zeeb
1836c92544dSBjoern A. Zeeb static int
mt7615_mcu_send_message(struct mt76_dev * mdev,struct sk_buff * skb,int cmd,int * seq)1846c92544dSBjoern A. Zeeb mt7615_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
1856c92544dSBjoern A. Zeeb int cmd, int *seq)
1866c92544dSBjoern A. Zeeb {
1876c92544dSBjoern A. Zeeb struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
1886c92544dSBjoern A. Zeeb enum mt76_mcuq_id qid;
1896c92544dSBjoern A. Zeeb
1906c92544dSBjoern A. Zeeb mt7615_mcu_fill_msg(dev, skb, cmd, seq);
1916c92544dSBjoern A. Zeeb if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
1926c92544dSBjoern A. Zeeb qid = MT_MCUQ_WM;
1936c92544dSBjoern A. Zeeb else
1946c92544dSBjoern A. Zeeb qid = MT_MCUQ_FWDL;
1956c92544dSBjoern A. Zeeb
1966c92544dSBjoern A. Zeeb return mt76_tx_queue_skb_raw(dev, dev->mt76.q_mcu[qid], skb, 0);
1976c92544dSBjoern A. Zeeb }
1986c92544dSBjoern A. Zeeb
mt7615_rf_rr(struct mt7615_dev * dev,u32 wf,u32 reg)1996c92544dSBjoern A. Zeeb u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg)
2006c92544dSBjoern A. Zeeb {
2016c92544dSBjoern A. Zeeb struct {
2026c92544dSBjoern A. Zeeb __le32 wifi_stream;
2036c92544dSBjoern A. Zeeb __le32 address;
2046c92544dSBjoern A. Zeeb __le32 data;
2056c92544dSBjoern A. Zeeb } req = {
2066c92544dSBjoern A. Zeeb .wifi_stream = cpu_to_le32(wf),
2076c92544dSBjoern A. Zeeb .address = cpu_to_le32(reg),
2086c92544dSBjoern A. Zeeb };
2096c92544dSBjoern A. Zeeb
2106c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),
2116c92544dSBjoern A. Zeeb &req, sizeof(req), true);
2126c92544dSBjoern A. Zeeb }
2136c92544dSBjoern A. Zeeb
mt7615_rf_wr(struct mt7615_dev * dev,u32 wf,u32 reg,u32 val)2146c92544dSBjoern A. Zeeb int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val)
2156c92544dSBjoern A. Zeeb {
2166c92544dSBjoern A. Zeeb struct {
2176c92544dSBjoern A. Zeeb __le32 wifi_stream;
2186c92544dSBjoern A. Zeeb __le32 address;
2196c92544dSBjoern A. Zeeb __le32 data;
2206c92544dSBjoern A. Zeeb } req = {
2216c92544dSBjoern A. Zeeb .wifi_stream = cpu_to_le32(wf),
2226c92544dSBjoern A. Zeeb .address = cpu_to_le32(reg),
2236c92544dSBjoern A. Zeeb .data = cpu_to_le32(val),
2246c92544dSBjoern A. Zeeb };
2256c92544dSBjoern A. Zeeb
2266c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),
2276c92544dSBjoern A. Zeeb &req, sizeof(req), false);
2286c92544dSBjoern A. Zeeb }
2296c92544dSBjoern A. Zeeb
mt7622_trigger_hif_int(struct mt7615_dev * dev,bool en)2306c92544dSBjoern A. Zeeb void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
2316c92544dSBjoern A. Zeeb {
2326c92544dSBjoern A. Zeeb if (!is_mt7622(&dev->mt76))
2336c92544dSBjoern A. Zeeb return;
2346c92544dSBjoern A. Zeeb
23577285868SBjoern A. Zeeb #if defined(__linux__)
2366c92544dSBjoern A. Zeeb regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC,
2376c92544dSBjoern A. Zeeb MT_INFRACFG_MISC_AP2CONN_WAKE,
2386c92544dSBjoern A. Zeeb !en * MT_INFRACFG_MISC_AP2CONN_WAKE);
23977285868SBjoern A. Zeeb #elif defined(__FreeBSD__)
24077285868SBjoern A. Zeeb panic("%s: LinuxKPI needs regmap\n", __func__);
24177285868SBjoern A. Zeeb #endif
2426c92544dSBjoern A. Zeeb }
2436c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int);
2446c92544dSBjoern A. Zeeb
mt7615_mcu_drv_pmctrl(struct mt7615_dev * dev)2456c92544dSBjoern A. Zeeb static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
2466c92544dSBjoern A. Zeeb {
2476c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
2486c92544dSBjoern A. Zeeb struct mt76_connac_pm *pm = &dev->pm;
2496c92544dSBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76;
2506c92544dSBjoern A. Zeeb u32 addr;
2516c92544dSBjoern A. Zeeb int err;
2526c92544dSBjoern A. Zeeb
2536c92544dSBjoern A. Zeeb if (is_mt7663(mdev)) {
2546c92544dSBjoern A. Zeeb /* Clear firmware own via N9 eint */
2556c92544dSBjoern A. Zeeb mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);
2566c92544dSBjoern A. Zeeb mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
2576c92544dSBjoern A. Zeeb
2586c92544dSBjoern A. Zeeb addr = MT_CONN_HIF_ON_LPCTL;
2596c92544dSBjoern A. Zeeb } else {
2606c92544dSBjoern A. Zeeb addr = MT_CFG_LPCR_HOST;
2616c92544dSBjoern A. Zeeb }
2626c92544dSBjoern A. Zeeb
2636c92544dSBjoern A. Zeeb mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);
2646c92544dSBjoern A. Zeeb
2656c92544dSBjoern A. Zeeb mt7622_trigger_hif_int(dev, true);
2666c92544dSBjoern A. Zeeb
2676c92544dSBjoern A. Zeeb err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
2686c92544dSBjoern A. Zeeb
2696c92544dSBjoern A. Zeeb mt7622_trigger_hif_int(dev, false);
2706c92544dSBjoern A. Zeeb
2716c92544dSBjoern A. Zeeb if (err) {
2726c92544dSBjoern A. Zeeb dev_err(mdev->dev, "driver own failed\n");
2736c92544dSBjoern A. Zeeb return -ETIMEDOUT;
2746c92544dSBjoern A. Zeeb }
2756c92544dSBjoern A. Zeeb
2766c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_PM, &mphy->state);
2776c92544dSBjoern A. Zeeb
2786c92544dSBjoern A. Zeeb pm->stats.last_wake_event = jiffies;
2796c92544dSBjoern A. Zeeb pm->stats.doze_time += pm->stats.last_wake_event -
2806c92544dSBjoern A. Zeeb pm->stats.last_doze_event;
2816c92544dSBjoern A. Zeeb
2826c92544dSBjoern A. Zeeb return 0;
2836c92544dSBjoern A. Zeeb }
2846c92544dSBjoern A. Zeeb
mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev * dev)2856c92544dSBjoern A. Zeeb static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)
2866c92544dSBjoern A. Zeeb {
2876c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
2886c92544dSBjoern A. Zeeb struct mt76_connac_pm *pm = &dev->pm;
2896c92544dSBjoern A. Zeeb int i, err = 0;
2906c92544dSBjoern A. Zeeb
2916c92544dSBjoern A. Zeeb mutex_lock(&pm->mutex);
2926c92544dSBjoern A. Zeeb
2936c92544dSBjoern A. Zeeb if (!test_bit(MT76_STATE_PM, &mphy->state))
2946c92544dSBjoern A. Zeeb goto out;
2956c92544dSBjoern A. Zeeb
2966c92544dSBjoern A. Zeeb for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {
2976c92544dSBjoern A. Zeeb mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);
2986c92544dSBjoern A. Zeeb if (mt76_poll_msec(dev, MT_CONN_HIF_ON_LPCTL,
2996c92544dSBjoern A. Zeeb MT_CFG_LPCR_HOST_FW_OWN, 0, 50))
3006c92544dSBjoern A. Zeeb break;
3016c92544dSBjoern A. Zeeb }
3026c92544dSBjoern A. Zeeb
3036c92544dSBjoern A. Zeeb if (i == MT7615_DRV_OWN_RETRY_COUNT) {
3046c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "driver own failed\n");
3056c92544dSBjoern A. Zeeb err = -EIO;
3066c92544dSBjoern A. Zeeb goto out;
3076c92544dSBjoern A. Zeeb }
3086c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_PM, &mphy->state);
3096c92544dSBjoern A. Zeeb
3106c92544dSBjoern A. Zeeb pm->stats.last_wake_event = jiffies;
3116c92544dSBjoern A. Zeeb pm->stats.doze_time += pm->stats.last_wake_event -
3126c92544dSBjoern A. Zeeb pm->stats.last_doze_event;
3136c92544dSBjoern A. Zeeb out:
3146c92544dSBjoern A. Zeeb mutex_unlock(&pm->mutex);
3156c92544dSBjoern A. Zeeb
3166c92544dSBjoern A. Zeeb return err;
3176c92544dSBjoern A. Zeeb }
3186c92544dSBjoern A. Zeeb
mt7615_mcu_fw_pmctrl(struct mt7615_dev * dev)3196c92544dSBjoern A. Zeeb static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)
3206c92544dSBjoern A. Zeeb {
3216c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
3226c92544dSBjoern A. Zeeb struct mt76_connac_pm *pm = &dev->pm;
3236c92544dSBjoern A. Zeeb int err = 0;
3246c92544dSBjoern A. Zeeb u32 addr;
3256c92544dSBjoern A. Zeeb
3266c92544dSBjoern A. Zeeb mutex_lock(&pm->mutex);
3276c92544dSBjoern A. Zeeb
3286c92544dSBjoern A. Zeeb if (mt76_connac_skip_fw_pmctrl(mphy, pm))
3296c92544dSBjoern A. Zeeb goto out;
3306c92544dSBjoern A. Zeeb
3316c92544dSBjoern A. Zeeb mt7622_trigger_hif_int(dev, true);
3326c92544dSBjoern A. Zeeb
3336c92544dSBjoern A. Zeeb addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
3346c92544dSBjoern A. Zeeb mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN);
3356c92544dSBjoern A. Zeeb
3366c92544dSBjoern A. Zeeb if (is_mt7622(&dev->mt76) &&
3376c92544dSBjoern A. Zeeb !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN,
3386c92544dSBjoern A. Zeeb MT_CFG_LPCR_HOST_FW_OWN, 3000)) {
3396c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for firmware own\n");
3406c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_PM, &mphy->state);
3416c92544dSBjoern A. Zeeb err = -EIO;
3426c92544dSBjoern A. Zeeb }
3436c92544dSBjoern A. Zeeb
3446c92544dSBjoern A. Zeeb mt7622_trigger_hif_int(dev, false);
3456c92544dSBjoern A. Zeeb if (!err) {
3466c92544dSBjoern A. Zeeb pm->stats.last_doze_event = jiffies;
3476c92544dSBjoern A. Zeeb pm->stats.awake_time += pm->stats.last_doze_event -
3486c92544dSBjoern A. Zeeb pm->stats.last_wake_event;
3496c92544dSBjoern A. Zeeb }
3506c92544dSBjoern A. Zeeb out:
3516c92544dSBjoern A. Zeeb mutex_unlock(&pm->mutex);
3526c92544dSBjoern A. Zeeb
3536c92544dSBjoern A. Zeeb return err;
3546c92544dSBjoern A. Zeeb }
3556c92544dSBjoern A. Zeeb
3566c92544dSBjoern A. Zeeb static void
mt7615_mcu_csa_finish(void * priv,u8 * mac,struct ieee80211_vif * vif)3576c92544dSBjoern A. Zeeb mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
3586c92544dSBjoern A. Zeeb {
3596c92544dSBjoern A. Zeeb if (vif->bss_conf.csa_active)
360*8ba4d145SBjoern A. Zeeb ieee80211_csa_finish(vif, 0);
3616c92544dSBjoern A. Zeeb }
3626c92544dSBjoern A. Zeeb
3636c92544dSBjoern A. Zeeb static void
mt7615_mcu_rx_csa_notify(struct mt7615_dev * dev,struct sk_buff * skb)3646c92544dSBjoern A. Zeeb mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb)
3656c92544dSBjoern A. Zeeb {
3666c92544dSBjoern A. Zeeb struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);
3676c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
3686c92544dSBjoern A. Zeeb struct mt7615_mcu_csa_notify *c;
3696c92544dSBjoern A. Zeeb
3706c92544dSBjoern A. Zeeb c = (struct mt7615_mcu_csa_notify *)skb->data;
3716c92544dSBjoern A. Zeeb
3726c92544dSBjoern A. Zeeb if (c->omac_idx > EXT_BSSID_MAX)
3736c92544dSBjoern A. Zeeb return;
3746c92544dSBjoern A. Zeeb
3756c92544dSBjoern A. Zeeb if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
3766c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
3776c92544dSBjoern A. Zeeb
3786c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(mphy->hw,
3796c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
3806c92544dSBjoern A. Zeeb mt7615_mcu_csa_finish, mphy->hw);
3816c92544dSBjoern A. Zeeb }
3826c92544dSBjoern A. Zeeb
3836c92544dSBjoern A. Zeeb static void
mt7615_mcu_rx_radar_detected(struct mt7615_dev * dev,struct sk_buff * skb)3846c92544dSBjoern A. Zeeb mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
3856c92544dSBjoern A. Zeeb {
3866c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy;
3876c92544dSBjoern A. Zeeb struct mt7615_mcu_rdd_report *r;
3886c92544dSBjoern A. Zeeb
3896c92544dSBjoern A. Zeeb r = (struct mt7615_mcu_rdd_report *)skb->data;
3906c92544dSBjoern A. Zeeb
3916c92544dSBjoern A. Zeeb if (!dev->radar_pattern.n_pulses && !r->long_detected &&
3926c92544dSBjoern A. Zeeb !r->constant_prf_detected && !r->staggered_prf_detected)
3936c92544dSBjoern A. Zeeb return;
3946c92544dSBjoern A. Zeeb
3956c92544dSBjoern A. Zeeb if (r->band_idx && dev->mt76.phys[MT_BAND1])
3966c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
3976c92544dSBjoern A. Zeeb
3986c92544dSBjoern A. Zeeb if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
3996c92544dSBjoern A. Zeeb return;
4006c92544dSBjoern A. Zeeb
401*8ba4d145SBjoern A. Zeeb ieee80211_radar_detected(mphy->hw, NULL);
4026c92544dSBjoern A. Zeeb dev->hw_pattern++;
4036c92544dSBjoern A. Zeeb }
4046c92544dSBjoern A. Zeeb
4056c92544dSBjoern A. Zeeb static void
mt7615_mcu_rx_log_message(struct mt7615_dev * dev,struct sk_buff * skb)4066c92544dSBjoern A. Zeeb mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb)
4076c92544dSBjoern A. Zeeb {
4086c92544dSBjoern A. Zeeb struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
4096c92544dSBjoern A. Zeeb const char *data = (char *)&rxd[1];
4106c92544dSBjoern A. Zeeb const char *type;
4116c92544dSBjoern A. Zeeb
4126c92544dSBjoern A. Zeeb switch (rxd->s2d_index) {
4136c92544dSBjoern A. Zeeb case 0:
4146c92544dSBjoern A. Zeeb type = "N9";
4156c92544dSBjoern A. Zeeb break;
4166c92544dSBjoern A. Zeeb case 2:
4176c92544dSBjoern A. Zeeb type = "CR4";
4186c92544dSBjoern A. Zeeb break;
4196c92544dSBjoern A. Zeeb default:
4206c92544dSBjoern A. Zeeb type = "unknown";
4216c92544dSBjoern A. Zeeb break;
4226c92544dSBjoern A. Zeeb }
4236c92544dSBjoern A. Zeeb
4246c92544dSBjoern A. Zeeb wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type,
4256c92544dSBjoern A. Zeeb (int)(skb->len - sizeof(*rxd)), data);
4266c92544dSBjoern A. Zeeb }
4276c92544dSBjoern A. Zeeb
4286c92544dSBjoern A. Zeeb static void
mt7615_mcu_rx_ext_event(struct mt7615_dev * dev,struct sk_buff * skb)4296c92544dSBjoern A. Zeeb mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
4306c92544dSBjoern A. Zeeb {
4316c92544dSBjoern A. Zeeb struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
4326c92544dSBjoern A. Zeeb
4336c92544dSBjoern A. Zeeb switch (rxd->ext_eid) {
4346c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_RDD_REPORT:
4356c92544dSBjoern A. Zeeb mt7615_mcu_rx_radar_detected(dev, skb);
4366c92544dSBjoern A. Zeeb break;
4376c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_CSA_NOTIFY:
4386c92544dSBjoern A. Zeeb mt7615_mcu_rx_csa_notify(dev, skb);
4396c92544dSBjoern A. Zeeb break;
4406c92544dSBjoern A. Zeeb case MCU_EXT_EVENT_FW_LOG_2_HOST:
4416c92544dSBjoern A. Zeeb mt7615_mcu_rx_log_message(dev, skb);
4426c92544dSBjoern A. Zeeb break;
4436c92544dSBjoern A. Zeeb default:
4446c92544dSBjoern A. Zeeb break;
4456c92544dSBjoern A. Zeeb }
4466c92544dSBjoern A. Zeeb }
4476c92544dSBjoern A. Zeeb
4486c92544dSBjoern A. Zeeb static void
mt7615_mcu_scan_event(struct mt7615_dev * dev,struct sk_buff * skb)4496c92544dSBjoern A. Zeeb mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
4506c92544dSBjoern A. Zeeb {
4516c92544dSBjoern A. Zeeb u8 *seq_num = skb->data + sizeof(struct mt7615_mcu_rxd);
4526c92544dSBjoern A. Zeeb struct mt7615_phy *phy;
4536c92544dSBjoern A. Zeeb struct mt76_phy *mphy;
4546c92544dSBjoern A. Zeeb
4556c92544dSBjoern A. Zeeb if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1])
4566c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
4576c92544dSBjoern A. Zeeb else
4586c92544dSBjoern A. Zeeb mphy = &dev->mt76.phy;
4596c92544dSBjoern A. Zeeb
460*8ba4d145SBjoern A. Zeeb phy = mphy->priv;
4616c92544dSBjoern A. Zeeb
4626c92544dSBjoern A. Zeeb spin_lock_bh(&dev->mt76.lock);
4636c92544dSBjoern A. Zeeb __skb_queue_tail(&phy->scan_event_list, skb);
4646c92544dSBjoern A. Zeeb spin_unlock_bh(&dev->mt76.lock);
4656c92544dSBjoern A. Zeeb
4666c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work,
4676c92544dSBjoern A. Zeeb MT7615_HW_SCAN_TIMEOUT);
4686c92544dSBjoern A. Zeeb }
4696c92544dSBjoern A. Zeeb
4706c92544dSBjoern A. Zeeb static void
mt7615_mcu_roc_event(struct mt7615_dev * dev,struct sk_buff * skb)4716c92544dSBjoern A. Zeeb mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
4726c92544dSBjoern A. Zeeb {
4736c92544dSBjoern A. Zeeb struct mt7615_roc_tlv *event;
4746c92544dSBjoern A. Zeeb struct mt7615_phy *phy;
4756c92544dSBjoern A. Zeeb struct mt76_phy *mphy;
4766c92544dSBjoern A. Zeeb int duration;
4776c92544dSBjoern A. Zeeb
4786c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
4796c92544dSBjoern A. Zeeb event = (struct mt7615_roc_tlv *)skb->data;
4806c92544dSBjoern A. Zeeb
4816c92544dSBjoern A. Zeeb if (event->dbdc_band && dev->mt76.phys[MT_BAND1])
4826c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
4836c92544dSBjoern A. Zeeb else
4846c92544dSBjoern A. Zeeb mphy = &dev->mt76.phy;
4856c92544dSBjoern A. Zeeb
4866c92544dSBjoern A. Zeeb ieee80211_ready_on_channel(mphy->hw);
4876c92544dSBjoern A. Zeeb
488*8ba4d145SBjoern A. Zeeb phy = mphy->priv;
4896c92544dSBjoern A. Zeeb phy->roc_grant = true;
4906c92544dSBjoern A. Zeeb wake_up(&phy->roc_wait);
4916c92544dSBjoern A. Zeeb
4926c92544dSBjoern A. Zeeb duration = le32_to_cpu(event->max_interval);
4936c92544dSBjoern A. Zeeb mod_timer(&phy->roc_timer,
4946c92544dSBjoern A. Zeeb round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
4956c92544dSBjoern A. Zeeb }
4966c92544dSBjoern A. Zeeb
4976c92544dSBjoern A. Zeeb static void
mt7615_mcu_beacon_loss_event(struct mt7615_dev * dev,struct sk_buff * skb)4986c92544dSBjoern A. Zeeb mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb)
4996c92544dSBjoern A. Zeeb {
5006c92544dSBjoern A. Zeeb struct mt76_connac_beacon_loss_event *event;
5016c92544dSBjoern A. Zeeb struct mt76_phy *mphy;
5026c92544dSBjoern A. Zeeb u8 band_idx = 0; /* DBDC support */
5036c92544dSBjoern A. Zeeb
5046c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
5056c92544dSBjoern A. Zeeb event = (struct mt76_connac_beacon_loss_event *)skb->data;
5066c92544dSBjoern A. Zeeb if (band_idx && dev->mt76.phys[MT_BAND1])
5076c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
5086c92544dSBjoern A. Zeeb else
5096c92544dSBjoern A. Zeeb mphy = &dev->mt76.phy;
5106c92544dSBjoern A. Zeeb
5116c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces_atomic(mphy->hw,
5126c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL,
5136c92544dSBjoern A. Zeeb mt76_connac_mcu_beacon_loss_iter,
5146c92544dSBjoern A. Zeeb event);
5156c92544dSBjoern A. Zeeb }
5166c92544dSBjoern A. Zeeb
5176c92544dSBjoern A. Zeeb static void
mt7615_mcu_bss_event(struct mt7615_dev * dev,struct sk_buff * skb)5186c92544dSBjoern A. Zeeb mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb)
5196c92544dSBjoern A. Zeeb {
5206c92544dSBjoern A. Zeeb struct mt76_connac_mcu_bss_event *event;
5216c92544dSBjoern A. Zeeb struct mt76_phy *mphy;
5226c92544dSBjoern A. Zeeb u8 band_idx = 0; /* DBDC support */
5236c92544dSBjoern A. Zeeb
5246c92544dSBjoern A. Zeeb skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
5256c92544dSBjoern A. Zeeb event = (struct mt76_connac_mcu_bss_event *)skb->data;
5266c92544dSBjoern A. Zeeb
5276c92544dSBjoern A. Zeeb if (band_idx && dev->mt76.phys[MT_BAND1])
5286c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1];
5296c92544dSBjoern A. Zeeb else
5306c92544dSBjoern A. Zeeb mphy = &dev->mt76.phy;
5316c92544dSBjoern A. Zeeb
5326c92544dSBjoern A. Zeeb if (event->is_absent)
5336c92544dSBjoern A. Zeeb ieee80211_stop_queues(mphy->hw);
5346c92544dSBjoern A. Zeeb else
5356c92544dSBjoern A. Zeeb ieee80211_wake_queues(mphy->hw);
5366c92544dSBjoern A. Zeeb }
5376c92544dSBjoern A. Zeeb
5386c92544dSBjoern A. Zeeb static void
mt7615_mcu_rx_unsolicited_event(struct mt7615_dev * dev,struct sk_buff * skb)5396c92544dSBjoern A. Zeeb mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)
5406c92544dSBjoern A. Zeeb {
5416c92544dSBjoern A. Zeeb struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
5426c92544dSBjoern A. Zeeb
5436c92544dSBjoern A. Zeeb switch (rxd->eid) {
5446c92544dSBjoern A. Zeeb case MCU_EVENT_EXT:
5456c92544dSBjoern A. Zeeb mt7615_mcu_rx_ext_event(dev, skb);
5466c92544dSBjoern A. Zeeb break;
5476c92544dSBjoern A. Zeeb case MCU_EVENT_BSS_BEACON_LOSS:
5486c92544dSBjoern A. Zeeb mt7615_mcu_beacon_loss_event(dev, skb);
5496c92544dSBjoern A. Zeeb break;
5506c92544dSBjoern A. Zeeb case MCU_EVENT_ROC:
5516c92544dSBjoern A. Zeeb mt7615_mcu_roc_event(dev, skb);
5526c92544dSBjoern A. Zeeb break;
5536c92544dSBjoern A. Zeeb case MCU_EVENT_SCHED_SCAN_DONE:
5546c92544dSBjoern A. Zeeb case MCU_EVENT_SCAN_DONE:
5556c92544dSBjoern A. Zeeb mt7615_mcu_scan_event(dev, skb);
5566c92544dSBjoern A. Zeeb return;
5576c92544dSBjoern A. Zeeb case MCU_EVENT_BSS_ABSENCE:
5586c92544dSBjoern A. Zeeb mt7615_mcu_bss_event(dev, skb);
5596c92544dSBjoern A. Zeeb break;
5606c92544dSBjoern A. Zeeb case MCU_EVENT_COREDUMP:
5616c92544dSBjoern A. Zeeb mt76_connac_mcu_coredump_event(&dev->mt76, skb,
5626c92544dSBjoern A. Zeeb &dev->coredump);
5636c92544dSBjoern A. Zeeb return;
5646c92544dSBjoern A. Zeeb default:
5656c92544dSBjoern A. Zeeb break;
5666c92544dSBjoern A. Zeeb }
5676c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
5686c92544dSBjoern A. Zeeb }
5696c92544dSBjoern A. Zeeb
mt7615_mcu_rx_event(struct mt7615_dev * dev,struct sk_buff * skb)5706c92544dSBjoern A. Zeeb void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)
5716c92544dSBjoern A. Zeeb {
5726c92544dSBjoern A. Zeeb struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
5736c92544dSBjoern A. Zeeb
5746c92544dSBjoern A. Zeeb if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
5756c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
5766c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
5776c92544dSBjoern A. Zeeb rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
5786c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||
5796c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
5806c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_BSS_ABSENCE ||
5816c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_SCAN_DONE ||
5826c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_COREDUMP ||
5836c92544dSBjoern A. Zeeb rxd->eid == MCU_EVENT_ROC ||
5846c92544dSBjoern A. Zeeb !rxd->seq)
5856c92544dSBjoern A. Zeeb mt7615_mcu_rx_unsolicited_event(dev, skb);
5866c92544dSBjoern A. Zeeb else
5876c92544dSBjoern A. Zeeb mt76_mcu_rx_event(&dev->mt76, skb);
5886c92544dSBjoern A. Zeeb }
5896c92544dSBjoern A. Zeeb
5906c92544dSBjoern A. Zeeb static int
mt7615_mcu_muar_config(struct mt7615_dev * dev,struct ieee80211_vif * vif,bool bssid,bool enable)5916c92544dSBjoern A. Zeeb mt7615_mcu_muar_config(struct mt7615_dev *dev, struct ieee80211_vif *vif,
5926c92544dSBjoern A. Zeeb bool bssid, bool enable)
5936c92544dSBjoern A. Zeeb {
5946c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
5956c92544dSBjoern A. Zeeb u32 idx = mvif->mt76.omac_idx - REPEATER_BSSID_START;
5966c92544dSBjoern A. Zeeb u32 mask = dev->omac_mask >> 32 & ~BIT(idx);
5976c92544dSBjoern A. Zeeb const u8 *addr = vif->addr;
5986c92544dSBjoern A. Zeeb struct {
5996c92544dSBjoern A. Zeeb u8 mode;
6006c92544dSBjoern A. Zeeb u8 force_clear;
6016c92544dSBjoern A. Zeeb u8 clear_bitmap[8];
6026c92544dSBjoern A. Zeeb u8 entry_count;
6036c92544dSBjoern A. Zeeb u8 write;
6046c92544dSBjoern A. Zeeb
6056c92544dSBjoern A. Zeeb u8 index;
6066c92544dSBjoern A. Zeeb u8 bssid;
6076c92544dSBjoern A. Zeeb u8 addr[ETH_ALEN];
6086c92544dSBjoern A. Zeeb } __packed req = {
6096c92544dSBjoern A. Zeeb .mode = !!mask || enable,
6106c92544dSBjoern A. Zeeb .entry_count = 1,
6116c92544dSBjoern A. Zeeb .write = 1,
6126c92544dSBjoern A. Zeeb
6136c92544dSBjoern A. Zeeb .index = idx * 2 + bssid,
6146c92544dSBjoern A. Zeeb };
6156c92544dSBjoern A. Zeeb
6166c92544dSBjoern A. Zeeb if (bssid)
6176c92544dSBjoern A. Zeeb addr = vif->bss_conf.bssid;
6186c92544dSBjoern A. Zeeb
6196c92544dSBjoern A. Zeeb if (enable)
6206c92544dSBjoern A. Zeeb ether_addr_copy(req.addr, addr);
6216c92544dSBjoern A. Zeeb
6226c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MUAR_UPDATE),
6236c92544dSBjoern A. Zeeb &req, sizeof(req), true);
6246c92544dSBjoern A. Zeeb }
6256c92544dSBjoern A. Zeeb
6266c92544dSBjoern A. Zeeb static int
mt7615_mcu_add_dev(struct mt7615_phy * phy,struct ieee80211_vif * vif,bool enable)6276c92544dSBjoern A. Zeeb mt7615_mcu_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif,
6286c92544dSBjoern A. Zeeb bool enable)
6296c92544dSBjoern A. Zeeb {
6306c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
6316c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
6326c92544dSBjoern A. Zeeb struct {
6336c92544dSBjoern A. Zeeb struct req_hdr {
6346c92544dSBjoern A. Zeeb u8 omac_idx;
6356c92544dSBjoern A. Zeeb u8 band_idx;
6366c92544dSBjoern A. Zeeb __le16 tlv_num;
6376c92544dSBjoern A. Zeeb u8 is_tlv_append;
6386c92544dSBjoern A. Zeeb u8 rsv[3];
6396c92544dSBjoern A. Zeeb } __packed hdr;
6406c92544dSBjoern A. Zeeb struct req_tlv {
6416c92544dSBjoern A. Zeeb __le16 tag;
6426c92544dSBjoern A. Zeeb __le16 len;
6436c92544dSBjoern A. Zeeb u8 active;
6446c92544dSBjoern A. Zeeb u8 band_idx;
6456c92544dSBjoern A. Zeeb u8 omac_addr[ETH_ALEN];
6466c92544dSBjoern A. Zeeb } __packed tlv;
6476c92544dSBjoern A. Zeeb } data = {
6486c92544dSBjoern A. Zeeb .hdr = {
6496c92544dSBjoern A. Zeeb .omac_idx = mvif->mt76.omac_idx,
6506c92544dSBjoern A. Zeeb .band_idx = mvif->mt76.band_idx,
6516c92544dSBjoern A. Zeeb .tlv_num = cpu_to_le16(1),
6526c92544dSBjoern A. Zeeb .is_tlv_append = 1,
6536c92544dSBjoern A. Zeeb },
6546c92544dSBjoern A. Zeeb .tlv = {
6556c92544dSBjoern A. Zeeb .tag = cpu_to_le16(DEV_INFO_ACTIVE),
6566c92544dSBjoern A. Zeeb .len = cpu_to_le16(sizeof(struct req_tlv)),
6576c92544dSBjoern A. Zeeb .active = enable,
6586c92544dSBjoern A. Zeeb .band_idx = mvif->mt76.band_idx,
6596c92544dSBjoern A. Zeeb },
6606c92544dSBjoern A. Zeeb };
6616c92544dSBjoern A. Zeeb
6626c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)
6636c92544dSBjoern A. Zeeb return mt7615_mcu_muar_config(dev, vif, false, enable);
6646c92544dSBjoern A. Zeeb
6656c92544dSBjoern A. Zeeb memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN);
6666c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DEV_INFO_UPDATE),
6676c92544dSBjoern A. Zeeb &data, sizeof(data), true);
6686c92544dSBjoern A. Zeeb }
6696c92544dSBjoern A. Zeeb
6706c92544dSBjoern A. Zeeb static int
mt7615_mcu_add_beacon_offload(struct mt7615_dev * dev,struct ieee80211_hw * hw,struct ieee80211_vif * vif,bool enable)6716c92544dSBjoern A. Zeeb mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
6726c92544dSBjoern A. Zeeb struct ieee80211_hw *hw,
6736c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, bool enable)
6746c92544dSBjoern A. Zeeb {
6756c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
6766c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid;
6776c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets offs;
6786c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info;
6796c92544dSBjoern A. Zeeb struct req {
6806c92544dSBjoern A. Zeeb u8 omac_idx;
6816c92544dSBjoern A. Zeeb u8 enable;
6826c92544dSBjoern A. Zeeb u8 wlan_idx;
6836c92544dSBjoern A. Zeeb u8 band_idx;
6846c92544dSBjoern A. Zeeb u8 pkt_type;
6856c92544dSBjoern A. Zeeb u8 need_pre_tbtt_int;
6866c92544dSBjoern A. Zeeb __le16 csa_ie_pos;
6876c92544dSBjoern A. Zeeb __le16 pkt_len;
6886c92544dSBjoern A. Zeeb __le16 tim_ie_pos;
6896c92544dSBjoern A. Zeeb u8 pkt[512];
6906c92544dSBjoern A. Zeeb u8 csa_cnt;
6916c92544dSBjoern A. Zeeb /* bss color change */
6926c92544dSBjoern A. Zeeb u8 bcc_cnt;
6936c92544dSBjoern A. Zeeb __le16 bcc_ie_pos;
6946c92544dSBjoern A. Zeeb } __packed req = {
6956c92544dSBjoern A. Zeeb .omac_idx = mvif->mt76.omac_idx,
6966c92544dSBjoern A. Zeeb .enable = enable,
6976c92544dSBjoern A. Zeeb .wlan_idx = wcid->idx,
6986c92544dSBjoern A. Zeeb .band_idx = mvif->mt76.band_idx,
6996c92544dSBjoern A. Zeeb };
7006c92544dSBjoern A. Zeeb struct sk_buff *skb;
7016c92544dSBjoern A. Zeeb
7026c92544dSBjoern A. Zeeb if (!enable)
7036c92544dSBjoern A. Zeeb goto out;
7046c92544dSBjoern A. Zeeb
7056c92544dSBjoern A. Zeeb skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
7066c92544dSBjoern A. Zeeb if (!skb)
7076c92544dSBjoern A. Zeeb return -EINVAL;
7086c92544dSBjoern A. Zeeb
7096c92544dSBjoern A. Zeeb if (skb->len > 512 - MT_TXD_SIZE) {
7106c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
7116c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
7126c92544dSBjoern A. Zeeb return -EINVAL;
7136c92544dSBjoern A. Zeeb }
7146c92544dSBjoern A. Zeeb
7156c92544dSBjoern A. Zeeb info = IEEE80211_SKB_CB(skb);
7166c92544dSBjoern A. Zeeb info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, mvif->mt76.band_idx);
7176c92544dSBjoern A. Zeeb
7186c92544dSBjoern A. Zeeb mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL,
7196c92544dSBjoern A. Zeeb 0, NULL, 0, true);
7206c92544dSBjoern A. Zeeb memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
7216c92544dSBjoern A. Zeeb req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
7226c92544dSBjoern A. Zeeb req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
7236c92544dSBjoern A. Zeeb if (offs.cntdwn_counter_offs[0]) {
7246c92544dSBjoern A. Zeeb u16 csa_offs;
7256c92544dSBjoern A. Zeeb
7266c92544dSBjoern A. Zeeb csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
7276c92544dSBjoern A. Zeeb req.csa_ie_pos = cpu_to_le16(csa_offs);
7286c92544dSBjoern A. Zeeb req.csa_cnt = skb->data[offs.cntdwn_counter_offs[0]];
7296c92544dSBjoern A. Zeeb }
7306c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
7316c92544dSBjoern A. Zeeb
7326c92544dSBjoern A. Zeeb out:
7336c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(BCN_OFFLOAD), &req,
7346c92544dSBjoern A. Zeeb sizeof(req), true);
7356c92544dSBjoern A. Zeeb }
7366c92544dSBjoern A. Zeeb
7376c92544dSBjoern A. Zeeb static int
mt7615_mcu_ctrl_pm_state(struct mt7615_dev * dev,int band,int state)7386c92544dSBjoern A. Zeeb mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
7396c92544dSBjoern A. Zeeb {
7406c92544dSBjoern A. Zeeb return mt76_connac_mcu_set_pm(&dev->mt76, band, state);
7416c92544dSBjoern A. Zeeb }
7426c92544dSBjoern A. Zeeb
7436c92544dSBjoern A. Zeeb static int
mt7615_mcu_add_bss(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable)7446c92544dSBjoern A. Zeeb mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,
7456c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable)
7466c92544dSBjoern A. Zeeb {
7476c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
7486c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
7496c92544dSBjoern A. Zeeb struct sk_buff *skb;
7506c92544dSBjoern A. Zeeb
7516c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx >= REPEATER_BSSID_START)
7526c92544dSBjoern A. Zeeb mt7615_mcu_muar_config(dev, vif, true, enable);
7536c92544dSBjoern A. Zeeb
7546c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL);
7556c92544dSBjoern A. Zeeb if (IS_ERR(skb))
7566c92544dSBjoern A. Zeeb return PTR_ERR(skb);
7576c92544dSBjoern A. Zeeb
7586c92544dSBjoern A. Zeeb if (enable)
7596c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_omac_tlv(skb, vif);
7606c92544dSBjoern A. Zeeb
7616c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_basic_tlv(skb, vif, sta, phy->mt76,
7626c92544dSBjoern A. Zeeb mvif->sta.wcid.idx, enable);
7636c92544dSBjoern A. Zeeb
7646c92544dSBjoern A. Zeeb if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START &&
7656c92544dSBjoern A. Zeeb mvif->mt76.omac_idx < REPEATER_BSSID_START)
7666c92544dSBjoern A. Zeeb mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76);
7676c92544dSBjoern A. Zeeb
7686c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
7696c92544dSBjoern A. Zeeb MCU_EXT_CMD(BSS_INFO_UPDATE), true);
7706c92544dSBjoern A. Zeeb }
7716c92544dSBjoern A. Zeeb
7726c92544dSBjoern A. Zeeb static int
mt7615_mcu_wtbl_tx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)7736c92544dSBjoern A. Zeeb mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev,
7746c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
7756c92544dSBjoern A. Zeeb bool enable)
7766c92544dSBjoern A. Zeeb {
7776c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;
7786c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = msta->vif;
7796c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
7806c92544dSBjoern A. Zeeb struct sk_buff *skb = NULL;
7816c92544dSBjoern A. Zeeb int err;
7826c92544dSBjoern A. Zeeb
7836c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
7846c92544dSBjoern A. Zeeb WTBL_SET, NULL, &skb);
7856c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
7866c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
7876c92544dSBjoern A. Zeeb
7886c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, true,
7896c92544dSBjoern A. Zeeb NULL, wtbl_hdr);
7906c92544dSBjoern A. Zeeb
7916c92544dSBjoern A. Zeeb err = mt76_mcu_skb_send_msg(&dev->mt76, skb,
7926c92544dSBjoern A. Zeeb MCU_EXT_CMD(WTBL_UPDATE), true);
7936c92544dSBjoern A. Zeeb if (err < 0)
7946c92544dSBjoern A. Zeeb return err;
7956c92544dSBjoern A. Zeeb
7966c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
7976c92544dSBjoern A. Zeeb &msta->wcid);
7986c92544dSBjoern A. Zeeb if (IS_ERR(skb))
7996c92544dSBjoern A. Zeeb return PTR_ERR(skb);
8006c92544dSBjoern A. Zeeb
8016c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_ba_tlv(skb, params, enable, true);
8026c92544dSBjoern A. Zeeb
8036c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
8046c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
8056c92544dSBjoern A. Zeeb }
8066c92544dSBjoern A. Zeeb
8076c92544dSBjoern A. Zeeb static int
mt7615_mcu_wtbl_rx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)8086c92544dSBjoern A. Zeeb mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev,
8096c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
8106c92544dSBjoern A. Zeeb bool enable)
8116c92544dSBjoern A. Zeeb {
8126c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;
8136c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = msta->vif;
8146c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
8156c92544dSBjoern A. Zeeb struct sk_buff *skb;
8166c92544dSBjoern A. Zeeb int err;
8176c92544dSBjoern A. Zeeb
8186c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
8196c92544dSBjoern A. Zeeb &msta->wcid);
8206c92544dSBjoern A. Zeeb if (IS_ERR(skb))
8216c92544dSBjoern A. Zeeb return PTR_ERR(skb);
8226c92544dSBjoern A. Zeeb
8236c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);
8246c92544dSBjoern A. Zeeb
8256c92544dSBjoern A. Zeeb err = mt76_mcu_skb_send_msg(&dev->mt76, skb,
8266c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
8276c92544dSBjoern A. Zeeb if (err < 0 || !enable)
8286c92544dSBjoern A. Zeeb return err;
8296c92544dSBjoern A. Zeeb
8306c92544dSBjoern A. Zeeb skb = NULL;
8316c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
8326c92544dSBjoern A. Zeeb WTBL_SET, NULL, &skb);
8336c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
8346c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
8356c92544dSBjoern A. Zeeb
8366c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false,
8376c92544dSBjoern A. Zeeb NULL, wtbl_hdr);
8386c92544dSBjoern A. Zeeb
8396c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
8406c92544dSBjoern A. Zeeb MCU_EXT_CMD(WTBL_UPDATE), true);
8416c92544dSBjoern A. Zeeb }
8426c92544dSBjoern A. Zeeb
8436c92544dSBjoern A. Zeeb static int
mt7615_mcu_wtbl_sta_add(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable)8446c92544dSBjoern A. Zeeb mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
8456c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable)
8466c92544dSBjoern A. Zeeb {
8476c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
8486c92544dSBjoern A. Zeeb struct sk_buff *skb, *sskb, *wskb = NULL;
849*8ba4d145SBjoern A. Zeeb struct ieee80211_link_sta *link_sta;
8506c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
8516c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
8526c92544dSBjoern A. Zeeb struct mt7615_sta *msta;
8536c92544dSBjoern A. Zeeb bool new_entry = true;
854*8ba4d145SBjoern A. Zeeb int conn_state;
8556c92544dSBjoern A. Zeeb int cmd, err;
8566c92544dSBjoern A. Zeeb
8576c92544dSBjoern A. Zeeb msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta;
858*8ba4d145SBjoern A. Zeeb link_sta = sta ? &sta->deflink : NULL;
8596c92544dSBjoern A. Zeeb
8606c92544dSBjoern A. Zeeb sskb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
8616c92544dSBjoern A. Zeeb &msta->wcid);
8626c92544dSBjoern A. Zeeb if (IS_ERR(sskb))
8636c92544dSBjoern A. Zeeb return PTR_ERR(sskb);
8646c92544dSBjoern A. Zeeb
8656c92544dSBjoern A. Zeeb if (!sta) {
8666c92544dSBjoern A. Zeeb if (mvif->sta_added)
8676c92544dSBjoern A. Zeeb new_entry = false;
8686c92544dSBjoern A. Zeeb else
8696c92544dSBjoern A. Zeeb mvif->sta_added = true;
8706c92544dSBjoern A. Zeeb }
871*8ba4d145SBjoern A. Zeeb conn_state = enable ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT;
872*8ba4d145SBjoern A. Zeeb mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, &vif->bss_conf,
873*8ba4d145SBjoern A. Zeeb link_sta, conn_state, new_entry);
8746c92544dSBjoern A. Zeeb if (enable && sta)
8756c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
8766c92544dSBjoern A. Zeeb MT76_STA_INFO_STATE_ASSOC);
8776c92544dSBjoern A. Zeeb
8786c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
8796c92544dSBjoern A. Zeeb WTBL_RESET_AND_SET, NULL,
8806c92544dSBjoern A. Zeeb &wskb);
8816c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
8826c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
8836c92544dSBjoern A. Zeeb
8846c92544dSBjoern A. Zeeb if (enable) {
8856c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, wskb, vif, sta,
8866c92544dSBjoern A. Zeeb NULL, wtbl_hdr);
8876c92544dSBjoern A. Zeeb if (sta)
8886c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
8896c92544dSBjoern A. Zeeb NULL, wtbl_hdr, true, true);
8906c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,
8916c92544dSBjoern A. Zeeb NULL, wtbl_hdr);
8926c92544dSBjoern A. Zeeb }
8936c92544dSBjoern A. Zeeb
8946c92544dSBjoern A. Zeeb cmd = enable ? MCU_EXT_CMD(WTBL_UPDATE) : MCU_EXT_CMD(STA_REC_UPDATE);
8956c92544dSBjoern A. Zeeb skb = enable ? wskb : sskb;
8966c92544dSBjoern A. Zeeb
8976c92544dSBjoern A. Zeeb err = mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);
8986c92544dSBjoern A. Zeeb if (err < 0) {
8996c92544dSBjoern A. Zeeb skb = enable ? sskb : wskb;
9006c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
9016c92544dSBjoern A. Zeeb
9026c92544dSBjoern A. Zeeb return err;
9036c92544dSBjoern A. Zeeb }
9046c92544dSBjoern A. Zeeb
9056c92544dSBjoern A. Zeeb cmd = enable ? MCU_EXT_CMD(STA_REC_UPDATE) : MCU_EXT_CMD(WTBL_UPDATE);
9066c92544dSBjoern A. Zeeb skb = enable ? sskb : wskb;
9076c92544dSBjoern A. Zeeb
9086c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);
9096c92544dSBjoern A. Zeeb }
9106c92544dSBjoern A. Zeeb
9116c92544dSBjoern A. Zeeb static int
mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)9126c92544dSBjoern A. Zeeb mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,
9136c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
9146c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
9156c92544dSBjoern A. Zeeb {
9166c92544dSBjoern A. Zeeb return mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
9176c92544dSBjoern A. Zeeb }
9186c92544dSBjoern A. Zeeb
9196c92544dSBjoern A. Zeeb static const struct mt7615_mcu_ops wtbl_update_ops = {
9206c92544dSBjoern A. Zeeb .add_beacon_offload = mt7615_mcu_add_beacon_offload,
9216c92544dSBjoern A. Zeeb .set_pm_state = mt7615_mcu_ctrl_pm_state,
9226c92544dSBjoern A. Zeeb .add_dev_info = mt7615_mcu_add_dev,
9236c92544dSBjoern A. Zeeb .add_bss_info = mt7615_mcu_add_bss,
9246c92544dSBjoern A. Zeeb .add_tx_ba = mt7615_mcu_wtbl_tx_ba,
9256c92544dSBjoern A. Zeeb .add_rx_ba = mt7615_mcu_wtbl_rx_ba,
9266c92544dSBjoern A. Zeeb .sta_add = mt7615_mcu_wtbl_sta_add,
9276c92544dSBjoern A. Zeeb .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
9286c92544dSBjoern A. Zeeb .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
9296c92544dSBjoern A. Zeeb .set_sta_decap_offload = mt7615_mcu_wtbl_update_hdr_trans,
9306c92544dSBjoern A. Zeeb };
9316c92544dSBjoern A. Zeeb
9326c92544dSBjoern A. Zeeb static int
mt7615_mcu_sta_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable,bool tx)9336c92544dSBjoern A. Zeeb mt7615_mcu_sta_ba(struct mt7615_dev *dev,
9346c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
9356c92544dSBjoern A. Zeeb bool enable, bool tx)
9366c92544dSBjoern A. Zeeb {
9376c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;
9386c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = msta->vif;
9396c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
9406c92544dSBjoern A. Zeeb struct tlv *sta_wtbl;
9416c92544dSBjoern A. Zeeb struct sk_buff *skb;
9426c92544dSBjoern A. Zeeb
9436c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
9446c92544dSBjoern A. Zeeb &msta->wcid);
9456c92544dSBjoern A. Zeeb if (IS_ERR(skb))
9466c92544dSBjoern A. Zeeb return PTR_ERR(skb);
9476c92544dSBjoern A. Zeeb
9486c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);
9496c92544dSBjoern A. Zeeb
9506c92544dSBjoern A. Zeeb sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv));
9516c92544dSBjoern A. Zeeb
9526c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
9536c92544dSBjoern A. Zeeb WTBL_SET, sta_wtbl, &skb);
9546c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
9556c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
9566c92544dSBjoern A. Zeeb
9576c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx,
9586c92544dSBjoern A. Zeeb sta_wtbl, wtbl_hdr);
9596c92544dSBjoern A. Zeeb
9606c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
9616c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), true);
9626c92544dSBjoern A. Zeeb }
9636c92544dSBjoern A. Zeeb
9646c92544dSBjoern A. Zeeb static int
mt7615_mcu_sta_tx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)9656c92544dSBjoern A. Zeeb mt7615_mcu_sta_tx_ba(struct mt7615_dev *dev,
9666c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
9676c92544dSBjoern A. Zeeb bool enable)
9686c92544dSBjoern A. Zeeb {
9696c92544dSBjoern A. Zeeb return mt7615_mcu_sta_ba(dev, params, enable, true);
9706c92544dSBjoern A. Zeeb }
9716c92544dSBjoern A. Zeeb
9726c92544dSBjoern A. Zeeb static int
mt7615_mcu_sta_rx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)9736c92544dSBjoern A. Zeeb mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev,
9746c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
9756c92544dSBjoern A. Zeeb bool enable)
9766c92544dSBjoern A. Zeeb {
9776c92544dSBjoern A. Zeeb return mt7615_mcu_sta_ba(dev, params, enable, false);
9786c92544dSBjoern A. Zeeb }
9796c92544dSBjoern A. Zeeb
9806c92544dSBjoern A. Zeeb static int
__mt7615_mcu_add_sta(struct mt76_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable,int cmd,bool offload_fw)9816c92544dSBjoern A. Zeeb __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
9826c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable, int cmd,
9836c92544dSBjoern A. Zeeb bool offload_fw)
9846c92544dSBjoern A. Zeeb {
9856c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
9866c92544dSBjoern A. Zeeb struct mt76_sta_cmd_info info = {
9876c92544dSBjoern A. Zeeb .sta = sta,
9886c92544dSBjoern A. Zeeb .vif = vif,
9896c92544dSBjoern A. Zeeb .offload_fw = offload_fw,
9906c92544dSBjoern A. Zeeb .enable = enable,
9916c92544dSBjoern A. Zeeb .newly = true,
9926c92544dSBjoern A. Zeeb .cmd = cmd,
9936c92544dSBjoern A. Zeeb };
9946c92544dSBjoern A. Zeeb
9956c92544dSBjoern A. Zeeb info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
9966c92544dSBjoern A. Zeeb return mt76_connac_mcu_sta_cmd(phy, &info);
9976c92544dSBjoern A. Zeeb }
9986c92544dSBjoern A. Zeeb
9996c92544dSBjoern A. Zeeb static int
mt7615_mcu_add_sta(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable)10006c92544dSBjoern A. Zeeb mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,
10016c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable)
10026c92544dSBjoern A. Zeeb {
10036c92544dSBjoern A. Zeeb return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,
10046c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE), false);
10056c92544dSBjoern A. Zeeb }
10066c92544dSBjoern A. Zeeb
10076c92544dSBjoern A. Zeeb static int
mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)10086c92544dSBjoern A. Zeeb mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
10096c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
10106c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
10116c92544dSBjoern A. Zeeb {
10126c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
10136c92544dSBjoern A. Zeeb
10146c92544dSBjoern A. Zeeb return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
10156c92544dSBjoern A. Zeeb vif, &msta->wcid,
10166c92544dSBjoern A. Zeeb MCU_EXT_CMD(STA_REC_UPDATE));
10176c92544dSBjoern A. Zeeb }
10186c92544dSBjoern A. Zeeb
10196c92544dSBjoern A. Zeeb static const struct mt7615_mcu_ops sta_update_ops = {
10206c92544dSBjoern A. Zeeb .add_beacon_offload = mt7615_mcu_add_beacon_offload,
10216c92544dSBjoern A. Zeeb .set_pm_state = mt7615_mcu_ctrl_pm_state,
10226c92544dSBjoern A. Zeeb .add_dev_info = mt7615_mcu_add_dev,
10236c92544dSBjoern A. Zeeb .add_bss_info = mt7615_mcu_add_bss,
10246c92544dSBjoern A. Zeeb .add_tx_ba = mt7615_mcu_sta_tx_ba,
10256c92544dSBjoern A. Zeeb .add_rx_ba = mt7615_mcu_sta_rx_ba,
10266c92544dSBjoern A. Zeeb .sta_add = mt7615_mcu_add_sta,
10276c92544dSBjoern A. Zeeb .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
10286c92544dSBjoern A. Zeeb .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
10296c92544dSBjoern A. Zeeb .set_sta_decap_offload = mt7615_mcu_sta_update_hdr_trans,
10306c92544dSBjoern A. Zeeb };
10316c92544dSBjoern A. Zeeb
10326c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev * dev,int band,int state)10336c92544dSBjoern A. Zeeb mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
10346c92544dSBjoern A. Zeeb {
10356c92544dSBjoern A. Zeeb return 0;
10366c92544dSBjoern A. Zeeb }
10376c92544dSBjoern A. Zeeb
10386c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev * dev,struct ieee80211_hw * hw,struct ieee80211_vif * vif,bool enable)10396c92544dSBjoern A. Zeeb mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
10406c92544dSBjoern A. Zeeb struct ieee80211_hw *hw,
10416c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
10426c92544dSBjoern A. Zeeb bool enable)
10436c92544dSBjoern A. Zeeb {
10446c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
10456c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid;
10466c92544dSBjoern A. Zeeb struct ieee80211_mutable_offsets offs;
10476c92544dSBjoern A. Zeeb struct {
10486c92544dSBjoern A. Zeeb struct req_hdr {
10496c92544dSBjoern A. Zeeb u8 bss_idx;
10506c92544dSBjoern A. Zeeb u8 pad[3];
10516c92544dSBjoern A. Zeeb } __packed hdr;
10526c92544dSBjoern A. Zeeb struct bcn_content_tlv {
10536c92544dSBjoern A. Zeeb __le16 tag;
10546c92544dSBjoern A. Zeeb __le16 len;
10556c92544dSBjoern A. Zeeb __le16 tim_ie_pos;
10566c92544dSBjoern A. Zeeb __le16 csa_ie_pos;
10576c92544dSBjoern A. Zeeb __le16 bcc_ie_pos;
10586c92544dSBjoern A. Zeeb /* 0: disable beacon offload
10596c92544dSBjoern A. Zeeb * 1: enable beacon offload
10606c92544dSBjoern A. Zeeb * 2: update probe respond offload
10616c92544dSBjoern A. Zeeb */
10626c92544dSBjoern A. Zeeb u8 enable;
10636c92544dSBjoern A. Zeeb /* 0: legacy format (TXD + payload)
10646c92544dSBjoern A. Zeeb * 1: only cap field IE
10656c92544dSBjoern A. Zeeb */
10666c92544dSBjoern A. Zeeb u8 type;
10676c92544dSBjoern A. Zeeb __le16 pkt_len;
10686c92544dSBjoern A. Zeeb u8 pkt[512];
10696c92544dSBjoern A. Zeeb } __packed beacon_tlv;
10706c92544dSBjoern A. Zeeb } req = {
10716c92544dSBjoern A. Zeeb .hdr = {
10726c92544dSBjoern A. Zeeb .bss_idx = mvif->mt76.idx,
10736c92544dSBjoern A. Zeeb },
10746c92544dSBjoern A. Zeeb .beacon_tlv = {
10756c92544dSBjoern A. Zeeb .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),
10766c92544dSBjoern A. Zeeb .len = cpu_to_le16(sizeof(struct bcn_content_tlv)),
10776c92544dSBjoern A. Zeeb .enable = enable,
10786c92544dSBjoern A. Zeeb },
10796c92544dSBjoern A. Zeeb };
10806c92544dSBjoern A. Zeeb struct sk_buff *skb;
10816c92544dSBjoern A. Zeeb
10826c92544dSBjoern A. Zeeb if (!enable)
10836c92544dSBjoern A. Zeeb goto out;
10846c92544dSBjoern A. Zeeb
10856c92544dSBjoern A. Zeeb skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0);
10866c92544dSBjoern A. Zeeb if (!skb)
10876c92544dSBjoern A. Zeeb return -EINVAL;
10886c92544dSBjoern A. Zeeb
10896c92544dSBjoern A. Zeeb if (skb->len > 512 - MT_TXD_SIZE) {
10906c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "beacon size limit exceed\n");
10916c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
10926c92544dSBjoern A. Zeeb return -EINVAL;
10936c92544dSBjoern A. Zeeb }
10946c92544dSBjoern A. Zeeb
10956c92544dSBjoern A. Zeeb mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
10966c92544dSBjoern A. Zeeb wcid, NULL, 0, NULL, 0, true);
10976c92544dSBjoern A. Zeeb memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
10986c92544dSBjoern A. Zeeb req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
10996c92544dSBjoern A. Zeeb req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
11006c92544dSBjoern A. Zeeb
11016c92544dSBjoern A. Zeeb if (offs.cntdwn_counter_offs[0]) {
11026c92544dSBjoern A. Zeeb u16 csa_offs;
11036c92544dSBjoern A. Zeeb
11046c92544dSBjoern A. Zeeb csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
11056c92544dSBjoern A. Zeeb req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);
11066c92544dSBjoern A. Zeeb }
11076c92544dSBjoern A. Zeeb dev_kfree_skb(skb);
11086c92544dSBjoern A. Zeeb
11096c92544dSBjoern A. Zeeb out:
11106c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),
11116c92544dSBjoern A. Zeeb &req, sizeof(req), true);
11126c92544dSBjoern A. Zeeb }
11136c92544dSBjoern A. Zeeb
11146c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_add_dev(struct mt7615_phy * phy,struct ieee80211_vif * vif,bool enable)11156c92544dSBjoern A. Zeeb mt7615_mcu_uni_add_dev(struct mt7615_phy *phy, struct ieee80211_vif *vif,
11166c92544dSBjoern A. Zeeb bool enable)
11176c92544dSBjoern A. Zeeb {
11186c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
11196c92544dSBjoern A. Zeeb
1120*8ba4d145SBjoern A. Zeeb return mt76_connac_mcu_uni_add_dev(phy->mt76, &vif->bss_conf, &mvif->mt76,
1121*8ba4d145SBjoern A. Zeeb &mvif->sta.wcid, enable);
11226c92544dSBjoern A. Zeeb }
11236c92544dSBjoern A. Zeeb
11246c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_add_bss(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable)11256c92544dSBjoern A. Zeeb mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,
11266c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable)
11276c92544dSBjoern A. Zeeb {
11286c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
11296c92544dSBjoern A. Zeeb
11306c92544dSBjoern A. Zeeb return mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
1131cbb3ec25SBjoern A. Zeeb enable, NULL);
11326c92544dSBjoern A. Zeeb }
11336c92544dSBjoern A. Zeeb
11346c92544dSBjoern A. Zeeb static inline int
mt7615_mcu_uni_add_sta(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enable)11356c92544dSBjoern A. Zeeb mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,
11366c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, bool enable)
11376c92544dSBjoern A. Zeeb {
11386c92544dSBjoern A. Zeeb return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable,
11396c92544dSBjoern A. Zeeb MCU_UNI_CMD(STA_REC_UPDATE), true);
11406c92544dSBjoern A. Zeeb }
11416c92544dSBjoern A. Zeeb
11426c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_tx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)11436c92544dSBjoern A. Zeeb mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev,
11446c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
11456c92544dSBjoern A. Zeeb bool enable)
11466c92544dSBjoern A. Zeeb {
11476c92544dSBjoern A. Zeeb struct mt7615_sta *sta = (struct mt7615_sta *)params->sta->drv_priv;
11486c92544dSBjoern A. Zeeb
11496c92544dSBjoern A. Zeeb return mt76_connac_mcu_sta_ba(&dev->mt76, &sta->vif->mt76, params,
11506c92544dSBjoern A. Zeeb MCU_UNI_CMD(STA_REC_UPDATE), enable,
11516c92544dSBjoern A. Zeeb true);
11526c92544dSBjoern A. Zeeb }
11536c92544dSBjoern A. Zeeb
11546c92544dSBjoern A. Zeeb static int
mt7615_mcu_uni_rx_ba(struct mt7615_dev * dev,struct ieee80211_ampdu_params * params,bool enable)11556c92544dSBjoern A. Zeeb mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,
11566c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params,
11576c92544dSBjoern A. Zeeb bool enable)
11586c92544dSBjoern A. Zeeb {
11596c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv;
11606c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = msta->vif;
11616c92544dSBjoern A. Zeeb struct wtbl_req_hdr *wtbl_hdr;
11626c92544dSBjoern A. Zeeb struct tlv *sta_wtbl;
11636c92544dSBjoern A. Zeeb struct sk_buff *skb;
11646c92544dSBjoern A. Zeeb int err;
11656c92544dSBjoern A. Zeeb
11666c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
11676c92544dSBjoern A. Zeeb &msta->wcid);
11686c92544dSBjoern A. Zeeb if (IS_ERR(skb))
11696c92544dSBjoern A. Zeeb return PTR_ERR(skb);
11706c92544dSBjoern A. Zeeb
11716c92544dSBjoern A. Zeeb mt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);
11726c92544dSBjoern A. Zeeb
11736c92544dSBjoern A. Zeeb err = mt76_mcu_skb_send_msg(&dev->mt76, skb,
11746c92544dSBjoern A. Zeeb MCU_UNI_CMD(STA_REC_UPDATE), true);
11756c92544dSBjoern A. Zeeb if (err < 0 || !enable)
11766c92544dSBjoern A. Zeeb return err;
11776c92544dSBjoern A. Zeeb
11786c92544dSBjoern A. Zeeb skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
11796c92544dSBjoern A. Zeeb &msta->wcid);
11806c92544dSBjoern A. Zeeb if (IS_ERR(skb))
11816c92544dSBjoern A. Zeeb return PTR_ERR(skb);
11826c92544dSBjoern A. Zeeb
11836c92544dSBjoern A. Zeeb sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
11846c92544dSBjoern A. Zeeb sizeof(struct tlv));
11856c92544dSBjoern A. Zeeb
11866c92544dSBjoern A. Zeeb wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
11876c92544dSBjoern A. Zeeb WTBL_SET, sta_wtbl, &skb);
11886c92544dSBjoern A. Zeeb if (IS_ERR(wtbl_hdr))
11896c92544dSBjoern A. Zeeb return PTR_ERR(wtbl_hdr);
11906c92544dSBjoern A. Zeeb
11916c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, false,
11926c92544dSBjoern A. Zeeb sta_wtbl, wtbl_hdr);
11936c92544dSBjoern A. Zeeb
11946c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
11956c92544dSBjoern A. Zeeb MCU_UNI_CMD(STA_REC_UPDATE), true);
11966c92544dSBjoern A. Zeeb }
11976c92544dSBjoern A. Zeeb
11986c92544dSBjoern A. Zeeb static int
mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)11996c92544dSBjoern A. Zeeb mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev,
12006c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
12016c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
12026c92544dSBjoern A. Zeeb {
12036c92544dSBjoern A. Zeeb struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
12046c92544dSBjoern A. Zeeb
12056c92544dSBjoern A. Zeeb return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
12066c92544dSBjoern A. Zeeb vif, &msta->wcid,
12076c92544dSBjoern A. Zeeb MCU_UNI_CMD(STA_REC_UPDATE));
12086c92544dSBjoern A. Zeeb }
12096c92544dSBjoern A. Zeeb
12106c92544dSBjoern A. Zeeb static const struct mt7615_mcu_ops uni_update_ops = {
12116c92544dSBjoern A. Zeeb .add_beacon_offload = mt7615_mcu_uni_add_beacon_offload,
12126c92544dSBjoern A. Zeeb .set_pm_state = mt7615_mcu_uni_ctrl_pm_state,
12136c92544dSBjoern A. Zeeb .add_dev_info = mt7615_mcu_uni_add_dev,
12146c92544dSBjoern A. Zeeb .add_bss_info = mt7615_mcu_uni_add_bss,
12156c92544dSBjoern A. Zeeb .add_tx_ba = mt7615_mcu_uni_tx_ba,
12166c92544dSBjoern A. Zeeb .add_rx_ba = mt7615_mcu_uni_rx_ba,
12176c92544dSBjoern A. Zeeb .sta_add = mt7615_mcu_uni_add_sta,
12186c92544dSBjoern A. Zeeb .set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,
12196c92544dSBjoern A. Zeeb .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
12206c92544dSBjoern A. Zeeb .set_sta_decap_offload = mt7615_mcu_sta_uni_update_hdr_trans,
12216c92544dSBjoern A. Zeeb };
12226c92544dSBjoern A. Zeeb
mt7615_mcu_restart(struct mt76_dev * dev)12236c92544dSBjoern A. Zeeb int mt7615_mcu_restart(struct mt76_dev *dev)
12246c92544dSBjoern A. Zeeb {
12256c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(dev, MCU_CMD(RESTART_DL_REQ), NULL, 0, true);
12266c92544dSBjoern A. Zeeb }
12276c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_mcu_restart);
12286c92544dSBjoern A. Zeeb
mt7615_load_patch(struct mt7615_dev * dev,u32 addr,const char * name)12296c92544dSBjoern A. Zeeb static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)
12306c92544dSBjoern A. Zeeb {
12316c92544dSBjoern A. Zeeb const struct mt7615_patch_hdr *hdr;
12326c92544dSBjoern A. Zeeb const struct firmware *fw = NULL;
12336c92544dSBjoern A. Zeeb int len, ret, sem;
12346c92544dSBjoern A. Zeeb
12356c92544dSBjoern A. Zeeb ret = firmware_request_nowarn(&fw, name, dev->mt76.dev);
12366c92544dSBjoern A. Zeeb if (ret)
12376c92544dSBjoern A. Zeeb return ret;
12386c92544dSBjoern A. Zeeb
12396c92544dSBjoern A. Zeeb if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
12406c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Invalid firmware\n");
12416c92544dSBjoern A. Zeeb ret = -EINVAL;
12426c92544dSBjoern A. Zeeb goto release_fw;
12436c92544dSBjoern A. Zeeb }
12446c92544dSBjoern A. Zeeb
12456c92544dSBjoern A. Zeeb sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);
12466c92544dSBjoern A. Zeeb switch (sem) {
12476c92544dSBjoern A. Zeeb case PATCH_IS_DL:
12486c92544dSBjoern A. Zeeb goto release_fw;
12496c92544dSBjoern A. Zeeb case PATCH_NOT_DL_SEM_SUCCESS:
12506c92544dSBjoern A. Zeeb break;
12516c92544dSBjoern A. Zeeb default:
12526c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
12536c92544dSBjoern A. Zeeb ret = -EAGAIN;
12546c92544dSBjoern A. Zeeb goto release_fw;
12556c92544dSBjoern A. Zeeb }
12566c92544dSBjoern A. Zeeb
12576c92544dSBjoern A. Zeeb hdr = (const struct mt7615_patch_hdr *)(fw->data);
12586c92544dSBjoern A. Zeeb
12596c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
12606c92544dSBjoern A. Zeeb be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
12616c92544dSBjoern A. Zeeb
12626c92544dSBjoern A. Zeeb len = fw->size - sizeof(*hdr);
12636c92544dSBjoern A. Zeeb
12646c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
12656c92544dSBjoern A. Zeeb DL_MODE_NEED_RSP);
12666c92544dSBjoern A. Zeeb if (ret) {
12676c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Download request failed\n");
12686c92544dSBjoern A. Zeeb goto out;
12696c92544dSBjoern A. Zeeb }
12706c92544dSBjoern A. Zeeb
12716c92544dSBjoern A. Zeeb ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
12726c92544dSBjoern A. Zeeb fw->data + sizeof(*hdr), len);
12736c92544dSBjoern A. Zeeb if (ret) {
12746c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
12756c92544dSBjoern A. Zeeb goto out;
12766c92544dSBjoern A. Zeeb }
12776c92544dSBjoern A. Zeeb
12786c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_start_patch(&dev->mt76);
12796c92544dSBjoern A. Zeeb if (ret)
12806c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to start patch\n");
12816c92544dSBjoern A. Zeeb
12826c92544dSBjoern A. Zeeb out:
12836c92544dSBjoern A. Zeeb sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
12846c92544dSBjoern A. Zeeb switch (sem) {
12856c92544dSBjoern A. Zeeb case PATCH_REL_SEM_SUCCESS:
12866c92544dSBjoern A. Zeeb break;
12876c92544dSBjoern A. Zeeb default:
12886c92544dSBjoern A. Zeeb ret = -EAGAIN;
12896c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
12906c92544dSBjoern A. Zeeb break;
12916c92544dSBjoern A. Zeeb }
12926c92544dSBjoern A. Zeeb
12936c92544dSBjoern A. Zeeb release_fw:
12946c92544dSBjoern A. Zeeb release_firmware(fw);
12956c92544dSBjoern A. Zeeb
12966c92544dSBjoern A. Zeeb return ret;
12976c92544dSBjoern A. Zeeb }
12986c92544dSBjoern A. Zeeb
12996c92544dSBjoern A. Zeeb static int
mt7615_mcu_send_ram_firmware(struct mt7615_dev * dev,const struct mt7615_fw_trailer * hdr,const u8 * data,bool is_cr4)13006c92544dSBjoern A. Zeeb mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,
13016c92544dSBjoern A. Zeeb const struct mt7615_fw_trailer *hdr,
13026c92544dSBjoern A. Zeeb const u8 *data, bool is_cr4)
13036c92544dSBjoern A. Zeeb {
13046c92544dSBjoern A. Zeeb int n_region = is_cr4 ? CR4_REGION_NUM : N9_REGION_NUM;
13056c92544dSBjoern A. Zeeb int err, i, offset = 0;
13066c92544dSBjoern A. Zeeb u32 len, addr, mode;
13076c92544dSBjoern A. Zeeb
13086c92544dSBjoern A. Zeeb for (i = 0; i < n_region; i++) {
13096c92544dSBjoern A. Zeeb mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
13106c92544dSBjoern A. Zeeb hdr[i].feature_set, is_cr4);
13116c92544dSBjoern A. Zeeb len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;
13126c92544dSBjoern A. Zeeb addr = le32_to_cpu(hdr[i].addr);
13136c92544dSBjoern A. Zeeb
13146c92544dSBjoern A. Zeeb err = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
13156c92544dSBjoern A. Zeeb mode);
13166c92544dSBjoern A. Zeeb if (err) {
13176c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Download request failed\n");
13186c92544dSBjoern A. Zeeb return err;
13196c92544dSBjoern A. Zeeb }
13206c92544dSBjoern A. Zeeb
13216c92544dSBjoern A. Zeeb err = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
13226c92544dSBjoern A. Zeeb data + offset, len);
13236c92544dSBjoern A. Zeeb if (err) {
13246c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
13256c92544dSBjoern A. Zeeb return err;
13266c92544dSBjoern A. Zeeb }
13276c92544dSBjoern A. Zeeb
13286c92544dSBjoern A. Zeeb offset += len;
13296c92544dSBjoern A. Zeeb }
13306c92544dSBjoern A. Zeeb
13316c92544dSBjoern A. Zeeb return 0;
13326c92544dSBjoern A. Zeeb }
13336c92544dSBjoern A. Zeeb
mt7615_load_n9(struct mt7615_dev * dev,const char * name)13346c92544dSBjoern A. Zeeb static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)
13356c92544dSBjoern A. Zeeb {
13366c92544dSBjoern A. Zeeb const struct mt7615_fw_trailer *hdr;
13376c92544dSBjoern A. Zeeb const struct firmware *fw;
13386c92544dSBjoern A. Zeeb int ret;
13396c92544dSBjoern A. Zeeb
13406c92544dSBjoern A. Zeeb ret = request_firmware(&fw, name, dev->mt76.dev);
13416c92544dSBjoern A. Zeeb if (ret)
13426c92544dSBjoern A. Zeeb return ret;
13436c92544dSBjoern A. Zeeb
13446c92544dSBjoern A. Zeeb if (!fw || !fw->data || fw->size < N9_REGION_NUM * sizeof(*hdr)) {
13456c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Invalid firmware\n");
13466c92544dSBjoern A. Zeeb ret = -EINVAL;
13476c92544dSBjoern A. Zeeb goto out;
13486c92544dSBjoern A. Zeeb }
13496c92544dSBjoern A. Zeeb
13506c92544dSBjoern A. Zeeb hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -
13516c92544dSBjoern A. Zeeb N9_REGION_NUM * sizeof(*hdr));
13526c92544dSBjoern A. Zeeb
13536c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
13546c92544dSBjoern A. Zeeb hdr->fw_ver, hdr->build_date);
13556c92544dSBjoern A. Zeeb
13566c92544dSBjoern A. Zeeb ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, false);
13576c92544dSBjoern A. Zeeb if (ret)
13586c92544dSBjoern A. Zeeb goto out;
13596c92544dSBjoern A. Zeeb
13606c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_start_firmware(&dev->mt76,
13616c92544dSBjoern A. Zeeb le32_to_cpu(hdr->addr),
13626c92544dSBjoern A. Zeeb FW_START_OVERRIDE);
13636c92544dSBjoern A. Zeeb if (ret) {
13646c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");
13656c92544dSBjoern A. Zeeb goto out;
13666c92544dSBjoern A. Zeeb }
13676c92544dSBjoern A. Zeeb
13686c92544dSBjoern A. Zeeb snprintf(dev->mt76.hw->wiphy->fw_version,
13696c92544dSBjoern A. Zeeb sizeof(dev->mt76.hw->wiphy->fw_version),
13706c92544dSBjoern A. Zeeb "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
13716c92544dSBjoern A. Zeeb
13726c92544dSBjoern A. Zeeb if (!is_mt7615(&dev->mt76)) {
13736c92544dSBjoern A. Zeeb dev->fw_ver = MT7615_FIRMWARE_V2;
13746c92544dSBjoern A. Zeeb dev->mcu_ops = &sta_update_ops;
13756c92544dSBjoern A. Zeeb } else {
13766c92544dSBjoern A. Zeeb dev->fw_ver = MT7615_FIRMWARE_V1;
13776c92544dSBjoern A. Zeeb dev->mcu_ops = &wtbl_update_ops;
13786c92544dSBjoern A. Zeeb }
13796c92544dSBjoern A. Zeeb
13806c92544dSBjoern A. Zeeb out:
13816c92544dSBjoern A. Zeeb release_firmware(fw);
13826c92544dSBjoern A. Zeeb return ret;
13836c92544dSBjoern A. Zeeb }
13846c92544dSBjoern A. Zeeb
mt7615_load_cr4(struct mt7615_dev * dev,const char * name)13856c92544dSBjoern A. Zeeb static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name)
13866c92544dSBjoern A. Zeeb {
13876c92544dSBjoern A. Zeeb const struct mt7615_fw_trailer *hdr;
13886c92544dSBjoern A. Zeeb const struct firmware *fw;
13896c92544dSBjoern A. Zeeb int ret;
13906c92544dSBjoern A. Zeeb
13916c92544dSBjoern A. Zeeb ret = request_firmware(&fw, name, dev->mt76.dev);
13926c92544dSBjoern A. Zeeb if (ret)
13936c92544dSBjoern A. Zeeb return ret;
13946c92544dSBjoern A. Zeeb
13956c92544dSBjoern A. Zeeb if (!fw || !fw->data || fw->size < CR4_REGION_NUM * sizeof(*hdr)) {
13966c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Invalid firmware\n");
13976c92544dSBjoern A. Zeeb ret = -EINVAL;
13986c92544dSBjoern A. Zeeb goto out;
13996c92544dSBjoern A. Zeeb }
14006c92544dSBjoern A. Zeeb
14016c92544dSBjoern A. Zeeb hdr = (const struct mt7615_fw_trailer *)(fw->data + fw->size -
14026c92544dSBjoern A. Zeeb CR4_REGION_NUM * sizeof(*hdr));
14036c92544dSBjoern A. Zeeb
14046c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "CR4 Firmware Version: %.10s, Build Time: %.15s\n",
14056c92544dSBjoern A. Zeeb hdr->fw_ver, hdr->build_date);
14066c92544dSBjoern A. Zeeb
14076c92544dSBjoern A. Zeeb ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, true);
14086c92544dSBjoern A. Zeeb if (ret)
14096c92544dSBjoern A. Zeeb goto out;
14106c92544dSBjoern A. Zeeb
14116c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_start_firmware(&dev->mt76, 0,
14126c92544dSBjoern A. Zeeb FW_START_WORKING_PDA_CR4);
14136c92544dSBjoern A. Zeeb if (ret) {
14146c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n");
14156c92544dSBjoern A. Zeeb goto out;
14166c92544dSBjoern A. Zeeb }
14176c92544dSBjoern A. Zeeb
14186c92544dSBjoern A. Zeeb out:
14196c92544dSBjoern A. Zeeb release_firmware(fw);
14206c92544dSBjoern A. Zeeb
14216c92544dSBjoern A. Zeeb return ret;
14226c92544dSBjoern A. Zeeb }
14236c92544dSBjoern A. Zeeb
mt7615_load_ram(struct mt7615_dev * dev)14246c92544dSBjoern A. Zeeb static int mt7615_load_ram(struct mt7615_dev *dev)
14256c92544dSBjoern A. Zeeb {
14266c92544dSBjoern A. Zeeb int ret;
14276c92544dSBjoern A. Zeeb
14286c92544dSBjoern A. Zeeb ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9);
14296c92544dSBjoern A. Zeeb if (ret)
14306c92544dSBjoern A. Zeeb return ret;
14316c92544dSBjoern A. Zeeb
14326c92544dSBjoern A. Zeeb return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4);
14336c92544dSBjoern A. Zeeb }
14346c92544dSBjoern A. Zeeb
mt7615_load_firmware(struct mt7615_dev * dev)14356c92544dSBjoern A. Zeeb static int mt7615_load_firmware(struct mt7615_dev *dev)
14366c92544dSBjoern A. Zeeb {
14376c92544dSBjoern A. Zeeb int ret;
14386c92544dSBjoern A. Zeeb u32 val;
14396c92544dSBjoern A. Zeeb
14406c92544dSBjoern A. Zeeb val = mt76_get_field(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE);
14416c92544dSBjoern A. Zeeb
14426c92544dSBjoern A. Zeeb if (val != FW_STATE_FW_DOWNLOAD) {
14436c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Firmware is not ready for download\n");
14446c92544dSBjoern A. Zeeb return -EIO;
14456c92544dSBjoern A. Zeeb }
14466c92544dSBjoern A. Zeeb
14476c92544dSBjoern A. Zeeb ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH);
14486c92544dSBjoern A. Zeeb if (ret)
14496c92544dSBjoern A. Zeeb return ret;
14506c92544dSBjoern A. Zeeb
14516c92544dSBjoern A. Zeeb ret = mt7615_load_ram(dev);
14526c92544dSBjoern A. Zeeb if (ret)
14536c92544dSBjoern A. Zeeb return ret;
14546c92544dSBjoern A. Zeeb
14556c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_TOP_MISC2, MT_TOP_MISC2_FW_STATE,
14566c92544dSBjoern A. Zeeb FIELD_PREP(MT_TOP_MISC2_FW_STATE,
14576c92544dSBjoern A. Zeeb FW_STATE_RDY), 500)) {
14586c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
14596c92544dSBjoern A. Zeeb return -EIO;
14606c92544dSBjoern A. Zeeb }
14616c92544dSBjoern A. Zeeb
14626c92544dSBjoern A. Zeeb return 0;
14636c92544dSBjoern A. Zeeb }
14646c92544dSBjoern A. Zeeb
mt7622_load_firmware(struct mt7615_dev * dev)14656c92544dSBjoern A. Zeeb static int mt7622_load_firmware(struct mt7615_dev *dev)
14666c92544dSBjoern A. Zeeb {
14676c92544dSBjoern A. Zeeb int ret;
14686c92544dSBjoern A. Zeeb u32 val;
14696c92544dSBjoern A. Zeeb
14706c92544dSBjoern A. Zeeb mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);
14716c92544dSBjoern A. Zeeb
14726c92544dSBjoern A. Zeeb val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE);
14736c92544dSBjoern A. Zeeb if (val != FW_STATE_FW_DOWNLOAD) {
14746c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Firmware is not ready for download\n");
14756c92544dSBjoern A. Zeeb return -EIO;
14766c92544dSBjoern A. Zeeb }
14776c92544dSBjoern A. Zeeb
14786c92544dSBjoern A. Zeeb ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH);
14796c92544dSBjoern A. Zeeb if (ret)
14806c92544dSBjoern A. Zeeb return ret;
14816c92544dSBjoern A. Zeeb
14826c92544dSBjoern A. Zeeb ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9);
14836c92544dSBjoern A. Zeeb if (ret)
14846c92544dSBjoern A. Zeeb return ret;
14856c92544dSBjoern A. Zeeb
14866c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE,
14876c92544dSBjoern A. Zeeb FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE,
14886c92544dSBjoern A. Zeeb FW_STATE_NORMAL_TRX), 1500)) {
14896c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
14906c92544dSBjoern A. Zeeb return -EIO;
14916c92544dSBjoern A. Zeeb }
14926c92544dSBjoern A. Zeeb
14936c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);
14946c92544dSBjoern A. Zeeb
14956c92544dSBjoern A. Zeeb return 0;
14966c92544dSBjoern A. Zeeb }
14976c92544dSBjoern A. Zeeb
mt7615_mcu_fw_log_2_host(struct mt7615_dev * dev,u8 ctrl)14986c92544dSBjoern A. Zeeb int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl)
14996c92544dSBjoern A. Zeeb {
15006c92544dSBjoern A. Zeeb struct {
15016c92544dSBjoern A. Zeeb u8 ctrl_val;
15026c92544dSBjoern A. Zeeb u8 pad[3];
15036c92544dSBjoern A. Zeeb } data = {
15046c92544dSBjoern A. Zeeb .ctrl_val = ctrl
15056c92544dSBjoern A. Zeeb };
15066c92544dSBjoern A. Zeeb
15076c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST),
15086c92544dSBjoern A. Zeeb &data, sizeof(data), true);
15096c92544dSBjoern A. Zeeb }
15106c92544dSBjoern A. Zeeb
mt7615_mcu_cal_cache_apply(struct mt7615_dev * dev)15116c92544dSBjoern A. Zeeb static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)
15126c92544dSBjoern A. Zeeb {
15136c92544dSBjoern A. Zeeb struct {
15146c92544dSBjoern A. Zeeb bool cache_enable;
15156c92544dSBjoern A. Zeeb u8 pad[3];
15166c92544dSBjoern A. Zeeb } data = {
15176c92544dSBjoern A. Zeeb .cache_enable = true
15186c92544dSBjoern A. Zeeb };
15196c92544dSBjoern A. Zeeb
15206c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(CAL_CACHE), &data,
15216c92544dSBjoern A. Zeeb sizeof(data), false);
15226c92544dSBjoern A. Zeeb }
15236c92544dSBjoern A. Zeeb
mt7663_load_n9(struct mt7615_dev * dev,const char * name)15246c92544dSBjoern A. Zeeb static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
15256c92544dSBjoern A. Zeeb {
15266c92544dSBjoern A. Zeeb u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;
15276c92544dSBjoern A. Zeeb const struct mt76_connac2_fw_trailer *hdr;
15286c92544dSBjoern A. Zeeb const struct mt7663_fw_buf *buf;
15296c92544dSBjoern A. Zeeb const struct firmware *fw;
15306c92544dSBjoern A. Zeeb const u8 *base_addr;
15316c92544dSBjoern A. Zeeb int i, ret;
15326c92544dSBjoern A. Zeeb
15336c92544dSBjoern A. Zeeb ret = request_firmware(&fw, name, dev->mt76.dev);
15346c92544dSBjoern A. Zeeb if (ret)
15356c92544dSBjoern A. Zeeb return ret;
15366c92544dSBjoern A. Zeeb
15376c92544dSBjoern A. Zeeb if (!fw || !fw->data || fw->size < FW_V3_COMMON_TAILER_SIZE) {
15386c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Invalid firmware\n");
15396c92544dSBjoern A. Zeeb ret = -EINVAL;
15406c92544dSBjoern A. Zeeb goto out;
15416c92544dSBjoern A. Zeeb }
15426c92544dSBjoern A. Zeeb
15436c92544dSBjoern A. Zeeb hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);
15446c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
15456c92544dSBjoern A. Zeeb hdr->fw_ver, hdr->build_date);
15466c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);
15476c92544dSBjoern A. Zeeb
15486c92544dSBjoern A. Zeeb base_addr = fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE;
15496c92544dSBjoern A. Zeeb for (i = 0; i < hdr->n_region; i++) {
15506c92544dSBjoern A. Zeeb u32 shift = (hdr->n_region - i) * FW_V3_REGION_TAILER_SIZE;
15516c92544dSBjoern A. Zeeb u32 len, addr, mode;
15526c92544dSBjoern A. Zeeb
15536c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i);
15546c92544dSBjoern A. Zeeb
15556c92544dSBjoern A. Zeeb buf = (const struct mt7663_fw_buf *)(base_addr - shift);
15566c92544dSBjoern A. Zeeb mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
15576c92544dSBjoern A. Zeeb buf->feature_set, false);
15586c92544dSBjoern A. Zeeb addr = le32_to_cpu(buf->img_dest_addr);
15596c92544dSBjoern A. Zeeb len = le32_to_cpu(buf->img_size);
15606c92544dSBjoern A. Zeeb
15616c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
15626c92544dSBjoern A. Zeeb mode);
15636c92544dSBjoern A. Zeeb if (ret) {
15646c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Download request failed\n");
15656c92544dSBjoern A. Zeeb goto out;
15666c92544dSBjoern A. Zeeb }
15676c92544dSBjoern A. Zeeb
15686c92544dSBjoern A. Zeeb ret = mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
15696c92544dSBjoern A. Zeeb fw->data + offset, len);
15706c92544dSBjoern A. Zeeb if (ret) {
15716c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to send firmware\n");
15726c92544dSBjoern A. Zeeb goto out;
15736c92544dSBjoern A. Zeeb }
15746c92544dSBjoern A. Zeeb
15756c92544dSBjoern A. Zeeb offset += le32_to_cpu(buf->img_size);
15766c92544dSBjoern A. Zeeb if (buf->feature_set & DL_MODE_VALID_RAM_ENTRY) {
15776c92544dSBjoern A. Zeeb override_addr = le32_to_cpu(buf->img_dest_addr);
15786c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "Region %d, override_addr = 0x%08x\n",
15796c92544dSBjoern A. Zeeb i, override_addr);
15806c92544dSBjoern A. Zeeb }
15816c92544dSBjoern A. Zeeb }
15826c92544dSBjoern A. Zeeb
15836c92544dSBjoern A. Zeeb if (override_addr)
15846c92544dSBjoern A. Zeeb flag |= FW_START_OVERRIDE;
15856c92544dSBjoern A. Zeeb
15866c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "override_addr = 0x%08x, option = %d\n",
15876c92544dSBjoern A. Zeeb override_addr, flag);
15886c92544dSBjoern A. Zeeb
15896c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_start_firmware(&dev->mt76, override_addr, flag);
15906c92544dSBjoern A. Zeeb if (ret) {
15916c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");
15926c92544dSBjoern A. Zeeb goto out;
15936c92544dSBjoern A. Zeeb }
15946c92544dSBjoern A. Zeeb
15956c92544dSBjoern A. Zeeb snprintf(dev->mt76.hw->wiphy->fw_version,
15966c92544dSBjoern A. Zeeb sizeof(dev->mt76.hw->wiphy->fw_version),
15976c92544dSBjoern A. Zeeb "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
15986c92544dSBjoern A. Zeeb
15996c92544dSBjoern A. Zeeb out:
16006c92544dSBjoern A. Zeeb release_firmware(fw);
16016c92544dSBjoern A. Zeeb
16026c92544dSBjoern A. Zeeb return ret;
16036c92544dSBjoern A. Zeeb }
16046c92544dSBjoern A. Zeeb
16056c92544dSBjoern A. Zeeb static int
mt7663_load_rom_patch(struct mt7615_dev * dev,const char ** n9_firmware)16066c92544dSBjoern A. Zeeb mt7663_load_rom_patch(struct mt7615_dev *dev, const char **n9_firmware)
16076c92544dSBjoern A. Zeeb {
16086c92544dSBjoern A. Zeeb const char *selected_rom, *secondary_rom = MT7663_ROM_PATCH;
16096c92544dSBjoern A. Zeeb const char *primary_rom = MT7663_OFFLOAD_ROM_PATCH;
16106c92544dSBjoern A. Zeeb int ret;
16116c92544dSBjoern A. Zeeb
16126c92544dSBjoern A. Zeeb if (!prefer_offload_fw) {
16136c92544dSBjoern A. Zeeb secondary_rom = MT7663_OFFLOAD_ROM_PATCH;
16146c92544dSBjoern A. Zeeb primary_rom = MT7663_ROM_PATCH;
16156c92544dSBjoern A. Zeeb }
16166c92544dSBjoern A. Zeeb selected_rom = primary_rom;
16176c92544dSBjoern A. Zeeb
16186c92544dSBjoern A. Zeeb ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS, primary_rom);
16196c92544dSBjoern A. Zeeb if (ret) {
16206c92544dSBjoern A. Zeeb dev_info(dev->mt76.dev, "%s not found, switching to %s",
16216c92544dSBjoern A. Zeeb primary_rom, secondary_rom);
16226c92544dSBjoern A. Zeeb ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS,
16236c92544dSBjoern A. Zeeb secondary_rom);
16246c92544dSBjoern A. Zeeb if (ret) {
16256c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "failed to load %s",
16266c92544dSBjoern A. Zeeb secondary_rom);
16276c92544dSBjoern A. Zeeb return ret;
16286c92544dSBjoern A. Zeeb }
16296c92544dSBjoern A. Zeeb selected_rom = secondary_rom;
16306c92544dSBjoern A. Zeeb }
16316c92544dSBjoern A. Zeeb
16326c92544dSBjoern A. Zeeb if (!strcmp(selected_rom, MT7663_OFFLOAD_ROM_PATCH)) {
16336c92544dSBjoern A. Zeeb *n9_firmware = MT7663_OFFLOAD_FIRMWARE_N9;
16346c92544dSBjoern A. Zeeb dev->fw_ver = MT7615_FIRMWARE_V3;
16356c92544dSBjoern A. Zeeb dev->mcu_ops = &uni_update_ops;
16366c92544dSBjoern A. Zeeb } else {
16376c92544dSBjoern A. Zeeb *n9_firmware = MT7663_FIRMWARE_N9;
16386c92544dSBjoern A. Zeeb dev->fw_ver = MT7615_FIRMWARE_V2;
16396c92544dSBjoern A. Zeeb dev->mcu_ops = &sta_update_ops;
16406c92544dSBjoern A. Zeeb }
16416c92544dSBjoern A. Zeeb
16426c92544dSBjoern A. Zeeb return 0;
16436c92544dSBjoern A. Zeeb }
16446c92544dSBjoern A. Zeeb
__mt7663_load_firmware(struct mt7615_dev * dev)16456c92544dSBjoern A. Zeeb int __mt7663_load_firmware(struct mt7615_dev *dev)
16466c92544dSBjoern A. Zeeb {
16476c92544dSBjoern A. Zeeb const char *n9_firmware;
16486c92544dSBjoern A. Zeeb int ret;
16496c92544dSBjoern A. Zeeb
16506c92544dSBjoern A. Zeeb ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
16516c92544dSBjoern A. Zeeb if (ret) {
16526c92544dSBjoern A. Zeeb dev_dbg(dev->mt76.dev, "Firmware is already download\n");
16536c92544dSBjoern A. Zeeb return -EIO;
16546c92544dSBjoern A. Zeeb }
16556c92544dSBjoern A. Zeeb
16566c92544dSBjoern A. Zeeb ret = mt7663_load_rom_patch(dev, &n9_firmware);
16576c92544dSBjoern A. Zeeb if (ret)
16586c92544dSBjoern A. Zeeb return ret;
16596c92544dSBjoern A. Zeeb
16606c92544dSBjoern A. Zeeb ret = mt7663_load_n9(dev, n9_firmware);
16616c92544dSBjoern A. Zeeb if (ret)
16626c92544dSBjoern A. Zeeb return ret;
16636c92544dSBjoern A. Zeeb
16646c92544dSBjoern A. Zeeb if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,
16656c92544dSBjoern A. Zeeb MT_TOP_MISC2_FW_N9_RDY, 1500)) {
16666c92544dSBjoern A. Zeeb ret = mt76_get_field(dev, MT_CONN_ON_MISC,
16676c92544dSBjoern A. Zeeb MT7663_TOP_MISC2_FW_STATE);
16686c92544dSBjoern A. Zeeb dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
16696c92544dSBjoern A. Zeeb return -EIO;
16706c92544dSBjoern A. Zeeb }
16716c92544dSBjoern A. Zeeb
16726c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
16736c92544dSBjoern A. Zeeb if (mt7615_firmware_offload(dev))
16746c92544dSBjoern A. Zeeb dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
16756c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
16766c92544dSBjoern A. Zeeb
16776c92544dSBjoern A. Zeeb dev_dbg(dev->mt76.dev, "Firmware init done\n");
16786c92544dSBjoern A. Zeeb
16796c92544dSBjoern A. Zeeb return 0;
16806c92544dSBjoern A. Zeeb }
16816c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(__mt7663_load_firmware);
16826c92544dSBjoern A. Zeeb
mt7663_load_firmware(struct mt7615_dev * dev)16836c92544dSBjoern A. Zeeb static int mt7663_load_firmware(struct mt7615_dev *dev)
16846c92544dSBjoern A. Zeeb {
16856c92544dSBjoern A. Zeeb int ret;
16866c92544dSBjoern A. Zeeb
16876c92544dSBjoern A. Zeeb mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);
16886c92544dSBjoern A. Zeeb
16896c92544dSBjoern A. Zeeb ret = __mt7663_load_firmware(dev);
16906c92544dSBjoern A. Zeeb if (ret)
16916c92544dSBjoern A. Zeeb return ret;
16926c92544dSBjoern A. Zeeb
16936c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);
16946c92544dSBjoern A. Zeeb
16956c92544dSBjoern A. Zeeb return 0;
16966c92544dSBjoern A. Zeeb }
16976c92544dSBjoern A. Zeeb
mt7615_mcu_init(struct mt7615_dev * dev)16986c92544dSBjoern A. Zeeb int mt7615_mcu_init(struct mt7615_dev *dev)
16996c92544dSBjoern A. Zeeb {
17006c92544dSBjoern A. Zeeb static const struct mt76_mcu_ops mt7615_mcu_ops = {
17016c92544dSBjoern A. Zeeb .headroom = sizeof(struct mt7615_mcu_txd),
17026c92544dSBjoern A. Zeeb .mcu_skb_send_msg = mt7615_mcu_send_message,
17036c92544dSBjoern A. Zeeb .mcu_parse_response = mt7615_mcu_parse_response,
17046c92544dSBjoern A. Zeeb };
17056c92544dSBjoern A. Zeeb int ret;
17066c92544dSBjoern A. Zeeb
1707*8ba4d145SBjoern A. Zeeb dev->mt76.mcu_ops = &mt7615_mcu_ops;
17086c92544dSBjoern A. Zeeb
17096c92544dSBjoern A. Zeeb ret = mt7615_mcu_drv_pmctrl(dev);
17106c92544dSBjoern A. Zeeb if (ret)
17116c92544dSBjoern A. Zeeb return ret;
17126c92544dSBjoern A. Zeeb
17136c92544dSBjoern A. Zeeb switch (mt76_chip(&dev->mt76)) {
17146c92544dSBjoern A. Zeeb case 0x7622:
17156c92544dSBjoern A. Zeeb ret = mt7622_load_firmware(dev);
17166c92544dSBjoern A. Zeeb break;
17176c92544dSBjoern A. Zeeb case 0x7663:
17186c92544dSBjoern A. Zeeb ret = mt7663_load_firmware(dev);
17196c92544dSBjoern A. Zeeb break;
17206c92544dSBjoern A. Zeeb default:
17216c92544dSBjoern A. Zeeb ret = mt7615_load_firmware(dev);
17226c92544dSBjoern A. Zeeb break;
17236c92544dSBjoern A. Zeeb }
17246c92544dSBjoern A. Zeeb if (ret)
17256c92544dSBjoern A. Zeeb return ret;
17266c92544dSBjoern A. Zeeb
17276c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
17286c92544dSBjoern A. Zeeb dev_dbg(dev->mt76.dev, "Firmware init done\n");
17296c92544dSBjoern A. Zeeb set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
17306c92544dSBjoern A. Zeeb
17316c92544dSBjoern A. Zeeb if (dev->dbdc_support) {
17326c92544dSBjoern A. Zeeb ret = mt7615_mcu_cal_cache_apply(dev);
17336c92544dSBjoern A. Zeeb if (ret)
17346c92544dSBjoern A. Zeeb return ret;
17356c92544dSBjoern A. Zeeb }
17366c92544dSBjoern A. Zeeb
17376c92544dSBjoern A. Zeeb return mt7615_mcu_fw_log_2_host(dev, 0);
17386c92544dSBjoern A. Zeeb }
17396c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_mcu_init);
17406c92544dSBjoern A. Zeeb
mt7615_mcu_exit(struct mt7615_dev * dev)17416c92544dSBjoern A. Zeeb void mt7615_mcu_exit(struct mt7615_dev *dev)
17426c92544dSBjoern A. Zeeb {
1743cbb3ec25SBjoern A. Zeeb mt7615_mcu_restart(&dev->mt76);
17446c92544dSBjoern A. Zeeb mt7615_mcu_set_fw_ctrl(dev);
17456c92544dSBjoern A. Zeeb skb_queue_purge(&dev->mt76.mcu.res_q);
17466c92544dSBjoern A. Zeeb }
17476c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_mcu_exit);
17486c92544dSBjoern A. Zeeb
mt7615_mcu_set_eeprom(struct mt7615_dev * dev)17496c92544dSBjoern A. Zeeb int mt7615_mcu_set_eeprom(struct mt7615_dev *dev)
17506c92544dSBjoern A. Zeeb {
17516c92544dSBjoern A. Zeeb struct {
17526c92544dSBjoern A. Zeeb u8 buffer_mode;
17536c92544dSBjoern A. Zeeb u8 content_format;
17546c92544dSBjoern A. Zeeb __le16 len;
17556c92544dSBjoern A. Zeeb } __packed req_hdr = {
17566c92544dSBjoern A. Zeeb .buffer_mode = 1,
17576c92544dSBjoern A. Zeeb };
17586c92544dSBjoern A. Zeeb u8 *eep = (u8 *)dev->mt76.eeprom.data;
17596c92544dSBjoern A. Zeeb struct sk_buff *skb;
17606c92544dSBjoern A. Zeeb int eep_len, offset;
17616c92544dSBjoern A. Zeeb
17626c92544dSBjoern A. Zeeb switch (mt76_chip(&dev->mt76)) {
17636c92544dSBjoern A. Zeeb case 0x7622:
17646c92544dSBjoern A. Zeeb eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0;
17656c92544dSBjoern A. Zeeb offset = MT_EE_NIC_CONF_0;
17666c92544dSBjoern A. Zeeb break;
17676c92544dSBjoern A. Zeeb case 0x7663:
17686c92544dSBjoern A. Zeeb eep_len = MT7663_EE_MAX - MT_EE_CHIP_ID;
17696c92544dSBjoern A. Zeeb req_hdr.content_format = 1;
17706c92544dSBjoern A. Zeeb offset = MT_EE_CHIP_ID;
17716c92544dSBjoern A. Zeeb break;
17726c92544dSBjoern A. Zeeb default:
17736c92544dSBjoern A. Zeeb eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0;
17746c92544dSBjoern A. Zeeb offset = MT_EE_NIC_CONF_0;
17756c92544dSBjoern A. Zeeb break;
17766c92544dSBjoern A. Zeeb }
17776c92544dSBjoern A. Zeeb
17786c92544dSBjoern A. Zeeb req_hdr.len = cpu_to_le16(eep_len);
17796c92544dSBjoern A. Zeeb
17806c92544dSBjoern A. Zeeb skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + eep_len);
17816c92544dSBjoern A. Zeeb if (!skb)
17826c92544dSBjoern A. Zeeb return -ENOMEM;
17836c92544dSBjoern A. Zeeb
17846c92544dSBjoern A. Zeeb skb_put_data(skb, &req_hdr, sizeof(req_hdr));
17856c92544dSBjoern A. Zeeb skb_put_data(skb, eep + offset, eep_len);
17866c92544dSBjoern A. Zeeb
17876c92544dSBjoern A. Zeeb return mt76_mcu_skb_send_msg(&dev->mt76, skb,
17886c92544dSBjoern A. Zeeb MCU_EXT_CMD(EFUSE_BUFFER_MODE), true);
17896c92544dSBjoern A. Zeeb }
17906c92544dSBjoern A. Zeeb
mt7615_mcu_set_wmm(struct mt7615_dev * dev,u8 queue,const struct ieee80211_tx_queue_params * params)17916c92544dSBjoern A. Zeeb int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
17926c92544dSBjoern A. Zeeb const struct ieee80211_tx_queue_params *params)
17936c92544dSBjoern A. Zeeb {
17946c92544dSBjoern A. Zeeb #define WMM_AIFS_SET BIT(0)
17956c92544dSBjoern A. Zeeb #define WMM_CW_MIN_SET BIT(1)
17966c92544dSBjoern A. Zeeb #define WMM_CW_MAX_SET BIT(2)
17976c92544dSBjoern A. Zeeb #define WMM_TXOP_SET BIT(3)
17986c92544dSBjoern A. Zeeb #define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \
17996c92544dSBjoern A. Zeeb WMM_CW_MAX_SET | WMM_TXOP_SET)
18006c92544dSBjoern A. Zeeb struct req_data {
18016c92544dSBjoern A. Zeeb u8 number;
18026c92544dSBjoern A. Zeeb u8 rsv[3];
18036c92544dSBjoern A. Zeeb u8 queue;
18046c92544dSBjoern A. Zeeb u8 valid;
18056c92544dSBjoern A. Zeeb u8 aifs;
18066c92544dSBjoern A. Zeeb u8 cw_min;
18076c92544dSBjoern A. Zeeb __le16 cw_max;
18086c92544dSBjoern A. Zeeb __le16 txop;
18096c92544dSBjoern A. Zeeb } __packed req = {
18106c92544dSBjoern A. Zeeb .number = 1,
18116c92544dSBjoern A. Zeeb .queue = queue,
18126c92544dSBjoern A. Zeeb .valid = WMM_PARAM_SET,
18136c92544dSBjoern A. Zeeb .aifs = params->aifs,
18146c92544dSBjoern A. Zeeb .cw_min = 5,
18156c92544dSBjoern A. Zeeb .cw_max = cpu_to_le16(10),
18166c92544dSBjoern A. Zeeb .txop = cpu_to_le16(params->txop),
18176c92544dSBjoern A. Zeeb };
18186c92544dSBjoern A. Zeeb
18196c92544dSBjoern A. Zeeb if (params->cw_min)
18206c92544dSBjoern A. Zeeb req.cw_min = fls(params->cw_min);
18216c92544dSBjoern A. Zeeb if (params->cw_max)
18226c92544dSBjoern A. Zeeb req.cw_max = cpu_to_le16(fls(params->cw_max));
18236c92544dSBjoern A. Zeeb
18246c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EDCA_UPDATE),
18256c92544dSBjoern A. Zeeb &req, sizeof(req), true);
18266c92544dSBjoern A. Zeeb }
18276c92544dSBjoern A. Zeeb
mt7615_mcu_set_dbdc(struct mt7615_dev * dev)18286c92544dSBjoern A. Zeeb int mt7615_mcu_set_dbdc(struct mt7615_dev *dev)
18296c92544dSBjoern A. Zeeb {
18306c92544dSBjoern A. Zeeb struct mt7615_phy *ext_phy = mt7615_ext_phy(dev);
18316c92544dSBjoern A. Zeeb struct dbdc_entry {
18326c92544dSBjoern A. Zeeb u8 type;
18336c92544dSBjoern A. Zeeb u8 index;
18346c92544dSBjoern A. Zeeb u8 band;
18356c92544dSBjoern A. Zeeb u8 _rsv;
18366c92544dSBjoern A. Zeeb };
18376c92544dSBjoern A. Zeeb struct {
18386c92544dSBjoern A. Zeeb u8 enable;
18396c92544dSBjoern A. Zeeb u8 num;
18406c92544dSBjoern A. Zeeb u8 _rsv[2];
18416c92544dSBjoern A. Zeeb struct dbdc_entry entry[64];
18426c92544dSBjoern A. Zeeb } req = {
18436c92544dSBjoern A. Zeeb .enable = !!ext_phy,
18446c92544dSBjoern A. Zeeb };
18456c92544dSBjoern A. Zeeb int i;
18466c92544dSBjoern A. Zeeb
18476c92544dSBjoern A. Zeeb if (!ext_phy)
18486c92544dSBjoern A. Zeeb goto out;
18496c92544dSBjoern A. Zeeb
18506c92544dSBjoern A. Zeeb #define ADD_DBDC_ENTRY(_type, _idx, _band) \
18516c92544dSBjoern A. Zeeb do { \
18526c92544dSBjoern A. Zeeb req.entry[req.num].type = _type; \
18536c92544dSBjoern A. Zeeb req.entry[req.num].index = _idx; \
18546c92544dSBjoern A. Zeeb req.entry[req.num++].band = _band; \
18556c92544dSBjoern A. Zeeb } while (0)
18566c92544dSBjoern A. Zeeb
18576c92544dSBjoern A. Zeeb for (i = 0; i < 4; i++) {
18586c92544dSBjoern A. Zeeb bool band = !!(ext_phy->omac_mask & BIT_ULL(i));
18596c92544dSBjoern A. Zeeb
18606c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band);
18616c92544dSBjoern A. Zeeb }
18626c92544dSBjoern A. Zeeb
18636c92544dSBjoern A. Zeeb for (i = 0; i < 14; i++) {
18646c92544dSBjoern A. Zeeb bool band = !!(ext_phy->omac_mask & BIT_ULL(0x11 + i));
18656c92544dSBjoern A. Zeeb
18666c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band);
18676c92544dSBjoern A. Zeeb }
18686c92544dSBjoern A. Zeeb
18696c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1);
18706c92544dSBjoern A. Zeeb
18716c92544dSBjoern A. Zeeb for (i = 0; i < 3; i++)
18726c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1);
18736c92544dSBjoern A. Zeeb
18746c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0);
18756c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0);
18766c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1);
18776c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1);
18786c92544dSBjoern A. Zeeb
18796c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0);
18806c92544dSBjoern A. Zeeb ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1);
18816c92544dSBjoern A. Zeeb
18826c92544dSBjoern A. Zeeb out:
18836c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(DBDC_CTRL), &req,
18846c92544dSBjoern A. Zeeb sizeof(req), true);
18856c92544dSBjoern A. Zeeb }
18866c92544dSBjoern A. Zeeb
mt7615_mcu_set_fcc5_lpn(struct mt7615_dev * dev,int val)18876c92544dSBjoern A. Zeeb int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val)
18886c92544dSBjoern A. Zeeb {
18896c92544dSBjoern A. Zeeb struct {
18906c92544dSBjoern A. Zeeb __le16 tag;
18916c92544dSBjoern A. Zeeb __le16 min_lpn;
18926c92544dSBjoern A. Zeeb } req = {
18936c92544dSBjoern A. Zeeb .tag = cpu_to_le16(0x1),
18946c92544dSBjoern A. Zeeb .min_lpn = cpu_to_le16(val),
18956c92544dSBjoern A. Zeeb };
18966c92544dSBjoern A. Zeeb
18976c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),
18986c92544dSBjoern A. Zeeb &req, sizeof(req), true);
18996c92544dSBjoern A. Zeeb }
19006c92544dSBjoern A. Zeeb
mt7615_mcu_set_pulse_th(struct mt7615_dev * dev,const struct mt7615_dfs_pulse * pulse)19016c92544dSBjoern A. Zeeb int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
19026c92544dSBjoern A. Zeeb const struct mt7615_dfs_pulse *pulse)
19036c92544dSBjoern A. Zeeb {
19046c92544dSBjoern A. Zeeb struct {
19056c92544dSBjoern A. Zeeb __le16 tag;
19066c92544dSBjoern A. Zeeb __le32 max_width; /* us */
19076c92544dSBjoern A. Zeeb __le32 max_pwr; /* dbm */
19086c92544dSBjoern A. Zeeb __le32 min_pwr; /* dbm */
19096c92544dSBjoern A. Zeeb __le32 min_stgr_pri; /* us */
19106c92544dSBjoern A. Zeeb __le32 max_stgr_pri; /* us */
19116c92544dSBjoern A. Zeeb __le32 min_cr_pri; /* us */
19126c92544dSBjoern A. Zeeb __le32 max_cr_pri; /* us */
19136c92544dSBjoern A. Zeeb } req = {
19146c92544dSBjoern A. Zeeb .tag = cpu_to_le16(0x3),
19156c92544dSBjoern A. Zeeb #define __req_field(field) .field = cpu_to_le32(pulse->field)
19166c92544dSBjoern A. Zeeb __req_field(max_width),
19176c92544dSBjoern A. Zeeb __req_field(max_pwr),
19186c92544dSBjoern A. Zeeb __req_field(min_pwr),
19196c92544dSBjoern A. Zeeb __req_field(min_stgr_pri),
19206c92544dSBjoern A. Zeeb __req_field(max_stgr_pri),
19216c92544dSBjoern A. Zeeb __req_field(min_cr_pri),
19226c92544dSBjoern A. Zeeb __req_field(max_cr_pri),
19236c92544dSBjoern A. Zeeb #undef __req_field
19246c92544dSBjoern A. Zeeb };
19256c92544dSBjoern A. Zeeb
19266c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),
19276c92544dSBjoern A. Zeeb &req, sizeof(req), true);
19286c92544dSBjoern A. Zeeb }
19296c92544dSBjoern A. Zeeb
mt7615_mcu_set_radar_th(struct mt7615_dev * dev,int index,const struct mt7615_dfs_pattern * pattern)19306c92544dSBjoern A. Zeeb int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,
19316c92544dSBjoern A. Zeeb const struct mt7615_dfs_pattern *pattern)
19326c92544dSBjoern A. Zeeb {
19336c92544dSBjoern A. Zeeb struct {
19346c92544dSBjoern A. Zeeb __le16 tag;
19356c92544dSBjoern A. Zeeb __le16 radar_type;
19366c92544dSBjoern A. Zeeb u8 enb;
19376c92544dSBjoern A. Zeeb u8 stgr;
19386c92544dSBjoern A. Zeeb u8 min_crpn;
19396c92544dSBjoern A. Zeeb u8 max_crpn;
19406c92544dSBjoern A. Zeeb u8 min_crpr;
19416c92544dSBjoern A. Zeeb u8 min_pw;
19426c92544dSBjoern A. Zeeb u8 max_pw;
19436c92544dSBjoern A. Zeeb __le32 min_pri;
19446c92544dSBjoern A. Zeeb __le32 max_pri;
19456c92544dSBjoern A. Zeeb u8 min_crbn;
19466c92544dSBjoern A. Zeeb u8 max_crbn;
19476c92544dSBjoern A. Zeeb u8 min_stgpn;
19486c92544dSBjoern A. Zeeb u8 max_stgpn;
19496c92544dSBjoern A. Zeeb u8 min_stgpr;
19506c92544dSBjoern A. Zeeb } req = {
19516c92544dSBjoern A. Zeeb .tag = cpu_to_le16(0x2),
19526c92544dSBjoern A. Zeeb .radar_type = cpu_to_le16(index),
19536c92544dSBjoern A. Zeeb #define __req_field_u8(field) .field = pattern->field
19546c92544dSBjoern A. Zeeb #define __req_field_u32(field) .field = cpu_to_le32(pattern->field)
19556c92544dSBjoern A. Zeeb __req_field_u8(enb),
19566c92544dSBjoern A. Zeeb __req_field_u8(stgr),
19576c92544dSBjoern A. Zeeb __req_field_u8(min_crpn),
19586c92544dSBjoern A. Zeeb __req_field_u8(max_crpn),
19596c92544dSBjoern A. Zeeb __req_field_u8(min_crpr),
19606c92544dSBjoern A. Zeeb __req_field_u8(min_pw),
19616c92544dSBjoern A. Zeeb __req_field_u8(max_pw),
19626c92544dSBjoern A. Zeeb __req_field_u32(min_pri),
19636c92544dSBjoern A. Zeeb __req_field_u32(max_pri),
19646c92544dSBjoern A. Zeeb __req_field_u8(min_crbn),
19656c92544dSBjoern A. Zeeb __req_field_u8(max_crbn),
19666c92544dSBjoern A. Zeeb __req_field_u8(min_stgpn),
19676c92544dSBjoern A. Zeeb __req_field_u8(max_stgpn),
19686c92544dSBjoern A. Zeeb __req_field_u8(min_stgpr),
19696c92544dSBjoern A. Zeeb #undef __req_field_u8
19706c92544dSBjoern A. Zeeb #undef __req_field_u32
19716c92544dSBjoern A. Zeeb };
19726c92544dSBjoern A. Zeeb
19736c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RADAR_TH),
19746c92544dSBjoern A. Zeeb &req, sizeof(req), true);
19756c92544dSBjoern A. Zeeb }
19766c92544dSBjoern A. Zeeb
mt7615_mcu_rdd_send_pattern(struct mt7615_dev * dev)19776c92544dSBjoern A. Zeeb int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)
19786c92544dSBjoern A. Zeeb {
19796c92544dSBjoern A. Zeeb struct {
19806c92544dSBjoern A. Zeeb u8 pulse_num;
19816c92544dSBjoern A. Zeeb u8 rsv[3];
19826c92544dSBjoern A. Zeeb struct {
19836c92544dSBjoern A. Zeeb __le32 start_time;
19846c92544dSBjoern A. Zeeb __le16 width;
19856c92544dSBjoern A. Zeeb __le16 power;
19866c92544dSBjoern A. Zeeb } pattern[32];
19876c92544dSBjoern A. Zeeb } req = {
19886c92544dSBjoern A. Zeeb .pulse_num = dev->radar_pattern.n_pulses,
19896c92544dSBjoern A. Zeeb };
19906c92544dSBjoern A. Zeeb u32 start_time = ktime_to_ms(ktime_get_boottime());
19916c92544dSBjoern A. Zeeb int i;
19926c92544dSBjoern A. Zeeb
19936c92544dSBjoern A. Zeeb if (dev->radar_pattern.n_pulses > ARRAY_SIZE(req.pattern))
19946c92544dSBjoern A. Zeeb return -EINVAL;
19956c92544dSBjoern A. Zeeb
19966c92544dSBjoern A. Zeeb /* TODO: add some noise here */
19976c92544dSBjoern A. Zeeb for (i = 0; i < dev->radar_pattern.n_pulses; i++) {
19986c92544dSBjoern A. Zeeb u32 ts = start_time + i * dev->radar_pattern.period;
19996c92544dSBjoern A. Zeeb
20006c92544dSBjoern A. Zeeb req.pattern[i].width = cpu_to_le16(dev->radar_pattern.width);
20016c92544dSBjoern A. Zeeb req.pattern[i].power = cpu_to_le16(dev->radar_pattern.power);
20026c92544dSBjoern A. Zeeb req.pattern[i].start_time = cpu_to_le32(ts);
20036c92544dSBjoern A. Zeeb }
20046c92544dSBjoern A. Zeeb
20056c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_RDD_PATTERN),
20066c92544dSBjoern A. Zeeb &req, sizeof(req), false);
20076c92544dSBjoern A. Zeeb }
20086c92544dSBjoern A. Zeeb
mt7615_mcu_set_txpower_sku(struct mt7615_phy * phy,u8 * sku)20096c92544dSBjoern A. Zeeb static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
20106c92544dSBjoern A. Zeeb {
20116c92544dSBjoern A. Zeeb struct mt76_phy *mphy = phy->mt76;
20126c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = mphy->hw;
20136c92544dSBjoern A. Zeeb struct mt76_power_limits limits;
20146c92544dSBjoern A. Zeeb s8 *limits_array = (s8 *)&limits;
20156c92544dSBjoern A. Zeeb int n_chains = hweight8(mphy->antenna_mask);
20166c92544dSBjoern A. Zeeb int tx_power = hw->conf.power_level * 2;
20176c92544dSBjoern A. Zeeb int i;
20186c92544dSBjoern A. Zeeb static const u8 sku_mapping[] = {
20196c92544dSBjoern A. Zeeb #define SKU_FIELD(_type, _field) \
20206c92544dSBjoern A. Zeeb [MT_SKU_##_type] = offsetof(struct mt76_power_limits, _field)
20216c92544dSBjoern A. Zeeb SKU_FIELD(CCK_1_2, cck[0]),
20226c92544dSBjoern A. Zeeb SKU_FIELD(CCK_55_11, cck[2]),
20236c92544dSBjoern A. Zeeb SKU_FIELD(OFDM_6_9, ofdm[0]),
20246c92544dSBjoern A. Zeeb SKU_FIELD(OFDM_12_18, ofdm[2]),
20256c92544dSBjoern A. Zeeb SKU_FIELD(OFDM_24_36, ofdm[4]),
20266c92544dSBjoern A. Zeeb SKU_FIELD(OFDM_48, ofdm[6]),
20276c92544dSBjoern A. Zeeb SKU_FIELD(OFDM_54, ofdm[7]),
20286c92544dSBjoern A. Zeeb SKU_FIELD(HT20_0_8, mcs[0][0]),
20296c92544dSBjoern A. Zeeb SKU_FIELD(HT20_32, ofdm[0]),
20306c92544dSBjoern A. Zeeb SKU_FIELD(HT20_1_2_9_10, mcs[0][1]),
20316c92544dSBjoern A. Zeeb SKU_FIELD(HT20_3_4_11_12, mcs[0][3]),
20326c92544dSBjoern A. Zeeb SKU_FIELD(HT20_5_13, mcs[0][5]),
20336c92544dSBjoern A. Zeeb SKU_FIELD(HT20_6_14, mcs[0][6]),
20346c92544dSBjoern A. Zeeb SKU_FIELD(HT20_7_15, mcs[0][7]),
20356c92544dSBjoern A. Zeeb SKU_FIELD(HT40_0_8, mcs[1][0]),
20366c92544dSBjoern A. Zeeb SKU_FIELD(HT40_32, ofdm[0]),
20376c92544dSBjoern A. Zeeb SKU_FIELD(HT40_1_2_9_10, mcs[1][1]),
20386c92544dSBjoern A. Zeeb SKU_FIELD(HT40_3_4_11_12, mcs[1][3]),
20396c92544dSBjoern A. Zeeb SKU_FIELD(HT40_5_13, mcs[1][5]),
20406c92544dSBjoern A. Zeeb SKU_FIELD(HT40_6_14, mcs[1][6]),
20416c92544dSBjoern A. Zeeb SKU_FIELD(HT40_7_15, mcs[1][7]),
20426c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_0, mcs[0][0]),
20436c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_1_2, mcs[0][1]),
20446c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_3_4, mcs[0][3]),
20456c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_5_6, mcs[0][5]),
20466c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_7, mcs[0][7]),
20476c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_8, mcs[0][8]),
20486c92544dSBjoern A. Zeeb SKU_FIELD(VHT20_9, mcs[0][9]),
20496c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_0, mcs[1][0]),
20506c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_1_2, mcs[1][1]),
20516c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_3_4, mcs[1][3]),
20526c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_5_6, mcs[1][5]),
20536c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_7, mcs[1][7]),
20546c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_8, mcs[1][8]),
20556c92544dSBjoern A. Zeeb SKU_FIELD(VHT40_9, mcs[1][9]),
20566c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_0, mcs[2][0]),
20576c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_1_2, mcs[2][1]),
20586c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_3_4, mcs[2][3]),
20596c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_5_6, mcs[2][5]),
20606c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_7, mcs[2][7]),
20616c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_8, mcs[2][8]),
20626c92544dSBjoern A. Zeeb SKU_FIELD(VHT80_9, mcs[2][9]),
20636c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_0, mcs[3][0]),
20646c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_1_2, mcs[3][1]),
20656c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_3_4, mcs[3][3]),
20666c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_5_6, mcs[3][5]),
20676c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_7, mcs[3][7]),
20686c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_8, mcs[3][8]),
20696c92544dSBjoern A. Zeeb SKU_FIELD(VHT160_9, mcs[3][9]),
20706c92544dSBjoern A. Zeeb #undef SKU_FIELD
20716c92544dSBjoern A. Zeeb };
20726c92544dSBjoern A. Zeeb
20736c92544dSBjoern A. Zeeb tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power);
20746c92544dSBjoern A. Zeeb tx_power -= mt76_tx_power_nss_delta(n_chains);
20756c92544dSBjoern A. Zeeb tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
20766c92544dSBjoern A. Zeeb &limits, tx_power);
20776c92544dSBjoern A. Zeeb mphy->txpower_cur = tx_power;
20786c92544dSBjoern A. Zeeb
20796c92544dSBjoern A. Zeeb if (is_mt7663(mphy->dev)) {
20806c92544dSBjoern A. Zeeb memset(sku, tx_power, MT_SKU_4SS_DELTA + 1);
20816c92544dSBjoern A. Zeeb return;
20826c92544dSBjoern A. Zeeb }
20836c92544dSBjoern A. Zeeb
20846c92544dSBjoern A. Zeeb for (i = 0; i < MT_SKU_1SS_DELTA; i++)
20856c92544dSBjoern A. Zeeb sku[i] = limits_array[sku_mapping[i]];
20866c92544dSBjoern A. Zeeb
20876c92544dSBjoern A. Zeeb for (i = 0; i < 4; i++) {
20886c92544dSBjoern A. Zeeb int delta = 0;
20896c92544dSBjoern A. Zeeb
20906c92544dSBjoern A. Zeeb if (i < n_chains - 1)
20916c92544dSBjoern A. Zeeb delta = mt76_tx_power_nss_delta(n_chains) -
20926c92544dSBjoern A. Zeeb mt76_tx_power_nss_delta(i + 1);
20936c92544dSBjoern A. Zeeb sku[MT_SKU_1SS_DELTA + i] = delta;
20946c92544dSBjoern A. Zeeb }
20956c92544dSBjoern A. Zeeb }
20966c92544dSBjoern A. Zeeb
mt7615_mcu_chan_bw(struct cfg80211_chan_def * chandef)20976c92544dSBjoern A. Zeeb static u8 mt7615_mcu_chan_bw(struct cfg80211_chan_def *chandef)
20986c92544dSBjoern A. Zeeb {
20996c92544dSBjoern A. Zeeb static const u8 width_to_bw[] = {
21006c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ,
21016c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ,
21026c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ,
21036c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ,
21046c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ,
21056c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ,
21066c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ,
21076c92544dSBjoern A. Zeeb [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ,
21086c92544dSBjoern A. Zeeb };
21096c92544dSBjoern A. Zeeb
21106c92544dSBjoern A. Zeeb if (chandef->width >= ARRAY_SIZE(width_to_bw))
21116c92544dSBjoern A. Zeeb return 0;
21126c92544dSBjoern A. Zeeb
21136c92544dSBjoern A. Zeeb return width_to_bw[chandef->width];
21146c92544dSBjoern A. Zeeb }
21156c92544dSBjoern A. Zeeb
mt7615_mcu_set_chan_info(struct mt7615_phy * phy,int cmd)21166c92544dSBjoern A. Zeeb int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
21176c92544dSBjoern A. Zeeb {
21186c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
21196c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
21206c92544dSBjoern A. Zeeb int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
21216c92544dSBjoern A. Zeeb struct {
21226c92544dSBjoern A. Zeeb u8 control_chan;
21236c92544dSBjoern A. Zeeb u8 center_chan;
21246c92544dSBjoern A. Zeeb u8 bw;
21256c92544dSBjoern A. Zeeb u8 tx_streams;
21266c92544dSBjoern A. Zeeb u8 rx_streams_mask;
21276c92544dSBjoern A. Zeeb u8 switch_reason;
21286c92544dSBjoern A. Zeeb u8 band_idx;
21296c92544dSBjoern A. Zeeb /* for 80+80 only */
21306c92544dSBjoern A. Zeeb u8 center_chan2;
21316c92544dSBjoern A. Zeeb __le16 cac_case;
21326c92544dSBjoern A. Zeeb u8 channel_band;
21336c92544dSBjoern A. Zeeb u8 rsv0;
21346c92544dSBjoern A. Zeeb __le32 outband_freq;
21356c92544dSBjoern A. Zeeb u8 txpower_drop;
21366c92544dSBjoern A. Zeeb u8 rsv1[3];
21376c92544dSBjoern A. Zeeb u8 txpower_sku[53];
21386c92544dSBjoern A. Zeeb u8 rsv2[3];
21396c92544dSBjoern A. Zeeb } req = {
21406c92544dSBjoern A. Zeeb .control_chan = chandef->chan->hw_value,
21416c92544dSBjoern A. Zeeb .center_chan = ieee80211_frequency_to_channel(freq1),
21426c92544dSBjoern A. Zeeb .tx_streams = hweight8(phy->mt76->antenna_mask),
21436c92544dSBjoern A. Zeeb .rx_streams_mask = phy->mt76->chainmask,
21446c92544dSBjoern A. Zeeb .center_chan2 = ieee80211_frequency_to_channel(freq2),
21456c92544dSBjoern A. Zeeb };
21466c92544dSBjoern A. Zeeb
21476c92544dSBjoern A. Zeeb if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
2148*8ba4d145SBjoern A. Zeeb phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
21496c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_NORMAL;
2150*8ba4d145SBjoern A. Zeeb else if (phy->mt76->offchannel)
21516c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
21526c92544dSBjoern A. Zeeb else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
21536c92544dSBjoern A. Zeeb NL80211_IFTYPE_AP))
21546c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_DFS;
21556c92544dSBjoern A. Zeeb else
21566c92544dSBjoern A. Zeeb req.switch_reason = CH_SWITCH_NORMAL;
21576c92544dSBjoern A. Zeeb
21586c92544dSBjoern A. Zeeb req.band_idx = phy != &dev->phy;
21596c92544dSBjoern A. Zeeb req.bw = mt7615_mcu_chan_bw(chandef);
21606c92544dSBjoern A. Zeeb
21616c92544dSBjoern A. Zeeb if (mt76_testmode_enabled(phy->mt76))
21626c92544dSBjoern A. Zeeb memset(req.txpower_sku, 0x3f, 49);
21636c92544dSBjoern A. Zeeb else
21646c92544dSBjoern A. Zeeb mt7615_mcu_set_txpower_sku(phy, req.txpower_sku);
21656c92544dSBjoern A. Zeeb
21666c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
21676c92544dSBjoern A. Zeeb }
21686c92544dSBjoern A. Zeeb
mt7615_mcu_get_temperature(struct mt7615_dev * dev)21696c92544dSBjoern A. Zeeb int mt7615_mcu_get_temperature(struct mt7615_dev *dev)
21706c92544dSBjoern A. Zeeb {
21716c92544dSBjoern A. Zeeb struct {
21726c92544dSBjoern A. Zeeb u8 action;
21736c92544dSBjoern A. Zeeb u8 rsv[3];
21746c92544dSBjoern A. Zeeb } req = {};
21756c92544dSBjoern A. Zeeb
21766c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL),
21776c92544dSBjoern A. Zeeb &req, sizeof(req), true);
21786c92544dSBjoern A. Zeeb }
21796c92544dSBjoern A. Zeeb
mt7615_mcu_set_test_param(struct mt7615_dev * dev,u8 param,bool test_mode,u32 val)21806c92544dSBjoern A. Zeeb int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode,
21816c92544dSBjoern A. Zeeb u32 val)
21826c92544dSBjoern A. Zeeb {
21836c92544dSBjoern A. Zeeb struct {
21846c92544dSBjoern A. Zeeb u8 test_mode_en;
21856c92544dSBjoern A. Zeeb u8 param_idx;
21866c92544dSBjoern A. Zeeb u8 _rsv[2];
21876c92544dSBjoern A. Zeeb
21886c92544dSBjoern A. Zeeb __le32 value;
21896c92544dSBjoern A. Zeeb
21906c92544dSBjoern A. Zeeb u8 pad[8];
21916c92544dSBjoern A. Zeeb } req = {
21926c92544dSBjoern A. Zeeb .test_mode_en = test_mode,
21936c92544dSBjoern A. Zeeb .param_idx = param,
21946c92544dSBjoern A. Zeeb .value = cpu_to_le32(val),
21956c92544dSBjoern A. Zeeb };
21966c92544dSBjoern A. Zeeb
21976c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL),
21986c92544dSBjoern A. Zeeb &req, sizeof(req), false);
21996c92544dSBjoern A. Zeeb }
22006c92544dSBjoern A. Zeeb
mt7615_mcu_set_sku_en(struct mt7615_phy * phy,bool enable)22016c92544dSBjoern A. Zeeb int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)
22026c92544dSBjoern A. Zeeb {
22036c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
22046c92544dSBjoern A. Zeeb struct {
22056c92544dSBjoern A. Zeeb u8 format_id;
22066c92544dSBjoern A. Zeeb u8 sku_enable;
22076c92544dSBjoern A. Zeeb u8 band_idx;
22086c92544dSBjoern A. Zeeb u8 rsv;
22096c92544dSBjoern A. Zeeb } req = {
22106c92544dSBjoern A. Zeeb .format_id = 0,
22116c92544dSBjoern A. Zeeb .band_idx = phy != &dev->phy,
22126c92544dSBjoern A. Zeeb .sku_enable = enable,
22136c92544dSBjoern A. Zeeb };
22146c92544dSBjoern A. Zeeb
22156c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76,
22166c92544dSBjoern A. Zeeb MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
22176c92544dSBjoern A. Zeeb &req, sizeof(req), true);
22186c92544dSBjoern A. Zeeb }
22196c92544dSBjoern A. Zeeb
mt7615_find_freq_idx(const u16 * freqs,int n_freqs,u16 cur)22206c92544dSBjoern A. Zeeb static int mt7615_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
22216c92544dSBjoern A. Zeeb {
22226c92544dSBjoern A. Zeeb int i;
22236c92544dSBjoern A. Zeeb
22246c92544dSBjoern A. Zeeb for (i = 0; i < n_freqs; i++)
22256c92544dSBjoern A. Zeeb if (cur == freqs[i])
22266c92544dSBjoern A. Zeeb return i;
22276c92544dSBjoern A. Zeeb
22286c92544dSBjoern A. Zeeb return -1;
22296c92544dSBjoern A. Zeeb }
22306c92544dSBjoern A. Zeeb
mt7615_dcoc_freq_idx(u16 freq,u8 bw)22316c92544dSBjoern A. Zeeb static int mt7615_dcoc_freq_idx(u16 freq, u8 bw)
22326c92544dSBjoern A. Zeeb {
22336c92544dSBjoern A. Zeeb static const u16 freq_list[] = {
22346c92544dSBjoern A. Zeeb 4980, 5805, 5905, 5190,
22356c92544dSBjoern A. Zeeb 5230, 5270, 5310, 5350,
22366c92544dSBjoern A. Zeeb 5390, 5430, 5470, 5510,
22376c92544dSBjoern A. Zeeb 5550, 5590, 5630, 5670,
22386c92544dSBjoern A. Zeeb 5710, 5755, 5795, 5835,
22396c92544dSBjoern A. Zeeb 5875, 5210, 5290, 5370,
22406c92544dSBjoern A. Zeeb 5450, 5530, 5610, 5690,
22416c92544dSBjoern A. Zeeb 5775, 5855
22426c92544dSBjoern A. Zeeb };
22436c92544dSBjoern A. Zeeb static const u16 freq_bw40[] = {
22446c92544dSBjoern A. Zeeb 5190, 5230, 5270, 5310,
22456c92544dSBjoern A. Zeeb 5350, 5390, 5430, 5470,
22466c92544dSBjoern A. Zeeb 5510, 5550, 5590, 5630,
22476c92544dSBjoern A. Zeeb 5670, 5710, 5755, 5795,
22486c92544dSBjoern A. Zeeb 5835, 5875
22496c92544dSBjoern A. Zeeb };
22506c92544dSBjoern A. Zeeb int offset_2g = ARRAY_SIZE(freq_list);
22516c92544dSBjoern A. Zeeb int idx;
22526c92544dSBjoern A. Zeeb
22536c92544dSBjoern A. Zeeb if (freq < 4000) {
22546c92544dSBjoern A. Zeeb if (freq < 2427)
22556c92544dSBjoern A. Zeeb return offset_2g;
22566c92544dSBjoern A. Zeeb if (freq < 2442)
22576c92544dSBjoern A. Zeeb return offset_2g + 1;
22586c92544dSBjoern A. Zeeb if (freq < 2457)
22596c92544dSBjoern A. Zeeb return offset_2g + 2;
22606c92544dSBjoern A. Zeeb
22616c92544dSBjoern A. Zeeb return offset_2g + 3;
22626c92544dSBjoern A. Zeeb }
22636c92544dSBjoern A. Zeeb
22646c92544dSBjoern A. Zeeb switch (bw) {
22656c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_80:
22666c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_80P80:
22676c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_160:
22686c92544dSBjoern A. Zeeb break;
22696c92544dSBjoern A. Zeeb default:
22706c92544dSBjoern A. Zeeb idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),
22716c92544dSBjoern A. Zeeb freq + 10);
22726c92544dSBjoern A. Zeeb if (idx >= 0) {
22736c92544dSBjoern A. Zeeb freq = freq_bw40[idx];
22746c92544dSBjoern A. Zeeb break;
22756c92544dSBjoern A. Zeeb }
22766c92544dSBjoern A. Zeeb
22776c92544dSBjoern A. Zeeb idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),
22786c92544dSBjoern A. Zeeb freq - 10);
22796c92544dSBjoern A. Zeeb if (idx >= 0) {
22806c92544dSBjoern A. Zeeb freq = freq_bw40[idx];
22816c92544dSBjoern A. Zeeb break;
22826c92544dSBjoern A. Zeeb }
22836c92544dSBjoern A. Zeeb fallthrough;
22846c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_40:
22856c92544dSBjoern A. Zeeb idx = mt7615_find_freq_idx(freq_bw40, ARRAY_SIZE(freq_bw40),
22866c92544dSBjoern A. Zeeb freq);
22876c92544dSBjoern A. Zeeb if (idx >= 0)
22886c92544dSBjoern A. Zeeb break;
22896c92544dSBjoern A. Zeeb
22906c92544dSBjoern A. Zeeb return -1;
22916c92544dSBjoern A. Zeeb
22926c92544dSBjoern A. Zeeb }
22936c92544dSBjoern A. Zeeb
22946c92544dSBjoern A. Zeeb return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);
22956c92544dSBjoern A. Zeeb }
22966c92544dSBjoern A. Zeeb
mt7615_mcu_apply_rx_dcoc(struct mt7615_phy * phy)22976c92544dSBjoern A. Zeeb int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy)
22986c92544dSBjoern A. Zeeb {
22996c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
23006c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
23016c92544dSBjoern A. Zeeb int freq2 = chandef->center_freq2;
23026c92544dSBjoern A. Zeeb int ret;
23036c92544dSBjoern A. Zeeb struct {
23046c92544dSBjoern A. Zeeb u8 direction;
23056c92544dSBjoern A. Zeeb u8 runtime_calibration;
23066c92544dSBjoern A. Zeeb u8 _rsv[2];
23076c92544dSBjoern A. Zeeb
23086c92544dSBjoern A. Zeeb __le16 center_freq;
23096c92544dSBjoern A. Zeeb u8 bw;
23106c92544dSBjoern A. Zeeb u8 band;
23116c92544dSBjoern A. Zeeb u8 is_freq2;
23126c92544dSBjoern A. Zeeb u8 success;
23136c92544dSBjoern A. Zeeb u8 dbdc_en;
23146c92544dSBjoern A. Zeeb
23156c92544dSBjoern A. Zeeb u8 _rsv2;
23166c92544dSBjoern A. Zeeb
23176c92544dSBjoern A. Zeeb struct {
23186c92544dSBjoern A. Zeeb __le32 sx0_i_lna[4];
23196c92544dSBjoern A. Zeeb __le32 sx0_q_lna[4];
23206c92544dSBjoern A. Zeeb
23216c92544dSBjoern A. Zeeb __le32 sx2_i_lna[4];
23226c92544dSBjoern A. Zeeb __le32 sx2_q_lna[4];
23236c92544dSBjoern A. Zeeb } dcoc_data[4];
23246c92544dSBjoern A. Zeeb } req = {
23256c92544dSBjoern A. Zeeb .direction = 1,
23266c92544dSBjoern A. Zeeb
23276c92544dSBjoern A. Zeeb .bw = mt7615_mcu_chan_bw(chandef),
23286c92544dSBjoern A. Zeeb .band = chandef->center_freq1 > 4000,
23296c92544dSBjoern A. Zeeb .dbdc_en = !!dev->mt76.phys[MT_BAND1],
23306c92544dSBjoern A. Zeeb };
23316c92544dSBjoern A. Zeeb u16 center_freq = chandef->center_freq1;
23326c92544dSBjoern A. Zeeb int freq_idx;
23336c92544dSBjoern A. Zeeb u8 *eep = dev->mt76.eeprom.data;
23346c92544dSBjoern A. Zeeb
23356c92544dSBjoern A. Zeeb if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_RX_CAL))
23366c92544dSBjoern A. Zeeb return 0;
23376c92544dSBjoern A. Zeeb
23386c92544dSBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_160) {
23396c92544dSBjoern A. Zeeb freq2 = center_freq + 40;
23406c92544dSBjoern A. Zeeb center_freq -= 40;
23416c92544dSBjoern A. Zeeb }
23426c92544dSBjoern A. Zeeb
23436c92544dSBjoern A. Zeeb again:
23446c92544dSBjoern A. Zeeb req.runtime_calibration = 1;
23456c92544dSBjoern A. Zeeb freq_idx = mt7615_dcoc_freq_idx(center_freq, chandef->width);
23466c92544dSBjoern A. Zeeb if (freq_idx < 0)
23476c92544dSBjoern A. Zeeb goto out;
23486c92544dSBjoern A. Zeeb
23496c92544dSBjoern A. Zeeb memcpy(req.dcoc_data, eep + MT7615_EEPROM_DCOC_OFFSET +
23506c92544dSBjoern A. Zeeb freq_idx * MT7615_EEPROM_DCOC_SIZE,
23516c92544dSBjoern A. Zeeb sizeof(req.dcoc_data));
23526c92544dSBjoern A. Zeeb req.runtime_calibration = 0;
23536c92544dSBjoern A. Zeeb
23546c92544dSBjoern A. Zeeb out:
23556c92544dSBjoern A. Zeeb req.center_freq = cpu_to_le16(center_freq);
23566c92544dSBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RXDCOC_CAL), &req,
23576c92544dSBjoern A. Zeeb sizeof(req), true);
23586c92544dSBjoern A. Zeeb
23596c92544dSBjoern A. Zeeb if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||
23606c92544dSBjoern A. Zeeb chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {
23616c92544dSBjoern A. Zeeb req.is_freq2 = true;
23626c92544dSBjoern A. Zeeb center_freq = freq2;
23636c92544dSBjoern A. Zeeb goto again;
23646c92544dSBjoern A. Zeeb }
23656c92544dSBjoern A. Zeeb
23666c92544dSBjoern A. Zeeb return ret;
23676c92544dSBjoern A. Zeeb }
23686c92544dSBjoern A. Zeeb
mt7615_dpd_freq_idx(u16 freq,u8 bw)23696c92544dSBjoern A. Zeeb static int mt7615_dpd_freq_idx(u16 freq, u8 bw)
23706c92544dSBjoern A. Zeeb {
23716c92544dSBjoern A. Zeeb static const u16 freq_list[] = {
23726c92544dSBjoern A. Zeeb 4920, 4940, 4960, 4980,
23736c92544dSBjoern A. Zeeb 5040, 5060, 5080, 5180,
23746c92544dSBjoern A. Zeeb 5200, 5220, 5240, 5260,
23756c92544dSBjoern A. Zeeb 5280, 5300, 5320, 5340,
23766c92544dSBjoern A. Zeeb 5360, 5380, 5400, 5420,
23776c92544dSBjoern A. Zeeb 5440, 5460, 5480, 5500,
23786c92544dSBjoern A. Zeeb 5520, 5540, 5560, 5580,
23796c92544dSBjoern A. Zeeb 5600, 5620, 5640, 5660,
23806c92544dSBjoern A. Zeeb 5680, 5700, 5720, 5745,
23816c92544dSBjoern A. Zeeb 5765, 5785, 5805, 5825,
23826c92544dSBjoern A. Zeeb 5845, 5865, 5885, 5905
23836c92544dSBjoern A. Zeeb };
23846c92544dSBjoern A. Zeeb int offset_2g = ARRAY_SIZE(freq_list);
23856c92544dSBjoern A. Zeeb int idx;
23866c92544dSBjoern A. Zeeb
23876c92544dSBjoern A. Zeeb if (freq < 4000) {
23886c92544dSBjoern A. Zeeb if (freq < 2432)
23896c92544dSBjoern A. Zeeb return offset_2g;
23906c92544dSBjoern A. Zeeb if (freq < 2457)
23916c92544dSBjoern A. Zeeb return offset_2g + 1;
23926c92544dSBjoern A. Zeeb
23936c92544dSBjoern A. Zeeb return offset_2g + 2;
23946c92544dSBjoern A. Zeeb }
23956c92544dSBjoern A. Zeeb
23966c92544dSBjoern A. Zeeb if (bw != NL80211_CHAN_WIDTH_20) {
23976c92544dSBjoern A. Zeeb idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
23986c92544dSBjoern A. Zeeb freq + 10);
23996c92544dSBjoern A. Zeeb if (idx >= 0)
24006c92544dSBjoern A. Zeeb return idx;
24016c92544dSBjoern A. Zeeb
24026c92544dSBjoern A. Zeeb idx = mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
24036c92544dSBjoern A. Zeeb freq - 10);
24046c92544dSBjoern A. Zeeb if (idx >= 0)
24056c92544dSBjoern A. Zeeb return idx;
24066c92544dSBjoern A. Zeeb }
24076c92544dSBjoern A. Zeeb
24086c92544dSBjoern A. Zeeb return mt7615_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);
24096c92544dSBjoern A. Zeeb }
24106c92544dSBjoern A. Zeeb
24116c92544dSBjoern A. Zeeb
mt7615_mcu_apply_tx_dpd(struct mt7615_phy * phy)24126c92544dSBjoern A. Zeeb int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)
24136c92544dSBjoern A. Zeeb {
24146c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
24156c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
24166c92544dSBjoern A. Zeeb int freq2 = chandef->center_freq2;
24176c92544dSBjoern A. Zeeb int ret;
24186c92544dSBjoern A. Zeeb struct {
24196c92544dSBjoern A. Zeeb u8 direction;
24206c92544dSBjoern A. Zeeb u8 runtime_calibration;
24216c92544dSBjoern A. Zeeb u8 _rsv[2];
24226c92544dSBjoern A. Zeeb
24236c92544dSBjoern A. Zeeb __le16 center_freq;
24246c92544dSBjoern A. Zeeb u8 bw;
24256c92544dSBjoern A. Zeeb u8 band;
24266c92544dSBjoern A. Zeeb u8 is_freq2;
24276c92544dSBjoern A. Zeeb u8 success;
24286c92544dSBjoern A. Zeeb u8 dbdc_en;
24296c92544dSBjoern A. Zeeb
24306c92544dSBjoern A. Zeeb u8 _rsv2;
24316c92544dSBjoern A. Zeeb
24326c92544dSBjoern A. Zeeb struct {
24336c92544dSBjoern A. Zeeb struct {
24346c92544dSBjoern A. Zeeb u32 dpd_g0;
24356c92544dSBjoern A. Zeeb u8 data[32];
24366c92544dSBjoern A. Zeeb } wf0, wf1;
24376c92544dSBjoern A. Zeeb
24386c92544dSBjoern A. Zeeb struct {
24396c92544dSBjoern A. Zeeb u32 dpd_g0_prim;
24406c92544dSBjoern A. Zeeb u32 dpd_g0_sec;
24416c92544dSBjoern A. Zeeb u8 data_prim[32];
24426c92544dSBjoern A. Zeeb u8 data_sec[32];
24436c92544dSBjoern A. Zeeb } wf2, wf3;
24446c92544dSBjoern A. Zeeb } dpd_data;
24456c92544dSBjoern A. Zeeb } req = {
24466c92544dSBjoern A. Zeeb .direction = 1,
24476c92544dSBjoern A. Zeeb
24486c92544dSBjoern A. Zeeb .bw = mt7615_mcu_chan_bw(chandef),
24496c92544dSBjoern A. Zeeb .band = chandef->center_freq1 > 4000,
24506c92544dSBjoern A. Zeeb .dbdc_en = !!dev->mt76.phys[MT_BAND1],
24516c92544dSBjoern A. Zeeb };
24526c92544dSBjoern A. Zeeb u16 center_freq = chandef->center_freq1;
24536c92544dSBjoern A. Zeeb int freq_idx;
24546c92544dSBjoern A. Zeeb u8 *eep = dev->mt76.eeprom.data;
24556c92544dSBjoern A. Zeeb
24566c92544dSBjoern A. Zeeb if (!(eep[MT_EE_CALDATA_FLASH] & MT_EE_CALDATA_FLASH_TX_DPD))
24576c92544dSBjoern A. Zeeb return 0;
24586c92544dSBjoern A. Zeeb
24596c92544dSBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_160) {
24606c92544dSBjoern A. Zeeb freq2 = center_freq + 40;
24616c92544dSBjoern A. Zeeb center_freq -= 40;
24626c92544dSBjoern A. Zeeb }
24636c92544dSBjoern A. Zeeb
24646c92544dSBjoern A. Zeeb again:
24656c92544dSBjoern A. Zeeb req.runtime_calibration = 1;
24666c92544dSBjoern A. Zeeb freq_idx = mt7615_dpd_freq_idx(center_freq, chandef->width);
24676c92544dSBjoern A. Zeeb if (freq_idx < 0)
24686c92544dSBjoern A. Zeeb goto out;
24696c92544dSBjoern A. Zeeb
24706c92544dSBjoern A. Zeeb memcpy(&req.dpd_data, eep + MT7615_EEPROM_TXDPD_OFFSET +
24716c92544dSBjoern A. Zeeb freq_idx * MT7615_EEPROM_TXDPD_SIZE,
24726c92544dSBjoern A. Zeeb sizeof(req.dpd_data));
24736c92544dSBjoern A. Zeeb req.runtime_calibration = 0;
24746c92544dSBjoern A. Zeeb
24756c92544dSBjoern A. Zeeb out:
24766c92544dSBjoern A. Zeeb req.center_freq = cpu_to_le16(center_freq);
24776c92544dSBjoern A. Zeeb ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXDPD_CAL),
24786c92544dSBjoern A. Zeeb &req, sizeof(req), true);
24796c92544dSBjoern A. Zeeb
24806c92544dSBjoern A. Zeeb if ((chandef->width == NL80211_CHAN_WIDTH_80P80 ||
24816c92544dSBjoern A. Zeeb chandef->width == NL80211_CHAN_WIDTH_160) && !req.is_freq2) {
24826c92544dSBjoern A. Zeeb req.is_freq2 = true;
24836c92544dSBjoern A. Zeeb center_freq = freq2;
24846c92544dSBjoern A. Zeeb goto again;
24856c92544dSBjoern A. Zeeb }
24866c92544dSBjoern A. Zeeb
24876c92544dSBjoern A. Zeeb return ret;
24886c92544dSBjoern A. Zeeb }
24896c92544dSBjoern A. Zeeb
mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev * dev)24906c92544dSBjoern A. Zeeb int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)
24916c92544dSBjoern A. Zeeb {
24926c92544dSBjoern A. Zeeb struct {
24936c92544dSBjoern A. Zeeb u8 operation;
24946c92544dSBjoern A. Zeeb u8 count;
24956c92544dSBjoern A. Zeeb u8 _rsv[2];
24966c92544dSBjoern A. Zeeb u8 index;
24976c92544dSBjoern A. Zeeb u8 enable;
24986c92544dSBjoern A. Zeeb __le16 etype;
24996c92544dSBjoern A. Zeeb } req = {
25006c92544dSBjoern A. Zeeb .operation = 1,
25016c92544dSBjoern A. Zeeb .count = 1,
25026c92544dSBjoern A. Zeeb .enable = 1,
25036c92544dSBjoern A. Zeeb .etype = cpu_to_le16(ETH_P_PAE),
25046c92544dSBjoern A. Zeeb };
25056c92544dSBjoern A. Zeeb
25066c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RX_HDR_TRANS),
25076c92544dSBjoern A. Zeeb &req, sizeof(req), false);
25086c92544dSBjoern A. Zeeb }
25096c92544dSBjoern A. Zeeb
mt7615_mcu_set_bss_pm(struct mt7615_dev * dev,struct ieee80211_vif * vif,bool enable)25106c92544dSBjoern A. Zeeb int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
25116c92544dSBjoern A. Zeeb bool enable)
25126c92544dSBjoern A. Zeeb {
25136c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
25146c92544dSBjoern A. Zeeb struct {
25156c92544dSBjoern A. Zeeb u8 bss_idx;
25166c92544dSBjoern A. Zeeb u8 dtim_period;
25176c92544dSBjoern A. Zeeb __le16 aid;
25186c92544dSBjoern A. Zeeb __le16 bcn_interval;
25196c92544dSBjoern A. Zeeb __le16 atim_window;
25206c92544dSBjoern A. Zeeb u8 uapsd;
25216c92544dSBjoern A. Zeeb u8 bmc_delivered_ac;
25226c92544dSBjoern A. Zeeb u8 bmc_triggered_ac;
25236c92544dSBjoern A. Zeeb u8 pad;
25246c92544dSBjoern A. Zeeb } req = {
25256c92544dSBjoern A. Zeeb .bss_idx = mvif->mt76.idx,
25266c92544dSBjoern A. Zeeb .aid = cpu_to_le16(vif->cfg.aid),
25276c92544dSBjoern A. Zeeb .dtim_period = vif->bss_conf.dtim_period,
25286c92544dSBjoern A. Zeeb .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),
25296c92544dSBjoern A. Zeeb };
25306c92544dSBjoern A. Zeeb struct {
25316c92544dSBjoern A. Zeeb u8 bss_idx;
25326c92544dSBjoern A. Zeeb u8 pad[3];
25336c92544dSBjoern A. Zeeb } req_hdr = {
25346c92544dSBjoern A. Zeeb .bss_idx = mvif->mt76.idx,
25356c92544dSBjoern A. Zeeb };
25366c92544dSBjoern A. Zeeb int err;
25376c92544dSBjoern A. Zeeb
25386c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION)
25396c92544dSBjoern A. Zeeb return 0;
25406c92544dSBjoern A. Zeeb
25416c92544dSBjoern A. Zeeb err = mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_ABORT),
25426c92544dSBjoern A. Zeeb &req_hdr, sizeof(req_hdr), false);
25436c92544dSBjoern A. Zeeb if (err < 0 || !enable)
25446c92544dSBjoern A. Zeeb return err;
25456c92544dSBjoern A. Zeeb
25466c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_BSS_CONNECTED),
25476c92544dSBjoern A. Zeeb &req, sizeof(req), false);
25486c92544dSBjoern A. Zeeb }
25496c92544dSBjoern A. Zeeb
mt7615_mcu_set_roc(struct mt7615_phy * phy,struct ieee80211_vif * vif,struct ieee80211_channel * chan,int duration)25506c92544dSBjoern A. Zeeb int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
25516c92544dSBjoern A. Zeeb struct ieee80211_channel *chan, int duration)
25526c92544dSBjoern A. Zeeb {
25536c92544dSBjoern A. Zeeb struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
25546c92544dSBjoern A. Zeeb struct mt7615_dev *dev = phy->dev;
25556c92544dSBjoern A. Zeeb struct mt7615_roc_tlv req = {
25566c92544dSBjoern A. Zeeb .bss_idx = mvif->mt76.idx,
25576c92544dSBjoern A. Zeeb .active = !chan,
25586c92544dSBjoern A. Zeeb .max_interval = cpu_to_le32(duration),
25596c92544dSBjoern A. Zeeb .primary_chan = chan ? chan->hw_value : 0,
25606c92544dSBjoern A. Zeeb .band = chan ? chan->band : 0,
25616c92544dSBjoern A. Zeeb .req_type = 2,
25626c92544dSBjoern A. Zeeb };
25636c92544dSBjoern A. Zeeb
25646c92544dSBjoern A. Zeeb phy->roc_grant = false;
25656c92544dSBjoern A. Zeeb
25666c92544dSBjoern A. Zeeb return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_ROC),
25676c92544dSBjoern A. Zeeb &req, sizeof(req), false);
25686c92544dSBjoern A. Zeeb }
2569