summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/mcu.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c151
1 files changed, 126 insertions, 25 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9fcb22fa1f97..50ae7bf3af91 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -13,6 +13,9 @@
case 0x7915: \
_fw = MT7915_##name; \
break; \
+ case 0x7981: \
+ _fw = MT7981_##name; \
+ break; \
case 0x7986: \
_fw = MT7986_##name##__VA_ARGS__; \
break; \
@@ -164,7 +167,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
- if (seq != rxd->seq)
+ if (seq != rxd->seq &&
+ !(rxd->eid == MCU_CMD_EXT_CID &&
+ rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
return -EAGAIN;
if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
@@ -274,7 +279,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
r = (struct mt7915_mcu_rdd_report *)skb->data;
- if (r->band_idx > MT_BAND1)
+ if (r->band_idx > MT_RX_SEL2)
return;
if ((r->band_idx && !dev->phy.mt76->band_idx) &&
@@ -395,12 +400,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_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->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
- !rxd->seq)
+ 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->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
+ !rxd->seq) &&
+ !(rxd->eid == MCU_CMD_EXT_CID &&
+ rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
mt7915_mcu_rx_unsolicited_event(dev, skb);
else
mt76_mcu_rx_event(&dev->mt76, skb);
@@ -706,6 +713,7 @@ static void
mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct ieee80211_he_mcs_nss_supp mcs_map;
struct sta_rec_he *he;
@@ -739,7 +747,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
- if (vif->bss_conf.he_ldpc &&
+ if (mvif->cap.he_ldpc &&
(elem->phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
cap |= STA_REC_HE_CAP_LDPC;
@@ -848,6 +856,7 @@ static void
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
@@ -860,9 +869,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
muru = (struct sta_rec_muru *)tlv;
- muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformee;
+ muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
+ mvif->cap.vht_mu_ebfer ||
+ mvif->cap.vht_mu_ebfee;
if (!is_mt7915(&dev->mt76))
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
@@ -995,8 +1004,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
- wtbl_hdr, vif->bss_conf.ht_ldpc,
- vif->bss_conf.vht_ldpc);
+ wtbl_hdr, mvif->cap.ht_ldpc,
+ mvif->cap.vht_ldpc);
return 0;
}
@@ -1005,6 +1014,7 @@ static inline bool
mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -1018,10 +1028,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
if (bfee)
- return vif->bss_conf.he_su_beamformee &&
+ return mvif->cap.he_su_ebfee &&
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
else
- return vif->bss_conf.he_su_beamformer &&
+ return mvif->cap.he_su_ebfer &&
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
}
@@ -1029,10 +1039,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
u32 cap = sta->deflink.vht_cap.cap;
if (bfee)
- return vif->bss_conf.vht_su_beamformee &&
+ return mvif->cap.vht_su_ebfee &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
else
- return vif->bss_conf.vht_su_beamformer &&
+ return mvif->cap.vht_su_ebfer &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
}
@@ -1527,7 +1537,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_TX_STBC;
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
cap |= STA_CAP_RX_STBC;
- if (vif->bss_conf.ht_ldpc &&
+ if (mvif->cap.ht_ldpc &&
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC;
@@ -1553,7 +1563,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_VHT_TX_STBC;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
cap |= STA_CAP_VHT_RX_STBC;
- if (vif->bss_conf.vht_ldpc &&
+ if (mvif->cap.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC;
@@ -2112,12 +2122,11 @@ int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled)
sizeof(data), false);
}
-int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms)
+int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct sk_buff *skb;
- struct mt7915_mcu_muru_stats *mu_stats =
- (struct mt7915_mcu_muru_stats *)ms;
+ struct mt7915_mcu_muru_stats *mu_stats;
int ret;
struct {
@@ -2133,7 +2142,43 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms)
if (ret)
return ret;
- memcpy(mu_stats, skb->data, sizeof(struct mt7915_mcu_muru_stats));
+ mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data);
+
+ /* accumulate stats, these are clear-on-read */
+#define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s)
+#define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s)
+ __dl_u32(cck_cnt);
+ __dl_u32(ofdm_cnt);
+ __dl_u32(htmix_cnt);
+ __dl_u32(htgf_cnt);
+ __dl_u32(vht_su_cnt);
+ __dl_u32(vht_2mu_cnt);
+ __dl_u32(vht_3mu_cnt);
+ __dl_u32(vht_4mu_cnt);
+ __dl_u32(he_su_cnt);
+ __dl_u32(he_2ru_cnt);
+ __dl_u32(he_2mu_cnt);
+ __dl_u32(he_3ru_cnt);
+ __dl_u32(he_3mu_cnt);
+ __dl_u32(he_4ru_cnt);
+ __dl_u32(he_4mu_cnt);
+ __dl_u32(he_5to8ru_cnt);
+ __dl_u32(he_9to16ru_cnt);
+ __dl_u32(he_gtr16ru_cnt);
+
+ __ul_u32(hetrig_su_cnt);
+ __ul_u32(hetrig_2ru_cnt);
+ __ul_u32(hetrig_3ru_cnt);
+ __ul_u32(hetrig_4ru_cnt);
+ __ul_u32(hetrig_5to8ru_cnt);
+ __ul_u32(hetrig_9to16ru_cnt);
+ __ul_u32(hetrig_gtr16ru_cnt);
+ __ul_u32(hetrig_2mu_cnt);
+ __ul_u32(hetrig_3mu_cnt);
+ __ul_u32(hetrig_4mu_cnt);
+#undef __dl_u32
+#undef __ul_u32
+
dev_kfree_skb(skb);
return 0;
@@ -2993,7 +3038,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
}
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
- req, sizeof(req), true, &skb);
+ req, len * sizeof(req[0]), true, &skb);
if (ret)
return ret;
@@ -3733,6 +3778,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
+int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
+{
+ struct {
+ __le32 cmd;
+ __le32 num;
+ __le32 __rsv;
+ __le16 wlan_idx;
+ } req = {
+ .cmd = cpu_to_le32(0x15),
+ .num = cpu_to_le32(1),
+ .wlan_idx = cpu_to_le16(wlan_idx),
+ };
+ struct mt7915_mcu_wa_tx_stat {
+ __le16 wlan_idx;
+ u8 __rsv[2];
+
+ /* tx_bytes is deprecated since WA byte counter uses u32,
+ * which easily leads to overflow.
+ */
+ __le32 tx_bytes;
+ __le32 tx_packets;
+ } *res;
+ struct mt76_wcid *wcid;
+ struct sk_buff *skb;
+ int ret;
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
+ &req, sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ if (!is_mt7915(&dev->mt76))
+ skb_pull(skb, 4);
+
+ res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
+
+ if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rcu_read_lock();
+
+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+ if (wcid)
+ wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
+ else
+ ret = -EINVAL;
+
+ rcu_read_unlock();
+out:
+ dev_kfree_skb(skb);
+
+ return ret;
+}
+
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
{
struct {