diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/mcu.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 1432 |
1 files changed, 377 insertions, 1055 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 0911b6f973b5..119f9358162f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -64,136 +64,31 @@ struct mt7915_fw_region { u8 reserved1[15]; } __packed; -#define MCU_PATCH_ADDRESS 0x200000 - -#define FW_FEATURE_SET_ENCRYPT BIT(0) -#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) -#define FW_FEATURE_OVERRIDE_ADDR BIT(5) - -#define DL_MODE_ENCRYPT BIT(0) -#define DL_MODE_KEY_IDX GENMASK(2, 1) -#define DL_MODE_RESET_SEC_IV BIT(3) -#define DL_MODE_WORKING_PDA_CR4 BIT(4) -#define DL_MODE_NEED_RSP BIT(31) - -#define FW_START_OVERRIDE BIT(0) -#define FW_START_WORKING_PDA_CR4 BIT(2) - -#define PATCH_SEC_TYPE_MASK GENMASK(15, 0) -#define PATCH_SEC_TYPE_INFO 0x2 +#define fw_name(_dev, name, ...) ({ \ + char *_fw; \ + switch (mt76_chip(&(_dev)->mt76)) { \ + case 0x7915: \ + _fw = MT7915_##name; \ + break; \ + case 0x7986: \ + _fw = MT7986_##name##__VA_ARGS__; \ + break; \ + default: \ + _fw = MT7916_##name; \ + break; \ + } \ + _fw; \ +}) + +#define fw_name_var(_dev, name) (mt7915_check_adie(dev, false) ? \ + fw_name(_dev, name) : \ + fw_name(_dev, name, _MT7975)) -#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) -#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) +#define MCU_PATCH_ADDRESS 0x200000 #define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p) #define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m) -static enum mcu_cipher_type -mt7915_mcu_get_cipher(int cipher) -{ - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - return MCU_CIPHER_WEP40; - case WLAN_CIPHER_SUITE_WEP104: - return MCU_CIPHER_WEP104; - case WLAN_CIPHER_SUITE_TKIP: - return MCU_CIPHER_TKIP; - case WLAN_CIPHER_SUITE_AES_CMAC: - return MCU_CIPHER_BIP_CMAC_128; - case WLAN_CIPHER_SUITE_CCMP: - return MCU_CIPHER_AES_CCMP; - case WLAN_CIPHER_SUITE_CCMP_256: - return MCU_CIPHER_CCMP_256; - case WLAN_CIPHER_SUITE_GCMP: - return MCU_CIPHER_GCMP; - case WLAN_CIPHER_SUITE_GCMP_256: - return MCU_CIPHER_GCMP_256; - case WLAN_CIPHER_SUITE_SMS4: - return MCU_CIPHER_WAPI; - default: - return MCU_CIPHER_NONE; - } -} - -static u8 mt7915_mcu_chan_bw(struct cfg80211_chan_def *chandef) -{ - static const u8 width_to_bw[] = { - [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ, - [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ, - [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ, - [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ, - [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ, - [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, - [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, - [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, - }; - - if (chandef->width >= ARRAY_SIZE(width_to_bw)) - return 0; - - return width_to_bw[chandef->width]; -} - -static const struct ieee80211_sta_he_cap * -mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif) -{ - struct ieee80211_supported_band *sband; - enum nl80211_band band; - - band = phy->mt76->chandef.chan->band; - sband = phy->mt76->hw->wiphy->bands[band]; - - return ieee80211_get_he_iftype_cap(sband, vif->type); -} - -static u8 -mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - enum nl80211_band band = mvif->phy->mt76->chandef.chan->band; - struct ieee80211_sta_ht_cap *ht_cap; - struct ieee80211_sta_vht_cap *vht_cap; - const struct ieee80211_sta_he_cap *he_cap; - u8 mode = 0; - - if (sta) { - ht_cap = &sta->ht_cap; - vht_cap = &sta->vht_cap; - he_cap = &sta->he_cap; - } else { - struct ieee80211_supported_band *sband; - - sband = mvif->phy->mt76->hw->wiphy->bands[band]; - - ht_cap = &sband->ht_cap; - vht_cap = &sband->vht_cap; - he_cap = ieee80211_get_he_iftype_cap(sband, vif->type); - } - - if (band == NL80211_BAND_2GHZ) { - mode |= PHY_MODE_B | PHY_MODE_G; - - if (ht_cap->ht_supported) - mode |= PHY_MODE_GN; - - if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_24G; - } else if (band == NL80211_BAND_5GHZ) { - mode |= PHY_MODE_A; - - if (ht_cap->ht_supported) - mode |= PHY_MODE_AN; - - if (vht_cap->vht_supported) - mode |= PHY_MODE_AC; - - if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_5G; - } - - return mode; -} - static u8 mt7915_mcu_get_sta_nss(u16 mcs_map) { @@ -211,24 +106,13 @@ mt7915_mcu_get_sta_nss(u16 mcs_map) static void mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, - const u16 *mask) + u16 mcs_map) { struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct cfg80211_chan_def *chandef = &msta->vif->phy->mt76->chandef; + struct mt7915_dev *dev = msta->vif->phy->dev; + enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band; + const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs; int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss; - u16 mcs_map; - - switch (chandef->width) { - case NL80211_CHAN_WIDTH_80P80: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80p80); - break; - case NL80211_CHAN_WIDTH_160: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160); - break; - default: - mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80); - break; - } for (nss = 0; nss < max_nss; nss++) { int mcs; @@ -266,8 +150,9 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs, mcs_map &= ~(0x3 << (nss * 2)); mcs_map |= mcs << (nss * 2); - /* only support 2ss on 160MHz */ - if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160)) + /* only support 2ss on 160MHz for mt7915 */ + if (is_mt7915(&dev->mt76) && nss > 1 && + sta->bandwidth == IEEE80211_STA_RX_BW_160) break; } @@ -278,6 +163,8 @@ static void mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, const u16 *mask) { + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = msta->vif->phy->dev; u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss; u16 mcs; @@ -299,8 +186,9 @@ mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs, vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]); - /* only support 2ss on 160MHz */ - if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160)) + /* only support 2ss on 160MHz for mt7915 */ + if (is_mt7915(&dev->mt76) && nss > 1 && + sta->bandwidth == IEEE80211_STA_RX_BW_160) break; } } @@ -446,7 +334,7 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb) c = (struct mt7915_mcu_csa_notify *)skb->data; - if (c->band_idx && dev->mt76.phy2) + if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phy2) mphy = dev->mt76.phy2; ieee80211_iterate_active_interfaces_atomic(mphy->hw, @@ -465,7 +353,7 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb) if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE) return; - if (t->ctrl.band_idx && dev->mt76.phy2) + if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phy2) mphy = dev->mt76.phy2; phy = (struct mt7915_phy *)mphy->priv; @@ -480,10 +368,15 @@ 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 && dev->mt76.phy2) + if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phy2) mphy = dev->mt76.phy2; - ieee80211_radar_detected(mphy->hw); + if (r->band_idx == MT_RX_SEL2) + cfg80211_background_radar_event(mphy->hw->wiphy, + &dev->rdd2_chandef, + GFP_ATOMIC); + else + ieee80211_radar_detected(mphy->hw); dev->hw_pattern++; } @@ -493,9 +386,13 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; const char *data = (char *)&rxd[1]; const char *type; + int len = skb->len - sizeof(*rxd); switch (rxd->s2d_index) { case 0: + if (mt7915_debugfs_rx_log(dev, data, len)) + return; + type = "WM"; break; case 2: @@ -506,8 +403,7 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) break; } - wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, - (int)(skb->len - sizeof(*rxd)), data); + wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, len, data); } static void @@ -520,6 +416,22 @@ mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) } static void +mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7915_mcu_bcc_notify *b; + + b = (struct mt7915_mcu_bcc_notify *)skb->data; + + if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_mcu_cca_finish, mphy->hw); +} + +static void mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) { struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; @@ -538,9 +450,7 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) mt7915_mcu_rx_log_message(dev, skb); break; case MCU_EXT_EVENT_BCC_NOTIFY: - ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7915_mcu_cca_finish, dev); + mt7915_mcu_rx_bcc_notify(dev, skb); break; default: break; @@ -577,88 +487,6 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) mt76_mcu_rx_event(&dev->mt76, skb); } -static struct sk_buff * -mt7915_mcu_alloc_sta_req(struct mt7915_dev *dev, struct mt7915_vif *mvif, - struct mt7915_sta *msta, int len) -{ - struct sta_req_hdr hdr = { - .bss_idx = mvif->mt76.idx, - .wlan_idx_lo = msta ? to_wcid_lo(msta->wcid.idx) : 0, - .wlan_idx_hi = msta ? to_wcid_hi(msta->wcid.idx) : 0, - .muar_idx = msta && msta->wcid.sta ? mvif->mt76.omac_idx : 0xe, - .is_tlv_append = 1, - }; - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len); - if (!skb) - return ERR_PTR(-ENOMEM); - - skb_put_data(skb, &hdr, sizeof(hdr)); - - return skb; -} - -static struct wtbl_req_hdr * -mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, - int cmd, void *sta_wtbl, struct sk_buff **skb) -{ - struct tlv *sta_hdr = sta_wtbl; - struct wtbl_req_hdr hdr = { - .wlan_idx_lo = to_wcid_lo(msta->wcid.idx), - .wlan_idx_hi = to_wcid_hi(msta->wcid.idx), - .operation = cmd, - }; - struct sk_buff *nskb = *skb; - - if (!nskb) { - nskb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - MT76_CONNAC_WTBL_UPDATE_MAX_SIZE); - if (!nskb) - return ERR_PTR(-ENOMEM); - - *skb = nskb; - } - - if (sta_hdr) - le16_add_cpu(&sta_hdr->len, sizeof(hdr)); - - return skb_put_data(nskb, &hdr, sizeof(hdr)); -} - -static struct tlv * -mt7915_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, - void *sta_ntlv, void *sta_wtbl) -{ - struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv; - struct tlv *sta_hdr = sta_wtbl; - struct tlv *ptlv, tlv = { - .tag = cpu_to_le16(tag), - .len = cpu_to_le16(len), - }; - u16 ntlv; - - ptlv = skb_put(skb, len); - memcpy(ptlv, &tlv, sizeof(tlv)); - - ntlv = le16_to_cpu(ntlv_hdr->tlv_num); - ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); - - if (sta_hdr) { - u16 size = le16_to_cpu(sta_hdr->len); - - sta_hdr->len = cpu_to_le16(size + len); - } - - return ptlv; -} - -static struct tlv * -mt7915_mcu_add_tlv(struct sk_buff *skb, int tag, int len) -{ - return mt7915_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL); -} - static struct tlv * mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, __le16 *sub_ntlv, __le16 *len) @@ -678,105 +506,6 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, } /** bss info **/ -static int -mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct mt7915_phy *phy, bool enable) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct bss_info_basic *bss; - u16 wlan_idx = mvif->sta.wcid.idx; - u32 type = NETWORK_INFRA; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MONITOR: - break; - case NL80211_IFTYPE_STATION: - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ - if (enable) { - struct ieee80211_sta *sta; - struct mt7915_sta *msta; - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!sta) { - rcu_read_unlock(); - return -EINVAL; - } - - msta = (struct mt7915_sta *)sta->drv_priv; - wlan_idx = msta->wcid.idx; - rcu_read_unlock(); - } - break; - case NL80211_IFTYPE_ADHOC: - type = NETWORK_IBSS; - break; - default: - WARN_ON(1); - break; - } - - bss = (struct bss_info_basic *)tlv; - bss->network_type = cpu_to_le32(type); - bss->bmc_wcid_lo = to_wcid_lo(wlan_idx); - bss->bmc_wcid_hi = to_wcid_hi(wlan_idx); - bss->wmm_idx = mvif->mt76.wmm_idx; - bss->active = enable; - - if (vif->type != NL80211_IFTYPE_MONITOR) { - memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); - bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - bss->dtim_period = vif->bss_conf.dtim_period; - bss->phy_mode = mt7915_get_phy_mode(vif, NULL); - } else { - memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); - } - - return 0; -} - -static void -mt7915_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct bss_info_omac *omac; - struct tlv *tlv; - u32 type = 0; - u8 idx; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); - - switch (vif->type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: - type = CONNECTION_INFRA_STA; - break; - case NL80211_IFTYPE_ADHOC: - type = CONNECTION_IBSS_ADHOC; - break; - default: - WARN_ON(1); - break; - } - - omac = (struct bss_info_omac *)tlv; - idx = mvif->mt76.omac_idx > EXT_BSSID_START ? HW_BSSID_0 - : mvif->mt76.omac_idx; - omac->conn_type = cpu_to_le32(type); - omac->omac_idx = mvif->mt76.omac_idx; - omac->band_idx = mvif->mt76.band_idx; - omac->hw_bss_idx = idx; -} - struct mt7915_he_obss_narrow_bw_ru_data { bool tolerated; }; @@ -829,12 +558,12 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct tlv *tlv; int freq1 = chandef->center_freq1; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch)); ch = (struct bss_info_rf_ch *)tlv; ch->pri_ch = chandef->chan->hw_value; ch->center_ch0 = ieee80211_frequency_to_channel(freq1); - ch->bw = mt7915_mcu_chan_bw(chandef); + ch->bw = mt76_connac_chan_bw(chandef); if (chandef->width == NL80211_CHAN_WIDTH_80P80) { int freq2 = chandef->center_freq2; @@ -843,12 +572,7 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) { - struct mt7915_dev *dev = phy->dev; - struct mt76_phy *mphy = &dev->mt76.phy; - bool ext_phy = phy != &dev->phy; - - if (ext_phy && dev->mt76.phy2) - mphy = dev->mt76.phy2; + struct mt76_phy *mphy = phy->mt76; ch->he_ru26_block = mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif); @@ -866,7 +590,7 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct bss_info_ra *ra; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra)); ra = (struct bss_info_ra *)tlv; ra->op_mode = vif->type == NL80211_IFTYPE_AP; @@ -894,9 +618,9 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct bss_info_he *he; struct tlv *tlv; - cap = mt7915_get_he_phy_cap(phy, vif); + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); he = (struct bss_info_he *)tlv; he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; @@ -920,7 +644,7 @@ mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb) struct bss_info_hw_amsdu *amsdu; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct bss_info_hw_amsdu *)tlv; amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1); @@ -930,26 +654,6 @@ mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb) } static void -mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif) -{ -/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ -#define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss *ext; - int ext_bss_idx, tsf_offset; - struct tlv *tlv; - - ext_bss_idx = mvif->mt76.omac_idx - EXT_BSSID_START; - if (ext_bss_idx < 0) - return; - - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); - - ext = (struct bss_info_ext_bss *)tlv; - tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); -} - -static void mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) { struct bss_info_bmc_rate *bmc; @@ -957,7 +661,7 @@ mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) enum nl80211_band band = chandef->chan->band; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc)); bmc = (struct bss_info_bmc_rate *)tlv; if (band == NL80211_BAND_2GHZ) { @@ -1010,6 +714,7 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, struct ieee80211_vif *vif, int enable) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_dev *dev = phy->dev; struct sk_buff *skb; if (mvif->mt76.omac_idx >= REPEATER_BSSID_START) { @@ -1017,16 +722,17 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, mt7915_mcu_muar_config(phy, vif, true, enable); } - skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL, - MT7915_BSS_UPDATE_MAX_SIZE); + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL, + MT7915_BSS_UPDATE_MAX_SIZE); if (IS_ERR(skb)) return PTR_ERR(skb); /* bss_omac must be first */ if (enable) - mt7915_mcu_bss_omac_tlv(skb, vif); + mt76_connac_mcu_bss_omac_tlv(skb, vif); - mt7915_mcu_bss_basic_tlv(skb, vif, phy, enable); + mt76_connac_mcu_bss_basic_tlv(skb, vif, NULL, phy->mt76, + mvif->sta.wcid.idx, enable); if (vif->type == NL80211_IFTYPE_MONITOR) goto out; @@ -1042,309 +748,48 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, if (mvif->mt76.omac_idx >= EXT_BSSID_START && mvif->mt76.omac_idx < REPEATER_BSSID_START) - mt7915_mcu_bss_ext_tlv(skb, mvif); + mt76_connac_mcu_bss_ext_tlv(skb, &mvif->mt76); } out: - return mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(BSS_INFO_UPDATE), true); } /** starec & wtbl **/ -static int -mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, - struct ieee80211_key_conf *key, enum set_key_cmd cmd) -{ - struct mt7915_sta_key_conf *bip = &msta->bip; - struct sta_rec_sec *sec; - struct tlv *tlv; - u32 len = sizeof(*sec); - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); - - sec = (struct sta_rec_sec *)tlv; - sec->add = cmd; - - if (cmd == SET_KEY) { - struct sec_key *sec_key; - u8 cipher; - - cipher = mt7915_mcu_get_cipher(key->cipher); - if (cipher == MCU_CIPHER_NONE) - return -EOPNOTSUPP; - - sec_key = &sec->key[0]; - sec_key->cipher_len = sizeof(*sec_key); - - if (cipher == MCU_CIPHER_BIP_CMAC_128) { - sec_key->cipher_id = MCU_CIPHER_AES_CCMP; - sec_key->key_id = bip->keyidx; - sec_key->key_len = 16; - memcpy(sec_key->key, bip->key, 16); - - sec_key = &sec->key[1]; - sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; - sec_key->cipher_len = sizeof(*sec_key); - sec_key->key_len = 16; - memcpy(sec_key->key, key->key, 16); - - sec->n_cipher = 2; - } else { - sec_key->cipher_id = cipher; - sec_key->key_id = key->keyidx; - sec_key->key_len = key->keylen; - memcpy(sec_key->key, key->key, key->keylen); - - if (cipher == MCU_CIPHER_TKIP) { - /* Rx/Tx MIC keys are swapped */ - memcpy(sec_key->key + 16, key->key + 24, 8); - memcpy(sec_key->key + 24, key->key + 16, 8); - } - - /* store key_conf for BIP batch update */ - if (cipher == MCU_CIPHER_AES_CCMP) { - memcpy(bip->key, key->key, key->keylen); - bip->keyidx = key->keyidx; - } - - len -= sizeof(*sec_key); - sec->n_cipher = 1; - } - } else { - len -= sizeof(sec->key); - sec->n_cipher = 0; - } - sec->len = cpu_to_le16(len); - - return 0; -} - -int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct mt7915_sta *msta, struct ieee80211_key_conf *key, - enum set_key_cmd cmd) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct sk_buff *skb; - int len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_sec); - int ret; - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - ret = mt7915_mcu_sta_key_tlv(msta, skb, key, cmd); - if (ret) - return ret; - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - -static void -mt7915_mcu_sta_ba_tlv(struct sk_buff *skb, - struct ieee80211_ampdu_params *params, - bool enable, bool tx) -{ - struct sta_rec_ba *ba; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); - - ba = (struct sta_rec_ba *)tlv; - ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT; - ba->winsize = cpu_to_le16(params->buf_size); - ba->ssn = cpu_to_le16(params->ssn); - ba->ba_en = enable << params->tid; - ba->amsdu = params->amsdu; - ba->tid = params->tid; -} - -static void -mt7915_mcu_wtbl_ba_tlv(struct sk_buff *skb, - struct ieee80211_ampdu_params *params, - bool enable, bool tx, void *sta_wtbl, - void *wtbl_tlv) -{ - struct wtbl_ba *ba; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba), - wtbl_tlv, sta_wtbl); - - ba = (struct wtbl_ba *)tlv; - ba->tid = params->tid; - - if (tx) { - ba->ba_type = MT_BA_TYPE_ORIGINATOR; - ba->sn = enable ? cpu_to_le16(params->ssn) : 0; - ba->ba_en = enable; - } else { - memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN); - ba->ba_type = MT_BA_TYPE_RECIPIENT; - ba->rst_ba_tid = params->tid; - ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; - ba->rst_ba_sb = 1; - } - - if (enable) - ba->ba_winsize = cpu_to_le16(params->buf_size); -} - -static int -mt7915_mcu_sta_ba(struct mt7915_dev *dev, - struct ieee80211_ampdu_params *params, - bool enable, bool tx) +int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) { struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; struct mt7915_vif *mvif = msta->vif; - struct wtbl_req_hdr *wtbl_hdr; - struct tlv *sta_wtbl; - struct sk_buff *skb; - int ret; - if (enable && tx && !params->amsdu) + if (enable && !params->amsdu) msta->wcid.amsdu = false; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT76_CONNAC_STA_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, - &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); - - ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); - if (ret) - return ret; - - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT76_CONNAC_STA_UPDATE_MAX_SIZE); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - mt7915_mcu_sta_ba_tlv(skb, params, enable, tx); - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_EXT_CMD(STA_REC_UPDATE), true); -} - -int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, - struct ieee80211_ampdu_params *params, - bool enable) -{ - return mt7915_mcu_sta_ba(dev, params, enable, true); + return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, true); } int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - return mt7915_mcu_sta_ba(dev, params, enable, false); -} - -static void -mt7915_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct wtbl_generic *generic; - struct wtbl_rx *rx; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_GENERIC, sizeof(*generic), - wtbl_tlv, sta_wtbl); - - generic = (struct wtbl_generic *)tlv; - - if (sta) { - memcpy(generic->peer_addr, sta->addr, ETH_ALEN); - generic->partial_aid = cpu_to_le16(sta->aid); - generic->muar_idx = mvif->mt76.omac_idx; - generic->qos = sta->wme; - } else { - /* use BSSID in station mode */ - if (vif->type == NL80211_IFTYPE_STATION) - memcpy(generic->peer_addr, vif->bss_conf.bssid, - ETH_ALEN); - else - eth_broadcast_addr(generic->peer_addr); - - generic->muar_idx = 0xe; - } - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx), - wtbl_tlv, sta_wtbl); - - rx = (struct wtbl_rx *)tlv; - rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1; - rx->rca2 = 1; - rx->rv = 1; -} - -static void -mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable) -{ -#define EXTRA_INFO_VER BIT(0) -#define EXTRA_INFO_NEW BIT(1) - struct sta_rec_basic *basic; - struct tlv *tlv; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic)); - - basic = (struct sta_rec_basic *)tlv; - basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); - - if (enable) { - basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); - basic->conn_state = CONN_STATE_PORT_SECURE; - } else { - basic->conn_state = CONN_STATE_DISCONNECT; - } - - if (!sta) { - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); - eth_broadcast_addr(basic->peer_addr); - return; - } - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA); - break; - case NL80211_IFTYPE_STATION: - basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP); - break; - case NL80211_IFTYPE_ADHOC: - basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); - break; - default: - WARN_ON(1); - break; - } + struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; + struct mt7915_vif *mvif = msta->vif; - memcpy(basic->peer_addr, sta->addr, ETH_ALEN); - basic->aid = cpu_to_le16(sta->aid); - basic->qos = sta->wme; + return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, false); } static void mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->he_cap.he_cap_elem; - enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band; - const u16 *mcs_mask = msta->vif->bitrate_mask.control[band].he_mcs; + struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he *he; struct tlv *tlv; u32 cap = 0; @@ -1352,7 +797,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, if (!sta->he_cap.has_he) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he)); he = (struct sta_rec_he *)tlv; @@ -1434,22 +879,23 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, he->he_cap = cpu_to_le32(cap); + mcs_map = sta->he_cap.he_mcs_nss_supp; switch (sta->bandwidth) { case IEEE80211_STA_RX_BW_160: if (elem->phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW8080], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_80p80)); mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW160], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_160)); fallthrough; default: mt7915_mcu_set_sta_he_mcs(sta, &he->max_nss_mcs[CMD_HE_MCS_BW80], - mcs_mask); + le16_to_cpu(mcs_map.rx_mcs_80)); break; } @@ -1480,38 +926,6 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, } static void -mt7915_mcu_sta_uapsd_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - struct ieee80211_vif *vif) -{ - struct sta_rec_uapsd *uapsd; - struct tlv *tlv; - - if (vif->type != NL80211_IFTYPE_AP || !sta->wme) - return; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_APPS, sizeof(*uapsd)); - uapsd = (struct sta_rec_uapsd *)tlv; - - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) { - uapsd->dac_map |= BIT(3); - uapsd->tac_map |= BIT(3); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) { - uapsd->dac_map |= BIT(2); - uapsd->tac_map |= BIT(2); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) { - uapsd->dac_map |= BIT(1); - uapsd->tac_map |= BIT(1); - } - if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) { - uapsd->dac_map |= BIT(0); - uapsd->tac_map |= BIT(0); - } - uapsd->max_sp = sta->max_sp; -} - -static void mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { @@ -1524,19 +938,19 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, vif->type != NL80211_IFTYPE_AP) return; - if (!sta->vht_cap.vht_supported) - return; - - tlv = mt7915_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); muru = (struct sta_rec_muru *)tlv; muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || mvif->cap.vht_mu_ebfer || mvif->cap.vht_mu_ebfee; + muru->cfg.mimo_ul_en = true; + muru->cfg.ofdma_dl_en = true; - muru->mimo_dl.vht_mu_bfee = - !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + if (sta->vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); if (!sta->he_cap.has_he) return; @@ -1544,13 +958,11 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, muru->mimo_dl.partial_bw_dl_mimo = HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]); - muru->cfg.mimo_ul_en = true; muru->mimo_ul.full_ul_mimo = HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]); muru->mimo_ul.partial_ul_mimo = HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]); - muru->cfg.ofdma_dl_en = true; muru->ofdma_dl.punc_pream_rx = HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); muru->ofdma_dl.he_20m_in_40m_2g = @@ -1574,7 +986,7 @@ mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) struct sta_rec_ht *ht; struct tlv *tlv; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); @@ -1589,7 +1001,7 @@ mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) if (!sta->vht_cap.vht_supported) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); vht = (struct sta_rec_vht *)tlv; vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); @@ -1598,8 +1010,8 @@ mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) } static void -mt7915_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +mt7915_mcu_sta_amsdu_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; struct sta_rec_amsdu *amsdu; @@ -1612,96 +1024,27 @@ mt7915_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, if (!sta->max_amsdu_len) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu)); amsdu = (struct sta_rec_amsdu *)tlv; amsdu->max_amsdu_num = 8; amsdu->amsdu_en = true; - amsdu->max_mpdu_size = sta->max_amsdu_len >= - IEEE80211_MAX_MPDU_LEN_VHT_7991; msta->wcid.amsdu = true; -} - -static void -mt7915_mcu_wtbl_smps_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, - void *sta_wtbl, void *wtbl_tlv) -{ - struct wtbl_smps *smps; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), - wtbl_tlv, sta_wtbl); - smps = (struct wtbl_smps *)tlv; - smps->smps = (sta->smps_mode == IEEE80211_SMPS_DYNAMIC); -} - -static void -mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, void *sta_wtbl, - void *wtbl_tlv) -{ - struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct wtbl_ht *ht = NULL; - struct tlv *tlv; - - /* wtbl ht */ - if (sta->ht_cap.ht_supported) { - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), - wtbl_tlv, sta_wtbl); - ht = (struct wtbl_ht *)tlv; - ht->ldpc = mvif->cap.ldpc && - (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING); - ht->af = sta->ht_cap.ampdu_factor; - ht->mm = sta->ht_cap.ampdu_density; - ht->ht = true; - } - - /* wtbl vht */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *vht; - u8 af; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), - wtbl_tlv, sta_wtbl); - vht = (struct wtbl_vht *)tlv; - vht->ldpc = mvif->cap.ldpc && - (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - vht->vht = true; - - af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, - sta->vht_cap.cap); - if (ht) - ht->af = max_t(u8, ht->af, af); - } - mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv); -} - -static void -mt7915_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - void *sta_wtbl, void *wtbl_tlv) -{ - struct mt7915_sta *msta; - struct wtbl_hdr_trans *htr = NULL; - struct tlv *tlv; - - tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS, sizeof(*htr), - wtbl_tlv, sta_wtbl); - htr = (struct wtbl_hdr_trans *)tlv; - htr->no_rx_trans = true; - if (vif->type == NL80211_IFTYPE_STATION) - htr->to_ds = true; - else - htr->from_ds = true; - - if (!sta) + switch (sta->max_amsdu_len) { + case IEEE80211_MAX_MPDU_LEN_VHT_11454: + if (!is_mt7915(&dev->mt76)) { + amsdu->max_mpdu_size = + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; + return; + } + fallthrough; + case IEEE80211_MAX_MPDU_LEN_HT_7935: + case IEEE80211_MAX_MPDU_LEN_VHT_7991: + amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; + return; + default: + amsdu->max_mpdu_size = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; return; - - msta = (struct mt7915_sta *)sta->drv_priv; - htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); - if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) { - htr->to_ds = true; - htr->from_ds = true; } } @@ -1712,48 +1055,29 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct mt7915_sta *msta; struct wtbl_req_hdr *wtbl_hdr; + struct mt76_wcid *wcid; struct tlv *tlv; msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; + wcid = sta ? &msta->wcid : NULL; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, - tlv, &skb); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_RESET_AND_SET, tlv, + &skb); if (IS_ERR(wtbl_hdr)) return PTR_ERR(wtbl_hdr); - mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, tlv, wtbl_hdr); - mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, tlv, wtbl_hdr); - + mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, skb, vif, sta, tlv, + wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr); if (sta) - mt7915_mcu_wtbl_ht_tlv(skb, vif, sta, tlv, wtbl_hdr); + mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv, + wtbl_hdr, mvif->cap.ldpc); return 0; } -int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - MT76_CONNAC_WTBL_UPDATE_MAX_SIZE); - if (!skb) - return -ENOMEM; - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); - if (IS_ERR(wtbl_hdr)) - return PTR_ERR(wtbl_hdr); - - mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE), - true); -} - static inline bool mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) @@ -1870,7 +1194,8 @@ mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, { struct ieee80211_sta_he_cap *pc = &sta->he_cap; struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; - const struct ieee80211_sta_he_cap *vc = mt7915_get_he_phy_cap(phy, vif); + const struct ieee80211_sta_he_cap *vc = + mt76_connac_get_he_phy_cap(phy->mt76, vif); const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); @@ -1928,8 +1253,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_phy *phy = - mvif->mt76.band_idx ? mt7915_ext_phy(dev) : &dev->phy; + struct mt7915_phy *phy = mvif->phy; int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; @@ -1945,7 +1269,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, if (!ebf && !dev->ibf) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); bf = (struct sta_rec_bf *)tlv; /* he: eBF only, in accordance with spec @@ -1995,8 +1319,7 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct mt7915_phy *phy = - mvif->mt76.band_idx ? mt7915_ext_phy(dev) : &dev->phy; + struct mt7915_phy *phy = mvif->phy; int tx_ant = hweight8(phy->mt76->chainmask) - 1; struct sta_rec_bfee *bfee; struct tlv *tlv; @@ -2005,7 +1328,7 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb, if (!mt7915_is_ebf_supported(phy, vif, sta, true)) return; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BFEE, sizeof(*bfee)); bfee = (struct sta_rec_bfee *)tlv; if (sta->he_cap.has_he) { @@ -2050,13 +1373,13 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev, struct sta_rec_ra_fixed *ra; struct sk_buff *skb; struct tlv *tlv; - int len = sizeof(struct sta_req_hdr) + sizeof(*ra); - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); - tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); ra = (struct sta_rec_ra_fixed *)tlv; switch (field) { @@ -2091,19 +1414,19 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *skb; int ret; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT76_CONNAC_STA_UPDATE_MAX_SIZE); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); - sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); - - wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, - &skb); + sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, + sizeof(struct tlv)); + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_SET, sta_wtbl, &skb); if (IS_ERR(wtbl_hdr)) return PTR_ERR(wtbl_hdr); - mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); + mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(STA_REC_UPDATE), true); @@ -2134,9 +1457,12 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, phy.sgi |= gi << (i << (_he)); \ phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\ } \ - for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) \ - nrates += hweight16(mask->control[band]._mcs[i]); \ - phy.mcs = ffs(mask->control[band]._mcs[0]) - 1; \ + 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; \ + } \ } while (0) if (sta->he_cap.has_he) { @@ -2204,7 +1530,8 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; + struct mt76_phy *mphy = mvif->phy->mt76; + struct cfg80211_chan_def *chandef = &mphy->chandef; struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask; enum nl80211_band band = chandef->chan->band; struct sta_rec_ra *ra; @@ -2212,15 +1539,16 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, u32 supp_rate = sta->supp_rates[band]; u32 cap = sta->wme ? STA_CAP_WMM : 0; - tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); ra = (struct sta_rec_ra *)tlv; ra->valid = true; ra->auto_rate = true; - ra->phy_mode = mt7915_get_phy_mode(vif, sta); + ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta); ra->channel = chandef->chan->hw_value; ra->bw = sta->bandwidth; ra->phy.bw = sta->bandwidth; + ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->smps_mode); if (supp_rate) { supp_rate &= mask->control[band].legacy; @@ -2304,8 +1632,8 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct sk_buff *skb; int ret; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT76_CONNAC_STA_UPDATE_MAX_SIZE); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -2371,13 +1699,13 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, - MT76_CONNAC_STA_UPDATE_MAX_SIZE); + skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid); if (IS_ERR(skb)) return PTR_ERR(skb); /* starec basic */ - mt7915_mcu_sta_basic_tlv(skb, vif, sta, enable); + mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable, true); if (!enable) goto out; @@ -2390,16 +1718,18 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, /* starec vht */ mt7915_mcu_sta_vht_tlv(skb, sta); /* starec uapsd */ - mt7915_mcu_sta_uapsd_tlv(skb, sta, vif); + mt76_connac_mcu_sta_uapsd(skb, vif, sta); } ret = mt7915_mcu_sta_wtbl_tlv(dev, skb, vif, sta); - if (ret) + if (ret) { + dev_kfree_skb(skb); return ret; + } if (sta && sta->ht_cap.ht_supported) { /* starec amsdu */ - mt7915_mcu_sta_amsdu_tlv(skb, vif, sta); + mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta); /* starec he */ mt7915_mcu_sta_he_tlv(skb, sta, vif); /* starec muru */ @@ -2409,8 +1739,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, } ret = mt7915_mcu_add_group(dev, vif, sta); - if (ret) + if (ret) { + dev_kfree_skb(skb); return ret; + } out: return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(STA_REC_UPDATE), true); @@ -2571,7 +1903,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, mgmt->u.beacon.variable, len); if (ie && ie[1] >= sizeof(*he) + 1) { const struct ieee80211_sta_he_cap *pc = - mt7915_get_he_phy_cap(phy, vif); + mt76_connac_get_he_phy_cap(phy->mt76, vif); const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; he = (void *)(ie + 3); @@ -2601,12 +1933,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct tlv *tlv; struct bss_info_bcn *bcn; int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE; + bool ext_phy = phy != &dev->phy; - rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + NULL, len); if (IS_ERR(rskb)) return PTR_ERR(rskb); - tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); + tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); bcn = (struct bss_info_bcn *)tlv; bcn->enable = en; @@ -2623,7 +1957,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, return -EINVAL; } - if (mvif->mt76.band_idx) { + if (ext_phy) { info = IEEE80211_SKB_CB(skb); info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; } @@ -2640,91 +1974,20 @@ out: MCU_EXT_CMD(BSS_INFO_UPDATE), true); } -static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, - u32 option) -{ - struct { - __le32 option; - __le32 addr; - } req = { - .option = cpu_to_le32(option), - .addr = cpu_to_le32(addr), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(FW_START_REQ), &req, - sizeof(req), true); -} - -static int mt7915_mcu_restart(struct mt76_dev *dev) -{ - struct { - u8 power_mode; - u8 rsv[3]; - } req = { - .power_mode = 1, - }; - - return mt76_mcu_send_msg(dev, MCU_CMD(NIC_POWER_CTRL), &req, - sizeof(req), false); -} - -static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) -{ - struct { - __le32 op; - } req = { - .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(PATCH_SEM_CONTROL), &req, - sizeof(req), true); -} - -static int mt7915_mcu_start_patch(struct mt7915_dev *dev) -{ - struct { - u8 check_crc; - u8 reserved[3]; - } req = { - .check_crc = 0, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_CMD(PATCH_FINISH_REQ), &req, - sizeof(req), true); -} - -static int mt7915_driver_own(struct mt7915_dev *dev) +static int mt7915_driver_own(struct mt7915_dev *dev, u8 band) { - mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_DRV_OWN); - if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND0, - MT_TOP_LPCR_HOST_FW_OWN, 0, 500)) { + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(band), MT_TOP_LPCR_HOST_DRV_OWN); + if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND(band), + MT_TOP_LPCR_HOST_FW_OWN_STAT, 0, 500)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } - return 0; -} - -static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, - u32 len, u32 mode) -{ - struct { - __le32 addr; - __le32 len; - __le32 mode; - } req = { - .addr = cpu_to_le32(addr), - .len = cpu_to_le32(len), - .mode = cpu_to_le32(mode), - }; - int attr; + /* clear irq when the driver own success */ + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND_IRQ_STAT(band), + MT_TOP_LPCR_HOST_BAND_STAT); - if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS)) - attr = MCU_CMD(PATCH_START_REQ); - else - attr = MCU_CMD(TARGET_ADDRESS_LEN_REQ); - - return mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); + return 0; } static int mt7915_load_patch(struct mt7915_dev *dev) @@ -2733,7 +1996,7 @@ static int mt7915_load_patch(struct mt7915_dev *dev) const struct firmware *fw = NULL; int i, ret, sem; - sem = mt7915_mcu_patch_sem_ctrl(dev, 1); + sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 1); switch (sem) { case PATCH_IS_DL: return 0; @@ -2744,7 +2007,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev) return -EAGAIN; } - ret = request_firmware(&fw, MT7915_ROM_PATCH, dev->mt76.dev); + ret = request_firmware(&fw, fw_name_var(dev, ROM_PATCH), + dev->mt76.dev); if (ret) goto out; @@ -2776,8 +2040,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev) len = be32_to_cpu(sec->info.len); dl = fw->data + be32_to_cpu(sec->offs); - ret = mt7915_mcu_init_download(dev, addr, len, - DL_MODE_NEED_RSP); + ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len, + DL_MODE_NEED_RSP); if (ret) { dev_err(dev->mt76.dev, "Download request failed\n"); goto out; @@ -2791,12 +2055,12 @@ static int mt7915_load_patch(struct mt7915_dev *dev) } } - ret = mt7915_mcu_start_patch(dev); + ret = mt76_connac_mcu_start_patch(&dev->mt76); if (ret) dev_err(dev->mt76.dev, "Failed to start patch\n"); out: - sem = mt7915_mcu_patch_sem_ctrl(dev, 0); + sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 0); switch (sem) { case PATCH_REL_SEM_SUCCESS: break; @@ -2810,20 +2074,6 @@ out: return ret; } -static u32 mt7915_mcu_gen_dl_mode(u8 feature_set, bool is_wa) -{ - u32 ret = 0; - - ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? - (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; - ret |= FIELD_PREP(DL_MODE_KEY_IDX, - FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); - ret |= DL_MODE_NEED_RSP; - ret |= is_wa ? DL_MODE_WORKING_PDA_CR4 : 0; - - return ret; -} - static int mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, const struct mt7915_fw_trailer *hdr, @@ -2839,14 +2089,16 @@ mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, region = (const struct mt7915_fw_region *)((const u8 *)hdr - (hdr->n_region - i) * sizeof(*region)); - mode = mt7915_mcu_gen_dl_mode(region->feature_set, is_wa); + mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, + region->feature_set, is_wa); len = le32_to_cpu(region->len); addr = le32_to_cpu(region->addr); if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) override = addr; - err = mt7915_mcu_init_download(dev, addr, len, mode); + err = mt76_connac_mcu_init_download(&dev->mt76, addr, len, + mode); if (err) { dev_err(dev->mt76.dev, "Download request failed\n"); return err; @@ -2868,7 +2120,7 @@ mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, if (is_wa) option |= FW_START_WORKING_PDA_CR4; - return mt7915_mcu_start_firmware(dev, override, option); + return mt76_connac_mcu_start_firmware(&dev->mt76, override, option); } static int mt7915_load_ram(struct mt7915_dev *dev) @@ -2877,7 +2129,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev) const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7915_FIRMWARE_WM, dev->mt76.dev); + ret = request_firmware(&fw, fw_name_var(dev, FIRMWARE_WM), + dev->mt76.dev); if (ret) return ret; @@ -2901,7 +2154,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev) release_firmware(fw); - ret = request_firmware(&fw, MT7915_FIRMWARE_WA, dev->mt76.dev); + ret = request_firmware(&fw, fw_name(dev, FIRMWARE_WA), + dev->mt76.dev); if (ret) return ret; @@ -2933,10 +2187,36 @@ out: return ret; } +static int +mt7915_firmware_state(struct mt7915_dev *dev, bool wa) +{ + u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, + wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD); + + if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, + state, 1000)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + return 0; +} + static int mt7915_load_firmware(struct mt7915_dev *dev) { int ret; + /* make sure fw is download state */ + if (mt7915_firmware_state(dev, false)) { + /* restart firmware once */ + __mt76_mcu_restart(&dev->mt76); + ret = mt7915_firmware_state(dev, false); + if (ret) { + dev_err(dev->mt76.dev, + "Firmware is not ready for download\n"); + return ret; + } + } + ret = mt7915_load_patch(dev); if (ret) return ret; @@ -2945,12 +2225,9 @@ static int mt7915_load_firmware(struct mt7915_dev *dev) if (ret) return ret; - if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, - FIELD_PREP(MT_TOP_MISC_FW_STATE, - FW_STATE_RDY), 1000)) { - dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); - return -EIO; - } + ret = mt7915_firmware_state(dev, true); + if (ret) + return ret; mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); @@ -3021,7 +2298,7 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) u8 band_idx; } req = { .cmd = cpu_to_le32(MURU_GET_TXC_TX_STATS), - .band_idx = phy != &dev->phy, + .band_idx = phy->band_idx, }; ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL), @@ -3110,15 +2387,29 @@ int mt7915_mcu_init(struct mt7915_dev *dev) .headroom = sizeof(struct mt7915_mcu_txd), .mcu_skb_send_msg = mt7915_mcu_send_message, .mcu_parse_response = mt7915_mcu_parse_response, - .mcu_restart = mt7915_mcu_restart, + .mcu_restart = mt76_connac_mcu_restart, }; int ret; dev->mt76.mcu_ops = &mt7915_mcu_ops; - ret = mt7915_driver_own(dev); + /* force firmware operation mode into normal state, + * which should be set before firmware download stage. + */ + if (is_mt7915(&dev->mt76)) + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + else + mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE); + + ret = mt7915_driver_own(dev, 0); if (ret) return ret; + /* set driver own for band1 when two hif exist */ + if (dev->hif2) { + ret = mt7915_driver_own(dev, 1); + if (ret) + return ret; + } ret = mt7915_load_firmware(dev); if (ret) @@ -3153,14 +2444,15 @@ int mt7915_mcu_init(struct mt7915_dev *dev) void mt7915_mcu_exit(struct mt7915_dev *dev) { __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE, - FIELD_PREP(MT_TOP_MISC_FW_STATE, - FW_STATE_FW_DOWNLOAD), 1000)) { + if (mt7915_firmware_state(dev, false)) { dev_err(dev->mt76.dev, "Failed to exit mcu\n"); return; } - mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_FW_OWN); + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN); + if (dev->hif2) + mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1), + MT_TOP_LPCR_HOST_FW_OWN); skb_queue_purge(&dev->mt76.mcu.res_q); } @@ -3238,26 +2530,6 @@ int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) sizeof(req), false); } -int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) -{ - struct mt7915_dev *dev = phy->dev; - struct { - u8 prot_idx; - u8 band; - u8 rsv[2]; - __le32 len_thresh; - __le32 pkt_thresh; - } __packed req = { - .prot_idx = 1, - .band = phy != &dev->phy, - .len_thresh = cpu_to_le32(val), - .pkt_thresh = cpu_to_le32(0x2), - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PROTECT_CTRL), &req, - sizeof(req), true); -} - int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param) { struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param; @@ -3303,58 +2575,6 @@ int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) return mt7915_mcu_update_edca(dev, &req); } -int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) -{ -#define ENTER_PM_STATE 1 -#define EXIT_PM_STATE 2 - struct { - u8 pm_number; - u8 pm_state; - u8 bssid[ETH_ALEN]; - u8 dtim_period; - u8 wlan_idx_lo; - __le16 bcn_interval; - __le32 aid; - __le32 rx_filter; - u8 band_idx; - u8 wlan_idx_hi; - u8 rsv[2]; - __le32 feature; - u8 omac_idx; - u8 wmm_idx; - u8 bcn_loss_cnt; - u8 bcn_sp_duration; - } __packed req = { - .pm_number = 5, - .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = band, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(PM_STATE_CTRL), &req, - sizeof(req), true); -} - -int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, - enum mt7915_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]; - } __packed 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 mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val) { struct { @@ -3453,12 +2673,104 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, sizeof(req), true); } +static int +mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy, + struct cfg80211_chan_def *chandef, + int cmd) +{ + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_channel *chan = mphy->chandef.chan; + int freq = mphy->chandef.center_freq1; + struct mt7915_mcu_background_chain_ctrl req = { + .monitor_scan_type = 2, /* simple rx */ + }; + + if (!chandef && cmd != CH_SWITCH_BACKGROUND_SCAN_STOP) + return -EINVAL; + + if (!cfg80211_chandef_valid(&mphy->chandef)) + return -EINVAL; + + switch (cmd) { + case CH_SWITCH_BACKGROUND_SCAN_START: { + req.chan = chan->hw_value; + req.central_chan = ieee80211_frequency_to_channel(freq); + req.bw = mt76_connac_chan_bw(&mphy->chandef); + req.monitor_chan = chandef->chan->hw_value; + req.monitor_central_chan = + ieee80211_frequency_to_channel(chandef->center_freq1); + req.monitor_bw = mt76_connac_chan_bw(chandef); + req.band_idx = phy != &dev->phy; + req.scan_mode = 1; + break; + } + case CH_SWITCH_BACKGROUND_SCAN_RUNNING: + req.monitor_chan = chandef->chan->hw_value; + req.monitor_central_chan = + ieee80211_frequency_to_channel(chandef->center_freq1); + req.band_idx = phy != &dev->phy; + req.scan_mode = 2; + break; + case CH_SWITCH_BACKGROUND_SCAN_STOP: + req.chan = chan->hw_value; + req.central_chan = ieee80211_frequency_to_channel(freq); + req.bw = mt76_connac_chan_bw(&mphy->chandef); + req.tx_stream = hweight8(mphy->antenna_mask); + req.rx_stream = mphy->antenna_mask; + break; + default: + return -EINVAL; + } + req.band = chandef ? chandef->chan->band == NL80211_BAND_5GHZ : 1; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(OFFCH_SCAN_CTRL), + &req, sizeof(req), false); +} + +int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, + struct cfg80211_chan_def *chandef) +{ + struct mt7915_dev *dev = phy->dev; + int err, region; + + if (!chandef) { /* disable offchain */ + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2, + 0, 0); + if (err) + return err; + + return mt7915_mcu_background_chain_ctrl(phy, NULL, + CH_SWITCH_BACKGROUND_SCAN_STOP); + } + + err = mt7915_mcu_background_chain_ctrl(phy, chandef, + CH_SWITCH_BACKGROUND_SCAN_START); + if (err) + return err; + + switch (dev->mt76.region) { + case NL80211_DFS_ETSI: + region = 0; + break; + case NL80211_DFS_JP: + region = 2; + break; + case NL80211_DFS_FCC: + default: + region = 1; + break; + } + + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2, + 0, region); +} + int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) { struct mt7915_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1; - bool ext_phy = phy != &dev->phy; struct { u8 control_ch; u8 center_ch; @@ -3479,10 +2791,10 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) } __packed req = { .control_ch = chandef->chan->hw_value, .center_ch = ieee80211_frequency_to_channel(freq1), - .bw = mt7915_mcu_chan_bw(chandef), + .bw = mt76_connac_chan_bw(chandef), .tx_streams_num = hweight8(phy->mt76->antenna_mask), .rx_streams = phy->mt76->antenna_mask, - .band_idx = ext_phy, + .band_idx = phy->band_idx, .channel_band = chandef->chan->band, }; @@ -3494,17 +2806,17 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) req.tx_streams_num = fls(phy->mt76->test.tx_antenna_mask); req.rx_streams = phy->mt76->test.tx_antenna_mask; - if (ext_phy) { - req.tx_streams_num = 2; - req.rx_streams >>= 2; - } + if (phy != &dev->phy) + req.rx_streams >>= dev->chainshift; } #endif - if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (cmd == MCU_EXT_CMD(SET_RX_PATH)) + req.switch_reason = CH_SWITCH_NORMAL; + else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; - else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && - chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, + NL80211_IFTYPE_AP)) req.switch_reason = CH_SWITCH_DFS; else req.switch_reason = CH_SWITCH_NORMAL; @@ -3527,7 +2839,8 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) #define PAGE_IDX_MASK GENMASK(4, 2) #define PER_PAGE_SIZE 0x400 struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER }; - u8 total = DIV_ROUND_UP(MT7915_EEPROM_SIZE, PER_PAGE_SIZE); + u16 eeprom_size = mt7915_eeprom_size(dev); + u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE); u8 *eep = (u8 *)dev->mt76.eeprom.data; int eep_len; int i; @@ -3536,8 +2849,8 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) struct sk_buff *skb; int ret; - if (i == total - 1 && !!(MT7915_EEPROM_SIZE % PER_PAGE_SIZE)) - eep_len = MT7915_EEPROM_SIZE % PER_PAGE_SIZE; + if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE)) + eep_len = eeprom_size % PER_PAGE_SIZE; else eep_len = PER_PAGE_SIZE; @@ -3770,19 +3083,26 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy) int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) { /* strict order */ - static const enum mt7915_chan_mib_offs offs[] = { - MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME + static const u32 offs[] = { + MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME, + MIB_BUSY_TIME_V2, MIB_TX_TIME_V2, MIB_RX_TIME_V2, + MIB_OBSS_AIRTIME_V2 }; struct mt76_channel_state *state = phy->mt76->chan_state; struct mt76_channel_state *state_ts = &phy->state_ts; struct mt7915_dev *dev = phy->dev; struct mt7915_mcu_mib *res, req[4]; struct sk_buff *skb; - int i, ret; + int i, ret, start = 0, ofs = 20; + + if (!is_mt7915(&dev->mt76)) { + start = 4; + ofs = 0; + } for (i = 0; i < 4; i++) { req[i].band = cpu_to_le32(phy != &dev->phy); - req[i].offs = cpu_to_le32(offs[i]); + req[i].offs = cpu_to_le32(offs[i + start]); } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO), @@ -3790,7 +3110,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) if (ret) return ret; - res = (struct mt7915_mcu_mib *)(skb->data + 20); + res = (struct mt7915_mcu_mib *)(skb->data + ofs); if (chan_switch) goto out; @@ -3842,7 +3162,7 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state) u8 rsv[2]; } __packed req = { .ctrl = { - .band_idx = phy != &dev->phy, + .band_idx = phy->band_idx, }, }; int level; @@ -4210,11 +3530,13 @@ int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vi struct sk_buff *skb; struct tlv *tlv; - skb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + NULL, len); if (IS_ERR(skb)) return PTR_ERR(skb); - tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR, sizeof(*bss_color)); + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR, + sizeof(*bss_color)); bss_color = (struct bss_info_color *)tlv; bss_color->disable = !he_bss_color->enabled; bss_color->color = he_bss_color->color; |