aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7615/mcu.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.c483
1 files changed, 232 insertions, 251 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index cdad2c8dc297..842cd81704db 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -75,7 +75,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb,
txd = mcu_txd->txd;
- val = FIELD_PREP(MT_TXD0_TX_BYTES, cpu_to_le16(skb->len)) |
+ val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |
FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) |
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
txd[0] = cpu_to_le32(val);
@@ -113,12 +113,38 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb,
}
static int
+mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd,
+ struct sk_buff *skb, int seq)
+{
+ struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+ int ret = 0;
+
+ if (seq != rxd->seq)
+ return -EAGAIN;
+
+ switch (cmd) {
+ case -MCU_CMD_PATCH_SEM_CONTROL:
+ skb_pull(skb, sizeof(*rxd) - 4);
+ ret = *skb->data;
+ break;
+ case MCU_EXT_CMD_GET_TEMP:
+ skb_pull(skb, sizeof(*rxd));
+ ret = le32_to_cpu(*(__le32 *)skb->data);
+ break;
+ default:
+ break;
+ }
+ dev_kfree_skb(skb);
+
+ return ret;
+}
+
+static int
mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int len, bool wait_resp)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
unsigned long expires = jiffies + 10 * HZ;
- struct mt7615_mcu_rxd *rxd;
struct sk_buff *skb;
int ret, seq;
@@ -141,16 +167,9 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
break;
}
- rxd = (struct mt7615_mcu_rxd *)skb->data;
- if (seq != rxd->seq)
- continue;
-
- if (cmd == -MCU_CMD_PATCH_SEM_CONTROL) {
- skb_pull(skb, sizeof(*rxd) - 4);
- ret = *skb->data;
- }
- dev_kfree_skb(skb);
- break;
+ ret = mt7615_mcu_parse_response(dev, cmd, skb, seq);
+ if (ret != -EAGAIN)
+ break;
}
out:
@@ -159,6 +178,62 @@ out:
return ret;
}
+static void
+mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ if (vif->csa_active)
+ ieee80211_csa_finish(vif);
+}
+
+static void
+mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+ struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+ switch (rxd->ext_eid) {
+ case MCU_EXT_EVENT_RDD_REPORT:
+ ieee80211_radar_detected(dev->mt76.hw);
+ dev->hw_pattern++;
+ break;
+ case MCU_EXT_EVENT_CSA_NOTIFY:
+ ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7615_mcu_csa_finish, dev);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+ struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+ switch (rxd->eid) {
+ case MCU_EVENT_EXT:
+ mt7615_mcu_rx_ext_event(dev, skb);
+ break;
+ default:
+ break;
+ }
+ dev_kfree_skb(skb);
+}
+
+void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+ struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
+
+ if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
+ rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
+ rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
+ rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
+ !rxd->seq)
+ mt7615_mcu_rx_unsolicited_event(dev, skb);
+ else
+ mt76_mcu_rx_event(&dev->mt76, skb);
+}
+
static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr,
u32 len, u32 mode)
{
@@ -192,6 +267,7 @@ static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data,
data += cur_len;
len -= cur_len;
+ mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false);
}
return ret;
@@ -257,9 +333,8 @@ static int mt7615_driver_own(struct mt7615_dev *dev)
static int mt7615_load_patch(struct mt7615_dev *dev)
{
- const struct firmware *fw;
const struct mt7615_patch_hdr *hdr;
- const char *firmware = MT7615_ROM_PATCH;
+ const struct firmware *fw = NULL;
int len, ret, sem;
sem = mt7615_mcu_patch_sem_ctrl(dev, 1);
@@ -273,9 +348,9 @@ static int mt7615_load_patch(struct mt7615_dev *dev)
return -EAGAIN;
}
- ret = request_firmware(&fw, firmware, dev->mt76.dev);
+ ret = request_firmware(&fw, MT7615_ROM_PATCH, dev->mt76.dev);
if (ret)
- return ret;
+ goto out;
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
dev_err(dev->mt76.dev, "Invalid firmware\n");
@@ -323,7 +398,7 @@ out:
return ret;
}
-static u32 gen_dl_mode(u8 feature_set, bool is_cr4)
+static u32 mt7615_mcu_gen_dl_mode(u8 feature_set, bool is_cr4)
{
u32 ret = 0;
@@ -337,16 +412,45 @@ static u32 gen_dl_mode(u8 feature_set, bool is_cr4)
return ret;
}
+static int
+mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,
+ const struct mt7615_fw_trailer *hdr,
+ const u8 *data, bool is_cr4)
+{
+ int n_region = is_cr4 ? CR4_REGION_NUM : N9_REGION_NUM;
+ int err, i, offset = 0;
+ u32 len, addr, mode;
+
+ for (i = 0; i < n_region; i++) {
+ mode = mt7615_mcu_gen_dl_mode(hdr[i].feature_set, is_cr4);
+ len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;
+ addr = le32_to_cpu(hdr[i].addr);
+
+ err = mt7615_mcu_init_download(dev, addr, len, mode);
+ if (err) {
+ dev_err(dev->mt76.dev, "Download request failed\n");
+ return err;
+ }
+
+ err = mt7615_mcu_send_firmware(dev, data + offset, len);
+ if (err) {
+ dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
+ return err;
+ }
+
+ offset += len;
+ }
+
+ return 0;
+}
+
static int mt7615_load_ram(struct mt7615_dev *dev)
{
- const struct firmware *fw;
const struct mt7615_fw_trailer *hdr;
- const char *n9_firmware = MT7615_FIRMWARE_N9;
- const char *cr4_firmware = MT7615_FIRMWARE_CR4;
- u32 n9_ilm_addr, offset;
- int i, ret;
+ const struct firmware *fw;
+ int ret;
- ret = request_firmware(&fw, n9_firmware, dev->mt76.dev);
+ ret = request_firmware(&fw, MT7615_FIRMWARE_N9, dev->mt76.dev);
if (ret)
return ret;
@@ -362,31 +466,12 @@ static int mt7615_load_ram(struct mt7615_dev *dev)
dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
- n9_ilm_addr = le32_to_cpu(hdr->addr);
-
- for (offset = 0, i = 0; i < N9_REGION_NUM; i++) {
- u32 len, addr, mode;
-
- len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;
- addr = le32_to_cpu(hdr[i].addr);
- mode = gen_dl_mode(hdr[i].feature_set, false);
-
- ret = mt7615_mcu_init_download(dev, addr, len, mode);
- if (ret) {
- dev_err(dev->mt76.dev, "Download request failed\n");
- goto out;
- }
-
- ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len);
- if (ret) {
- dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
- goto out;
- }
-
- offset += len;
- }
+ ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, false);
+ if (ret)
+ goto out;
- ret = mt7615_mcu_start_firmware(dev, n9_ilm_addr, FW_START_OVERRIDE);
+ ret = mt7615_mcu_start_firmware(dev, le32_to_cpu(hdr->addr),
+ FW_START_OVERRIDE);
if (ret) {
dev_err(dev->mt76.dev, "Failed to start N9 firmware\n");
goto out;
@@ -394,7 +479,7 @@ static int mt7615_load_ram(struct mt7615_dev *dev)
release_firmware(fw);
- ret = request_firmware(&fw, cr4_firmware, dev->mt76.dev);
+ ret = request_firmware(&fw, MT7615_FIRMWARE_CR4, dev->mt76.dev);
if (ret)
return ret;
@@ -410,27 +495,9 @@ static int mt7615_load_ram(struct mt7615_dev *dev)
dev_info(dev->mt76.dev, "CR4 Firmware Version: %.10s, Build Time: %.15s\n",
hdr->fw_ver, hdr->build_date);
- for (offset = 0, i = 0; i < CR4_REGION_NUM; i++) {
- u32 len, addr, mode;
-
- len = le32_to_cpu(hdr[i].len) + IMG_CRC_LEN;
- addr = le32_to_cpu(hdr[i].addr);
- mode = gen_dl_mode(hdr[i].feature_set, true);
-
- ret = mt7615_mcu_init_download(dev, addr, len, mode);
- if (ret) {
- dev_err(dev->mt76.dev, "Download request failed\n");
- goto out;
- }
-
- ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len);
- if (ret) {
- dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
- goto out;
- }
-
- offset += len;
- }
+ ret = mt7615_mcu_send_ram_firmware(dev, hdr, fw->data, true);
+ if (ret)
+ goto out;
ret = mt7615_mcu_start_firmware(dev, 0, FW_START_WORKING_PDA_CR4);
if (ret)
@@ -469,6 +536,8 @@ static int mt7615_load_firmware(struct mt7615_dev *dev)
return -EIO;
}
+ mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false);
+
dev_dbg(dev->mt76.dev, "Firmware init done\n");
return 0;
@@ -573,6 +642,8 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
#define WMM_CW_MIN_SET BIT(1)
#define WMM_CW_MAX_SET BIT(2)
#define WMM_TXOP_SET BIT(3)
+#define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \
+ WMM_CW_MAX_SET | WMM_TXOP_SET)
struct req_data {
u8 number;
u8 rsv[3];
@@ -585,19 +656,17 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
} __packed req = {
.number = 1,
.queue = queue,
- .valid = WMM_AIFS_SET | WMM_TXOP_SET,
+ .valid = WMM_PARAM_SET,
.aifs = params->aifs,
+ .cw_min = 5,
+ .cw_max = cpu_to_le16(10),
.txop = cpu_to_le16(params->txop),
};
- if (params->cw_min) {
- req.valid |= WMM_CW_MIN_SET;
- req.cw_min = params->cw_min;
- }
- if (params->cw_max) {
- req.valid |= WMM_CW_MAX_SET;
- req.cw_max = cpu_to_le16(params->cw_max);
- }
+ if (params->cw_min)
+ req.cw_min = fls(params->cw_min);
+ if (params->cw_max)
+ req.cw_max = cpu_to_le16(fls(params->cw_max));
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE,
&req, sizeof(req), true);
@@ -824,78 +893,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
return ret;
}
-static enum mt7615_cipher_type
-mt7615_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
-{
- if (!key || key->keylen > 32)
- return MT_CIPHER_NONE;
-
- memcpy(key_data, key->key, key->keylen);
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- return MT_CIPHER_WEP40;
- case WLAN_CIPHER_SUITE_WEP104:
- return MT_CIPHER_WEP104;
- case WLAN_CIPHER_SUITE_TKIP:
- /* Rx/Tx MIC keys are swapped */
- memcpy(key_data + 16, key->key + 24, 8);
- memcpy(key_data + 24, key->key + 16, 8);
- return MT_CIPHER_TKIP;
- case WLAN_CIPHER_SUITE_CCMP:
- return MT_CIPHER_AES_CCMP;
- case WLAN_CIPHER_SUITE_CCMP_256:
- return MT_CIPHER_CCMP_256;
- case WLAN_CIPHER_SUITE_GCMP:
- return MT_CIPHER_GCMP;
- case WLAN_CIPHER_SUITE_GCMP_256:
- return MT_CIPHER_GCMP_256;
- case WLAN_CIPHER_SUITE_SMS4:
- return MT_CIPHER_WAPI;
- default:
- return MT_CIPHER_NONE;
- }
-}
-
-int mt7615_mcu_set_wtbl_key(struct mt7615_dev *dev, int wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd)
-{
- struct {
- struct wtbl_req_hdr hdr;
- struct wtbl_sec_key key;
- } req = {
- .hdr = {
- .wlan_idx = wcid,
- .operation = WTBL_SET,
- .tlv_num = cpu_to_le16(1),
- },
- .key = {
- .tag = cpu_to_le16(WTBL_SEC_KEY),
- .len = cpu_to_le16(sizeof(struct wtbl_sec_key)),
- .add = cmd,
- },
- };
-
- if (cmd == SET_KEY) {
- u8 cipher;
-
- cipher = mt7615_get_key_info(key, req.key.key_material);
- if (cipher == MT_CIPHER_NONE)
- return -EOPNOTSUPP;
-
- req.key.rkv = 1;
- req.key.cipher_id = cipher;
- req.key.key_id = key->keyidx;
- req.key.key_len = key->keylen;
- } else {
- req.key.key_len = sizeof(req.key.key_material);
- }
-
- return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE,
- &req, sizeof(req), true);
-}
-
static int
mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev,
struct mt7615_vif *mvif)
@@ -1099,6 +1096,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+ struct ieee80211_mutable_offsets offs;
struct req {
u8 omac_idx;
u8 enable;
@@ -1119,13 +1117,10 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
.enable = en,
.wlan_idx = wcid->idx,
.band_idx = mvif->band_idx,
- /* pky_type: 0 for bcn, 1 for tim */
- .pkt_type = 0,
};
struct sk_buff *skb;
- u16 tim_off;
- skb = ieee80211_beacon_get_tim(mt76_hw(dev), vif, &tim_off, NULL);
+ skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
if (!skb)
return -EINVAL;
@@ -1139,8 +1134,14 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif,
0, NULL);
memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
- req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + tim_off);
+ req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
+ if (offs.csa_counter_offs[0]) {
+ u16 csa_offs;
+ csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4;
+ req.csa_ie_pos = cpu_to_le16(csa_offs);
+ req.csa_cnt = skb->data[offs.csa_counter_offs[0]];
+ }
dev_kfree_skb(skb);
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD,
@@ -1213,9 +1214,62 @@ out:
return ret;
}
+int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev,
+ enum mt7615_rdd_cmd cmd, u8 index,
+ u8 rx_sel, u8 val)
+{
+ struct {
+ u8 ctrl;
+ u8 rdd_idx;
+ u8 rdd_rx_sel;
+ u8 val;
+ u8 rsv[4];
+ } req = {
+ .ctrl = cmd,
+ .rdd_idx = index,
+ .rdd_rx_sel = rx_sel,
+ .val = val,
+ };
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL,
+ &req, sizeof(req), true);
+}
+
+int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev)
+{
+ struct {
+ u8 pulse_num;
+ u8 rsv[3];
+ struct {
+ u32 start_time;
+ u16 width;
+ s16 power;
+ } pattern[32];
+ } req = {
+ .pulse_num = dev->radar_pattern.n_pulses,
+ };
+ u32 start_time = ktime_to_ms(ktime_get_boottime());
+ int i;
+
+ if (dev->radar_pattern.n_pulses > ARRAY_SIZE(req.pattern))
+ return -EINVAL;
+
+ /* TODO: add some noise here */
+ for (i = 0; i < dev->radar_pattern.n_pulses; i++) {
+ req.pattern[i].width = dev->radar_pattern.width;
+ req.pattern[i].power = dev->radar_pattern.power;
+ req.pattern[i].start_time = start_time +
+ i * dev->radar_pattern.period;
+ }
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_PATTERN,
+ &req, sizeof(req), false);
+}
+
int mt7615_mcu_set_channel(struct mt7615_dev *dev)
{
- struct cfg80211_chan_def *chdef = &dev->mt76.chandef;
+ struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
+ int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
struct {
u8 control_chan;
u8 center_chan;
@@ -1234,17 +1288,20 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev)
u8 rsv1[3];
u8 txpower_sku[53];
u8 rsv2[3];
- } req = {0};
+ } req = {
+ .control_chan = chandef->chan->hw_value,
+ .center_chan = ieee80211_frequency_to_channel(freq1),
+ .tx_streams = (dev->mt76.chainmask >> 8) & 0xf,
+ .rx_streams_mask = dev->mt76.antenna_mask,
+ .center_chan2 = ieee80211_frequency_to_channel(freq2),
+ };
int ret;
- req.control_chan = chdef->chan->hw_value;
- req.center_chan = ieee80211_frequency_to_channel(chdef->center_freq1);
- req.tx_streams = (dev->mt76.chainmask >> 8) & 0xf;
- req.rx_streams_mask = dev->mt76.antenna_mask;
- req.switch_reason = CH_SWITCH_NORMAL;
- req.band_idx = 0;
- req.center_chan2 = ieee80211_frequency_to_channel(chdef->center_freq2);
- req.txpower_drop = 0;
+ if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
+ chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
+ req.switch_reason = CH_SWITCH_DFS;
+ else
+ req.switch_reason = CH_SWITCH_NORMAL;
switch (dev->mt76.chandef.width) {
case NL80211_CHAN_WIDTH_40:
@@ -1269,6 +1326,7 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev)
case NL80211_CHAN_WIDTH_20:
default:
req.bw = CMD_CBW_20MHZ;
+ break;
}
memset(req.txpower_sku, 0x3f, 49);
@@ -1533,92 +1591,15 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev,
&wtbl_req, sizeof(wtbl_req), true);
}
-void mt7615_mcu_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta,
- struct ieee80211_tx_rate *probe_rate,
- struct ieee80211_tx_rate *rates)
+int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index)
{
- int wcid = sta->wcid.idx;
- u32 addr = MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE;
- bool stbc = false;
- int n_rates = sta->n_rates;
- u8 bw, bw_prev, bw_idx = 0;
- u16 val[4];
- u16 probe_val;
- u32 w5, w27;
- int i;
-
- if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))
- return;
-
- for (i = n_rates; i < 4; i++)
- rates[i] = rates[n_rates - 1];
-
- val[0] = mt7615_mac_tx_rate_val(dev, &rates[0], stbc, &bw);
- bw_prev = bw;
-
- if (probe_rate) {
- probe_val = mt7615_mac_tx_rate_val(dev, probe_rate, stbc, &bw);
- if (bw)
- bw_idx = 1;
- else
- bw_prev = 0;
- } else {
- probe_val = val[0];
- }
-
- val[1] = mt7615_mac_tx_rate_val(dev, &rates[1], stbc, &bw);
- if (bw_prev) {
- bw_idx = 3;
- bw_prev = bw;
- }
-
- val[2] = mt7615_mac_tx_rate_val(dev, &rates[2], stbc, &bw);
- if (bw_prev) {
- bw_idx = 5;
- bw_prev = bw;
- }
-
- val[3] = mt7615_mac_tx_rate_val(dev, &rates[3], stbc, &bw);
- if (bw_prev)
- bw_idx = 7;
-
- w27 = mt76_rr(dev, addr + 27 * 4);
- w27 &= ~MT_WTBL_W27_CC_BW_SEL;
- w27 |= FIELD_PREP(MT_WTBL_W27_CC_BW_SEL, bw);
-
- w5 = mt76_rr(dev, addr + 5 * 4);
- w5 &= ~(MT_WTBL_W5_BW_CAP | MT_WTBL_W5_CHANGE_BW_RATE);
- w5 |= FIELD_PREP(MT_WTBL_W5_BW_CAP, bw) |
- FIELD_PREP(MT_WTBL_W5_CHANGE_BW_RATE, bw_idx ? bw_idx - 1 : 7);
-
- mt76_wr(dev, MT_WTBL_RIUCR0, w5);
-
- mt76_wr(dev, MT_WTBL_RIUCR1,
- FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) |
- FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) |
- FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0]));
-
- mt76_wr(dev, MT_WTBL_RIUCR2,
- FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) |
- FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) |
- FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) |
- FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2]));
-
- mt76_wr(dev, MT_WTBL_RIUCR3,
- FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) |
- FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) |
- FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3]));
-
- mt76_wr(dev, MT_WTBL_UPDATE,
- FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) |
- MT_WTBL_UPDATE_RATE_UPDATE |
- MT_WTBL_UPDATE_TX_COUNT_CLEAR);
-
- mt76_wr(dev, addr + 27 * 4, w27);
-
- if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET))
- mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
+ struct {
+ u8 action;
+ u8 rsv[3];
+ } req = {
+ .action = index,
+ };
- sta->rate_count = 2 * MT7615_RATE_RETRY * n_rates;
- sta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req,
+ sizeof(req), true);
}