diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:35:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 17:39:31 +0000 |
commit | 85c675d0d09a45a135bddd15d7b385f8758c32fb (patch) | |
tree | 76267dbc9b9a130337be3640948fe397b04ac629 /drivers/net/wireless/mediatek/mt76/mt7996 | |
parent | Adding upstream version 6.6.15. (diff) | |
download | linux-85c675d0d09a45a135bddd15d7b385f8758c32fb.tar.xz linux-85c675d0d09a45a135bddd15d7b385f8758c32fb.zip |
Adding upstream version 6.7.7.upstream/6.7.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7996')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/init.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 99 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/main.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 292 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 26 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/pci.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/regs.h | 8 |
8 files changed, 447 insertions, 79 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 66d8cc0eea..55cb1770fa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -54,23 +54,31 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev, dev = container_of(mphy->dev, struct mt7996_dev, mt76); /* select TX blink mode, 2: only data frames */ - mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2); + mt76_rmw_field(dev, MT_TMAC_TCR0(mphy->band_idx), MT_TMAC_TCR0_TX_BLINK, 2); /* enable LED */ - mt76_wr(dev, MT_LED_EN(0), 1); + mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1); /* set LED Tx blink on/off time */ val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) | FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off); - mt76_wr(dev, MT_LED_TX_BLINK(0), val); + mt76_wr(dev, MT_LED_TX_BLINK(mphy->band_idx), val); + + /* turn LED off */ + if (delay_off == 0xff && delay_on == 0x0) { + val = MT_LED_CTRL_POLARITY | MT_LED_CTRL_KICK; + } else { + /* control LED */ + val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK; + if (mphy->band_idx == MT_BAND1) + val |= MT_LED_CTRL_BLINK_BAND_SEL; + } - /* control LED */ - val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK; if (mphy->leds.al) val |= MT_LED_CTRL_POLARITY; - mt76_wr(dev, MT_LED_CTRL(0), val); - mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK); + mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val); + mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK); } static int mt7996_led_set_blink(struct led_classdev *led_cdev, @@ -173,6 +181,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7996_regd_notifier; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy->mbssid_max_interfaces = 16; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); @@ -196,6 +205,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); hw->max_tx_fragments = 4; @@ -223,6 +233,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); } + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness; + phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink; + } + mt76_set_stream_caps(phy->mt76, true); mt7996_set_stream_vht_txbf_caps(phy); mt7996_set_stream_he_eht_caps(phy); @@ -258,6 +274,11 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band) set = FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_MODE, 0) | FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_PARAM, 0x3); mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set); + + /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than + * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. + */ + mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H); } static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev) @@ -828,8 +849,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy, n++; } - sband->iftype_data = data; - sband->n_iftype_data = n; + _ieee80211_set_sband_iftype_data(sband, data, n); } void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy) @@ -871,12 +891,6 @@ int mt7996_register_device(struct mt7996_dev *dev) mt7996_init_wiphy(hw); - /* init led callbacks */ - if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness; - dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink; - } - ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 26d5675202..fa3001e59a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -950,15 +950,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (!wcid) wcid = &dev->mt76.global_wcid; - if (sta) { - struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - - if (time_after(jiffies, msta->jiffies + HZ / 4)) { - info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - msta->jiffies = jiffies; - } - } - t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; @@ -1006,22 +997,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, } static void -mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb) { struct mt7996_sta *msta; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; u16 fc, tid; - u32 val; if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) return; - tid = le32_get_bits(txwi[1], MT_TXD1_TID); + tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; if (tid >= 6) /* skip VO queue */ return; - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; + if (is_8023) { + fc = IEEE80211_FTYPE_DATA | + (sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA); + } else { + /* No need to get precise TID for Action/Management Frame, + * since it will not meet the following Frame Control + * condition anyway. + */ + + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + fc = le16_to_cpu(hdr->frame_control) & + (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); + } + if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) return; @@ -1049,7 +1053,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, wcid_idx = wcid->idx; if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7996_tx_check_aggr(sta, txwi); + mt7996_tx_check_aggr(sta, t->skb); } else { wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX); } @@ -1070,6 +1074,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) struct mt76_phy *phy3 = mdev->phys[MT_BAND2]; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + struct mt76_wcid *wcid = NULL; LIST_HEAD(free_list); struct sk_buff *skb, *tmp; void *end = data + len; @@ -1088,7 +1093,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false); } - if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4)) + if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5)) return; total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); @@ -1104,7 +1109,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) info = le32_to_cpu(*cur_info); if (info & MT_TXFREE_INFO_PAIR) { struct mt7996_sta *msta; - struct mt76_wcid *wcid; u16 idx; idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); @@ -1120,10 +1124,21 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) &mdev->sta_poll_list); spin_unlock_bh(&mdev->sta_poll_lock); continue; - } + } else if (info & MT_TXFREE_INFO_HEADER) { + u32 tx_retries = 0, tx_failed = 0; - if (info & MT_TXFREE_INFO_HEADER) + if (!wcid) + continue; + + tx_retries = + FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1; + tx_failed = tx_retries + + !!FIELD_GET(MT_TXFREE_INFO_STAT, info); + + wcid->stats.tx_retries += tx_retries; + wcid->stats.tx_failed += tx_failed; continue; + } for (i = 0; i < 2; i++) { msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID; @@ -1167,22 +1182,31 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, bool cck = false; u32 txrate, txs, mode, stbc; + txs = le32_to_cpu(txs_data[0]); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); - if (!skb) - goto out_no_skb; - txs = le32_to_cpu(txs_data[0]); + if (skb) { + info = IEEE80211_SKB_CB(skb); + if (!(txs & MT_TXS0_ACK_ERROR_MASK)) + info->flags |= IEEE80211_TX_STAT_ACK; - info = IEEE80211_SKB_CB(skb); - if (!(txs & MT_TXS0_ACK_ERROR_MASK)) - info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ampdu_len = 1; + info->status.ampdu_ack_len = + !!(info->flags & IEEE80211_TX_STAT_ACK); + + info->status.rates[0].idx = -1; + } - info->status.ampdu_len = 1; - info->status.ampdu_ack_len = !!(info->flags & - IEEE80211_TX_STAT_ACK); + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wcid->sta) { + struct ieee80211_sta *sta; + u8 tid; - info->status.rates[0].idx = -1; + sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); + tid = FIELD_GET(MT_TXS0_TID, txs); + ieee80211_refresh_tx_agg_session_timer(sta, tid); + } txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); @@ -1282,9 +1306,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, wcid->rate = rate; out: - mt76_tx_status_skb_done(mdev, skb, &list); - -out_no_skb: + if (skb) + mt76_tx_status_skb_done(mdev, skb, &list); mt76_tx_status_unlock(mdev, &list); return !!skb; @@ -1298,13 +1321,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) u16 wcidx; u8 pid; - if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) - return; - wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); pid = le32_get_bits(txs_data[3], MT_TXS3_PID); - if (pid < MT_PACKET_ID_FIRST) + if (pid < MT_PACKET_ID_NO_SKB) return; if (wcidx >= mt7996_wtbl_size(dev)) @@ -2191,6 +2211,11 @@ void mt7996_mac_work(struct work_struct *work) mphy->mac_work_count = 0; mt7996_mac_update_stats(phy); + + if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT); + mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT); + } } mutex_unlock(&mphy->dev->mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 620880e560..09c7a28a3d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -207,7 +207,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, mvif->sta.wcid.phy_idx = band_idx; mvif->sta.wcid.hw_key_idx = -1; mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; - mt76_packet_id_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid); mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -248,8 +248,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, struct mt7996_phy *phy = mt7996_hw_phy(hw); int idx = msta->wcid.idx; - mt7996_mcu_add_bss_info(phy, vif, false); mt7996_mcu_add_sta(dev, vif, NULL, false); + mt7996_mcu_add_bss_info(phy, vif, false); if (vif == phy->monitor_vif) phy->monitor_vif = NULL; @@ -268,7 +268,7 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, list_del_init(&msta->wcid.poll_list); spin_unlock_bh(&dev->mt76.sta_poll_lock); - mt76_packet_id_flush(&dev->mt76, &msta->wcid); + mt76_wcid_cleanup(&dev->mt76, &msta->wcid); } int mt7996_set_channel(struct mt7996_phy *phy) @@ -570,17 +570,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, /* station mode uses BSSID to map the wlan entry to a peer, * and then peer references bss_info_rfch to set bandwidth cap. */ - if (changed & BSS_CHANGED_BSSID && - vif->type == NL80211_IFTYPE_STATION) { - bool join = !is_zero_ether_addr(info->bssid); - - mt7996_mcu_add_bss_info(phy, vif, join); - mt7996_mcu_add_sta(dev, vif, NULL, join); + if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) || + (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) || + (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) { + mt7996_mcu_add_bss_info(phy, vif, true); + mt7996_mcu_add_sta(dev, vif, NULL, true); } - if (changed & BSS_CHANGED_ASSOC) - mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc); - if (changed & BSS_CHANGED_ERP_CTS_PROT) mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot); @@ -601,11 +597,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, mvif->basic_rates_idx = mt7996_get_rates_table(hw, vif, false, false); - if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { - mt7996_mcu_add_bss_info(phy, vif, true); - mt7996_mcu_add_sta(dev, vif, NULL, true); - } - /* ensure that enable txcmd_mode after bss_info */ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7996_mcu_set_tx(dev, vif); @@ -666,7 +657,6 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->wcid.idx = idx; msta->wcid.phy_idx = band_idx; msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; - msta->jiffies = jiffies; ewma_avg_signal_init(&msta->avg_ack_signal); @@ -978,6 +968,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { + struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct rate_info *txrate = &msta->wcid.rate; @@ -998,11 +989,31 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + sinfo->ack_signal = (s8)msta->ack_signal; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); + + if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + sinfo->tx_bytes = msta->wcid.stats.tx_bytes; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); + + sinfo->rx_bytes = msta->wcid.stats.rx_bytes; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); + + sinfo->tx_packets = msta->wcid.stats.tx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + + sinfo->rx_packets = msta->wcid.stats.rx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); + } } static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 7575d3506e..bf917beb94 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, @@ -2036,6 +2296,9 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, 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_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) @@ -2065,7 +2328,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, 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); out: dev_kfree_skb(skb); @@ -3801,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); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index dc8d0a30c7..9300cd8eeb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -153,6 +153,32 @@ struct mt7996_mcu_mib { __le64 data; } __packed; +struct mt7996_mcu_all_sta_info_event { + u8 rsv[4]; + __le16 tag; + __le16 len; + u8 more; + u8 rsv2; + __le16 sta_num; + u8 rsv3[4]; + + union { + struct { + __le16 wlan_idx; + u8 rsv[2]; + __le32 tx_bytes[IEEE80211_NUM_ACS]; + __le32 rx_bytes[IEEE80211_NUM_ACS]; + } adm_stat[0] __packed; + + struct { + __le16 wlan_idx; + u8 rsv[2]; + __le32 tx_msdu_cnt; + __le32 rx_msdu_cnt; + } msdu_cnt[0] __packed; + } __packed; +} __packed; + enum mt7996_chan_mib_offs { UNI_MIB_OBSS_AIRTIME = 26, UNI_MIB_NON_WIFI_TIME = 27, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 7354e5cf8e..e53cf6a370 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -110,7 +110,6 @@ struct mt7996_sta { struct ewma_avg_signal avg_ack_signal; unsigned long changed; - unsigned long jiffies; struct mt76_connac_sta_key_conf bip; @@ -402,6 +401,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level); int mt7996_mcu_trigger_assert(struct mt7996_dev *dev); void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb); void mt7996_mcu_exit(struct mt7996_dev *dev); +int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag); static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c index c5301050ff..67c0158962 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -17,11 +17,13 @@ static u32 hif_idx; static const struct pci_device_id mt7996_pci_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) }, { }, }; static const struct pci_device_id mt7996_hif_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) }, { }, }; @@ -60,7 +62,9 @@ static void mt7996_put_hif2(struct mt7996_hif *hif) static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev) { hif_idx++; - if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL)) + + if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) && + !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL)) return NULL; writel(hif_idx | MT_PCIE_RECOG_ID_SEM, @@ -113,7 +117,7 @@ static int mt7996_pci_probe(struct pci_dev *pdev, mt76_pci_disable_aspm(pdev); - if (id->device == 0x7991) + if (id->device == 0x7991 || id->device == 0x799a) return mt7996_pci_hif2_probe(pdev); dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 97beab9245..0086a78666 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -243,6 +243,13 @@ enum base_rev { FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) +/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */ +#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band)) +#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) + +#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, 0x3c) +#define MT_AGG_ACR_PPDU_TXS2H BIT(1) + /* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */ #define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band)) #define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) @@ -509,6 +516,7 @@ enum base_rev { #define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4)) #define MT_LED_CTRL_KICK BIT(7) +#define MT_LED_CTRL_BLINK_BAND_SEL BIT(4) #define MT_LED_CTRL_BLINK_MODE BIT(2) #define MT_LED_CTRL_POLARITY BIT(1) |