diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7996/mcu.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 182 |
1 files changed, 143 insertions, 39 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 88e2f9d0e513..4a30db49ef33 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) return; - mphy = dev->mt76.phys[r->band_idx]; + if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2) + mphy = dev->rdd2_phy->mt76; + else + mphy = dev->mt76.phys[r->band_idx]; + if (!mphy) return; @@ -600,7 +604,7 @@ static void mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7996_phy *phy) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct bss_rate_tlv *bmc; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; @@ -701,6 +705,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, sizeof(req), true); } +static void +mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mvif->phy; + struct bss_ifs_time_tlv *ifs_time; + struct tlv *tlv; + bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time)); + + ifs_time = (struct bss_ifs_time_tlv *)tlv; + ifs_time->slot_valid = true; + ifs_time->sifs_valid = true; + ifs_time->rifs_valid = true; + ifs_time->eifs_valid = true; + + ifs_time->slot_time = cpu_to_le16(phy->slottime); + ifs_time->sifs_time = cpu_to_le16(10); + ifs_time->rifs_time = cpu_to_le16(2); + ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84); + + if (is_2ghz) { + ifs_time->eifs_cck_valid = true; + ifs_time->eifs_cck_time = cpu_to_le16(314); + } +} + static int mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, @@ -712,6 +744,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct cfg80211_chan_def *chandef = &phy->chandef; struct mt76_connac_bss_basic_tlv *bss; u32 type = CONNECTION_INFRA_AP; + u16 sta_wlan_idx = wlan_idx; struct tlv *tlv; int idx; @@ -731,7 +764,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct mt76_wcid *wcid; wcid = (struct mt76_wcid *)sta->drv_priv; - wlan_idx = wcid->idx; + sta_wlan_idx = wcid->idx; } rcu_read_unlock(); } @@ -751,7 +784,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); bss->dtim_period = vif->bss_conf.dtim_period; bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); - bss->sta_idx = cpu_to_le16(wlan_idx); + bss->sta_idx = cpu_to_le16(sta_wlan_idx); bss->conn_type = cpu_to_le32(type); bss->omac_idx = mvif->omac_idx; bss->band_idx = mvif->band_idx; @@ -825,6 +858,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, mt7996_mcu_bss_bmc_tlv(skb, vif, phy); mt7996_mcu_bss_ra_tlv(skb, vif, phy); mt7996_mcu_bss_txcmd_tlv(skb, true); + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); if (vif->bss_conf.he_support) mt7996_mcu_bss_he_tlv(skb, vif, phy); @@ -837,6 +871,23 @@ out: MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_dev *dev = phy->dev; + struct sk_buff *skb; + + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + MT7996_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); +} + static int mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, @@ -1050,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, } } +static void +mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct sta_rec_muru *muru; + struct tlv *tlv; + + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); + + muru = (struct sta_rec_muru *)tlv; + muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer || + vif->bss_conf.he_mu_beamformer || + vif->bss_conf.vht_mu_beamformer || + vif->bss_conf.vht_mu_beamformee; + muru->cfg.ofdma_dl_en = true; + + if (sta->deflink.vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + + if (!sta->deflink.he_cap.has_he) + return; + + muru->mimo_dl.partial_bw_dl_mimo = + HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]); + + 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->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 = + HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]); + muru->ofdma_dl.he_20m_in_160m = + HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + muru->ofdma_dl.he_80m_in_160m = + HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + + muru->ofdma_ul.t_frame_dur = + HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]); + muru->ofdma_ul.mu_cascading = + 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]); +} + static inline bool mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) @@ -1727,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, mt7996_mcu_sta_he_6g_tlv(skb, sta); /* starec eht */ mt7996_mcu_sta_eht_tlv(skb, sta); - /* TODO: starec muru */ + /* starec muru */ + mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta); /* starec bfee */ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta); /* starec hdr trans */ @@ -2155,7 +2260,7 @@ out: static int mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, const struct mt7996_fw_trailer *hdr, - const u8 *data, bool is_wa) + const u8 *data, enum mt7996_ram_type type) { int i, offset = 0; u32 override = 0, option = 0; @@ -2167,8 +2272,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, region = (const struct mt7996_fw_region *)((const u8 *)hdr - (hdr->n_region - i) * sizeof(*region)); + /* DSP and WA use same mode */ mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, - region->feature_set, is_wa); + region->feature_set, + type != MT7996_RAM_TYPE_WM); len = le32_to_cpu(region->len); addr = le32_to_cpu(region->addr); @@ -2195,19 +2302,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, if (override) option |= FW_START_OVERRIDE; - if (is_wa) + if (type == MT7996_RAM_TYPE_WA) option |= FW_START_WORKING_PDA_CR4; + else if (type == MT7996_RAM_TYPE_DSP) + option |= FW_START_WORKING_PDA_DSP; return mt76_connac_mcu_start_firmware(&dev->mt76, override, option); } -static int mt7996_load_ram(struct mt7996_dev *dev) +static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type, + const char *fw_file, enum mt7996_ram_type ram_type) { const struct mt7996_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev); + ret = request_firmware(&fw, fw_file, dev->mt76.dev); if (ret) return ret; @@ -2217,37 +2327,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev) goto out; } - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n", + fw_type, hdr->fw_ver, hdr->build_date); - dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false); + ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type); if (ret) { - dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); - goto out; - } - - release_firmware(fw); - - ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WA firmware\n"); + dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type); goto out; } @@ -2261,6 +2347,24 @@ out: return ret; } +static int mt7996_load_ram(struct mt7996_dev *dev) +{ + int ret; + + ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM, + MT7996_RAM_TYPE_WM); + if (ret) + return ret; + + ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP, + MT7996_RAM_TYPE_DSP); + if (ret) + return ret; + + return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA, + MT7996_RAM_TYPE_WA); +} + static int mt7996_firmware_state(struct mt7996_dev *dev, bool wa) { |