aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7996/mcu.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c359
1 files changed, 327 insertions, 32 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 4a30db49ef33..bf917beb9439 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -324,8 +324,10 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
static void
mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
- if (vif->bss_conf.csa_active)
- ieee80211_csa_finish(vif);
+ if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
+ return;
+
+ ieee80211_csa_finish(vif);
}
static void
@@ -399,7 +401,7 @@ out:
static void
mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
- if (!vif->bss_conf.color_change_active)
+ if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;
ieee80211_color_change_finish(vif);
@@ -448,6 +450,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
}
static void
+mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+{
+ struct mt7996_mcu_all_sta_info_event *res;
+ u16 i;
+
+ skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
+
+ res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
+
+ for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
+ u8 ac;
+ u16 wlan_idx;
+ struct mt76_wcid *wcid;
+
+ switch (le16_to_cpu(res->tag)) {
+ case UNI_ALL_STA_TXRX_ADM_STAT:
+ wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+
+ if (!wcid)
+ break;
+
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ wcid->stats.tx_bytes +=
+ le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
+ wcid->stats.rx_bytes +=
+ le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
+ }
+ break;
+ case UNI_ALL_STA_TXRX_MSDU_COUNT:
+ wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+
+ if (!wcid)
+ break;
+
+ wcid->stats.tx_packets +=
+ le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
+ wcid->stats.rx_packets +=
+ le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
struct mt7996_mcu_rxd *rxd = (struct mt7996_mcu_rxd *)skb->data;
@@ -491,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_RDD_REPORT:
mt7996_mcu_rx_radar_detected(dev, skb);
break;
+ case MCU_UNI_EVENT_ALL_STA_INFO:
+ mt7996_mcu_rx_all_sta_info_event(dev, skb);
+ break;
default:
break;
}
@@ -601,6 +654,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
}
static void
+mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ struct mt7996_phy *phy, int enable)
+{
+ struct bss_info_uni_mbssid *mbssid;
+ struct tlv *tlv;
+
+ tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid));
+
+ mbssid = (struct bss_info_uni_mbssid *)tlv;
+
+ if (enable && vif->bss_conf.bssid_indicator) {
+ mbssid->max_indicator = vif->bss_conf.bssid_indicator;
+ mbssid->mbss_idx = vif->bss_conf.bssid_index;
+ mbssid->tx_bss_omac_idx = 0;
+ }
+}
+
+static void
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct mt7996_phy *phy)
{
@@ -866,6 +937,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
/* this tag is necessary no matter if the vif is MLD */
mt7996_mcu_bss_mld_tlv(skb, vif);
}
+
+ mt7996_mcu_bss_mbssid_tlv(skb, vif, phy, enable);
+
out:
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
@@ -1152,6 +1226,8 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
muru->ofdma_ul.uo_ra =
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
+ muru->ofdma_ul.rx_ctrl_frame_to_mbss =
+ HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
}
static inline bool
@@ -1624,6 +1700,132 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
MCU_WM_UNI_CMD(RA), true);
}
+static int
+mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, void *data, u32 field)
+{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+ struct sta_phy *phy = data;
+ struct sta_rec_ra_fixed *ra;
+ struct sk_buff *skb;
+ struct tlv *tlv;
+
+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
+ &msta->wcid,
+ MT7996_STA_UPDATE_MAX_SIZE);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
+ ra = (struct sta_rec_ra_fixed *)tlv;
+
+ switch (field) {
+ case RATE_PARAM_AUTO:
+ break;
+ case RATE_PARAM_FIXED:
+ case RATE_PARAM_FIXED_MCS:
+ case RATE_PARAM_FIXED_GI:
+ case RATE_PARAM_FIXED_HE_LTF:
+ if (phy)
+ ra->phy = *phy;
+ break;
+ default:
+ break;
+ }
+ ra->field = cpu_to_le32(field);
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+}
+
+static int
+mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
+ struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
+ enum nl80211_band band = chandef->chan->band;
+ struct sta_phy phy = {};
+ int ret, nrates = 0;
+
+#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
+ do { \
+ u8 i, gi = mask->control[band]._gi; \
+ gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
+ phy.sgi = gi; \
+ phy.he_ltf = mask->control[band].he_ltf; \
+ for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
+ if (!mask->control[band]._mcs[i]) \
+ continue; \
+ nrates += hweight16(mask->control[band]._mcs[i]); \
+ phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
+ if (_ht) \
+ phy.mcs += 8 * i; \
+ } \
+ } while (0)
+
+ if (sta->deflink.he_cap.has_he) {
+ __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
+ } else if (sta->deflink.vht_cap.vht_supported) {
+ __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
+ } else if (sta->deflink.ht_cap.ht_supported) {
+ __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
+ } else {
+ nrates = hweight32(mask->control[band].legacy);
+ phy.mcs = ffs(mask->control[band].legacy) - 1;
+ }
+#undef __sta_phy_bitrate_mask_check
+
+ /* fall back to auto rate control */
+ if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
+ mask->control[band].he_gi == GENMASK(7, 0) &&
+ mask->control[band].he_ltf == GENMASK(7, 0) &&
+ nrates != 1)
+ return 0;
+
+ /* fixed single rate */
+ if (nrates == 1) {
+ ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+ RATE_PARAM_FIXED_MCS);
+ if (ret)
+ return ret;
+ }
+
+ /* fixed GI */
+ if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
+ mask->control[band].he_gi != GENMASK(7, 0)) {
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+ u32 addr;
+
+ /* firmware updates only TXCMD but doesn't take WTBL into
+ * account, so driver should update here to reflect the
+ * actual txrate hardware sends out.
+ */
+ addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
+ if (sta->deflink.he_cap.has_he)
+ mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
+ else
+ mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
+
+ ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+ RATE_PARAM_FIXED_GI);
+ if (ret)
+ return ret;
+ }
+
+ /* fixed HE_LTF */
+ if (mask->control[band].he_ltf != GENMASK(7, 0)) {
+ ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
+ RATE_PARAM_FIXED_HE_LTF);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static void
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
@@ -1733,6 +1935,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct sk_buff *skb;
+ int ret;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
&msta->wcid,
@@ -1752,8 +1955,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
*/
mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
- return mt76_mcu_skb_send_msg(&dev->mt76, skb,
- MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+ if (ret)
+ return ret;
+
+ return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
}
static int
@@ -1996,6 +2203,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
}
static void
+mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
+ struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn,
+ struct ieee80211_mutable_offsets *offs)
+{
+ struct bss_bcn_mbss_tlv *mbss;
+ const struct element *elem;
+ struct tlv *tlv;
+
+ if (!vif->bss_conf.bssid_indicator)
+ return;
+
+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss));
+
+ mbss = (struct bss_bcn_mbss_tlv *)tlv;
+ mbss->offset[0] = cpu_to_le16(offs->tim_offset);
+ mbss->bitmap = cpu_to_le32(1);
+
+ for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
+ &skb->data[offs->mbssid_off],
+ skb->len - offs->mbssid_off) {
+ const struct element *sub_elem;
+
+ if (elem->datalen < 2)
+ continue;
+
+ for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
+ const struct ieee80211_bssid_index *idx;
+ const u8 *idx_ie;
+
+ /* not a valid BSS profile */
+ if (sub_elem->id || sub_elem->datalen < 4)
+ continue;
+
+ /* Find WLAN_EID_MULTI_BSSID_IDX
+ * in the merged nontransmitted profile
+ */
+ idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+ sub_elem->data, sub_elem->datalen);
+ if (!idx_ie || idx_ie[1] < sizeof(*idx))
+ continue;
+
+ idx = (void *)(idx_ie + 2);
+ if (!idx->bssid_index || idx->bssid_index > 31)
+ continue;
+
+ mbss->offset[idx->bssid_index] = cpu_to_le16(idx_ie -
+ skb->data);
+ mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
+ }
+ }
+}
+
+static void
mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct sk_buff *rskb, struct sk_buff *skb,
struct bss_bcn_content_tlv *bcn,
@@ -2016,7 +2276,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
bcn->bcc_ie_pos = cpu_to_le16(offset - 3);
}
- buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
+ buf = (u8 *)bcn + sizeof(*bcn);
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
BSS_CHANGED_BEACON);
@@ -2034,26 +2294,25 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
struct sk_buff *skb, *rskb;
struct tlv *tlv;
struct bss_bcn_content_tlv *bcn;
+ int len;
+
+ if (vif->bss_conf.nontransmitted)
+ return 0;
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
- MT7996_BEACON_UPDATE_SIZE);
+ MT7996_MAX_BSS_OFFLOAD_SIZE);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
- tlv = mt7996_mcu_add_uni_tlv(rskb,
- UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn));
- bcn = (struct bss_bcn_content_tlv *)tlv;
- bcn->enable = en;
-
- if (!en)
- goto out;
-
skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
- if (!skb)
+ if (!skb) {
+ dev_kfree_skb(rskb);
return -EINVAL;
+ }
- if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
+ if (skb->len > MT7996_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
+ dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return -EINVAL;
}
@@ -2061,11 +2320,18 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
+ len = sizeof(*bcn) + MT_TXD_SIZE + skb->len;
+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
+ bcn = (struct bss_bcn_content_tlv *)tlv;
+ bcn->enable = en;
+ if (!en)
+ goto out;
+
mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
- /* TODO: subtag - 11v MBSSID */
+ mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
- dev_kfree_skb(skb);
out:
+ dev_kfree_skb(skb);
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
@@ -2086,9 +2352,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
struct sk_buff *rskb, *skb = NULL;
struct tlv *tlv;
u8 *buf, interval;
+ int len;
+
+ if (vif->bss_conf.nontransmitted)
+ return 0;
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
- MT7996_INBAND_FRAME_SIZE);
+ MT7996_MAX_BSS_OFFLOAD_SIZE);
if (IS_ERR(rskb))
return PTR_ERR(rskb);
@@ -2102,11 +2372,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
}
- if (!skb)
+ if (!skb) {
+ dev_kfree_skb(rskb);
return -EINVAL;
+ }
- if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) {
+ if (skb->len > MT7996_MAX_BEACON_SIZE) {
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
+ dev_kfree_skb(rskb);
dev_kfree_skb(skb);
return -EINVAL;
}
@@ -2116,7 +2389,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
info->band = band;
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
- tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov));
+ len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
+
+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
discov = (struct bss_inband_discovery_tlv *)tlv;
discov->tx_mode = OFFLOAD_TX_MODE_SU;
@@ -2127,7 +2402,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
discov->enable = true;
discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
- buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
+ buf = (u8 *)tlv + sizeof(*discov);
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
@@ -2679,7 +2954,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
e = (struct edca *)tlv;
e->set = WMM_PARAM_SET;
- e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS;
+ e->queue = ac;
e->aifs = q->aifs;
e->txop = cpu_to_le16(q->txop);
@@ -2960,10 +3235,10 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
.channel_band = ch_band[chandef->chan->band],
};
- if (tag == UNI_CHANNEL_RX_PATH ||
- dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
+ if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
req.switch_reason = CH_SWITCH_NORMAL;
- else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
+ else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
+ phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
NL80211_IFTYPE_AP))
@@ -3307,8 +3582,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en));
req_mod_en = (struct bf_mod_en_ctrl *)tlv;
- req_mod_en->bf_num = 2;
- req_mod_en->bf_bitmap = GENMASK(0, 0);
+ req_mod_en->bf_num = 3;
+ req_mod_en->bf_bitmap = GENMASK(2, 0);
break;
}
default:
@@ -3548,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
int cmd)
{
struct {
- u8 _rsv[4];
+ /* fixed field */
+ u8 bss;
+ u8 _rsv[3];
__le16 tag;
__le16 len;
@@ -3566,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
u8 exponent;
u8 is_ap;
u8 agrt_params;
- u8 __rsv2[135];
+ u8 __rsv2[23];
} __packed req = {
.tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE),
.len = cpu_to_le16(sizeof(req) - 4),
@@ -3576,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
.flowid = flow->id,
.peer_id = cpu_to_le16(flow->wcid),
.duration = flow->duration,
+ .bss = mvif->mt76.idx,
.bss_idx = mvif->mt76.idx,
.start_tsf = cpu_to_le64(flow->tsf),
.mantissa = flow->mantissa,
@@ -3786,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
sizeof(req), true);
}
+
+int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+{
+ struct mt7996_dev *dev = phy->dev;
+ struct {
+ u8 _rsv[4];
+
+ __le16 tag;
+ __le16 len;
+ } __packed req = {
+ .tag = cpu_to_le16(tag),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ };
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
+ &req, sizeof(req), false);
+}