diff options
author | Jakub Kicinski <kuba@kernel.org> | 2023-10-17 16:52:53 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-10-17 16:52:54 -0700 |
commit | 56a7bb12c78ffa1b02e154b1d779ed2a1555fa3c (patch) | |
tree | 4a1236780c8a32834546ebd0dc34f5658ac558a4 /drivers | |
parent | 7713ec844756a9883ba9a91381369256275de4fb (diff) | |
parent | b650981501bf00bc84f09cf3b3e0b6190cfed794 (diff) |
Merge tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says:
====================
wireless-next patches for v6.7
The second pull request for v6.7, with only driver changes this time.
We have now support for mt7925 PCIe and USB variants, few new features
and of course some fixes.
Major changes:
mt76
- mt7925 support
ath12k
- read board data variant name from SMBIOS
wfx
- Remain-On-Channel (ROC) support
* tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (109 commits)
wifi: rtw89: mac: do bf_monitor only if WiFi 6 chips
wifi: rtw89: mac: set bf_assoc capabilities according to chip gen
wifi: rtw89: mac: set bfee_ctrl() according to chip gen
wifi: rtw89: mac: add registers of MU-EDCA parameters for WiFi 7 chips
wifi: rtw89: mac: generalize register of MU-EDCA switch according to chip gen
wifi: rtw89: mac: update RTS threshold according to chip gen
wifi: rtlwifi: simplify TX command fill callbacks
wifi: hostap: remove unused ioctl function
wifi: atmel: remove unused ioctl function
wifi: rtw89: coex: add annotation __counted_by() to struct rtw89_btc_btf_set_mon_reg
wifi: rtw89: coex: add annotation __counted_by() for struct rtw89_btc_btf_set_slot_table
wifi: rtw89: add EHT radiotap in monitor mode
wifi: rtw89: show EHT rate in debugfs
wifi: rtw89: parse TX EHT rate selected by firmware from RA C2H report
wifi: rtw89: Add EHT rate mask as parameters of RA H2C command
wifi: rtw89: parse EHT information from RX descriptor and PPDU status packet
wifi: radiotap: add bandwidth definition of EHT U-SIG
wifi: rtlwifi: use convenient list_count_nodes()
wifi: p54: Annotate struct p54_cal_database with __counted_by
wifi: brcmfmac: fweh: Add __counted_by for struct brcmf_fweh_queue_item and use struct_size()
...
====================
Link: https://lore.kernel.org/r/20231016143822.880D8C433C8@smtp.kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
152 files changed, 12722 insertions, 2288 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index fe89bc61e531..ad9cf953a2fc 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1964,20 +1964,13 @@ static ssize_t ath10k_write_btcoex(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - char buf[32]; - size_t buf_size; - int ret; + ssize_t ret; bool val; u32 pdev_param; - buf_size = min(count, (sizeof(buf) - 1)); - if (copy_from_user(buf, ubuf, buf_size)) - return -EFAULT; - - buf[buf_size] = '\0'; - - if (kstrtobool(buf, &val) != 0) - return -EINVAL; + ret = kstrtobool_from_user(ubuf, count, &val); + if (ret) + return ret; if (!ar->coex_support) return -EOPNOTSUPP; @@ -2000,7 +1993,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, ar->running_fw->fw_file.fw_features)) { ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val); if (ret) { - ath10k_warn(ar, "failed to enable btcoex: %d\n", ret); + ath10k_warn(ar, "failed to enable btcoex: %zd\n", ret); ret = count; goto exit; } @@ -2103,19 +2096,12 @@ static ssize_t ath10k_write_peer_stats(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - char buf[32]; - size_t buf_size; - int ret; + ssize_t ret; bool val; - buf_size = min(count, (sizeof(buf) - 1)); - if (copy_from_user(buf, ubuf, buf_size)) - return -EFAULT; - - buf[buf_size] = '\0'; - - if (kstrtobool(buf, &val) != 0) - return -EINVAL; + ret = kstrtobool_from_user(ubuf, count, &val); + if (ret) + return ret; mutex_lock(&ar->conf_mutex); @@ -2239,21 +2225,16 @@ static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - char buf[32]; - ssize_t len; + ssize_t ret; u32 mask; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoint(buf, 0, &mask)) - return -EINVAL; + ret = kstrtoint_from_user(user_buf, count, 0, &mask); + if (ret) + return ret; ar->sta_tid_stats_mask = mask; - return len; + return count; } static const struct file_operations fops_sta_tid_stats_mask = { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 03e7bc5b6c0b..2cf693f3fea9 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -728,20 +728,13 @@ static int ath10k_peer_create(struct ath10k *ar, const u8 *addr, enum wmi_peer_type peer_type) { - struct ath10k_vif *arvif; struct ath10k_peer *peer; - int num_peers = 0; int ret; lockdep_assert_held(&ar->conf_mutex); - num_peers = ar->num_peers; - - /* Each vdev consumes a peer entry as well */ - list_for_each_entry(arvif, &ar->arvifs, list) - num_peers++; - - if (num_peers >= ar->max_num_peers) + /* Each vdev consumes a peer entry as well. */ + if (ar->num_peers + list_count_nodes(&ar->arvifs) >= ar->max_num_peers) return -ENOBUFS; ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type); @@ -4503,18 +4496,21 @@ void __ath10k_scan_finish(struct ath10k *ar) break; case ATH10K_SCAN_RUNNING: case ATH10K_SCAN_ABORTING: + if (ar->scan.is_roc && ar->scan.roc_notify) + ieee80211_remain_on_channel_expired(ar->hw); + fallthrough; + case ATH10K_SCAN_STARTING: if (!ar->scan.is_roc) { struct cfg80211_scan_info info = { - .aborted = (ar->scan.state == - ATH10K_SCAN_ABORTING), + .aborted = ((ar->scan.state == + ATH10K_SCAN_ABORTING) || + (ar->scan.state == + ATH10K_SCAN_STARTING)), }; ieee80211_scan_completed(ar->hw, &info); - } else if (ar->scan.roc_notify) { - ieee80211_remain_on_channel_expired(ar->hw); } - fallthrough; - case ATH10K_SCAN_STARTING: + ar->scan.state = ATH10K_SCAN_IDLE; ar->scan_channel = NULL; ar->scan.roc_freq = 0; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 26214c00cd0d..2c39bad7ebfb 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -828,12 +828,20 @@ static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar, static inline void ath10k_snoc_irq_disable(struct ath10k *ar) { - ath10k_ce_disable_interrupts(ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int id; + + for (id = 0; id < CE_COUNT_MAX; id++) + disable_irq(ar_snoc->ce_irqs[id].irq_line); } static inline void ath10k_snoc_irq_enable(struct ath10k *ar) { - ath10k_ce_enable_interrupts(ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int id; + + for (id = 0; id < CE_COUNT_MAX; id++) + enable_irq(ar_snoc->ce_irqs[id].irq_line); } static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe) @@ -1090,6 +1098,8 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar, goto err_free_rri; } + ath10k_ce_enable_interrupts(ar); + return 0; err_free_rri: @@ -1253,8 +1263,8 @@ static int ath10k_snoc_request_irq(struct ath10k *ar) for (id = 0; id < CE_COUNT_MAX; id++) { ret = request_irq(ar_snoc->ce_irqs[id].irq_line, - ath10k_snoc_per_engine_handler, 0, - ce_name[id], ar); + ath10k_snoc_per_engine_handler, + IRQF_NO_AUTOEN, ce_name[id], ar); if (ret) { ath10k_err(ar, "failed to register IRQ handler for CE %d: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 68254a967ccb..2240994390ed 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -384,16 +384,11 @@ static ssize_t write_file_spectral_count(struct file *file, { struct ath10k *ar = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val > 255) return -EINVAL; @@ -440,16 +435,11 @@ static ssize_t write_file_spectral_bins(struct file *file, { struct ath10k *ar = file->private_data; unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + ssize_t ret; - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; + ret = kstrtoul_from_user(user_buf, count, 0, &val); + if (ret) + return ret; if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS) return -EINVAL; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 20b04723daec..a36208a0aab5 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5,6 +5,7 @@ */ #include <net/mac80211.h> +#include <net/cfg80211.h> #include <linux/etherdevice.h> #include <linux/bitfield.h> #include <linux/inetdevice.h> @@ -7196,6 +7197,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, struct wmi_vdev_start_req_arg arg = {}; const struct cfg80211_chan_def *chandef = &ctx->def; int ret = 0; + unsigned int dfs_cac_time; lockdep_assert_held(&ar->conf_mutex); @@ -7275,20 +7277,21 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM started, vdev_id %d\n", arvif->vif->addr, arvif->vdev_id); - /* Enable CAC Flag in the driver by checking the channel DFS cac time, - * i.e dfs_cac_ms value which will be valid only for radar channels - * and state as NL80211_DFS_USABLE which indicates CAC needs to be + /* Enable CAC Flag in the driver by checking the all sub-channel's DFS + * state as NL80211_DFS_USABLE which indicates CAC needs to be * done before channel usage. This flags is used to drop rx packets. * during CAC. */ /* TODO Set the flag for other interface types as required */ - if (arvif->vdev_type == WMI_VDEV_TYPE_AP && - chandef->chan->dfs_cac_ms && - chandef->chan->dfs_state == NL80211_DFS_USABLE) { + if (arvif->vdev_type == WMI_VDEV_TYPE_AP && ctx->radar_enabled && + cfg80211_chandef_dfs_usable(ar->hw->wiphy, chandef)) { set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags); + dfs_cac_time = cfg80211_chandef_dfs_cac_time(ar->hw->wiphy, + chandef); ath11k_dbg(ab, ATH11K_DBG_MAC, - "CAC Started in chan_freq %d for vdev %d\n", - arg.channel.freq, arg.vdev_id); + "cac started dfs_cac_time %u center_freq %d center_freq1 %d for vdev %d\n", + dfs_cac_time, arg.channel.freq, chandef->center_freq1, + arg.vdev_id); } ret = ath11k_mac_set_txbf_conf(arvif); @@ -9057,6 +9060,14 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, if (ar->state != ATH11K_STATE_ON) goto err_fallback; + /* Firmware doesn't provide Tx power during CAC hence no need to fetch + * the stats. + */ + if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) { + mutex_unlock(&ar->conf_mutex); + return -EAGAIN; + } + req_param.pdev_id = ar->pdev->pdev_id; req_param.stats_id = WMI_REQUEST_PDEV_STAT; diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 9a9a471ff130..c68750cb3c4d 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -398,6 +398,75 @@ static void ath12k_core_stop(struct ath12k_base *ab) /* De-Init of components as needed */ } +static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data) +{ + struct ath12k_base *ab = data; + const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC; + struct ath12k_smbios_bdf *smbios = (struct ath12k_smbios_bdf *)hdr; + ssize_t copied; + size_t len; + int i; + + if (ab->qmi.target.bdf_ext[0] != '\0') + return; + + if (hdr->type != ATH12K_SMBIOS_BDF_EXT_TYPE) + return; + + if (hdr->length != ATH12K_SMBIOS_BDF_EXT_LENGTH) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "wrong smbios bdf ext type length (%d).\n", + hdr->length); + return; + } + + if (!smbios->bdf_enabled) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n"); + return; + } + + /* Only one string exists (per spec) */ + if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "bdf variant magic does not match.\n"); + return; + } + + len = min_t(size_t, + strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext)); + for (i = 0; i < len; i++) { + if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "bdf variant name contains non ascii chars.\n"); + return; + } + } + + /* Copy extension name without magic prefix */ + copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic), + sizeof(ab->qmi.target.bdf_ext)); + if (copied < 0) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "bdf variant string is longer than the buffer can accommodate\n"); + return; + } + + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "found and validated bdf variant smbios_type 0x%x bdf %s\n", + ATH12K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext); +} + +int ath12k_core_check_smbios(struct ath12k_base *ab) +{ + ab->qmi.target.bdf_ext[0] = '\0'; + dmi_walk(ath12k_core_check_bdfext, ab); + + if (ab->qmi.target.bdf_ext[0] == '\0') + return -ENODATA; + + return 0; +} + static int ath12k_core_soc_create(struct ath12k_base *ab) { int ret; diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 3f5f0471f640..254eb42a85c5 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -11,6 +11,8 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/bitfield.h> +#include <linux/dmi.h> +#include <linux/ctype.h> #include "qmi.h" #include "htc.h" #include "wmi.h" @@ -32,6 +34,15 @@ /* Pending management packets threshold for dropping probe responses */ #define ATH12K_PRB_RSP_DROP_THRESHOLD ((ATH12K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4) +/* SMBIOS type containing Board Data File Name Extension */ +#define ATH12K_SMBIOS_BDF_EXT_TYPE 0xF8 + +/* SMBIOS type structure length (excluding strings-set) */ +#define ATH12K_SMBIOS_BDF_EXT_LENGTH 0x9 + +/* The magic used by QCA spec */ +#define ATH12K_SMBIOS_BDF_EXT_MAGIC "BDF_" + #define ATH12K_INVALID_HW_MAC_ID 0xFF #define ATH12K_RX_RATE_TABLE_NUM 320 #define ATH12K_RX_RATE_TABLE_11AX_NUM 576 @@ -129,6 +140,13 @@ struct ath12k_ext_irq_grp { struct net_device napi_ndev; }; +struct ath12k_smbios_bdf { + struct dmi_header hdr; + u32 padding; + u8 bdf_enabled; + u8 bdf_ext[]; +} __packed; + #define HEHANDLE_CAP_PHYINFO_SIZE 3 #define HECAP_PHYINFO_SIZE 9 #define HECAP_MACINFO_SIZE 5 @@ -792,7 +810,8 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab, int ath12k_core_fetch_bdf(struct ath12k_base *ath12k, struct ath12k_board_data *bd); void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd); - +int ath12k_core_check_dt(struct ath12k_base *ath12k); +int ath12k_core_check_smbios(struct ath12k_base *ab); void ath12k_core_halt(struct ath12k *ar); int ath12k_core_resume(struct ath12k_base *ab); int ath12k_core_suspend(struct ath12k_base *ab); diff --git a/drivers/net/wireless/ath/ath12k/debug.c b/drivers/net/wireless/ath/ath12k/debug.c index 67893923e010..45d33279e665 100644 --- a/drivers/net/wireless/ath/ath12k/debug.c +++ b/drivers/net/wireless/ath/ath12k/debug.c @@ -64,7 +64,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask, vaf.va = &args; if (ath12k_debug_mask & mask) - dev_dbg(ab->dev, "%pV", &vaf); + dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf); /* TODO: trace log */ diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 39ef3c0d2e65..54e0a09bf8dd 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -3526,23 +3526,13 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list) { struct ath12k_base *ab = ar->ab; - u16 msdu_len, peer_id; + u16 msdu_len; struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data; u8 l3pad_bytes; struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu); u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz; msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc); - peer_id = ath12k_dp_rx_h_peer_id(ab, desc); - - spin_lock(&ab->base_lock); - if (!ath12k_peer_find_by_id(ab, peer_id)) { - spin_unlock(&ab->base_lock); - ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n", - peer_id); - return -EINVAL; - } - spin_unlock(&ab->base_lock); if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) { /* First buffer will be freed by the caller, so deduct it's length */ diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index d4a2f82612b6..c092451f8580 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4554,7 +4554,8 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg * } } -static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap, +static void ath12k_mac_copy_eht_cap(struct ath12k *ar, + struct ath12k_band_cap *band_cap, struct ieee80211_he_cap_elem *he_cap_elem, int iftype, struct ieee80211_sta_eht_cap *eht_cap) @@ -4562,6 +4563,10 @@ static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap, struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem; memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap)); + + if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map))) + return; + eht_cap->has_eht = true; memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info, sizeof(eht_cap_elem->mac_cap_info)); @@ -4627,7 +4632,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar, data[idx].he_6ghz_capa.capa = ath12k_mac_setup_he_6ghz_cap(cap, band_cap); } - ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i, + ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i, &data[idx].eht_cap); idx++; } @@ -5847,6 +5852,59 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw, mutex_unlock(&ar->conf_mutex); } +static enum wmi_phy_mode +ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar, + enum wmi_phy_mode mode, + enum nl80211_band band, + enum nl80211_iftype type) +{ + struct ieee80211_sta_eht_cap *eht_cap; + enum wmi_phy_mode down_mode; + + if (mode < MODE_11BE_EHT20) + return mode; + + eht_cap = &ar->mac.iftype[band][type].eht_cap; + if (eht_cap->has_eht) + return mode; + + switch (mode) { + case MODE_11BE_EHT20: + down_mode = MODE_11AX_HE20; + break; + case MODE_11BE_EHT40: + down_mode = MODE_11AX_HE40; + break; + case MODE_11BE_EHT80: + down_mode = MODE_11AX_HE80; + break; + case MODE_11BE_EHT80_80: + down_mode = MODE_11AX_HE80_80; + break; + case MODE_11BE_EHT160: + case MODE_11BE_EHT160_160: + case MODE_11BE_EHT320: + down_mode = MODE_11AX_HE160; + break; + case MODE_11BE_EHT20_2G: + down_mode = MODE_11AX_HE20_2G; + break; + case MODE_11BE_EHT40_2G: + down_mode = MODE_11AX_HE40_2G; + break; + default: + down_mode = mode; + break; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "mac vdev start phymode %s downgrade to %s\n", + ath12k_mac_phymode_str(mode), + ath12k_mac_phymode_str(down_mode)); + + return down_mode; +} + static int ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, struct ieee80211_chanctx_conf *ctx, @@ -5873,6 +5931,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif, arg.band_center_freq2 = chandef->center_freq2; arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width]; + arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode, + chandef->chan->band, + arvif->vif->type); arg.min_power = 0; arg.max_power = chandef->chan->max_power * 2; arg.max_reg_power = chandef->chan->max_reg_power * 2; diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c index 42f1140baa4f..f83d3e09ae36 100644 --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c @@ -370,8 +370,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) ret = ath12k_mhi_get_msi(ab_pci); if (ret) { ath12k_err(ab, "failed to get msi for mhi\n"); - mhi_free_controller(mhi_ctrl); - return ret; + goto free_controller; } mhi_ctrl->iova_start = 0; @@ -388,11 +387,15 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config); if (ret) { ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret); - mhi_free_controller(mhi_ctrl); - return ret; + goto free_controller; } return 0; + +free_controller: + mhi_free_controller(mhi_ctrl); + ab_pci->mhi_ctrl = NULL; + return ret; } void ath12k_mhi_unregister(struct ath12k_pci *ab_pci) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index b2db0436bdde..fd1bf53c2502 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2213,6 +2213,7 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab) struct qmi_txn txn = {}; unsigned int board_id = ATH12K_BOARD_ID_DEFAULT; int ret = 0; + int r; int i; memset(&req, 0, sizeof(req)); @@ -2297,6 +2298,10 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab) ab->qmi.target.fw_build_timestamp, ab->qmi.target.fw_build_id); + r = ath12k_core_check_smbios(ab); + if (r) + ath12k_dbg(ab, ATH12K_DBG_QMI, "SMBIOS bdf variant name not set.\n"); + out: return ret; } diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 965755b4cbfd..629373d67421 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2158,6 +2158,9 @@ enum wmi_tlv_service { WMI_MAX_EXT_SERVICE = 256, WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + + WMI_TLV_SERVICE_11BE = 289, + WMI_MAX_EXT2_SERVICE, }; diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index e4eb666c6eea..c4edf8355941 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -178,7 +178,7 @@ static void carl9170_usb_tx_data_complete(struct urb *urb) switch (urb->status) { /* everything is fine */ case 0: - carl9170_tx_callback(ar, (void *)urb->context); + carl9170_tx_callback(ar, urb->context); break; /* disconnect */ @@ -369,7 +369,7 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar) struct urb *urb; while ((urb = usb_get_from_anchor(&ar->tx_err))) { - struct sk_buff *skb = (void *)urb->context; + struct sk_buff *skb = urb->context; carl9170_tx_drop(ar, skb); carl9170_tx_callback(ar, skb); @@ -397,7 +397,7 @@ static void carl9170_usb_tasklet(struct tasklet_struct *t) static void carl9170_usb_rx_complete(struct urb *urb) { - struct ar9170 *ar = (struct ar9170 *)urb->context; + struct ar9170 *ar = urb->context; int err; if (WARN_ON_ONCE(!ar)) @@ -559,7 +559,7 @@ static int carl9170_usb_flush(struct ar9170 *ar) int ret, err = 0; while ((urb = usb_get_from_anchor(&ar->tx_wait))) { - struct sk_buff *skb = (void *)urb->context; + struct sk_buff *skb = urb->context; carl9170_tx_drop(ar, skb); carl9170_tx_callback(ar, skb); usb_free_urb(urb); @@ -668,7 +668,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd, memcpy(ar->cmd.data, payload, plen); spin_lock_bh(&ar->cmd_lock); - ar->readbuf = (u8 *)out; + ar->readbuf = out; ar->readlen = outlen; spin_unlock_bh(&ar->cmd_lock); diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 27f4d74a41c8..700da9f4531e 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -161,7 +161,7 @@ get_dfs_domain_radar_types(enum nl80211_dfs_regions region) struct channel_detector { struct list_head head; u16 freq; - struct pri_detector **detectors; + struct pri_detector *detectors[]; }; /* channel_detector_reset() - reset detector lines for a given channel */ @@ -183,14 +183,13 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd, if (cd == NULL) return; list_del(&cd->head); - if (cd->detectors) { - for (i = 0; i < dpd->num_radar_types; i++) { - struct pri_detector *de = cd->detectors[i]; - if (de != NULL) - de->exit(de); - } + + for (i = 0; i < dpd->num_radar_types; i++) { + struct pri_detector *de = cd->detectors[i]; + if (de != NULL) + de->exit(de); } - kfree(cd->detectors); + kfree(cd); } @@ -200,16 +199,12 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) u32 i; struct channel_detector *cd; - cd = kmalloc(sizeof(*cd), GFP_ATOMIC); + cd = kzalloc(struct_size(cd, detectors, dpd->num_radar_types), GFP_ATOMIC); if (cd == NULL) goto fail; INIT_LIST_HEAD(&cd->head); cd->freq = freq; - cd->detectors = kmalloc_array(dpd->num_radar_types, - sizeof(*cd->detectors), GFP_ATOMIC); - if (cd->detectors == NULL) - goto fail; for (i = 0; i < dpd->num_radar_types; i++) { const struct radar_detector_specs *rs = &dpd->radar_spec[i]; diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c index 7c2d1c588156..461dce21de2b 100644 --- a/drivers/net/wireless/atmel/atmel.c +++ b/drivers/net/wireless/atmel/atmel.c @@ -571,7 +571,6 @@ static const struct { { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} }; static void build_wpa_mib(struct atmel_private *priv); -static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void atmel_copy_to_card(struct net_device *dev, u16 dest, const unsigned char *src, u16 len); static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, @@ -1487,7 +1486,6 @@ static const struct net_device_ops atmel_netdev_ops = { .ndo_stop = atmel_close, .ndo_set_mac_address = atmel_set_mac_address, .ndo_start_xmit = start_tx, - .ndo_do_ioctl = atmel_ioctl, .ndo_validate_addr = eth_validate_addr, }; @@ -2616,76 +2614,6 @@ static const struct iw_handler_def atmel_handler_def = { .get_wireless_stats = atmel_get_wireless_stats }; -static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int i, rc = 0; - struct atmel_private *priv = netdev_priv(dev); - struct atmel_priv_ioctl com; - struct iwreq *wrq = (struct iwreq *) rq; - unsigned char *new_firmware; - char domain[REGDOMAINSZ + 1]; - - switch (cmd) { - case ATMELIDIFC: - wrq->u.param.value = ATMELMAGIC; - break; - - case ATMELFWL: - if (copy_from_user(&com, rq->ifr_data, sizeof(com))) { - rc = -EFAULT; - break; - } - - if (!capable(CAP_NET_ADMIN)) { - rc = -EPERM; - break; - } - - new_firmware = memdup_user(com.data, com.len); - if (IS_ERR(new_firmware)) { - rc = PTR_ERR(new_firmware); - break; - } - - kfree(priv->firmware); - - priv->firmware = new_firmware; - priv->firmware_length = com.len; - strncpy(priv->firmware_id, com.id, 31); - priv->firmware_id[31] = '\0'; - break; - - case ATMELRD: - if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) { - rc = -EFAULT; - break; - } - - if (!capable(CAP_NET_ADMIN)) { - rc = -EPERM; - break; - } - - domain[REGDOMAINSZ] = 0; - rc = -EINVAL; - for (i = 0; i < ARRAY_SIZE(channel_table); i++) { - if (!strcasecmp(channel_table[i].name, domain)) { - priv->config_reg_domain = channel_table[i].reg_domain; - rc = 0; - } - } - - if (rc == 0 && priv->station_state != STATION_STATE_DOWN) - rc = atmel_open(dev); - break; - - default: - rc = -EOPNOTSUPP; - } - - return rc; -} - struct auth_body { __le16 alg; __le16 trans_seq; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index dac7eb77799b..68960ae98987 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -33,7 +33,7 @@ struct brcmf_fweh_queue_item { u8 ifaddr[ETH_ALEN]; struct brcmf_event_msg_be emsg; u32 datalen; - u8 data[]; + u8 data[] __counted_by(datalen); }; /* @@ -418,17 +418,17 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, datalen + sizeof(*event_packet) > packet_len) return; - event = kzalloc(sizeof(*event) + datalen, gfp); + event = kzalloc(struct_size(event, data, datalen), gfp); if (!event) return; + event->datalen = datalen; event->code = code; event->ifidx = event_packet->msg.ifidx; /* use memcpy to get aligned event message */ memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); memcpy(event->data, data, datalen); - event->datalen = datalen; memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN); brcmf_fweh_queue_event(fweh, event); diff --git a/drivers/net/wireless/intersil/hostap/hostap.h b/drivers/net/wireless/intersil/hostap/hostap.h index c17ab6dbbb53..552ae33d7875 100644 --- a/drivers/net/wireless/intersil/hostap/hostap.h +++ b/drivers/net/wireless/intersil/hostap/hostap.h @@ -92,7 +92,6 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb); extern const struct iw_handler_def hostap_iw_handler_def; extern const struct ethtool_ops prism2_ethtool_ops; -int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); int hostap_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd); diff --git a/drivers/net/wireless/intersil/hostap/hostap_download.c b/drivers/net/wireless/intersil/hostap/hostap_download.c index 3672291ced5c..5e5bada28b5b 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_download.c +++ b/drivers/net/wireless/intersil/hostap/hostap_download.c @@ -732,8 +732,7 @@ static int prism2_download(local_info_t *local, goto out; } - dl = kzalloc(sizeof(*dl) + param->num_areas * - sizeof(struct prism2_download_data_area), GFP_KERNEL); + dl = kzalloc(struct_size(dl, data, param->num_areas), GFP_KERNEL); if (dl == NULL) { ret = -ENOMEM; goto out; diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c index b4adfc190ae8..26162f92e3c3 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c @@ -2316,21 +2316,6 @@ static const struct iw_priv_args prism2_priv[] = { }; -static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL)) - return -EOPNOTSUPP; - - return 0; -} - - static int prism2_ioctl_priv_prism2_param(struct net_device *dev, struct iw_request_info *info, union iwreq_data *uwrq, char *extra) @@ -2910,146 +2895,6 @@ static int prism2_ioctl_priv_writemif(struct net_device *dev, } -static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - union iwreq_data wrqu; - - iface = netdev_priv(dev); - local = iface->local; - - printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor " - "- update software to use iwconfig mode monitor\n", - dev->name, task_pid_nr(current), current->comm); - - /* Backward compatibility code - this can be removed at some point */ - - if (*i == 0) { - /* Disable monitor mode - old mode was not saved, so go to - * Master mode */ - wrqu.mode = IW_MODE_MASTER; - ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL); - } else if (*i == 1) { - /* netlink socket mode is not supported anymore since it did - * not separate different devices from each other and was not - * best method for delivering large amount of packets to - * user space */ - ret = -EOPNOTSUPP; - } else if (*i == 2 || *i == 3) { - switch (*i) { - case 2: - local->monitor_type = PRISM2_MONITOR_80211; - break; - case 3: - local->monitor_type = PRISM2_MONITOR_PRISM; - break; - } - wrqu.mode = IW_MODE_MONITOR; - ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL); - hostap_monitor_mode_enable(local); - } else - ret = -EINVAL; - - return ret; -} - - -static int prism2_ioctl_priv_reset(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i); - switch (*i) { - case 0: - /* Disable and enable card */ - local->func->hw_shutdown(dev, 1); - local->func->hw_config(dev, 0); - break; - - case 1: - /* COR sreset */ - local->func->hw_reset(dev); - break; - - case 2: - /* Disable and enable port 0 */ - local->func->reset_port(dev); - break; - - case 3: - prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING); - if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, - NULL)) - return -EINVAL; - break; - - case 4: - if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, - NULL)) - return -EINVAL; - break; - - default: - printk(KERN_DEBUG "Unknown reset request %d\n", *i); - return -EOPNOTSUPP; - } - - return 0; -} - - -static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i) -{ - int rid = *i; - int value = *(i + 1); - - printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value); - - if (hostap_set_word(dev, rid, value)) - return -EINVAL; - - return 0; -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd) -{ - int ret = 0; - - switch (*cmd) { - case AP_MAC_CMD_POLICY_OPEN: - local->ap->mac_restrictions.policy = MAC_POLICY_OPEN; - break; - case AP_MAC_CMD_POLICY_ALLOW: - local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW; - break; - case AP_MAC_CMD_POLICY_DENY: - local->ap->mac_restrictions.policy = MAC_POLICY_DENY; - break; - case AP_MAC_CMD_FLUSH: - ap_control_flush_macs(&local->ap->mac_restrictions); - break; - case AP_MAC_CMD_KICKALL: - ap_control_kickall(local->ap); - hostap_deauth_all_stas(local->dev, local->ap, 0); - break; - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - #ifdef PRISM2_DOWNLOAD_SUPPORT static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p) { @@ -3963,79 +3808,6 @@ const struct iw_handler_def hostap_iw_handler_def = .get_wireless_stats = hostap_get_wireless_stats, }; -/* Private ioctls (iwpriv) that have not yet been converted - * into new wireless extensions API */ -int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct iwreq *wrq = (struct iwreq *) ifr; - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - switch (cmd) { - case PRISM2_IOCTL_INQUIRE: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_MONITOR: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_RESET: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_WDS_ADD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1); - break; - - case PRISM2_IOCTL_WDS_DEL: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0); - break; - - case PRISM2_IOCTL_SET_RID_WORD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_set_rid_word(dev, - (int *) wrq->u.name); - break; - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - case PRISM2_IOCTL_MACCMD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_ADDMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_add_mac(&local->ap->mac_restrictions, - wrq->u.ap_addr.sa_data); - break; - case PRISM2_IOCTL_DELMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_del_mac(&local->ap->mac_restrictions, - wrq->u.ap_addr.sa_data); - break; - case PRISM2_IOCTL_KICKMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_kick_mac(local->ap, local->dev, - wrq->u.ap_addr.sa_data); - break; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} /* Private ioctls that are not used with iwpriv; * in SIOCDEVPRIVATE range */ diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c index 787f685e70b4..bf86ac26c2ac 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_main.c +++ b/drivers/net/wireless/intersil/hostap/hostap_main.c @@ -796,7 +796,6 @@ static const struct net_device_ops hostap_netdev_ops = { .ndo_open = prism2_open, .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, .ndo_siocdevprivate = hostap_siocdevprivate, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, @@ -809,7 +808,6 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = { .ndo_open = prism2_open, .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, .ndo_siocdevprivate = hostap_siocdevprivate, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, @@ -822,7 +820,6 @@ static const struct net_device_ops hostap_master_ops = { .ndo_open = prism2_open, .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, .ndo_siocdevprivate = hostap_siocdevprivate, .ndo_set_mac_address = prism2_set_mac_address, .ndo_set_rx_mode = hostap_set_multicast_list, diff --git a/drivers/net/wireless/intersil/hostap/hostap_wlan.h b/drivers/net/wireless/intersil/hostap/hostap_wlan.h index c25cd21d18bd..f71c0545c0be 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_wlan.h +++ b/drivers/net/wireless/intersil/hostap/hostap_wlan.h @@ -617,7 +617,7 @@ struct prism2_download_data { u32 addr; /* wlan card address */ u32 len; u8 *data; /* allocated data */ - } data[]; + } data[] __counted_by(num_areas); }; diff --git a/drivers/net/wireless/intersil/p54/p54.h b/drivers/net/wireless/intersil/p54/p54.h index 3356ea708d81..522656de4159 100644 --- a/drivers/net/wireless/intersil/p54/p54.h +++ b/drivers/net/wireless/intersil/p54/p54.h @@ -126,7 +126,7 @@ struct p54_cal_database { size_t entry_size; size_t offset; size_t len; - u8 data[]; + u8 data[] __counted_by(len); }; #define EEPROM_READBACK_LEN 0x3fc diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 7eb1b0b63d11..a86f800b8bf5 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -44,3 +44,4 @@ source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7996/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 85c4799be954..d6575fe18c6b 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_MT7615_COMMON) += mt7615/ obj-$(CONFIG_MT7915E) += mt7915/ obj-$(CONFIG_MT7921_COMMON) += mt7921/ obj-$(CONFIG_MT7996E) += mt7996/ +obj-$(CONFIG_MT7925_COMMON) += mt7925/ diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 57fbcc83e074..ae83be572b94 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -109,8 +109,6 @@ mt76_register_debugfs_fops(struct mt76_phy *phy, struct dentry *dir; dir = debugfs_create_dir("mt76", phy->hw->wiphy->debugfsdir); - if (!dir) - return NULL; debugfs_create_u8("led_pin", 0600, dir, &phy->leds.pin); debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg); diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index dc8f4e157eb2..511fe7e6e744 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -53,6 +53,11 @@ mt76_alloc_txwi(struct mt76_dev *dev) addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { + kfree(txwi); + return NULL; + } + t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size); t->dma_addr = addr; @@ -330,9 +335,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, if (e->txwi == DMA_DUMMY_DATA) e->txwi = NULL; - if (e->skb == DMA_DUMMY_DATA) - e->skb = NULL; - *prev_e = *e; memset(e, 0, sizeof(*e)); } @@ -737,16 +739,18 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) if (!q->ndesc) return; - spin_lock_bh(&q->lock); - do { + spin_lock_bh(&q->lock); buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL); + spin_unlock_bh(&q->lock); + if (!buf) break; mt76_put_page_pool_buf(buf, false); } while (1); + spin_lock_bh(&q->lock); if (q->rx_head) { dev_kfree_skb(q->rx_head); q->rx_head = NULL; diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 36564930aef1..7725dd6763ef 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -188,7 +188,7 @@ static bool mt76_string_prop_find(struct property *prop, const char *str) return false; } -static struct device_node * +struct device_node * mt76_find_power_limits_node(struct mt76_dev *dev) { struct device_node *np = dev->dev->of_node; @@ -227,6 +227,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev) of_node_put(np); return fallback; } +EXPORT_SYMBOL_GPL(mt76_find_power_limits_node); static const __be32 * mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min) @@ -241,7 +242,7 @@ mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min) return prop->value; } -static struct device_node * +struct device_node * mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) { struct device_node *cur; @@ -265,6 +266,8 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) return NULL; } +EXPORT_SYMBOL_GPL(mt76_find_channel_node); + static s8 mt76_get_txs_delta(struct device_node *np, u8 nss) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index d158320bc15d..cb76053973aa 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -415,6 +415,9 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) struct mt76_dev *dev = phy->dev; struct wiphy *wiphy = hw->wiphy; + INIT_LIST_HEAD(&phy->tx_list); + spin_lock_init(&phy->tx_lock); + SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, phy->macaddr); @@ -452,7 +455,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); - if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) { + if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) && + hw->max_tx_fragments > 1) { ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, TX_FRAG_LIST); } @@ -688,6 +692,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, int ret; dev_set_drvdata(dev->dev, dev); + mt76_wcid_init(&dev->global_wcid); ret = mt76_phy_init(phy, hw); if (ret) return ret; @@ -743,6 +748,7 @@ void mt76_unregister_device(struct mt76_dev *dev) if (IS_ENABLED(CONFIG_MT76_LEDS)) mt76_led_cleanup(&dev->phy); mt76_tx_status_check(dev, true); + mt76_wcid_cleanup(dev, &dev->global_wcid); ieee80211_unregister_hw(hw); } EXPORT_SYMBOL_GPL(mt76_unregister_device); @@ -1411,7 +1417,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif, wcid->phy_idx = phy->band_idx; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); - mt76_packet_id_init(wcid); + mt76_wcid_init(wcid); out: mutex_unlock(&dev->mutex); @@ -1430,7 +1436,7 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, if (dev->drv->sta_remove) dev->drv->sta_remove(dev, vif, sta); - mt76_packet_id_flush(dev, wcid); + mt76_wcid_cleanup(dev, wcid); mt76_wcid_mask_clear(dev->wcid_mask, idx); mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); @@ -1486,6 +1492,47 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); +void mt76_wcid_init(struct mt76_wcid *wcid) +{ + INIT_LIST_HEAD(&wcid->tx_list); + skb_queue_head_init(&wcid->tx_pending); + + INIT_LIST_HEAD(&wcid->list); + idr_init(&wcid->pktid); +} +EXPORT_SYMBOL_GPL(mt76_wcid_init); + +void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) +{ + struct mt76_phy *phy = dev->phys[wcid->phy_idx]; + struct ieee80211_hw *hw; + struct sk_buff_head list; + struct sk_buff *skb; + + mt76_tx_status_lock(dev, &list); + mt76_tx_status_skb_get(dev, wcid, -1, &list); + mt76_tx_status_unlock(dev, &list); + + idr_destroy(&wcid->pktid); + + spin_lock_bh(&phy->tx_lock); + + if (!list_empty(&wcid->tx_list)) + list_del_init(&wcid->tx_list); + + spin_lock(&wcid->tx_pending.lock); + skb_queue_splice_tail_init(&wcid->tx_pending, &list); + spin_unlock(&wcid->tx_pending.lock); + + spin_unlock_bh(&phy->tx_lock); + + while ((skb = __skb_dequeue(&list)) != NULL) { + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); + } +} +EXPORT_SYMBOL_GPL(mt76_wcid_cleanup); + int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { @@ -1697,11 +1744,16 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, } EXPORT_SYMBOL_GPL(mt76_init_queue); -u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx) +u16 mt76_calculate_default_rate(struct mt76_phy *phy, + struct ieee80211_vif *vif, int rateidx) { + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = mvif->ctx ? + &mvif->ctx->def : + &phy->chandef; int offset = 0; - if (phy->chandef.chan->band != NL80211_BAND_2GHZ) + if (chandef->chan->band != NL80211_BAND_2GHZ) offset = 4; /* pick the lowest rate for hidden nodes */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e8757865a3d0..ea828ba0b83a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -334,6 +334,9 @@ struct mt76_wcid { u32 tx_info; bool sw_iv; + struct list_head tx_list; + struct sk_buff_head tx_pending; + struct list_head list; struct idr pktid; @@ -376,7 +379,7 @@ struct mt76_rx_tid { u8 started:1, stopped:1, timer_pending:1; - struct sk_buff *reorder_buf[]; + struct sk_buff *reorder_buf[] __counted_by(size); }; #define MT_TX_CB_DMA_DONE BIT(0) @@ -709,6 +712,7 @@ struct mt76_vif { u8 basic_rates_idx; u8 mcast_rates_idx; u8 beacon_rates_idx; + struct ieee80211_chanctx_conf *ctx; }; struct mt76_phy { @@ -719,6 +723,8 @@ struct mt76_phy { unsigned long state; u8 band_idx; + spinlock_t tx_lock; + struct list_head tx_list; struct mt76_queue *q_tx[__MT_TXQ_MAX]; struct cfg80211_chan_def chandef; @@ -967,6 +973,7 @@ struct mt76_power_limits { s8 ofdm[8]; s8 mcs[4][10]; s8 ru[7][12]; + s8 eht[16][16]; }; struct mt76_ethtool_worker_info { @@ -1100,7 +1107,8 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, int ring_base, u32 flags); -u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx); +u16 mt76_calculate_default_rate(struct mt76_phy *phy, + struct ieee80211_vif *vif, int rateidx); static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, int n_desc, int ring_base, u32 flags) { @@ -1529,6 +1537,11 @@ mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set); +struct device_node * +mt76_find_power_limits_node(struct mt76_dev *dev); +struct device_node * +mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan); + s8 mt76_get_rate_power_limits(struct mt76_phy *phy, struct ieee80211_channel *chan, struct mt76_power_limits *dest, @@ -1598,22 +1611,7 @@ mt76_token_put(struct mt76_dev *dev, int token) return txwi; } -static inline void mt76_packet_id_init(struct mt76_wcid *wcid) -{ - INIT_LIST_HEAD(&wcid->list); - idr_init(&wcid->pktid); -} - -static inline void -mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid) -{ - struct sk_buff_head list; - - mt76_tx_status_lock(dev, &list); - mt76_tx_status_skb_get(dev, wcid, -1, &list); - mt76_tx_status_unlock(dev, &list); - - idr_destroy(&wcid->pktid); -} +void mt76_wcid_init(struct mt76_wcid *wcid); +void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index 888678732f29..c223f7c19e6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -10,12 +10,31 @@ struct beacon_bc_data { }; static void +mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev) +{ + if (dev->beacon_check % 5 != 4) + return; + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN); + mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET); + mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET); + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN); + + mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS); + mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE); + mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE); + mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS); +} + +static void mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7603_dev *dev = (struct mt7603_dev *)priv; struct mt76_dev *mdev = &dev->mt76; struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; struct sk_buff *skb = NULL; + u32 om_idx = mvif->idx; + u32 val; if (!(mdev->beacon_mask & BIT(mvif->idx))) return; @@ -24,20 +43,33 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!skb) return; - mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], - MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); + if (om_idx) + om_idx |= 0x10; + val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE | + FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) | + FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | + FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8); spin_lock_bh(&dev->ps_lock); - mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | - FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) | - FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, - dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) | - FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | - FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); - if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) + mt76_wr(dev, MT_DMA_FQCR0, val | + FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN)); + if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) { dev->beacon_check = MT7603_WATCHDOG_TIMEOUT; + goto out; + } + + mt76_wr(dev, MT_DMA_FQCR0, val | + FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC)); + if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) { + dev->beacon_check = MT7603_WATCHDOG_TIMEOUT; + goto out; + } + mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], + MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL); + +out: spin_unlock_bh(&dev->ps_lock); } @@ -81,6 +113,18 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) data.dev = dev; __skb_queue_head_init(&data.q); + /* Flush all previous CAB queue packets and beacons */ + mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); + + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false); + + if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0) + dev->beacon_check++; + else + dev->beacon_check = 0; + mt7603_mac_stuck_beacon_recovery(dev); + q = dev->mphy.q_tx[MT_TXQ_BEACON]; spin_lock(&q->lock); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), @@ -89,14 +133,9 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) mt76_queue_kick(dev, q); spin_unlock(&q->lock); - /* Flush all previous CAB queue packets */ - mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); - - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false); - mt76_csa_check(mdev); if (mdev->csa_complete) - goto out; + return; q = dev->mphy.q_tx[MT_TXQ_CAB]; do { @@ -108,7 +147,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) skb_queue_len(&data.q) < 8); if (skb_queue_empty(&data.q)) - goto out; + return; for (i = 0; i < ARRAY_SIZE(data.tail); i++) { if (!data.tail[i]) @@ -136,11 +175,6 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) MT_WF_ARB_CAB_START_BSSn(0) | (MT_WF_ARB_CAB_START_BSS0n(1) * ((1 << (MT7603_MAX_INTERFACES - 1)) - 1))); - -out: - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false); - if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask)) - dev->beacon_check++; } void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index 60a996b63c0c..915b8349146a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) } if (intr & MT_INT_RX_DONE(0)) { + dev->rx_pse_check = 0; mt7603_irq_disable(dev, MT_INT_RX_DONE(0)); napi_schedule(&dev->mt76.napi[0]); } if (intr & MT_INT_RX_DONE(1)) { + dev->rx_pse_check = 0; mt7603_irq_disable(dev, MT_INT_RX_DONE(1)); napi_schedule(&dev->mt76.napi[1]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 0762de3ce5ac..6c55c72f28a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -184,6 +184,13 @@ mt7603_mac_init(struct mt7603_dev *dev) mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE); + if (is_mt7628(dev)) { + mt76_set(dev, MT_TMAC_TCR, + MT_TMAC_TCR_TXOP_BURST_STOP | BIT(1) | BIT(0)); + mt76_set(dev, MT_TXREQ, BIT(27)); + mt76_set(dev, MT_AGG_TMP, GENMASK(4, 2)); + } + mt7603_set_tmac_template(dev); /* Enable RX group to HIF */ @@ -517,6 +524,7 @@ int mt7603_register_device(struct mt7603_dev *dev) hw->max_rates = 3; hw->max_report_rates = 7; hw->max_rate_tries = 11; + hw->max_tx_fragments = 1; hw->radiotap_timestamp.units_pos = IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 99ae080502d8..cf21d06257e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1441,15 +1441,6 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_beacon_set_timer(dev, -1, 0); - if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] || - dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY || - dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK || - dev->cur_reset_cause == RESET_CAUSE_TX_HANG) - mt7603_pse_reset(dev); - - if (dev->reset_cause[RESET_CAUSE_RESET_FAILED]) - goto skip_dma_reset; - mt7603_mac_stop(dev); mt76_clear(dev, MT_WPDMA_GLO_CFG, @@ -1459,28 +1450,32 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_irq_disable(dev, mask); - mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); - mt7603_pse_client_reset(dev); mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); + mt7603_dma_sched_reset(dev); + + mt76_tx_status_check(&dev->mt76, true); + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); } - mt76_tx_status_check(&dev->mt76, true); + if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] || + dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY) + mt7603_pse_reset(dev); - mt7603_dma_sched_reset(dev); + if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) { + mt7603_mac_dma_start(dev); - mt7603_mac_dma_start(dev); + mt7603_irq_enable(dev, mask); - mt7603_irq_enable(dev, mask); + clear_bit(MT76_RESET, &dev->mphy.state); + } -skip_dma_reset: - clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); mt76_worker_enable(&dev->mt76.tx_worker); @@ -1570,20 +1565,29 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev) { u32 addr, val; - if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES) - return true; - if (mt7603_rx_fifo_busy(dev)) - return false; + goto out; addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS); mt76_wr(dev, addr, 3); val = mt76_rr(dev, addr) >> 16; - if (is_mt7628(dev) && (val & 0x4001) == 0x4001) - return true; + if (!(val & BIT(0))) + return false; - return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001; + if (is_mt7628(dev)) + val &= 0xa000; + else + val &= 0x8000; + if (!val) + return false; + +out: + if (mt76_rr(dev, MT_INT_SOURCE_CSR) & + (MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1))) + return false; + + return true; } static bool diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index c213fd2a5216..89d738deea62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -70,7 +70,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; mvif->sta.vif = mvif; - mt76_packet_id_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid); eth_broadcast_addr(bc_addr); mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); @@ -110,7 +110,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); mutex_unlock(&dev->mt76.mutex); - mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); + mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid); } void mt7603_init_edcca(struct mt7603_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index a39c9a0fcb1c..524bceb8e958 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -469,6 +469,11 @@ enum { #define MT_WF_SEC_BASE 0x21a00 #define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs)) +#define MT_WF_CFG_OFF_BASE 0x21e00 +#define MT_WF_CFG_OFF(ofs) (MT_WF_CFG_OFF_BASE + (ofs)) +#define MT_WF_CFG_OFF_WOCCR MT_WF_CFG_OFF(0x004) +#define MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS BIT(4) + #define MT_SEC_SCR MT_WF_SEC(0x004) #define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 18a50ccff106..f7722f67db57 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -58,10 +58,7 @@ int mt7615_thermal_init(struct mt7615_dev *dev) wiphy_name(wiphy)); hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, mt7615_hwmon_groups); - if (IS_ERR(hwmon)) - return PTR_ERR(hwmon); - - return 0; + return PTR_ERR_OR_ZERO(hwmon); } EXPORT_SYMBOL_GPL(mt7615_thermal_init); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 200b1752ca77..dab16b5fc386 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -226,7 +226,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; - mt76_packet_id_init(&mvif->sta.wcid); + mt76_wcid_init(&mvif->sta.wcid); mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -279,7 +279,7 @@ static void mt7615_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, &mvif->sta.wcid); + mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid); } int mt7615_set_channel(struct mt7615_phy *phy) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 8d745c9730c7..955974a82180 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -2147,7 +2147,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) }; if (cmd == MCU_EXT_CMD(SET_RX_PATH) || - dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index 0019890fdb78..fbb1181c58ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -106,7 +106,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, else mt76_connac_write_hw_txp(mdev, tx_info, txp, id); - tx_info->skb = DMA_DUMMY_DATA; + tx_info->skb = NULL; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 22878f088804..1f29d8cd900c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -172,6 +172,11 @@ struct mt76_connac_tx_free { extern const struct wiphy_wowlan_support mt76_connac_wowlan_support; +static inline bool is_mt7925(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7925; +} + static inline bool is_mt7922(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7922; @@ -245,6 +250,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev) switch (mt76_chip(dev)) { case 0x7961: case 0x7922: + case 0x7925: case 0x7663: case 0x7622: return false; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h index 68ca0844cbbf..2250252b2047 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h @@ -257,6 +257,8 @@ enum tx_mgnt_type { #define MT_TXD7_UDP_TCP_SUM BIT(15) #define MT_TXD7_TX_TIME GENMASK(9, 0) +#define MT_TXD9_WLAN_IDX GENMASK(23, 8) + #define MT_TX_RATE_STBC BIT(14) #define MT_TX_RATE_NSS GENMASK(13, 10) #define MT_TX_RATE_MODE GENMASK(9, 6) @@ -269,7 +271,7 @@ enum tx_mgnt_type { #define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) #define MT_TXFREE0_RX_BYTE GENMASK(15, 0) -#define MT_TXFREE1_VER GENMASK(18, 16) +#define MT_TXFREE1_VER GENMASK(19, 16) #define MT_TXFREE_INFO_PAIR BIT(31) #define MT_TXFREE_INFO_HEADER BIT(30) @@ -315,6 +317,7 @@ enum tx_mgnt_type { #define MT_TXS4_TIMESTAMP GENMASK(31, 0) +/* MPDU based TXS */ #define MT_TXS5_F0_FINAL_MPDU BIT(31) #define MT_TXS5_F0_QOS BIT(30) #define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) @@ -336,4 +339,17 @@ enum tx_mgnt_type { #define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24) #define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0) +/* PPDU based TXS */ +#define MT_TXS5_MPDU_TX_CNT GENMASK(30, 20) +#define MT_TXS5_MPDU_TX_BYTE_SCALE BIT(15) +#define MT_TXS5_MPDU_TX_BYTE GENMASK(14, 0) + +#define MT_TXS6_MPDU_FAIL_CNT GENMASK(30, 20) +#define MT_TXS6_MPDU_FAIL_BYTE_SCALE BIT(15) +#define MT_TXS6_MPDU_FAIL_BYTE GENMASK(14, 0) + +#define MT_TXS7_MPDU_RETRY_CNT GENMASK(30, 20) +#define MT_TXS7_MPDU_RETRY_BYTE_SCALE BIT(15) +#define MT_TXS7_MPDU_RETRY_BYTE GENMASK(14, 0) + #endif /* __MT76_CONNAC3_MAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index ee5177fd6dde..93402d2c2538 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -151,23 +151,6 @@ void mt76_connac_tx_complete_skb(struct mt76_dev *mdev, return; } - /* error path */ - if (e->skb == DMA_DUMMY_DATA) { - struct mt76_connac_txp_common *txp; - struct mt76_txwi_cache *t; - u16 token; - - txp = mt76_connac_txwi_to_txp(mdev, e->txwi); - if (is_mt76_fw_txp(mdev)) - token = le16_to_cpu(txp->fw.token); - else - token = le16_to_cpu(txp->hw.msdu_id[0]) & - ~MT_MSDU_ID_VALID; - - t = mt76_token_put(mdev, token); - e->skb = t ? t->skb : NULL; - } - if (e->skb) mt76_tx_complete_skb(mdev, e->wcid, e->skb); } @@ -187,7 +170,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev, txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); - if (is_mt7663(dev) || is_mt7921(dev)) + if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev)) last_mask = MT_TXD_LEN_LAST; else last_mask = MT_TXD_LEN_AMSDU_LAST | @@ -231,7 +214,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev, u32 last_mask; int i; - if (is_mt7663(dev) || is_mt7921(dev)) + if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev)) last_mask = MT_TXD_LEN_LAST; else last_mask = MT_TXD_LEN_MSDU_LAST; @@ -310,7 +293,10 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, bool beacon, bool mcast) { - u8 nss = 0, mode = 0, band = mphy->chandef.chan->band; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = mvif->ctx ? + &mvif->ctx->def : &mphy->chandef; + u8 nss = 0, mode = 0, band = chandef->chan->band; int rateidx = 0, mcast_rate; if (!vif) @@ -343,7 +329,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, rateidx = ffs(vif->bss_conf.basic_rates) - 1; legacy: - rateidx = mt76_calculate_default_rate(mphy, rateidx); + rateidx = mt76_calculate_default_rate(mphy, vif, rateidx); mode = rateidx >> 8; rateidx &= GENMASK(7, 0); out: diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 0f0a519f956f..ae6bf3c968df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -66,6 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len, if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) || (is_mt7921(dev) && addr == 0x900000) || + (is_mt7925(dev) && addr == 0x900000) || (is_mt7996(dev) && addr == 0x900000)) cmd = MCU_CMD(PATCH_START_REQ); else @@ -745,7 +746,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) he->pkt_ext = 2; } -static void +void mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta) { struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; @@ -777,20 +778,23 @@ mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta) he->pkt_ext = IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US; } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2); -static u8 +u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, enum nl80211_band band, struct ieee80211_sta *sta) { struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_vht_cap *vht_cap; const struct ieee80211_sta_he_cap *he_cap; + const struct ieee80211_sta_eht_cap *eht_cap; u8 mode = 0; if (sta) { ht_cap = &sta->deflink.ht_cap; vht_cap = &sta->deflink.vht_cap; he_cap = &sta->deflink.he_cap; + eht_cap = &sta->deflink.eht_cap; } else { struct ieee80211_supported_band *sband; @@ -798,6 +802,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, ht_cap = &sband->ht_cap; vht_cap = &sband->vht_cap; he_cap = ieee80211_get_he_iftype_cap(sband, vif->type); + eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type); } if (band == NL80211_BAND_2GHZ) { @@ -808,6 +813,9 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, if (he_cap && he_cap->has_he) mode |= PHY_TYPE_BIT_HE; + + if (eht_cap && eht_cap->has_eht) + mode |= PHY_TYPE_BIT_BE; } else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) { mode |= PHY_TYPE_BIT_OFDM; @@ -819,17 +827,23 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, if (he_cap && he_cap->has_he) mode |= PHY_TYPE_BIT_HE; + + if (eht_cap && eht_cap->has_eht) + mode |= PHY_TYPE_BIT_BE; } return mode; } +EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_v2); void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 rcpi, u8 sta_state) { - struct cfg80211_chan_def *chandef = &mphy->chandef; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = mvif->ctx ? + &mvif->ctx->def : &mphy->chandef; enum nl80211_band band = chandef->chan->band; struct mt76_dev *dev = mphy->dev; struct sta_rec_ra_info *ra_info; @@ -1369,7 +1383,10 @@ EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext); const struct ieee80211_sta_he_cap * mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif) { - enum nl80211_band band = phy->chandef.chan->band; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = mvif->ctx ? + &mvif->ctx->def : &phy->chandef; + enum nl80211_band band = chandef->chan->band; struct ieee80211_supported_band *sband; sband = phy->hw->wiphy->bands[band]; @@ -1924,126 +1941,6 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event); -static void mt76_connac_mcu_parse_tx_resource(struct mt76_dev *dev, - struct sk_buff *skb) -{ - struct mt76_sdio *sdio = &dev->sdio; - struct mt76_connac_tx_resource { - __le32 version; - __le32 pse_data_quota; - __le32 pse_mcu_quota; - __le32 ple_data_quota; - __le32 ple_mcu_quota; - __le16 pse_page_size; - __le16 ple_page_size; - u8 pp_padding; - u8 pad[3]; - } __packed * tx_res; - - tx_res = (struct mt76_connac_tx_resource *)skb->data; - sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota); - sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota); - sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota); - sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size); - sdio->sched.deficit = tx_res->pp_padding; -} - -static void mt76_connac_mcu_parse_phy_cap(struct mt76_dev *dev, - struct sk_buff *skb) -{ - struct mt76_connac_phy_cap { - u8 ht; - u8 vht; - u8 _5g; - u8 max_bw; - u8 nss; - u8 dbdc; - u8 tx_ldpc; - u8 rx_ldpc; - u8 tx_stbc; - u8 rx_stbc; - u8 hw_path; - u8 he; - } __packed * cap; - - enum { - WF0_24G, - WF0_5G - }; - - cap = (struct mt76_connac_phy_cap *)skb->data; - - dev->phy.antenna_mask = BIT(cap->nss) - 1; - dev->phy.chainmask = dev->phy.antenna_mask; - dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G); - dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G); -} - -int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy) -{ - struct mt76_connac_cap_hdr { - __le16 n_element; - u8 rsv[2]; - } __packed * hdr; - struct sk_buff *skb; - int ret, i; - - ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB), - NULL, 0, true, &skb); - if (ret) - return ret; - - hdr = (struct mt76_connac_cap_hdr *)skb->data; - if (skb->len < sizeof(*hdr)) { - ret = -EINVAL; - goto out; - } - - skb_pull(skb, sizeof(*hdr)); - - for (i = 0; i < le16_to_cpu(hdr->n_element); i++) { - struct tlv_hdr { - __le32 type; - __le32 len; - } __packed * tlv = (struct tlv_hdr *)skb->data; - int len; - - if (skb->len < sizeof(*tlv)) - break; - - skb_pull(skb, sizeof(*tlv)); - - len = le32_to_cpu(tlv->len); - if (skb->len < len) - break; - - switch (le32_to_cpu(tlv->type)) { - case MT_NIC_CAP_6G: - phy->cap.has_6ghz = skb->data[0]; - break; - case MT_NIC_CAP_MAC_ADDR: - memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN); - break; - case MT_NIC_CAP_PHY: - mt76_connac_mcu_parse_phy_cap(phy->dev, skb); - break; - case MT_NIC_CAP_TX_RESOURCE: - if (mt76_is_sdio(phy->dev)) - mt76_connac_mcu_parse_tx_resource(phy->dev, - skb); - break; - default: - break; - } - skb_pull(skb, len); - } -out: - dev_kfree_skb(skb); - - return ret; -} -EXPORT_SYMBOL_GPL(mt76_connac_mcu_get_nic_capability); - static void mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, struct mt76_power_limits *limits, @@ -2087,9 +1984,9 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku, } } -static s8 mt76_connac_get_ch_power(struct mt76_phy *phy, - struct ieee80211_channel *chan, - s8 target_power) +s8 mt76_connac_get_ch_power(struct mt76_phy *phy, + struct ieee80211_channel *chan, + s8 target_power) { struct mt76_dev *dev = phy->dev; struct ieee80211_supported_band *sband; @@ -2126,6 +2023,7 @@ static s8 mt76_connac_get_ch_power(struct mt76_phy *phy, return target_power; } +EXPORT_SYMBOL_GPL(mt76_connac_get_ch_power); static int mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, @@ -2144,7 +2042,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, - 159, 161, 165 + 159, 161, 165, 169, 173, 177 }; static const u8 chan_list_6ghz[] = { 1, 3, 5, 7, 9, 11, 13, @@ -2164,11 +2062,15 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, 209, 211, 213, 215, 217, 219, 221, 225, 227, 229, 233 }; - int i, n_chan, batch_size, idx = 0, tx_power, last_ch; + int i, n_chan, batch_size, idx = 0, tx_power, last_ch, err = 0; struct mt76_connac_sku_tlv sku_tlbv; - struct mt76_power_limits limits; + struct mt76_power_limits *limits; const u8 *ch_list; + limits = devm_kmalloc(dev->dev, sizeof(*limits), GFP_KERNEL); + if (!limits) + return -ENOMEM; + sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92; tx_power = 2 * phy->hw->conf.power_level; if (!tx_power) @@ -2195,14 +2097,16 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, for (i = 0; i < batch_size; i++) { struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {}; - int j, err, msg_len, num_ch; + int j, msg_len, num_ch; struct sk_buff *skb; num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len; msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv); skb = mt76_mcu_msg_alloc(dev, NULL, msg_len); - if (!skb) - return -ENOMEM; + if (!skb) { + err = -ENOMEM; + goto out; + } skb_reserve(skb, sizeof(tx_power_tlv)); @@ -2233,14 +2137,14 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, tx_power); sar_power = mt76_get_sar_power(phy, &chan, reg_power); - mt76_get_rate_power_limits(phy, &chan, &limits, + mt76_get_rate_power_limits(phy, &chan, limits, sar_power); tx_power_tlv.last_msg = ch_list[idx] == last_ch; sku_tlbv.channel = ch_list[idx]; mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit, - &limits, band); + limits, band); skb_put_data(skb, &sku_tlbv, sku_len); } __skb_push(skb, sizeof(tx_power_tlv)); @@ -2250,10 +2154,12 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy, MCU_CE_CMD(SET_RATE_TX_POWER), false); if (err < 0) - return err; + goto out; } - return 0; +out: + devm_kfree(dev->dev, limits); + return err; } int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy) @@ -2457,7 +2363,7 @@ mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif, sizeof(req), true); } -static int +int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend) { @@ -2482,8 +2388,9 @@ mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req, sizeof(req), true); } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_gtk_rekey); -static int +int mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev, struct ieee80211_vif *vif, bool enable, u8 mdtim, @@ -2512,6 +2419,7 @@ mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev, return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req, sizeof(req), true); } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_mode); static int mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev, @@ -2547,7 +2455,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev, return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true); } -static int +int mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, bool suspend, struct cfg80211_wowlan *wowlan) { @@ -2599,6 +2507,7 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req, sizeof(req), true); } +EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_wow_ctrl); int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) { @@ -3064,7 +2973,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info) { u32 mode = DL_MODE_NEED_RSP; - if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT) + if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT) return mode; switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 4543e5bf0482..0563b1b22f48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -191,6 +191,7 @@ struct mt76_connac2_fw_region { struct tlv { __le16 tag; __le16 len; + u8 data[]; } __packed; struct bss_info_omac { @@ -795,6 +796,7 @@ enum { STA_REC_PHY = 0x15, STA_REC_HE_6G = 0x17, STA_REC_HE_V2 = 0x19, + STA_REC_MLD = 0x20, STA_REC_EHT = 0x22, STA_REC_HDRT = 0x28, STA_REC_HDR_TRANS = 0x2B, @@ -919,6 +921,7 @@ enum { PHY_TYPE_HT_INDEX, PHY_TYPE_VHT_INDEX, PHY_TYPE_HE_INDEX, + PHY_TYPE_BE_INDEX, PHY_TYPE_INDEX_NUM }; @@ -928,6 +931,7 @@ enum { #define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) #define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX) #define PHY_TYPE_BIT_HE BIT(PHY_TYPE_HE_INDEX) +#define PHY_TYPE_BIT_BE BIT(PHY_TYPE_BE_INDEX) #define MT_WTBL_RATE_TX_MODE GENMASK(9, 6) #define MT_WTBL_RATE_MCS GENMASK(5, 0) @@ -1009,8 +1013,17 @@ enum { enum { MCU_UNI_EVENT_RESULT = 0x01, MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04, + MCU_UNI_EVENT_ACCESS_REG = 0x6, MCU_UNI_EVENT_IE_COUNTDOWN = 0x09, + MCU_UNI_EVENT_COREDUMP = 0x0a, + MCU_UNI_EVENT_BSS_BEACON_LOSS = 0x0c, + MCU_UNI_EVENT_SCAN_DONE = 0x0e, MCU_UNI_EVENT_RDD_REPORT = 0x11, + MCU_UNI_EVENT_ROC = 0x27, + MCU_UNI_EVENT_TX_DONE = 0x2d, + MCU_UNI_EVENT_NIC_CAPAB = 0x43, + MCU_UNI_EVENT_PER_STA_INFO = 0x6d, + MCU_UNI_EVENT_ALL_STA_INFO = 0x6e, }; #define MCU_UNI_CMD_EVENT BIT(1) @@ -1209,12 +1222,17 @@ enum { MCU_UNI_CMD_RX_HDR_TRANS = 0x12, MCU_UNI_CMD_SER = 0x13, MCU_UNI_CMD_TWT = 0x14, + MCU_UNI_CMD_SET_DOMAIN_INFO = 0x15, + MCU_UNI_CMD_SCAN_REQ = 0x16, MCU_UNI_CMD_RDD_CTRL = 0x19, MCU_UNI_CMD_GET_MIB_INFO = 0x22, + MCU_UNI_CMD_GET_STAT_INFO = 0x23, MCU_UNI_CMD_SNIFFER = 0x24, MCU_UNI_CMD_SR = 0x25, MCU_UNI_CMD_ROC = 0x27, + MCU_UNI_CMD_SET_DBDC_PARMS = 0x28, MCU_UNI_CMD_TXPOWER = 0x2b, + MCU_UNI_CMD_SET_POWER_LIMIT = 0x2c, MCU_UNI_CMD_EFUSE_CTRL = 0x2d, MCU_UNI_CMD_RA = 0x2f, MCU_UNI_CMD_MURU = 0x31, @@ -1224,6 +1242,8 @@ enum { MCU_UNI_CMD_VOW = 0x37, MCU_UNI_CMD_RRO = 0x57, MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58, + MCU_UNI_CMD_PER_STA_INFO = 0x6d, + MCU_UNI_CMD_ALL_STA_INFO = 0x6e, MCU_UNI_CMD_ASSERT_DUMP = 0x6f, }; @@ -1279,6 +1299,7 @@ enum { UNI_BSS_INFO_RLM = 2, UNI_BSS_INFO_BSS_COLOR = 4, UNI_BSS_INFO_HE_BASIC = 5, + UNI_BSS_INFO_11V_MBSSID = 6, UNI_BSS_INFO_BCN_CONTENT = 7, UNI_BSS_INFO_BCN_CSA = 8, UNI_BSS_INFO_BCN_BCC = 9, @@ -1293,6 +1314,7 @@ enum { UNI_BSS_INFO_IFS_TIME = 23, UNI_BSS_INFO_OFFLOAD = 25, UNI_BSS_INFO_MLD = 26, + UNI_BSS_INFO_PM_DISABLE = 27, }; enum { @@ -1302,6 +1324,17 @@ enum { UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT, }; +enum UNI_ALL_STA_INFO_TAG { + UNI_ALL_STA_TX_RATE, + UNI_ALL_STA_TX_STAT, + UNI_ALL_STA_TXRX_ADM_STAT, + UNI_ALL_STA_TXRX_AIR_TIME, + UNI_ALL_STA_DATA_TX_RETRY_COUNT, + UNI_ALL_STA_GI_MODE, + UNI_ALL_STA_TXRX_MSDU_COUNT, + UNI_ALL_STA_MAX_NUM +}; + enum { MT_NIC_CAP_TX_RESOURCE, MT_NIC_CAP_TX_EFUSE_ADDR, @@ -1322,6 +1355,7 @@ enum { MT_NIC_CAP_ANTSWP = 0x16, MT_NIC_CAP_WFDMA_REALLOC, MT_NIC_CAP_6G, + MT_NIC_CAP_CHIP_CAP = 0x20, }; #define UNI_WOW_DETECT_TYPE_MAGIC BIT(0) @@ -1549,6 +1583,15 @@ struct bss_info_uni_he { u8 rsv[2]; } __packed; +struct bss_info_uni_mbssid { + __le16 tag; + __le16 len; + u8 max_indicator; + u8 mbss_idx; + u8 tx_bss_omac_idx; + u8 rsv; +} __packed; + struct mt76_connac_gtk_rekey_tlv { __le16 tag; __le16 len; @@ -1739,7 +1782,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa) ret |= feature_set & FW_FEATURE_SET_ENCRYPT ? DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0; - if (is_mt7921(dev)) + if (is_mt7921(dev) || is_mt7925(dev)) ret |= feature_set & FW_FEATURE_ENCRY_MODE ? DL_CONFIG_ENCRY_MODE_SEL : 0; ret |= FIELD_PREP(DL_MODE_KEY_IDX, @@ -1807,6 +1850,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb, int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid, int cmd); +void mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta); +u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta); int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -1851,7 +1897,6 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len, int mt76_connac_mcu_start_patch(struct mt76_dev *dev); int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get); int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option); -int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy); int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_scan_request *scan_req); @@ -1866,9 +1911,17 @@ int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy, int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, struct mt76_vif *vif, struct ieee80211_bss_conf *info); +int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif, + bool suspend); +int mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, + bool suspend, struct cfg80211_wowlan *wowlan); int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *key); +int mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev, + struct ieee80211_vif *vif, + bool enable, u8 mdtim, + bool wow_suspend); int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend); void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); @@ -1879,6 +1932,9 @@ int mt76_connac_mcu_chip_config(struct mt76_dev *dev); int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable); void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb, struct mt76_connac_coredump *coredump); +s8 mt76_connac_get_ch_power(struct mt76_phy *phy, + struct ieee80211_channel *chan, + s8 target_power); int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy); int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index ad4dc8e17b58..d570b99bccb9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -136,7 +136,8 @@ EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer); void mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76x02_dev *dev = (struct mt76x02_dev *)priv; + struct beacon_bc_data *data = priv; + struct mt76x02_dev *dev = data->dev; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct sk_buff *skb = NULL; @@ -147,7 +148,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!skb) return; - mt76x02_mac_set_beacon(dev, skb); + __skb_queue_tail(&data->q, skb); } EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter); @@ -182,9 +183,6 @@ mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev, { int i, nframes; - data->dev = dev; - __skb_queue_head_init(&data->q); - do { nframes = skb_queue_len(&data->q); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index e9c5e85ec07c..9b5e3fb7b0df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -16,13 +16,17 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t) struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet); struct mt76_dev *mdev = &dev->mt76; struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD]; - struct beacon_bc_data data = {}; + struct beacon_bc_data data = { + .dev = dev, + }; struct sk_buff *skb; int i; if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) return; + __skb_queue_head_init(&data.q); + mt76x02_resync_beacon_timer(dev); /* Prevent corrupt transmissions during update */ @@ -31,7 +35,10 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t) ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, - mt76x02_update_beacon_iter, dev); + mt76x02_update_beacon_iter, &data); + + while ((skb = __skb_dequeue(&data.q)) != NULL) + mt76x02_mac_set_beacon(dev, skb); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~(0xff00 >> dev->beacon_data_count)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 2c6c03809b20..85a78dea4085 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -182,7 +182,9 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) { struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, pre_tbtt_work); - struct beacon_bc_data data = {}; + struct beacon_bc_data data = { + .dev = dev, + }; struct sk_buff *skb; int nbeacons; @@ -192,15 +194,20 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL) return; + __skb_queue_head_init(&data.q); + mt76x02_resync_beacon_timer(dev); /* Prevent corrupt transmissions during update */ mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff); dev->beacon_data_count = 0; - ieee80211_iterate_active_interfaces(mt76_hw(dev), + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, - mt76x02_update_beacon_iter, dev); + mt76x02_update_beacon_iter, &data); + + while ((skb = __skb_dequeue(&data.q)) != NULL) + mt76x02_mac_set_beacon(dev, skb); mt76_csa_check(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index dcbb5c605dfe..8a0e8124b894 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -288,7 +288,7 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, mvif->idx = idx; mvif->group_wcid.idx = MT_VIF_WCID(idx); mvif->group_wcid.hw_key_idx = -1; - mt76_packet_id_init(&mvif->group_wcid); + mt76_wcid_init(&mvif->group_wcid); mtxq = (struct mt76_txq *)vif->txq->drv_priv; rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid); @@ -346,7 +346,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL); - mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid); + mt76_wcid_cleanup(&dev->mt76, &mvif->group_wcid); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index b27d04e02aba..81478289f17e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -213,10 +213,7 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, mt7915_hwmon_groups); - if (IS_ERR(hwmon)) - return PTR_ERR(hwmon); - - return 0; + return PTR_ERR_OR_ZERO(hwmon); } static void mt7915_led_set_config(struct led_classdev *led_cdev, @@ -347,6 +344,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy) hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; hw->netdev_features = NETIF_F_RXCSUM; + if (mtk_wed_device_active(&mdev->mmio.wed)) + hw->netdev_features |= NETIF_F_HW_TC; + hw->radiotap_timestamp.units_pos = IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; @@ -393,8 +393,12 @@ mt7915_init_wiphy(struct mt7915_phy *phy) phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; - phy->mt76->sband_2g.sband.ht_cap.ampdu_density = - IEEE80211_HT_MPDU_DENSITY_4; + if (is_mt7915(&dev->mt76)) + phy->mt76->sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_4; + else + phy->mt76->sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_2; } if (phy->mt76->cap.has_5ghz) { @@ -404,10 +408,11 @@ mt7915_init_wiphy(struct mt7915_phy *phy) phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; - phy->mt76->sband_5g.sband.ht_cap.ampdu_density = - IEEE80211_HT_MPDU_DENSITY_4; if (is_mt7915(&dev->mt76)) { + phy->mt76->sband_5g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_4; + vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; @@ -417,6 +422,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy) IEEE80211_VHT_CAP_SHORT_GI_160 | FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1); } else { + phy->mt76->sband_5g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_2; + vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index b8b0c0fda752..2222fb9aa103 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -809,7 +809,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, txp->rept_wds_wcid = cpu_to_le16(wcid->idx); else txp->rept_wds_wcid = cpu_to_le16(0x3ff); - tx_info->skb = DMA_DUMMY_DATA; + tx_info->skb = NULL; /* pass partial skb header to fw */ tx_info->buf[1].len = MT_CT_PARSE_LEN; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 8ebbf186fab2..a3fd54cc1911 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -253,7 +253,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, mvif->sta.wcid.phy_idx = ext_phy; 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); mt7915_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -314,7 +314,7 @@ static void mt7915_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 mt7915_set_channel(struct mt7915_phy *phy) @@ -483,16 +483,22 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_MONITOR) { bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); bool band = phy->mt76->band_idx; + u32 rxfilter = phy->rxfilter; - if (!enabled) - phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; - else - phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + if (!enabled) { + rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + dev->monitor_mask &= ~BIT(band); + } else { + rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + dev->monitor_mask |= BIT(band); + } mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN, enabled); + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_MDP_DCR0_RX_HDR_TRANS_EN, + !dev->monitor_mask); mt76_testmode_reset(phy->mt76, true); - mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), rxfilter); } mutex_unlock(&dev->mt76.mutex); @@ -527,6 +533,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR1_DROP_BA | MT_WF_RFCR1_DROP_CFEND | MT_WF_RFCR1_DROP_CFACK; + u32 rxfilter; u32 flags = 0; #define MT76_FILTER(_flag, _hw) do { \ @@ -561,7 +568,12 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + rxfilter = phy->rxfilter; + if (hw->conf.flags & IEEE80211_CONF_MONITOR) + rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + else + rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + mt76_wr(dev, MT_WF_RFCR(band), rxfilter); if (*total_flags & FIF_CONTROL) mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); @@ -646,11 +658,13 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, mt7915_update_bss_color(hw, vif, &info->he_bss_color); if (changed & (BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_ENABLED | - BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | - BSS_CHANGED_FILS_DISCOVERY)) + BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); + if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) + mt7915_mcu_add_inband_discov(dev, vif, changed); + if (set_bss_info == 0) mt7915_mcu_add_bss_info(phy, vif, false); if (set_sta == 0) @@ -1386,7 +1400,7 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw, if (sset != ETH_SS_STATS) return; - memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats)); + memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats)); data += sizeof(mt7915_gstrings_stats); page_pool_ethtool_stats_get_strings(data); } @@ -1639,6 +1653,20 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, return 0; } + +static int +mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct net_device *netdev, enum tc_setup_type type, + void *type_data) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + + if (!mtk_wed_device_active(wed)) + return -EOPNOTSUPP; + + return mtk_wed_device_setup_tc(wed, netdev, type, type_data); +} #endif const struct ieee80211_ops mt7915_ops = { @@ -1693,5 +1721,6 @@ const struct ieee80211_ops mt7915_ops = { .set_radar_background = mt7915_set_radar_background, #ifdef CONFIG_NET_MEDIATEK_SOC_WED .net_fill_forward_path = mt7915_net_fill_forward_path, + .net_setup_tc = mt7915_net_setup_tc, #endif }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 50ae7bf3af91..b22f06d4411a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -225,8 +225,10 @@ int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) static void mt7915_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 @@ -326,7 +328,7 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb) static void mt7915_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); @@ -906,6 +908,8 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_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 void @@ -1015,13 +1019,13 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; - int tx_ant = hweight8(phy->mt76->chainmask) - 1; + int sts = hweight16(phy->mt76->chainmask); if (vif->type != NL80211_IFTYPE_STATION && vif->type != NL80211_IFTYPE_AP) return false; - if (!bfee && tx_ant < 2) + if (!bfee && sts < 2) return false; if (sta->deflink.he_cap.has_he) { @@ -1882,10 +1886,9 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } -static void -mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, - struct sk_buff *rskb, struct bss_info_bcn *bcn, - u32 changed) +int +mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + u32 changed) { #define OFFLOAD_TX_MODE_SU BIT(0) #define OFFLOAD_TX_MODE_MU BIT(1) @@ -1895,14 +1898,27 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct bss_info_bcn *bcn; struct bss_info_inband_discovery *discov; struct ieee80211_tx_info *info; - struct sk_buff *skb = NULL; - struct tlv *tlv; + struct sk_buff *rskb, *skb = NULL; + struct tlv *tlv, *sub_tlv; bool ext_phy = phy != &dev->phy; u8 *buf, interval; int len; + if (vif->bss_conf.nontransmitted) + return 0; + + rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL, + MT7915_MAX_BSS_OFFLOAD_SIZE); + if (IS_ERR(rskb)) + return PTR_ERR(rskb); + + tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); + bcn = (struct bss_info_bcn *)tlv; + bcn->enable = true; + if (changed & BSS_CHANGED_FILS_DISCOVERY && vif->bss_conf.fils_discovery.max_interval) { interval = vif->bss_conf.fils_discovery.max_interval; @@ -1913,27 +1929,29 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); } - if (!skb) - return; + if (!skb) { + dev_kfree_skb(rskb); + return -EINVAL; + } info = IEEE80211_SKB_CB(skb); info->control.vif = vif; info->band = band; - info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy); len = sizeof(*discov) + MT_TXD_SIZE + skb->len; len = (len & 0x3) ? ((len | 0x3) + 1) : len; - if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) { + if (skb->len > MT7915_MAX_BEACON_SIZE) { dev_err(dev->mt76.dev, "inband discovery size limit exceed\n"); + dev_kfree_skb(rskb); dev_kfree_skb(skb); - return; + return -EINVAL; } - tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV, - len, &bcn->sub_ntlv, &bcn->len); - discov = (struct bss_info_inband_discovery *)tlv; + sub_tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV, + len, &bcn->sub_ntlv, &bcn->len); + discov = (struct bss_info_inband_discovery *)sub_tlv; discov->tx_mode = OFFLOAD_TX_MODE_SU; /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */ discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); @@ -1941,13 +1959,16 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); discov->enable = true; - buf = (u8 *)tlv + sizeof(*discov); + buf = (u8 *)sub_tlv + sizeof(*discov); mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL, 0, changed); memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); dev_kfree_skb(skb); + + return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, + MCU_EXT_CMD(BSS_INFO_UPDATE), true); } int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1980,11 +2001,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; skb = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!skb) + if (!skb) { + dev_kfree_skb(rskb); return -EINVAL; + } - if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) { + if (skb->len > MT7915_MAX_BEACON_SIZE) { dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(rskb); dev_kfree_skb(skb); return -EINVAL; } @@ -1997,11 +2021,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); dev_kfree_skb(skb); - if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || - changed & BSS_CHANGED_FILS_DISCOVERY) - mt7915_mcu_beacon_inband_discov(dev, vif, rskb, - bcn, changed); - out: return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, MCU_EXT_CMD(BSS_INFO_UPDATE), true); @@ -2725,10 +2744,10 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) if (mt76_connac_spe_idx(phy->mt76->antenna_mask)) req.tx_path_num = fls(phy->mt76->antenna_mask); - if (cmd == MCU_EXT_CMD(SET_RX_PATH) || - dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL || + phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, NL80211_IFTYPE_AP)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index b9ea297f382c..1592b5d6751a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -495,10 +495,14 @@ enum { SER_RECOVER }; -#define MT7915_MAX_BEACON_SIZE 512 -#define MT7915_MAX_INBAND_FRAME_SIZE 256 -#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \ - MT7915_MAX_INBAND_FRAME_SIZE + \ +#define MT7915_MAX_BEACON_SIZE 1308 +#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct bss_info_bcn) + \ + sizeof(struct bss_info_bcn_cntdwn) + \ + sizeof(struct bss_info_bcn_mbss) + \ + MT_TXD_SIZE + \ + sizeof(struct bss_info_bcn_cont)) +#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \ MT7915_BEACON_UPDATE_SIZE) #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ @@ -511,12 +515,6 @@ enum { sizeof(struct bss_info_bmc_rate) +\ sizeof(struct bss_info_ext_bss)) -#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ - sizeof(struct bss_info_bcn_cntdwn) + \ - sizeof(struct bss_info_bcn_mbss) + \ - sizeof(struct bss_info_bcn_cont) + \ - sizeof(struct bss_info_inband_discovery)) - static inline s8 mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 0456e56f6348..d317c523b23f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -295,6 +295,8 @@ struct mt7915_dev { bool muru_debug; bool ibf; + u8 monitor_mask; + struct dentry *debugfs_dir; struct rchan *relay_fwlog; @@ -447,6 +449,8 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, bool add); int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct cfg80211_he_bss_color *he_bss_color); +int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + u32 changed); int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int enable, u32 changed); int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index 588cd87e24e9..89ac8e6707b8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -172,6 +172,7 @@ enum offs_rev { #define MT_MDP_DCR0 MT_MDP(0x000) #define MT_MDP_DCR0_DAMSDU_EN BIT(15) +#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19) #define MT_MDP_DCR1 MT_MDP(0x004) #define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 37348b208736..06e3d9db996c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -1219,10 +1219,7 @@ static int mt798x_wmac_init(struct mt7915_dev *dev) return PTR_ERR(dev->sku); dev->rstc = devm_reset_control_get(pdev, "consys"); - if (IS_ERR(dev->rstc)) - return PTR_ERR(dev->rstc); - - return 0; + return PTR_ERR_OR_ZERO(dev->rstc); } static int mt798x_wmac_probe(struct platform_device *pdev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index ff63f37f67d9..55baac70860b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -55,10 +55,56 @@ static int mt7921_thermal_init(struct mt792x_phy *phy) hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, mt7921_hwmon_groups); - if (IS_ERR(hwmon)) - return PTR_ERR(hwmon); + return PTR_ERR_OR_ZERO(hwmon); +} - return 0; +static void +mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) +{ +#define IS_UNII_INVALID(idx, sfreq, efreq) \ + (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq)) + struct ieee80211_supported_band *sband; + struct mt76_dev *mdev = &dev->mt76; + struct device_node *np, *band_np; + struct ieee80211_channel *ch; + int i, cfreq; + + np = mt76_find_power_limits_node(mdev); + + sband = wiphy->bands[NL80211_BAND_5GHZ]; + band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL; + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + cfreq = ch->center_freq; + + if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) { + ch->flags |= IEEE80211_CHAN_DISABLED; + continue; + } + + /* UNII-4 */ + if (IS_UNII_INVALID(0, 5850, 5925)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } + + sband = wiphy->bands[NL80211_BAND_6GHZ]; + band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL; + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + cfreq = ch->center_freq; + + if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) { + ch->flags |= IEEE80211_CHAN_DISABLED; + continue; + } + + /* UNII-5/6/7/8 */ + if (IS_UNII_INVALID(1, 5925, 6425) || + IS_UNII_INVALID(2, 6425, 6525) || + IS_UNII_INVALID(3, 6525, 6875) || + IS_UNII_INVALID(4, 6875, 7125)) + ch->flags |= IEEE80211_CHAN_DISABLED; + } } static void @@ -77,6 +123,8 @@ mt7921_regd_notifier(struct wiphy *wiphy, mt76_connac_mcu_set_channel_domain(hw->priv); mt7921_set_tx_sar_pwr(hw, NULL); mt792x_mutex_release(dev); + + mt7921_regd_channel_update(wiphy, dev); } int mt7921_mac_init(struct mt792x_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 21f937454229..867e14f6b93a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -794,7 +794,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb); type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0; - mt7921_skb_add_usb_sdio_hdr(dev, skb, type); + mt792x_skb_add_usb_sdio_hdr(dev, skb, type); pad = round_up(skb->len, 4) - skb->len; if (mt76_is_usb(mdev)) pad += 4; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 62e6da1386aa..510a575a973b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -259,25 +259,6 @@ static int mt7921_start(struct ieee80211_hw *hw) return err; } -void mt7921_stop(struct ieee80211_hw *hw) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt792x_hw_phy(hw); - - cancel_delayed_work_sync(&phy->mt76->mac_work); - - cancel_delayed_work_sync(&dev->pm.ps_work); - cancel_work_sync(&dev->pm.wake_work); - cancel_work_sync(&dev->reset_work); - mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - - mt792x_mutex_acquire(dev); - clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); - mt792x_mutex_release(dev); -} -EXPORT_SYMBOL_GPL(mt7921_stop); - static int mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -315,7 +296,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mvif->sta.wcid.phy_idx = mvif->mt76.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); mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -701,6 +682,38 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, mt792x_mutex_release(dev); } +static void +mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mvif->phy; + struct mt792x_dev *dev = phy->dev; + + if (hweight64(dev->mt76.vif_mask) > 1) { + phy->power_type = MT_AP_DEFAULT; + goto out; + } + + switch (vif->bss_conf.power_type) { + case IEEE80211_REG_SP_AP: + phy->power_type = MT_AP_SP; + break; + case IEEE80211_REG_VLP_AP: + phy->power_type = MT_AP_VLP; + break; + case IEEE80211_REG_LPI_AP: + phy->power_type = MT_AP_LPI; + break; + case IEEE80211_REG_UNSET_AP: + default: + phy->power_type = MT_AP_DEFAULT; + break; + } + +out: + mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env); +} + int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { @@ -736,6 +749,8 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (ret) return ret; + mt7921_regd_set_6ghz_power_type(vif); + mt76_connac_power_save_sched(&dev->mphy, &dev->pm); return 0; @@ -753,7 +768,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, - true, mvif->ctx); + true, mvif->mt76.ctx); ewma_avg_signal_init(&msta->avg_ack_signal); @@ -788,7 +803,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (!sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, false, - mvif->ctx); + mvif->mt76.ctx); } spin_lock_bh(&dev->mt76.sta_poll_lock); @@ -1205,7 +1220,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt792x_mutex_acquire(dev); err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, - true, mvif->ctx); + true, mvif->mt76.ctx); if (err) goto out; @@ -1237,7 +1252,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false, - mvif->ctx); + mvif->mt76.ctx); out: mt792x_mutex_release(dev); @@ -1262,7 +1277,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct ieee80211_chanctx_conf *ctx = priv; - if (ctx != mvif->ctx) + if (ctx != mvif->mt76.ctx) return; if (vif->type == NL80211_IFTYPE_MONITOR) @@ -1295,7 +1310,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, jiffies_to_msecs(HZ); mt792x_mutex_acquire(dev); - mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration, + mt7921_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration, MT7921_ROC_REQ_JOIN); mt792x_mutex_release(dev); } @@ -1312,7 +1327,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, const struct ieee80211_ops mt7921_ops = { .tx = mt792x_tx, .start = mt7921_start, - .stop = mt7921_stop, + .stop = mt792x_stop, .add_interface = mt7921_add_interface, .remove_interface = mt792x_remove_interface, .config = mt7921_config, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 90c93970acab..63f3d4a5c9aa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -448,6 +448,129 @@ out: return ret; } +static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev, + struct sk_buff *skb) +{ + struct mt76_sdio *sdio = &dev->sdio; + struct mt7921_tx_resource { + __le32 version; + __le32 pse_data_quota; + __le32 pse_mcu_quota; + __le32 ple_data_quota; + __le32 ple_mcu_quota; + __le16 pse_page_size; + __le16 ple_page_size; + u8 pp_padding; + u8 pad[3]; + } __packed * tx_res; + + tx_res = (struct mt7921_tx_resource *)skb->data; + sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota); + sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota); + sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota); + sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size); + sdio->sched.deficit = tx_res->pp_padding; +} + +static void mt7921_mcu_parse_phy_cap(struct mt76_dev *dev, + struct sk_buff *skb) +{ + struct mt7921_phy_cap { + u8 ht; + u8 vht; + u8 _5g; + u8 max_bw; + u8 nss; + u8 dbdc; + u8 tx_ldpc; + u8 rx_ldpc; + u8 tx_stbc; + u8 rx_stbc; + u8 hw_path; + u8 he; + } __packed * cap; + + enum { + WF0_24G, + WF0_5G + }; + + cap = (struct mt7921_phy_cap *)skb->data; + + dev->phy.antenna_mask = BIT(cap->nss) - 1; + dev->phy.chainmask = dev->phy.antenna_mask; + dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G); + dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G); +} + +static int mt7921_mcu_get_nic_capability(struct mt792x_phy *mphy) +{ + struct mt76_connac_cap_hdr { + __le16 n_element; + u8 rsv[2]; + } __packed * hdr; + struct sk_buff *skb; + struct mt76_phy *phy = mphy->mt76; + int ret, i; + + ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB), + NULL, 0, true, &skb); + if (ret) + return ret; + + hdr = (struct mt76_connac_cap_hdr *)skb->data; + if (skb->len < sizeof(*hdr)) { + ret = -EINVAL; + goto out; + } + + skb_pull(skb, sizeof(*hdr)); + + for (i = 0; i < le16_to_cpu(hdr->n_element); i++) { + struct tlv_hdr { + __le32 type; + __le32 len; + } __packed * tlv = (struct tlv_hdr *)skb->data; + int len; + + if (skb->len < sizeof(*tlv)) + break; + + skb_pull(skb, sizeof(*tlv)); + + len = le32_to_cpu(tlv->len); + if (skb->len < len) + break; + + switch (le32_to_cpu(tlv->type)) { + case MT_NIC_CAP_6G: + phy->cap.has_6ghz = skb->data[0]; + break; + case MT_NIC_CAP_MAC_ADDR: + memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN); + break; + case MT_NIC_CAP_PHY: + mt7921_mcu_parse_phy_cap(phy->dev, skb); + break; + case MT_NIC_CAP_TX_RESOURCE: + if (mt76_is_sdio(phy->dev)) + mt7921_mcu_parse_tx_resource(phy->dev, + skb); + break; + case MT_NIC_CAP_CHIP_CAP: + memcpy(&mphy->chip_cap, (void *)skb->data, sizeof(u64)); + break; + default: + break; + } + skb_pull(skb, len); + } +out: + dev_kfree_skb(skb); + + return ret; +} + int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) { struct { @@ -469,7 +592,7 @@ int mt7921_run_firmware(struct mt792x_dev *dev) if (err) return err; - err = mt76_connac_mcu_get_nic_capability(&dev->mphy); + err = mt7921_mcu_get_nic_capability(&dev->phy); if (err) return err; @@ -1123,7 +1246,9 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, struct mt7921_clc *clc, u8 idx) { - struct sk_buff *skb; +#define CLC_CAP_EVT_EN BIT(0) +#define CLC_CAP_DTS_EN BIT(1) + struct sk_buff *skb, *ret_skb = NULL; struct { u8 ver; u8 pad0; @@ -1131,13 +1256,15 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, u8 idx; u8 env; u8 acpi_conf; - u8 pad1; + u8 cap; u8 alpha2[2]; u8 type[2]; - u8 rsvd[64]; + u8 env_6g; + u8 rsvd[63]; } __packed req = { .idx = idx, .env = env_cap, + .env_6g = dev->phy.power_type, .acpi_conf = mt792x_acpi_get_flags(&dev->phy), }; int ret, valid_cnt = 0; @@ -1146,6 +1273,11 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, if (!clc) return 0; + if (dev->phy.chip_cap & MT792x_CHIP_CAP_CLC_EVT_EN) + req.cap |= CLC_CAP_EVT_EN; + if (mt76_find_power_limits_node(&dev->mt76)) + req.cap |= CLC_CAP_DTS_EN; + pos = clc->data; for (i = 0; i < clc->nr_country; i++) { struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos; @@ -1167,10 +1299,21 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, return -ENOMEM; skb_put_data(skb, rule->data, len); - ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_CE_CMD(SET_CLC), false); + ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb, + MCU_CE_CMD(SET_CLC), + !!(req.cap & CLC_CAP_EVT_EN), + &ret_skb); if (ret < 0) return ret; + + if (ret_skb) { + struct mt7921_clc_info_tlv *info; + + info = (struct mt7921_clc_info_tlv *)(ret_skb->data + 4); + dev->phy.clc_chan_conf = info->chan_conf; + dev_kfree_skb(ret_skb); + } + valid_cnt++; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index 9b0aa3b70f0e..f9a259ee6b82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -99,4 +99,17 @@ struct mt7921_rftest_evt { __le32 param0; __le32 param1; } __packed; + +struct mt7921_clc_info_tlv { + __le16 tag; + __le16 len; + + u8 chan_conf; /* BIT(0) : Enable UNII-4 + * BIT(1) : Enable UNII-5 + * BIT(2) : Enable UNII-6 + * BIT(3) : Enable UNII-7 + * BIT(4) : Enable UNII-8 + */ + u8 rsv[63]; +} __packed; #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 87dd06855f68..f28621121927 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -23,10 +23,8 @@ #define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM #define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1) -#define MT7921_SDIO_HDR_TX_BYTES GENMASK(15, 0) -#define MT7921_SDIO_HDR_PKT_TYPE GENMASK(17, 16) - #define MCU_UNI_EVENT_ROC 0x27 +#define MCU_UNI_EVENT_CLC 0x80 enum { UNI_ROC_ACQUIRE, @@ -235,20 +233,6 @@ mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val) #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) -static inline void -mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, - int type) -{ - u32 hdr, len; - - len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr); - hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) | - FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type); - - put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr))); -} - -void mt7921_stop(struct ieee80211_hw *hw); int mt7921_mac_init(struct mt792x_dev *dev); bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 3dda84a93717..f04e7095e181 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -17,6 +17,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = { .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM }, { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7922), .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM }, + { PCI_DEVICE(PCI_VENDOR_ID_ITTIM, 0x7922), + .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM }, { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608), .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM }, { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616), diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index e7a995e7e70a..c866144ff061 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -48,7 +48,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, memset(txp, 0, sizeof(struct mt76_connac_hw_txp)); mt76_connac_write_hw_txp(mdev, tx_info, txp, id); - tx_info->skb = DMA_DUMMY_DATA; + tx_info->skb = NULL; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 310eeca024ad..5e4501d7f1c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -38,7 +38,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, if (cmd == MCU_CMD(FW_SCATTER)) type = MT7921_SDIO_FWDL; - mt7921_skb_add_usb_sdio_hdr(dev, skb, type); + mt792x_skb_add_usb_sdio_hdr(dev, skb, type); pad = round_up(skb->len, 4) - skb->len; __skb_put_zero(skb, pad); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 59cd3d98bf90..e5258c74fc07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -43,7 +43,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, else ep = MT_EP_OUT_AC_BE; - mt7921_skb_add_usb_sdio_hdr(dev, skb, 0); + mt792x_skb_add_usb_sdio_hdr(dev, skb, 0); pad = round_up(skb->len, 4) + 4 - skb->len; __skb_put_zero(skb, pad); @@ -135,14 +135,6 @@ out: return err; } -static void mt7921u_stop(struct ieee80211_hw *hw) -{ - struct mt792x_dev *dev = mt792x_hw_dev(hw); - - mt76u_stop_tx(&dev->mt76); - mt7921_stop(hw); -} - static int mt7921u_probe(struct usb_interface *usb_intf, const struct usb_device_id *id) { @@ -189,7 +181,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (!ops) return -ENOMEM; - ops->stop = mt7921u_stop; + ops->stop = mt792xu_stop; mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); if (!mdev) return -ENOMEM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7925/Kconfig new file mode 100644 index 000000000000..5854e95e68a5 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/Kconfig @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: ISC +config MT7925_COMMON + tristate + select MT792x_LIB + select WANT_DEV_COREDUMP + +config MT7925E + tristate "MediaTek MT7925E (PCIe) support" + select MT7925_COMMON + depends on MAC80211 + depends on PCI + help + This adds support for MT7925-based wireless PCIe devices, + which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be + 2x2:2SS 4096-QAM, 160MHz channels. + + To compile this driver as a module, choose M here. + +config MT7925U + tristate "MediaTek MT7925U (USB) support" + select MT792x_USB + select MT7925_COMMON + depends on MAC80211 + depends on USB + help + This adds support for MT7925-based wireless USB devices, + which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be + 2x2:2SS 4096-QAM, 160MHz channels. + + To compile this driver as a module, choose M here. diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile new file mode 100644 index 000000000000..d321e4ed732f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: ISC + +obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o +obj-$(CONFIG_MT7925E) += mt7925e.o +obj-$(CONFIG_MT7925U) += mt7925u.o + +mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o +mt7925e-y := pci.o pci_mac.o pci_mcu.o +mt7925u-y := usb.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c new file mode 100644 index 000000000000..1e2fc6577e78 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt7925.h" +#include "mcu.h" + +static int +mt7925_reg_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + u32 regval = val; + + mt792x_mutex_acquire(dev); + mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, ®val, true); + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_reg_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + u32 regval; + int ret; + + mt792x_mutex_acquire(dev); + ret = mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, ®val, false); + mt792x_mutex_release(dev); + if (!ret) + *val = regval; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set, + "0x%08llx\n"); +static int +mt7925_fw_debug_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + + mt792x_mutex_acquire(dev); + + dev->fw_debug = (u8)val; + mt7925_mcu_fw_log_2_host(dev, dev->fw_debug); + + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_fw_debug_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = dev->fw_debug; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get, + mt7925_fw_debug_set, "%lld\n"); + +DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats); + +static void +mt7925_seq_puts_array(struct seq_file *file, const char *str, + s8 val[][2], int len, u8 band_idx) +{ + int i; + + seq_printf(file, "%-22s:", str); + for (i = 0; i < len; i++) + if (val[i][band_idx] == 127) + seq_printf(file, " %6s", "N.A"); + else + seq_printf(file, " %6d", val[i][band_idx]); + seq_puts(file, "\n"); +} + +#define mt7925_print_txpwr_entry(prefix, rate, idx) \ +({ \ + mt7925_seq_puts_array(s, #prefix " (tmac)", \ + txpwr->rate, \ + ARRAY_SIZE(txpwr->rate), \ + idx); \ +}) + +static inline void +mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx) +{ + seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11", + "mcs12", "mcs13", "mcs14", "mcs15"); + mt7925_print_txpwr_entry(EHT26, eht26, band_idx); + mt7925_print_txpwr_entry(EHT52, eht52, band_idx); + mt7925_print_txpwr_entry(EHT106, eht106, band_idx); + mt7925_print_txpwr_entry(EHT242, eht242, band_idx); + mt7925_print_txpwr_entry(EHT484, eht484, band_idx); + + mt7925_print_txpwr_entry(EHT996, eht996, band_idx); + mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx); + mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx); + mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx); + mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx); + mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx); + mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx); + mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx); + mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx); + mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx); + mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx); +} + +static int +mt7925_txpwr(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + struct mt7925_txpwr *txpwr = NULL; + u8 band_idx = dev->mphy.band_idx; + int ret = 0; + + txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL); + + if (!txpwr) + return -ENOMEM; + + mt792x_mutex_acquire(dev); + ret = mt7925_get_txpwr_info(dev, band_idx, txpwr); + mt792x_mutex_release(dev); + + if (ret) + goto out; + + seq_printf(s, "%-22s %6s %6s %6s %6s\n", + " ", "1m", "2m", "5m", "11m"); + mt7925_print_txpwr_entry(CCK, cck, band_idx); + + seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "6m", "9m", "12m", "18m", "24m", "36m", + "48m", "54m"); + mt7925_print_txpwr_entry(OFDM, ofdm, band_idx); + + seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7"); + mt7925_print_txpwr_entry(HT20, ht20, band_idx); + + seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs32"); + mt7925_print_txpwr_entry(HT40, ht40, band_idx); + + seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); + mt7925_print_txpwr_entry(VHT20, vht20, band_idx); + mt7925_print_txpwr_entry(VHT40, vht40, band_idx); + + mt7925_print_txpwr_entry(VHT80, vht80, band_idx); + mt7925_print_txpwr_entry(VHT160, vht160, band_idx); + + mt7925_print_txpwr_entry(HE26, he26, band_idx); + mt7925_print_txpwr_entry(HE52, he52, band_idx); + mt7925_print_txpwr_entry(HE106, he106, band_idx); + mt7925_print_txpwr_entry(HE242, he242, band_idx); + mt7925_print_txpwr_entry(HE484, he484, band_idx); + + mt7925_print_txpwr_entry(HE996, he996, band_idx); + mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx); + + mt7925_eht_txpwr(s, txpwr, band_idx); + +out: + devm_kfree(dev->mt76.dev, txpwr); + return ret; +} + +static int +mt7925_pm_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + struct mt76_connac_pm *pm = &dev->pm; + + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + + mutex_lock(&dev->mt76.mutex); + + if (val == pm->enable_user) + goto out; + + if (!pm->enable_user) { + pm->stats.last_wake_event = jiffies; + pm->stats.last_doze_event = jiffies; + } + /* make sure the chip is awake here and ps_work is scheduled + * just at end of the this routine. + */ + pm->enable = false; + mt76_connac_pm_wake(&dev->mphy, pm); + + pm->enable_user = val; + mt7925_set_runtime_pm(dev); + mt76_connac_power_save_sched(&dev->mphy, pm); +out: + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7925_pm_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = dev->pm.enable_user; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, "%lld\n"); + +static int +mt7925_deep_sleep_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); + bool enable = !!val; + + if (mt76_is_usb(&dev->mt76)) + return -EOPNOTSUPP; + + mt792x_mutex_acquire(dev); + if (pm->ds_enable_user == enable) + goto out; + + pm->ds_enable_user = enable; + pm->ds_enable = enable && !monitor; + mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); +out: + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_deep_sleep_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = dev->pm.ds_enable_user; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get, + mt7925_deep_sleep_set, "%lld\n"); + +DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get, + mt792x_pm_idle_timeout_set, "%lld\n"); + +static int mt7925_chip_reset(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + int ret = 0; + + switch (val) { + case 1: + /* Reset wifisys directly. */ + mt792x_reset(&dev->mt76); + break; + default: + /* Collect the core dump before reset wifisys. */ + mt792x_mutex_acquire(dev); + ret = mt7925_mcu_chip_config(dev, "assert"); + mt792x_mutex_release(dev); + break; + } + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n"); + +int mt7925_init_debugfs(struct mt792x_dev *dev) +{ + struct dentry *dir; + + dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval); + if (!dir) + return -ENOMEM; + + if (mt76_is_mmio(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt792x_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", + dir, mt76_queues_read); + + debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, + mt792x_queues_acq); + debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, + mt7925_txpwr); + debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops); + debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); + debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); + debugfs_create_file("idle-timeout", 0600, dir, dev, + &fops_pm_idle_timeout); + debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset); + debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, + mt792x_pm_stats); + debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c new file mode 100644 index 000000000000..8f9b7a2f376c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/etherdevice.h> +#include <linux/firmware.h> +#include "mt7925.h" +#include "mac.h" +#include "mcu.h" + +static void +mt7925_regd_notifier(struct wiphy *wiphy, + struct regulatory_request *req) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_dev *mdev = &dev->mt76; + + /* allow world regdom at the first boot only */ + if (!memcmp(req->alpha2, "00", 2) && + mdev->alpha2[0] && mdev->alpha2[1]) + return; + + /* do not need to update the same country twice */ + if (!memcmp(req->alpha2, mdev->alpha2, 2) && + dev->country_ie_env == req->country_ie_env) + return; + + memcpy(mdev->alpha2, req->alpha2, 2); + mdev->region = req->dfs_region; + dev->country_ie_env = req->country_ie_env; + + mt792x_mutex_acquire(dev); + mt7925_mcu_set_clc(dev, req->alpha2, req->country_ie_env); + mt7925_mcu_set_channel_domain(hw->priv); + mt7925_set_tx_sar_pwr(hw, NULL); + mt792x_mutex_release(dev); +} + +static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) { + u16 rate = mt76_rates[i].hw_value; + u16 idx = MT792x_BASIC_RATES_TBL + i; + + rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) | + FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0)); + mt7925_mac_set_fixed_rate_table(dev, idx, rate); + } +} + +int mt7925_mac_init(struct mt792x_dev *dev) +{ + int i; + + mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); + /* enable hardware de-agg */ + mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); + + for (i = 0; i < MT792x_WTBL_SIZE; i++) + mt7925_mac_wtbl_update(dev, i, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + for (i = 0; i < 2; i++) + mt792x_mac_init_band(dev, i); + + mt7925_mac_init_basic_rates(dev); + + memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2)); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_mac_init); + +static int __mt7925_init_hardware(struct mt792x_dev *dev) +{ + int ret; + + ret = mt792x_mcu_init(dev); + if (ret) + goto out; + + mt76_eeprom_override(&dev->mphy); + + ret = mt7925_mcu_set_eeprom(dev); + if (ret) + goto out; + + ret = mt7925_mac_init(dev); + if (ret) + goto out; + +out: + return ret; +} + +static int mt7925_init_hardware(struct mt792x_dev *dev) +{ + int ret, i; + + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + + for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) { + ret = __mt7925_init_hardware(dev); + if (!ret) + break; + + mt792x_init_reset(dev); + } + + if (i == MT792x_MCU_INIT_RETRY_COUNT) { + dev_err(dev->mt76.dev, "hardware init failed\n"); + return ret; + } + + return 0; +} + +static void mt7925_init_work(struct work_struct *work) +{ + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + init_work); + int ret; + + ret = mt7925_init_hardware(dev); + if (ret) + return; + + mt76_set_stream_caps(&dev->mphy, true); + mt7925_set_stream_he_eht_caps(&dev->phy); + + ret = mt76_register_device(&dev->mt76, true, mt76_rates, + ARRAY_SIZE(mt76_rates)); + if (ret) { + dev_err(dev->mt76.dev, "register device failed\n"); + return; + } + + ret = mt7925_init_debugfs(dev); + if (ret) { + dev_err(dev->mt76.dev, "register debugfs failed\n"); + return; + } + + /* we support chip reset now */ + dev->hw_init_done = true; + + mt7925_mcu_set_deep_sleep(dev, dev->pm.ds_enable); +} + +int mt7925_register_device(struct mt792x_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + dev->mt76.tx_worker.fn = mt792x_tx_worker; + + INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work); + INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work); + spin_lock_init(&dev->pm.wake.lock); + mutex_init(&dev->pm.mutex); + init_waitqueue_head(&dev->pm.wait); + spin_lock_init(&dev->pm.txq_lock); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work); + INIT_DELAYED_WORK(&dev->phy.scan_work, mt7925_scan_work); + INIT_DELAYED_WORK(&dev->coredump.work, mt7925_coredump_work); +#if IS_ENABLED(CONFIG_IPV6) + INIT_WORK(&dev->ipv6_ns_work, mt7925_set_ipv6_ns_work); + skb_queue_head_init(&dev->ipv6_ns_list); +#endif + skb_queue_head_init(&dev->phy.scan_event_list); + skb_queue_head_init(&dev->coredump.msg_list); + + INIT_WORK(&dev->reset_work, mt7925_mac_reset_work); + INIT_WORK(&dev->init_work, mt7925_init_work); + + INIT_WORK(&dev->phy.roc_work, mt7925_roc_work); + timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0); + init_waitqueue_head(&dev->phy.roc_wait); + + dev->pm.idle_timeout = MT792x_PM_TIMEOUT; + dev->pm.stats.last_wake_event = jiffies; + dev->pm.stats.last_doze_event = jiffies; + if (!mt76_is_usb(&dev->mt76)) { + dev->pm.enable_user = true; + dev->pm.enable = true; + dev->pm.ds_enable_user = true; + dev->pm.ds_enable = true; + } + + if (!mt76_is_mmio(&dev->mt76)) + hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; + + mt792x_init_acpi_sar(dev); + + ret = mt792x_init_wcid(dev); + if (ret) + return ret; + + ret = mt792x_init_wiphy(hw); + if (ret) + return ret; + + hw->wiphy->reg_notifier = mt7925_regd_notifier; + dev->mphy.sband_2g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + dev->mphy.sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_2; + dev->mphy.sband_5g.sband.ht_cap.cap |= + IEEE80211_HT_CAP_LDPC_CODING | + IEEE80211_HT_CAP_MAX_AMSDU; + dev->mphy.sband_2g.sband.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_1; + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | + (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + IEEE80211_VHT_CAP_SHORT_GI_160; + + dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; + + queue_work(system_wq, &dev->init_work); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_register_device); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c new file mode 100644 index 000000000000..1b9fbd9a140d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -0,0 +1,1452 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/devcoredump.h> +#include <linux/etherdevice.h> +#include <linux/timekeeping.h> +#include "mt7925.h" +#include "../dma.h" +#include "mac.h" +#include "mcu.h" + +bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask) +{ + mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); + + return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, + 0, 5000); +} + +static void mt7925_mac_sta_poll(struct mt792x_dev *dev) +{ + static const u8 ac_to_tid[] = { + [IEEE80211_AC_BE] = 0, + [IEEE80211_AC_BK] = 1, + [IEEE80211_AC_VI] = 4, + [IEEE80211_AC_VO] = 6 + }; + struct ieee80211_sta *sta; + struct mt792x_sta *msta; + u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; + LIST_HEAD(sta_poll_list); + struct rate_info *rate; + s8 rssi[4]; + int i; + + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + while (true) { + bool clear = false; + u32 addr, val; + u16 idx; + u8 bw; + + if (list_empty(&sta_poll_list)) + break; + msta = list_first_entry(&sta_poll_list, + struct mt792x_sta, wcid.poll_list); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + idx = msta->wcid.idx; + addr = mt7925_mac_wtbl_lmac_addr(dev, idx, MT_WTBL_AC0_CTT_OFFSET); + + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + u32 tx_last = msta->airtime_ac[i]; + u32 rx_last = msta->airtime_ac[i + 4]; + + msta->airtime_ac[i] = mt76_rr(dev, addr); + msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); + + tx_time[i] = msta->airtime_ac[i] - tx_last; + rx_time[i] = msta->airtime_ac[i + 4] - rx_last; + + if ((tx_last | rx_last) & BIT(30)) + clear = true; + + addr += 8; + } + + if (clear) { + mt7925_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + } + + if (!msta->wcid.sta) + continue; + + sta = container_of((void *)msta, struct ieee80211_sta, + drv_priv); + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + u8 q = mt76_connac_lmac_mapping(i); + u32 tx_cur = tx_time[q]; + u32 rx_cur = rx_time[q]; + u8 tid = ac_to_tid[i]; + + if (!tx_cur && !rx_cur) + continue; + + ieee80211_sta_register_airtime(sta, tid, tx_cur, + rx_cur); + } + + /* We don't support reading GI info from txs packets. + * For accurate tx status reporting and AQL improvement, + * we need to make sure that flags match so polling GI + * from per-sta counters directly. + */ + rate = &msta->wcid.rate; + + switch (rate->bw) { + case RATE_INFO_BW_160: + bw = IEEE80211_STA_RX_BW_160; + break; + case RATE_INFO_BW_80: + bw = IEEE80211_STA_RX_BW_80; + break; + case RATE_INFO_BW_40: + bw = IEEE80211_STA_RX_BW_40; + break; + default: + bw = IEEE80211_STA_RX_BW_20; + break; + } + + addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 6); + val = mt76_rr(dev, addr); + if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) { + addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 5); + val = mt76_rr(dev, addr); + rate->eht_gi = FIELD_GET(GENMASK(25, 24), val); + } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { + u8 offs = MT_WTBL_TXRX_RATE_G2_HE + 2 * bw; + + rate->he_gi = (val & (0x3 << offs)) >> offs; + } else if (rate->flags & + (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { + if (val & BIT(MT_WTBL_TXRX_RATE_G2 + bw)) + rate->flags |= RATE_INFO_FLAGS_SHORT_GI; + else + rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; + } + + /* get signal strength of resp frames (CTS/BA/ACK) */ + addr = mt7925_mac_wtbl_lmac_addr(dev, idx, 34); + val = mt76_rr(dev, addr); + + rssi[0] = to_rssi(GENMASK(7, 0), val); + rssi[1] = to_rssi(GENMASK(15, 8), val); + rssi[2] = to_rssi(GENMASK(23, 16), val); + rssi[3] = to_rssi(GENMASK(31, 14), val); + + msta->ack_signal = + mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); + + ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); + } +} + +void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev, + u8 tbl_idx, u16 rate_idx) +{ + u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx; + + mt76_wr(dev, MT_WTBL_ITDR0, rate_idx); + /* use wtbl spe idx */ + mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL); + mt76_wr(dev, MT_WTBL_ITCR, ctrl); +} + +/* The HW does not translate the mac header to 802.3 for mesh point */ +static int mt7925_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap); + struct mt792x_sta *msta = (struct mt792x_sta *)status->wcid; + __le32 *rxd = (__le32 *)skb->data; + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct ieee80211_hdr hdr; + u16 frame_control; + + if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != + MT_RXD3_NORMAL_U2M) + return -EINVAL; + + if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) + return -EINVAL; + + if (!msta || !msta->vif) + return -EINVAL; + + sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + + /* store the info from RXD and ethhdr to avoid being overridden */ + frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL); + hdr.frame_control = cpu_to_le16(frame_control); + hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL)); + hdr.duration_id = 0; + + ether_addr_copy(hdr.addr1, vif->addr); + ether_addr_copy(hdr.addr2, sta->addr); + switch (frame_control & (IEEE80211_FCTL_TODS | + IEEE80211_FCTL_FROMDS)) { + case 0: + ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); + break; + case IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_source); + break; + case IEEE80211_FCTL_TODS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + break; + case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: + ether_addr_copy(hdr.addr3, eth_hdr->h_dest); + ether_addr_copy(hdr.addr4, eth_hdr->h_source); + break; + default: + break; + } + + skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); + if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || + eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) + ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); + else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) + ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); + else + skb_pull(skb, 2); + + if (ieee80211_has_order(hdr.frame_control)) + memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11], + IEEE80211_HT_CTL_LEN); + if (ieee80211_is_data_qos(hdr.frame_control)) { + __le16 qos_ctrl; + + qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL)); + memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, + IEEE80211_QOS_CTL_LEN); + } + + if (ieee80211_has_a4(hdr.frame_control)) + memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); + else + memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); + + return 0; +} + +static int +mt7925_mac_fill_rx_rate(struct mt792x_dev *dev, + struct mt76_rx_status *status, + struct ieee80211_supported_band *sband, + __le32 *rxv, u8 *mode) +{ + u32 v0, v2; + u8 stbc, gi, bw, dcm, nss; + int i, idx; + bool cck = false; + + v0 = le32_to_cpu(rxv[0]); + v2 = le32_to_cpu(rxv[2]); + + idx = FIELD_GET(MT_PRXV_TX_RATE, v0); + i = idx; + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; + + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2); + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2); + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2); + dcm = FIELD_GET(MT_PRXV_DCM, v2); + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2); + + switch (*mode) { + case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; + case MT_PHY_TYPE_OFDM: + i = mt76_get_rate(&dev->mt76, sband, i, cck); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + status->encoding = RX_ENC_HT; + if (gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (i > 31) + return -EINVAL; + break; + case MT_PHY_TYPE_VHT: + status->nss = nss; + status->encoding = RX_ENC_VHT; + if (gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (i > 11) + return -EINVAL; + break; + case MT_PHY_TYPE_HE_MU: + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + status->nss = nss; + status->encoding = RX_ENC_HE; + i &= GENMASK(3, 0); + + if (gi <= NL80211_RATE_INFO_HE_GI_3_2) + status->he_gi = gi; + + status->he_dcm = dcm; + break; + case MT_PHY_TYPE_EHT_SU: + case MT_PHY_TYPE_EHT_TRIG: + case MT_PHY_TYPE_EHT_MU: + status->nss = nss; + status->encoding = RX_ENC_EHT; + i &= GENMASK(3, 0); + + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2) + status->eht.gi = gi; + break; + default: + return -EINVAL; + } + status->rate_idx = i; + + switch (bw) { + case IEEE80211_STA_RX_BW_20: + break; + case IEEE80211_STA_RX_BW_40: + if (*mode & MT_PHY_TYPE_HE_EXT_SU && + (idx & MT_PRXV_TX_ER_SU_106T)) { + status->bw = RATE_INFO_BW_HE_RU; + status->he_ru = + NL80211_RATE_INFO_HE_RU_ALLOC_106; + } else { + status->bw = RATE_INFO_BW_40; + } + break; + case IEEE80211_STA_RX_BW_80: + status->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_160: + status->bw = RATE_INFO_BW_160; + break; + default: + return -EINVAL; + } + + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; + if (*mode < MT_PHY_TYPE_HE_SU && gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + + return 0; +} + +static int +mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) +{ + u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + bool hdr_trans, unicast, insert_ccmp_hdr = false; + u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info; + u16 hdr_gap; + __le32 *rxv = NULL, *rxd = (__le32 *)skb->data; + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt792x_phy *phy = &dev->phy; + struct ieee80211_supported_band *sband; + u32 csum_status = *(u32 *)skb->cb; + u32 rxd0 = le32_to_cpu(rxd[0]); + u32 rxd1 = le32_to_cpu(rxd[1]); + u32 rxd2 = le32_to_cpu(rxd[2]); + u32 rxd3 = le32_to_cpu(rxd[3]); + u32 rxd4 = le32_to_cpu(rxd[4]); + struct mt792x_sta *msta = NULL; + u8 mode = 0; /* , band_idx; */ + u16 seq_ctrl = 0; + __le16 fc = 0; + int idx; + + memset(status, 0, sizeof(*status)); + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + + hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; + if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) + return -EINVAL; + + /* ICV error or CCMP/BIP/WPI MIC error */ + if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) + status->flag |= RX_FLAG_ONLY_MONITOR; + + chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; + idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); + status->wcid = mt792x_rx_get_wcid(dev, idx, unicast); + + if (status->wcid) { + msta = container_of(status->wcid, struct mt792x_sta, wcid); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + } + + mt792x_get_status_freq_info(status, chfreq); + + switch (status->band) { + case NL80211_BAND_5GHZ: + sband = &mphy->sband_5g.sband; + break; + case NL80211_BAND_6GHZ: + sband = &mphy->sband_6g.sband; + break; + default: + sband = &mphy->sband_2g.sband; + break; + } + + if (!sband->channels) + return -EINVAL; + + if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && + !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (rxd3 & MT_RXD3_NORMAL_FCS_ERR) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + + if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && + !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { + status->flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_IV_STRIPPED; + status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; + } + + remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); + + if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) + return -EINVAL; + + rxd += 8; + if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { + u32 v0 = le32_to_cpu(rxd[0]); + u32 v2 = le32_to_cpu(rxd[2]); + + /* TODO: need to map rxd address */ + fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0)); + seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2); + qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2); + + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { + u8 *data = (u8 *)rxd; + + if (status->flag & RX_FLAG_DECRYPTED) { + switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { + case MT_CIPHER_AES_CCMP: + case MT_CIPHER_CCMP_CCX: + case MT_CIPHER_CCMP_256: + insert_ccmp_hdr = + FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + fallthrough; + case MT_CIPHER_TKIP: + case MT_CIPHER_TKIP_NO_MIC: + case MT_CIPHER_GCMP: + case MT_CIPHER_GCMP_256: + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + break; + default: + break; + } + } + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + /* RXD Group 3 - P-RXV */ + if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { + u32 v3; + int ret; + + rxv = rxd; + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + + v3 = le32_to_cpu(rxv[3]); + + status->chains = mphy->antenna_mask; + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3); + status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3); + status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3); + + /* RXD Group 5 - C-RXV */ + if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { + rxd += 24; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + ret = mt7925_mac_fill_rx_rate(dev, status, sband, rxv, &mode); + if (ret < 0) + return ret; + } + + amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); + status->amsdu = !!amsdu_info; + if (status->amsdu) { + status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; + status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; + } + + hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; + if (hdr_trans && ieee80211_has_morefrags(fc)) { + if (mt7925_reverse_frag0_hdr_trans(skb, hdr_gap)) + return -EINVAL; + hdr_trans = false; + } else { + int pad_start = 0; + + skb_pull(skb, hdr_gap); + if (!hdr_trans && status->amsdu) { + pad_start = ieee80211_get_hdrlen_from_skb(skb); + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { + /* When header translation failure is indicated, + * the hardware will insert an extra 2-byte field + * containing the data length after the protocol + * type field. + */ + pad_start = 12; + if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) + pad_start += 4; + else + pad_start = 0; + } + + if (pad_start) { + memmove(skb->data + 2, skb->data, pad_start); + skb_pull(skb, 2); + } + } + + if (!hdr_trans) { + struct ieee80211_hdr *hdr; + + if (insert_ccmp_hdr) { + u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + + mt76_insert_ccmp_hdr(skb, key_id); + } + + hdr = mt76_skb_get_hdr(skb); + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } + } else { + status->flag |= RX_FLAG_8023; + } + + mt792x_mac_assoc_rssi(dev, skb); + + if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) + mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); + + if (!status->wcid || !ieee80211_is_data_qos(fc)) + return 0; + + status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc); + status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); + status->qos_ctl = qos_ctl; + + return 0; +} + +static void +mt7925_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb, + struct mt76_wcid *wcid) +{ + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + u8 fc_type, fc_stype; + u16 ethertype; + bool wmm = false; + u32 val; + + if (wcid->sta) { + struct ieee80211_sta *sta; + + sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); + wmm = sta->wme; + } + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | + FIELD_PREP(MT_TXD1_TID, tid); + + ethertype = get_unaligned_be16(&skb->data[12]); + if (ethertype >= ETH_P_802_3_MIN) + val |= MT_TXD1_ETH_802_3; + + txwi[1] |= cpu_to_le32(val); + + fc_type = IEEE80211_FTYPE_DATA >> 2; + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + + txwi[2] |= cpu_to_le32(val); +} + +static void +mt7925_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, + struct ieee80211_key_conf *key) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool multicast = is_multicast_ether_addr(hdr->addr1); + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + __le16 fc = hdr->frame_control; + u8 fc_type, fc_stype; + u32 val; + + if (ieee80211_is_action(fc) && + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) + tid = MT_TX_ADDBA; + else if (ieee80211_is_mgmt(hdr->frame_control)) + tid = MT_TX_NORMAL; + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, + ieee80211_get_hdrlen_from_skb(skb) / 2) | + FIELD_PREP(MT_TXD1_TID, tid); + + if (!ieee80211_is_data(fc) || multicast || + info->flags & IEEE80211_TX_CTL_USE_MINRATE) + val |= MT_TXD1_FIXED_RATE; + + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + val |= MT_TXD1_BIP; + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); + } + + txwi[1] |= cpu_to_le32(val); + + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); + + txwi[2] |= cpu_to_le32(val); + + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); + if (ieee80211_is_beacon(fc)) + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); + + if (info->flags & IEEE80211_TX_CTL_INJECTED) { + u16 seqno = le16_to_cpu(hdr->seq_ctrl); + + if (ieee80211_is_back_req(hdr->frame_control)) { + struct ieee80211_bar *bar; + + bar = (struct ieee80211_bar *)skb->data; + seqno = le16_to_cpu(bar->start_seq_num); + } + + val = MT_TXD3_SN_VALID | + FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); + txwi[3] |= cpu_to_le32(val); + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); + } +} + +void +mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0; + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE; + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; + struct mt76_vif *mvif; + bool beacon = !!(changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)); + bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)); + + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; + if (mvif) { + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + band_idx = mvif->band_idx; + } + + if (inband_disc) { + p_fmt = MT_TX_TYPE_FW; + q_idx = MT_LMAC_ALTX0; + } else if (beacon) { + p_fmt = MT_TX_TYPE_FW; + q_idx = MT_LMAC_BCN0; + } else if (qid >= MT_TXQ_PSD) { + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; + q_idx = MT_LMAC_ALTX0; + } else { + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF; + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + + mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); + + /* counting non-offloading skbs */ + wcid->stats.tx_bytes += skb->len; + wcid->stats.tx_packets++; + } + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); + txwi[0] = cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); + + if (band_idx) + val |= FIELD_PREP(MT_TXD1_TGID, band_idx); + + txwi[1] = cpu_to_le32(val); + txwi[2] = 0; + + val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 15); + + if (key) + val |= MT_TXD3_PROTECT_FRAME; + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + val |= MT_TXD3_NO_ACK; + if (wcid->amsdu) + val |= MT_TXD3_HW_AMSDU; + + txwi[3] = cpu_to_le32(val); + txwi[4] = 0; + + val = FIELD_PREP(MT_TXD5_PID, pid); + if (pid >= MT_PACKET_ID_FIRST) { + val |= MT_TXD5_TX_STATUS_HOST; + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); + } + + txwi[5] = cpu_to_le32(val); + + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | + FIELD_PREP(MT_TXD6_MSDU_CNT, 1); + txwi[6] = cpu_to_le32(val); + txwi[7] = 0; + + if (is_8023) + mt7925_mac_write_txwi_8023(txwi, skb, wcid); + else + mt7925_mac_write_txwi_80211(dev, txwi, skb, key); + + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool mcast = ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1); + u8 idx = MT792x_BASIC_RATES_TBL; + + if (mvif) { + if (mcast && mvif->mcast_rates_idx) + idx = mvif->mcast_rates_idx; + else if (beacon && mvif->beacon_rates_idx) + idx = mvif->beacon_rates_idx; + else + idx = mvif->basic_rates_idx; + } + + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx)); + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + } +} +EXPORT_SYMBOL_GPL(mt7925_mac_write_txwi); + +static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +{ + struct mt792x_sta *msta; + 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); + 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 (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) + return; + + msta = (struct mt792x_sta *)sta->drv_priv; + if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) + ieee80211_start_tx_ba_session(sta, tid, 0); +} + +static bool +mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data) +{ + struct mt76_sta_stats *stats = &wcid->stats; + struct ieee80211_supported_band *sband; + struct mt76_dev *mdev = &dev->mt76; + struct mt76_phy *mphy; + struct ieee80211_tx_info *info; + struct sk_buff_head list; + struct rate_info rate = {}; + struct sk_buff *skb; + bool cck = false; + u32 txrate, txs, mode, stbc; + + 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]); + + 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; + + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); + + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); + + if (stbc && rate.nss > 1) + rate.nss >>= 1; + + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) + stats->tx_nss[rate.nss - 1]++; + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) + stats->tx_mcs[rate.mcs]++; + + mode = FIELD_GET(MT_TX_RATE_MODE, txrate); + switch (mode) { + case MT_PHY_TYPE_CCK: + cck = true; + fallthrough; + case MT_PHY_TYPE_OFDM: + mphy = mt76_dev_phy(mdev, wcid->phy_idx); + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) + sband = &mphy->sband_6g.sband; + else + sband = &mphy->sband_2g.sband; + + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); + rate.legacy = sband->bitrates[rate.mcs].bitrate; + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: + if (rate.mcs > 31) + goto out; + + rate.flags = RATE_INFO_FLAGS_MCS; + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) + rate.flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_VHT: + if (rate.mcs > 9) + goto out; + + rate.flags = RATE_INFO_FLAGS_VHT_MCS; + break; + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + case MT_PHY_TYPE_HE_MU: + if (rate.mcs > 11) + goto out; + + rate.he_gi = wcid->rate.he_gi; + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); + rate.flags = RATE_INFO_FLAGS_HE_MCS; + break; + case MT_PHY_TYPE_EHT_SU: + case MT_PHY_TYPE_EHT_TRIG: + case MT_PHY_TYPE_EHT_MU: + if (rate.mcs > 13) + goto out; + + rate.eht_gi = wcid->rate.eht_gi; + rate.flags = RATE_INFO_FLAGS_EHT_MCS; + break; + default: + goto out; + } + + stats->tx_mode[mode]++; + + switch (FIELD_GET(MT_TXS0_BW, txs)) { + case IEEE80211_STA_RX_BW_160: + rate.bw = RATE_INFO_BW_160; + stats->tx_bw[3]++; + break; + case IEEE80211_STA_RX_BW_80: + rate.bw = RATE_INFO_BW_80; + stats->tx_bw[2]++; + break; + case IEEE80211_STA_RX_BW_40: + rate.bw = RATE_INFO_BW_40; + stats->tx_bw[1]++; + break; + default: + rate.bw = RATE_INFO_BW_20; + stats->tx_bw[0]++; + break; + } + wcid->rate = rate; + +out: + mt76_tx_status_skb_done(mdev, skb, &list); + +out_no_skb: + mt76_tx_status_unlock(mdev, &list); + + return !!skb; +} + +void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data) +{ + struct mt792x_sta *msta = NULL; + struct mt76_wcid *wcid; + __le32 *txs_data = 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) + return; + + if (wcidx >= MT792x_WTBL_SIZE) + return; + + rcu_read_lock(); + + wcid = rcu_dereference(dev->mt76.wcid[wcidx]); + if (!wcid) + goto out; + + msta = container_of(wcid, struct mt792x_sta, wcid); + + mt7925_mac_add_txs_skb(dev, wcid, pid, txs_data); + if (!wcid->sta) + goto out; + + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + +out: + rcu_read_unlock(); +} + +void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, bool clear_status, + struct list_head *free_list) +{ + struct mt76_dev *mdev = &dev->mt76; + __le32 *txwi; + u16 wcid_idx; + + mt76_connac_txp_skb_unmap(mdev, t); + if (!t->skb) + goto out; + + txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); + if (sta) { + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7925_tx_check_aggr(sta, txwi); + + wcid_idx = wcid->idx; + } else { + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + } + + __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); +out: + t->skb = NULL; + mt76_put_txwi(mdev, t); +} +EXPORT_SYMBOL_GPL(mt7925_txwi_free); + +static void +mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len) +{ + __le32 *tx_free = (__le32 *)data, *cur_info; + struct mt76_dev *mdev = &dev->mt76; + 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; + bool wake = false; + u16 total, count = 0; + + /* clean DMA queues and unmap buffers first */ + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); + + if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4)) + return; + + total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); + for (cur_info = &tx_free[2]; count < total; cur_info++) { + u32 msdu, info; + u8 i; + + if (WARN_ON_ONCE((void *)cur_info >= end)) + return; + /* 1'b1: new wcid pair. + * 1'b0: msdu_id with the same 'wcid pair' as above. + */ + info = le32_to_cpu(*cur_info); + if (info & MT_TXFREE_INFO_PAIR) { + struct mt792x_sta *msta; + u16 idx; + + idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); + wcid = rcu_dereference(dev->mt76.wcid[idx]); + sta = wcid_to_sta(wcid); + if (!sta) + continue; + + msta = container_of(wcid, struct mt792x_sta, wcid); + spin_lock_bh(&mdev->sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); + continue; + } + + if (info & MT_TXFREE_INFO_HEADER) { + if (wcid) { + wcid->stats.tx_retries += + FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1; + wcid->stats.tx_failed += + !!FIELD_GET(MT_TXFREE_INFO_STAT, info); + } + continue; + } + + for (i = 0; i < 2; i++) { + msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID; + if (msdu == MT_TXFREE_INFO_MSDU_ID) + continue; + + count++; + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; + + mt7925_txwi_free(dev, txwi, sta, 0, &free_list); + } + } + + mt7925_mac_sta_poll(dev); + + if (wake) + mt76_set_tx_blocked(&dev->mt76, false); + + mt76_worker_schedule(&dev->mt76.tx_worker); + + list_for_each_entry_safe(skb, tmp, &free_list, list) { + skb_list_del_init(skb); + napi_consume_skb(skb, 1); + } +} + +bool mt7925_rx_check(struct mt76_dev *mdev, void *data, int len) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + __le32 *rxd = (__le32 *)data; + __le32 *end = (__le32 *)&rxd[len / 4]; + enum rx_pkt_type type; + + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + if (type != PKT_TYPE_NORMAL) { + u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); + + if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == + MT_RXD0_SW_PKT_TYPE_FRAME)) + return true; + } + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */ + mt7925_mac_tx_free(dev, data, len); /* mmio */ + return false; + case PKT_TYPE_TXS: + for (rxd += 4; rxd + 12 <= end; rxd += 12) + mt7925_mac_add_txs(dev, rxd); + return false; + default: + return true; + } +} +EXPORT_SYMBOL_GPL(mt7925_rx_check); + +void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb, u32 *info) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + __le32 *rxd = (__le32 *)skb->data; + __le32 *end = (__le32 *)&skb->data[skb->len]; + enum rx_pkt_type type; + u16 flag; + + type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); + flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG); + if (type != PKT_TYPE_NORMAL) { + u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); + + if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == + MT_RXD0_SW_PKT_TYPE_FRAME)) + type = PKT_TYPE_NORMAL; + } + + if (type == PKT_TYPE_RX_EVENT && flag == 0x1) + type = PKT_TYPE_NORMAL_MCU; + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */ + mt7925_mac_tx_free(dev, skb->data, skb->len); + napi_consume_skb(skb, 1); + break; + case PKT_TYPE_RX_EVENT: + mt7925_mcu_rx_event(dev, skb); + break; + case PKT_TYPE_TXS: + for (rxd += 2; rxd + 8 <= end; rxd += 8) + mt7925_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; + case PKT_TYPE_NORMAL_MCU: + case PKT_TYPE_NORMAL: + if (!mt7925_mac_fill_rx(dev, skb)) { + mt76_rx(&dev->mt76, q, skb); + return; + } + fallthrough; + default: + dev_kfree_skb(skb); + break; + } +} +EXPORT_SYMBOL_GPL(mt7925_queue_rx_skb); + +static void +mt7925_vif_connect_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mvif->phy->dev; + struct ieee80211_hw *hw = mt76_hw(dev); + + if (vif->type == NL80211_IFTYPE_STATION) + ieee80211_disconnect(vif, true); + + mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true); + mt7925_mcu_set_tx(dev, vif); + + if (vif->type == NL80211_IFTYPE_AP) { + mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid, + true, NULL); + mt7925_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); + mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true); + } +} + +/* system error recovery */ +void mt7925_mac_reset_work(struct work_struct *work) +{ + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + reset_work); + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; + int i, ret; + + dev_dbg(dev->mt76.dev, "chip reset\n"); + dev->hw_full_reset = true; + ieee80211_stop_queues(hw); + + cancel_delayed_work_sync(&dev->mphy.mac_work); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + + for (i = 0; i < 10; i++) { + mutex_lock(&dev->mt76.mutex); + ret = mt792x_dev_reset(dev); + mutex_unlock(&dev->mt76.mutex); + + if (!ret) + break; + } + + if (i == 10) + dev_err(dev->mt76.dev, "chip reset failed\n"); + + if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state)) { + struct cfg80211_scan_info info = { + .aborted = true, + }; + + ieee80211_scan_completed(dev->mphy.hw, &info); + } + + dev->hw_full_reset = false; + pm->suspended = false; + ieee80211_wake_queues(hw); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_vif_connect_iter, NULL); + mt76_connac_power_save_sched(&dev->mt76.phy, pm); +} + +void mt7925_coredump_work(struct work_struct *work) +{ + struct mt792x_dev *dev; + char *dump, *data; + + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, + coredump.work.work); + + if (time_is_after_jiffies(dev->coredump.last_activity + + 4 * MT76_CONNAC_COREDUMP_TIMEOUT)) { + queue_delayed_work(dev->mt76.wq, &dev->coredump.work, + MT76_CONNAC_COREDUMP_TIMEOUT); + return; + } + + dump = vzalloc(MT76_CONNAC_COREDUMP_SZ); + data = dump; + + while (true) { + struct sk_buff *skb; + + spin_lock_bh(&dev->mt76.lock); + skb = __skb_dequeue(&dev->coredump.msg_list); + spin_unlock_bh(&dev->mt76.lock); + + if (!skb) + break; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 8); + if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { + dev_kfree_skb(skb); + continue; + } + + memcpy(data, skb->data, skb->len); + data += skb->len; + + dev_kfree_skb(skb); + } + + if (dump) + dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, + GFP_KERNEL); + + mt792x_reset(&dev->mt76); +} + +/* usb_sdio */ +static void +mt7925_usb_sdio_write_txwi(struct mt792x_dev *dev, struct mt76_wcid *wcid, + enum mt76_txq_id qid, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, int pid, + struct sk_buff *skb) +{ + __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); + + memset(txwi, 0, MT_SDIO_TXD_SIZE); + mt7925_mac_write_txwi(&dev->mt76, txwi, skb, wcid, key, pid, qid, 0); + skb_push(skb, MT_SDIO_TXD_SIZE); +} + +int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct sk_buff *skb = tx_info->skb; + int err, pad, pktid; + + if (unlikely(tx_info->skb->len <= ETH_HLEN)) + return -EINVAL; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + if (sta) { + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + + if (time_after(jiffies, msta->last_txs + HZ / 4)) { + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + msta->last_txs = jiffies; + } + } + + pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); + mt7925_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb); + + mt792x_skb_add_usb_sdio_hdr(dev, skb, 0); + pad = round_up(skb->len, 4) - skb->len; + if (mt76_is_usb(mdev)) + pad += 4; + + err = mt76_skb_adjust_pad(skb, pad); + if (err) + /* Release pktid in case of error. */ + idr_remove(&wcid->pktid, pktid); + + return err; +} +EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_prepare_skb); + +void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e) +{ + __le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE); + unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; + struct ieee80211_sta *sta; + struct mt76_wcid *wcid; + u16 idx; + + idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(mdev->wcid[idx]); + sta = wcid_to_sta(wcid); + + if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7925_tx_check_aggr(sta, txwi); + + skb_pull(e->skb, headroom); + mt76_tx_complete_skb(mdev, e->wcid, e->skb); +} +EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_complete_skb); + +bool mt7925_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + + mt792x_mutex_acquire(dev); + mt7925_mac_sta_poll(dev); + mt792x_mutex_release(dev); + + return false; +} +EXPORT_SYMBOL_GPL(mt7925_usb_sdio_tx_status_data); + +#if IS_ENABLED(CONFIG_IPV6) +void mt7925_set_ipv6_ns_work(struct work_struct *work) +{ + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + ipv6_ns_work); + struct sk_buff *skb; + int ret = 0; + + do { + skb = skb_dequeue(&dev->ipv6_ns_list); + + if (!skb) + break; + + mt792x_mutex_acquire(dev); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(OFFLOAD), true); + mt792x_mutex_release(dev); + + } while (!ret); + + if (ret) + skb_queue_purge(&dev->ipv6_ns_list); +} +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.h b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h new file mode 100644 index 000000000000..b10a993326b9 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7925_MAC_H +#define __MT7925_MAC_H + +#include "../mt76_connac3_mac.h" + +#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7 +#define MT_WTBL_TXRX_RATE_G2_HE 24 +#define MT_WTBL_TXRX_RATE_G2 12 + +#define MT_WTBL_AC0_CTT_OFFSET 20 + +static inline u32 mt7925_mac_wtbl_lmac_addr(struct mt792x_dev *dev, u16 wcid, u8 dw) +{ + mt76_wr(dev, MT_WTBLON_TOP_WDUCR, + FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); + + return MT_WTBL_LMAC_OFFS(wcid, dw); +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c new file mode 100644 index 000000000000..15c2fb0bcb1b --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -0,0 +1,1454 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/etherdevice.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/module.h> +#include <linux/ctype.h> +#include <net/ipv6.h> +#include "mt7925.h" +#include "mcu.h" +#include "mac.h" + +static void +mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, + struct ieee80211_sband_iftype_data *data, + enum nl80211_iftype iftype) +{ + struct ieee80211_sta_he_cap *he_cap = &data->he_cap; + struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; + struct ieee80211_he_mcs_nss_supp *he_mcs = &he_cap->he_mcs_nss_supp; + int i, nss = hweight8(phy->mt76->antenna_mask); + u16 mcs_map = 0; + + for (i = 0; i < 8; i++) { + if (i < nss) + mcs_map |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2)); + else + mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2)); + } + + he_cap->has_he = true; + + he_cap_elem->mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE; + he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3; + he_cap_elem->mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; + + if (band == NL80211_BAND_2GHZ) + he_cap_elem->phy_cap_info[0] = + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G; + else + he_cap_elem->phy_cap_info[0] = + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + + he_cap_elem->phy_cap_info[1] = + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; + he_cap_elem->phy_cap_info[2] = + IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | + IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | + IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; + + switch (i) { + case NL80211_IFTYPE_AP: + he_cap_elem->mac_cap_info[2] |= + IEEE80211_HE_MAC_CAP2_BSR; + he_cap_elem->mac_cap_info[4] |= + IEEE80211_HE_MAC_CAP4_BQR; + he_cap_elem->mac_cap_info[5] |= + IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX; + he_cap_elem->phy_cap_info[3] |= + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; + he_cap_elem->phy_cap_info[6] |= + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; + break; + case NL80211_IFTYPE_STATION: + he_cap_elem->mac_cap_info[1] |= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; + + if (band == NL80211_BAND_2GHZ) + he_cap_elem->phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G; + else + he_cap_elem->phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G; + + he_cap_elem->phy_cap_info[1] |= + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | + IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US; + he_cap_elem->phy_cap_info[3] |= + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK; + he_cap_elem->phy_cap_info[4] |= + IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | + IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 | + IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4; + he_cap_elem->phy_cap_info[5] |= + IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | + IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; + he_cap_elem->phy_cap_info[6] |= + IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | + IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | + IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + he_cap_elem->phy_cap_info[7] |= + IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | + IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; + he_cap_elem->phy_cap_info[8] |= + IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | + IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | + IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | + IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484; + he_cap_elem->phy_cap_info[9] |= + IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM | + IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB; + break; + default: + break; + } + + he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map); + he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map); + he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map); + he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map); + + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + + if (he_cap_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { + mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss); + } else { + he_cap_elem->phy_cap_info[9] |= + u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US, + IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK); + } + + if (band == NL80211_BAND_6GHZ) { + u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | + IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS; + + cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | + u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | + u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); + + data->he_6ghz_capa.capa = cpu_to_le16(cap); + } +} + +static void +mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band, + struct ieee80211_sband_iftype_data *data, + enum nl80211_iftype iftype) +{ + struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap; + struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &eht_cap->eht_mcs_nss_supp; + enum nl80211_chan_width width = phy->mt76->chandef.width; + int nss = hweight8(phy->mt76->antenna_mask); + int sts = hweight16(phy->mt76->chainmask); + u8 val; + + if (!phy->dev->has_eht) + return; + + eht_cap->has_eht = true; + + eht_cap_elem->mac_cap_info[0] = + IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | + IEEE80211_EHT_MAC_CAP0_OM_CONTROL; + + eht_cap_elem->phy_cap_info[0] = + IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; + + eht_cap_elem->phy_cap_info[0] |= + u8_encode_bits(u8_get_bits(sts - 1, BIT(0)), + IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK); + + eht_cap_elem->phy_cap_info[1] = + u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)), + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | + u8_encode_bits(sts - 1, + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK); + + eht_cap_elem->phy_cap_info[2] = + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) | + u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK); + + eht_cap_elem->phy_cap_info[3] = + IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | + IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | + IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK; + + eht_cap_elem->phy_cap_info[4] = + u8_encode_bits(min_t(int, sts - 1, 2), + IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK); + + eht_cap_elem->phy_cap_info[5] = + IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | + u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US, + IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) | + u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)), + IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK); + + val = width == NL80211_CHAN_WIDTH_160 ? 0x7 : + width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1; + eht_cap_elem->phy_cap_info[6] = + u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)), + IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) | + u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK); + + eht_cap_elem->phy_cap_info[7] = + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | + IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | + IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ; + + val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) | + u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX); + + eht_nss->bw._80.rx_tx_mcs9_max_nss = val; + eht_nss->bw._80.rx_tx_mcs11_max_nss = val; + eht_nss->bw._80.rx_tx_mcs13_max_nss = val; + eht_nss->bw._160.rx_tx_mcs9_max_nss = val; + eht_nss->bw._160.rx_tx_mcs11_max_nss = val; + eht_nss->bw._160.rx_tx_mcs13_max_nss = val; +} + +static void +__mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy, + struct ieee80211_supported_band *sband, + enum nl80211_band band) +{ + struct ieee80211_sband_iftype_data *data = phy->iftype[band]; + int i, n = 0; + + for (i = 0; i < NUM_NL80211_IFTYPES; i++) { + switch (i) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: + break; + default: + continue; + } + + data[n].types_mask = BIT(i); + mt7925_init_he_caps(phy, band, &data[n], i); + mt7925_init_eht_caps(phy, band, &data[n], i); + + n++; + } + + _ieee80211_set_sband_iftype_data(sband, data, n); +} + +void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy) +{ + if (phy->mt76->cap.has_2ghz) + __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_2g.sband, + NL80211_BAND_2GHZ); + + if (phy->mt76->cap.has_5ghz) + __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_5g.sband, + NL80211_BAND_5GHZ); + + if (phy->mt76->cap.has_6ghz) + __mt7925_set_stream_he_eht_caps(phy, &phy->mt76->sband_6g.sband, + NL80211_BAND_6GHZ); +} + +int __mt7925_start(struct mt792x_phy *phy) +{ + struct mt76_phy *mphy = phy->mt76; + int err; + + err = mt7925_mcu_set_channel_domain(mphy); + if (err) + return err; + + err = mt7925_mcu_set_rts_thresh(phy, 0x92b); + if (err) + return err; + + err = mt7925_set_tx_sar_pwr(mphy->hw, NULL); + if (err) + return err; + + mt792x_mac_reset_counters(phy); + set_bit(MT76_STATE_RUNNING, &mphy->state); + + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT792x_WATCHDOG_TIME); + + return 0; +} +EXPORT_SYMBOL_GPL(__mt7925_start); + +static int mt7925_start(struct ieee80211_hw *hw) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int err; + + mt792x_mutex_acquire(phy->dev); + err = __mt7925_start(phy); + mt792x_mutex_release(phy->dev); + + return err; +} + +static int +mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt76_txq *mtxq; + int idx, ret = 0; + + mt792x_mutex_acquire(dev); + + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); + if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } + + mvif->mt76.omac_idx = mvif->mt76.idx; + mvif->phy = phy; + mvif->mt76.band_idx = 0; + mvif->mt76.wmm_idx = mvif->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; + + if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) + mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; + else + mvif->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL; + + ret = mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, + true); + if (ret) + goto out; + + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); + phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); + + idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; + + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); + mvif->sta.wcid.idx = idx; + mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; + mvif->sta.wcid.hw_key_idx = -1; + mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt76_wcid_init(&mvif->sta.wcid); + + mt7925_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + ewma_rssi_init(&mvif->rssi); + + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = idx; + } + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; +out: + mt792x_mutex_release(dev); + + return ret; +} + +static void mt7925_roc_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = priv; + + mt7925_mcu_abort_roc(phy, mvif, phy->roc_token_id); +} + +void mt7925_roc_work(struct work_struct *work) +{ + struct mt792x_phy *phy; + + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, + roc_work); + + if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + return; + + mt792x_mutex_acquire(phy->dev); + ieee80211_iterate_active_interfaces(phy->mt76->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_roc_iter, phy); + mt792x_mutex_release(phy->dev); + ieee80211_remain_on_channel_expired(phy->mt76->hw); +} + +static int mt7925_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) +{ + int err = 0; + + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); + + mt792x_mutex_acquire(phy->dev); + if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + err = mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); + mt792x_mutex_release(phy->dev); + + return err; +} + +static int mt7925_set_roc(struct mt792x_phy *phy, + struct mt792x_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum mt7925_roc_req type) +{ + int err; + + if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state)) + return -EBUSY; + + phy->roc_grant = false; + + err = mt7925_mcu_set_roc(phy, vif, chan, duration, type, + ++phy->roc_token_id); + if (err < 0) { + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + goto out; + } + + if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, 4 * HZ)) { + mt7925_mcu_abort_roc(phy, vif, phy->roc_token_id); + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + err = -ETIMEDOUT; + } + +out: + return err; +} + +static int mt7925_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum ieee80211_roc_type type) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int err; + + mt792x_mutex_acquire(phy->dev); + err = mt7925_set_roc(phy, mvif, chan, duration, MT7925_ROC_REQ_ROC); + mt792x_mutex_release(phy->dev); + + return err; +} + +static int mt7925_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + return mt7925_abort_roc(phy, mvif); +} + +static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; + u8 *wcid_keyidx = &wcid->hw_key_idx; + int idx = key->keyidx, err = 0; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. + */ + if ((vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + wcid_keyidx = &wcid->hw_key_idx2; + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + if (!mvif->wep_sta) + return -EOPNOTSUPP; + break; + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + case WLAN_CIPHER_SUITE_SMS4: + break; + default: + return -EOPNOTSUPP; + } + + mt792x_mutex_acquire(dev); + + if (cmd == SET_KEY && !mvif->mt76.cipher) { + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); + mt7925_mcu_add_bss_info(phy, mvif->mt76.ctx, vif, sta, true); + } + + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + + mt76_wcid_key_setup(&dev->mt76, wcid, + cmd == SET_KEY ? key : NULL); + + err = mt7925_mcu_add_key(&dev->mt76, vif, &msta->bip, + key, MCU_UNI_CMD(STA_REC_UPDATE), + &msta->wcid, cmd); + + if (err) + goto out; + + if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || + key->cipher == WLAN_CIPHER_SUITE_WEP40) + err = mt7925_mcu_add_key(&dev->mt76, vif, &mvif->wep_sta->bip, + key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), + &mvif->wep_sta->wcid, cmd); + +out: + mt792x_mutex_release(dev); + + return err; +} + +static void +mt7925_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt792x_dev *dev = priv; + struct ieee80211_hw *hw = mt76_hw(dev); + bool pm_enable = dev->pm.enable; + int err; + + err = mt7925_mcu_set_beacon_filter(dev, vif, pm_enable); + if (err < 0) + return; + + if (pm_enable) { + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + ieee80211_hw_set(hw, CONNECTION_MONITOR); + } else { + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; + __clear_bit(IEEE80211_HW_CONNECTION_MONITOR, hw->flags); + } +} + +static void +mt7925_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt792x_dev *dev = priv; + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + mt7925_mcu_set_sniffer(dev, vif, monitor); + pm->enable = pm->enable_user && !monitor; + pm->ds_enable = pm->ds_enable_user && !monitor; + + mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); + + if (monitor) + mt7925_mcu_set_beacon_filter(dev, vif, false); +} + +void mt7925_set_runtime_pm(struct mt792x_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; + bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); + + pm->enable = pm->enable_user && !monitor; + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_pm_interface_iter, dev); + pm->ds_enable = pm->ds_enable_user && !monitor; + mt7925_mcu_set_deep_sleep(dev, pm->ds_enable); +} + +static int mt7925_config(struct ieee80211_hw *hw, u32 changed) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int ret = 0; + + mt792x_mutex_acquire(dev); + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + ret = mt7925_set_tx_sar_pwr(hw, NULL); + if (ret) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_sniffer_interface_iter, dev); + } + +out: + mt792x_mutex_release(dev); + + return ret; +} + +static void mt7925_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ +#define MT7925_FILTER_FCSFAIL BIT(2) +#define MT7925_FILTER_CONTROL BIT(5) +#define MT7925_FILTER_OTHER_BSS BIT(6) +#define MT7925_FILTER_ENABLE BIT(31) + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u32 flags = MT7925_FILTER_ENABLE; + +#define MT7925_FILTER(_fif, _type) do { \ + if (*total_flags & (_fif)) \ + flags |= MT7925_FILTER_##_type; \ + } while (0) + + MT7925_FILTER(FIF_FCSFAIL, FCSFAIL); + MT7925_FILTER(FIF_CONTROL, CONTROL); + MT7925_FILTER(FIF_OTHER_BSS, OTHER_BSS); + + mt792x_mutex_acquire(dev); + mt7925_mcu_set_rxfilter(dev, flags, 0, 0); + mt792x_mutex_release(dev); + + *total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL); +} + +static u8 +mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + bool beacon, bool mcast) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_phy *mphy = hw->priv; + u16 rate; + u8 i, idx, ht; + + rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); + ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM; + + if (beacon && ht) { + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + /* must odd index */ + idx = MT7925_BEACON_RATES_TBL + 2 * (mvif->idx % 20); + mt7925_mac_set_fixed_rate_table(dev, idx, rate); + return idx; + } + + idx = FIELD_GET(MT_TX_RATE_IDX, rate); + for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) + if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx) + return MT792x_BASIC_RATES_TBL + i; + + return mvif->basic_rates_idx; +} + +static void mt7925_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u64 changed) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt792x_mutex_acquire(dev); + + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt792x_mac_set_timeing(phy); + } + } + + if (changed & BSS_CHANGED_MCAST_RATE) + mvif->mcast_rates_idx = + mt7925_get_rates_table(hw, vif, false, true); + + if (changed & BSS_CHANGED_BASIC_RATES) + mvif->basic_rates_idx = + mt7925_get_rates_table(hw, vif, false, false); + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) { + mvif->beacon_rates_idx = + mt7925_get_rates_table(hw, vif, true, false); + + mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, + info->enable_beacon); + } + + /* ensure that enable txcmd_mode after bss_info */ + if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) + mt7925_mcu_set_tx(dev, vif); + + if (changed & BSS_CHANGED_PS) + mt7925_mcu_uni_bss_ps(dev, vif); + + if (changed & BSS_CHANGED_ASSOC) { + mt7925_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_ASSOC); + mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); + } + + if (changed & BSS_CHANGED_ARP_FILTER) { + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + mt7925_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, info); + } + + mt792x_mutex_release(dev); +} + +int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + int ret, idx; + + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); + if (idx < 0) + return -ENOSPC; + + INIT_LIST_HEAD(&msta->wcid.poll_list); + msta->vif = mvif; + msta->wcid.sta = 1; + msta->wcid.idx = idx; + msta->wcid.phy_idx = mvif->mt76.band_idx; + msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta->last_txs = jiffies; + + ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); + if (ret) + return ret; + + if (vif->type == NL80211_IFTYPE_STATION) + mvif->wep_sta = msta; + + mt7925_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + /* should update bss info before STA add */ + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, + false); + + ret = mt7925_mcu_sta_update(dev, sta, vif, true, + MT76_STA_INFO_STATE_NONE); + if (ret) + return ret; + + mt76_connac_power_save_sched(&dev->mphy, &dev->pm); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_mac_sta_add); + +void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + mt792x_mutex_acquire(dev); + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, + true); + + ewma_avg_signal_init(&msta->avg_ack_signal); + + mt7925_mac_wtbl_update(dev, msta->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + + mt7925_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); + + mt792x_mutex_release(dev); +} +EXPORT_SYMBOL_GPL(mt7925_mac_sta_assoc); + +void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + + mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); + mt76_connac_pm_wake(&dev->mphy, &dev->pm); + + mt7925_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE); + mt7925_mac_wtbl_update(dev, msta->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + if (vif->type == NL80211_IFTYPE_STATION) { + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + mvif->wep_sta = NULL; + ewma_rssi_init(&mvif->rssi); + if (!sta->tdls) + mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, sta, + false); + } + + spin_lock_bh(&mdev->sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); + + mt76_connac_power_save_sched(&dev->mphy, &dev->pm); +} +EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove); + +static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, u32 val) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt792x_mutex_acquire(dev); + mt7925_mcu_set_rts_thresh(&dev->phy, val); + mt792x_mutex_release(dev); + + return 0; +} + +static int +mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + enum ieee80211_ampdu_mlme_action action = params->action; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct ieee80211_sta *sta = params->sta; + struct ieee80211_txq *txq = sta->txq[params->tid]; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + u16 tid = params->tid; + u16 ssn = params->ssn; + struct mt76_txq *mtxq; + int ret = 0; + + if (!txq) + return -EINVAL; + + mtxq = (struct mt76_txq *)txq->drv_priv; + + mt792x_mutex_acquire(dev); + switch (action) { + case IEEE80211_AMPDU_RX_START: + mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, + params->buf_size); + mt7925_mcu_uni_rx_ba(dev, params, true); + break; + case IEEE80211_AMPDU_RX_STOP: + mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt7925_mcu_uni_rx_ba(dev, params, false); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mtxq->aggr = true; + mtxq->send_bar = false; + mt7925_mcu_uni_tx_ba(dev, params, true); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mtxq->aggr = false; + clear_bit(tid, &msta->wcid.ampdu_state); + mt7925_mcu_uni_tx_ba(dev, params, false); + break; + case IEEE80211_AMPDU_TX_START: + set_bit(tid, &msta->wcid.ampdu_state); + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + clear_bit(tid, &msta->wcid.ampdu_state); + mt7925_mcu_uni_tx_ba(dev, params, false); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + } + mt792x_mutex_release(dev); + + return ret; +} + +static bool is_valid_alpha2(const char *alpha2) +{ + if (!alpha2) + return false; + + if (alpha2[0] == '0' && alpha2[1] == '0') + return true; + + if (isalpha(alpha2[0]) && isalpha(alpha2[1])) + return true; + + return false; +} + +void mt7925_scan_work(struct work_struct *work) +{ + struct mt792x_phy *phy; + + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, + scan_work.work); + + while (true) { + struct mt76_dev *mdev = &phy->dev->mt76; + struct sk_buff *skb; + struct tlv *tlv; + int tlv_len; + + spin_lock_bh(&phy->dev->mt76.lock); + skb = __skb_dequeue(&phy->scan_event_list); + spin_unlock_bh(&phy->dev->mt76.lock); + + if (!skb) + break; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + tlv = (struct tlv *)skb->data; + tlv_len = skb->len; + + while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) { + struct mt7925_mcu_scan_chinfo_event *evt; + + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_SCAN_DONE_BASIC: + if (test_and_clear_bit(MT76_HW_SCANNING, &phy->mt76->state)) { + struct cfg80211_scan_info info = { + .aborted = false, + }; + ieee80211_scan_completed(phy->mt76->hw, &info); + } + break; + case UNI_EVENT_SCAN_DONE_CHNLINFO: + evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data; + + if (!is_valid_alpha2(evt->alpha2)) + break; + + if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0') + break; + + mt7925_mcu_set_clc(phy->dev, evt->alpha2, ENVIRON_INDOOR); + + break; + case UNI_EVENT_SCAN_DONE_NLO: + ieee80211_sched_scan_results(phy->mt76->hw); + break; + default: + break; + } + + tlv_len -= le16_to_cpu(tlv->len); + tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len)); + } + + dev_kfree_skb(skb); + } +} + +static int +mt7925_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *req) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + int err; + + mt792x_mutex_acquire(dev); + err = mt7925_mcu_hw_scan(mphy, vif, req); + mt792x_mutex_release(dev); + + return err; +} + +static void +mt7925_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + + mt792x_mutex_acquire(dev); + mt7925_mcu_cancel_hw_scan(mphy, vif); + mt792x_mutex_release(dev); +} + +static int +mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *req, + struct ieee80211_scan_ies *ies) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + int err; + + mt792x_mutex_acquire(dev); + + err = mt7925_mcu_sched_scan_req(mphy, vif, req); + if (err < 0) + goto out; + + err = mt7925_mcu_sched_scan_enable(mphy, vif, true); +out: + mt792x_mutex_release(dev); + + return err; +} + +static int +mt7925_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + int err; + + mt792x_mutex_acquire(dev); + err = mt7925_mcu_sched_scan_enable(mphy, vif, false); + mt792x_mutex_release(dev); + + return err; +} + +static int +mt7925_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int max_nss = hweight8(hw->wiphy->available_antennas_tx); + + if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + return -EINVAL; + + if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) + tx_ant = BIT(ffs(tx_ant) - 1) - 1; + + mt792x_mutex_acquire(dev); + + phy->mt76->antenna_mask = tx_ant; + phy->mt76->chainmask = tx_ant; + + mt76_set_stream_caps(phy->mt76, true); + mt7925_set_stream_he_eht_caps(phy); + + /* TODO: update bmc_wtbl spe_idx when antenna changes */ + mt792x_mutex_release(dev); + + return 0; +} + +#ifdef CONFIG_PM +static int mt7925_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + cancel_delayed_work_sync(&phy->scan_work); + cancel_delayed_work_sync(&phy->mt76->mac_work); + + cancel_delayed_work_sync(&dev->pm.ps_work); + mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); + + mt792x_mutex_acquire(dev); + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_mcu_set_suspend_iter, + &dev->mphy); + + mt792x_mutex_release(dev); + + return 0; +} + +static int mt7925_resume(struct ieee80211_hw *hw) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + mt792x_mutex_acquire(dev); + + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + ieee80211_iterate_active_interfaces(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_mcu_set_suspend_iter, + &dev->mphy); + + ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + MT792x_WATCHDOG_TIME); + + mt792x_mutex_release(dev); + + return 0; +} + +static void mt7925_set_rekey_data(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_gtk_rekey_data *data) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt792x_mutex_acquire(dev); + mt76_connac_mcu_update_gtk_rekey(hw, vif, data); + mt792x_mutex_release(dev); +} +#endif /* CONFIG_PM */ + +static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool enabled) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt792x_mutex_acquire(dev); + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + + mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta); + + mt792x_mutex_release(dev); +} + +#if IS_ENABLED(CONFIG_IPV6) +static void mt7925_ipv6_addr_change(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct inet6_dev *idev) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mvif->phy->dev; + struct inet6_ifaddr *ifa; + struct sk_buff *skb; + u8 idx = 0; + + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt7925_arpns_tlv arpns; + struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; + } req_hdr = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arpns = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), + .len = cpu_to_le16(sizeof(req_hdr) - 4), + .enable = true, + }, + }; + + read_lock_bh(&idev->lock); + list_for_each_entry(ifa, &idev->addr_list, if_list) { + if (ifa->flags & IFA_F_TENTATIVE) + continue; + req_hdr.ns_addrs[idx] = ifa->addr; + if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN) + break; + } + read_unlock_bh(&idev->lock); + + if (!idx) + return; + + req_hdr.arpns.ips_num = idx; + + skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr), + 0, GFP_ATOMIC); + if (!skb) + return; + + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + + skb_queue_tail(&dev->ipv6_ns_list, skb); + + ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work); +} +#endif + +int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt76_phy *mphy = hw->priv; + + if (sar) { + int err = mt76_init_sar_power(hw, sar); + + if (err) + return err; + } + mt792x_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); + + return mt7925_mcu_set_rate_txpower(mphy); +} + +static int mt7925_set_sar_specs(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err; + + mt792x_mutex_acquire(dev); + err = mt7925_mcu_set_clc(dev, dev->mt76.alpha2, + dev->country_ie_env); + if (err < 0) + goto out; + + err = mt7925_set_tx_sar_pwr(hw, sar); +out: + mt792x_mutex_release(dev); + + return err; +} + +static void +mt7925_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt792x_mutex_acquire(dev); + mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true); + mt792x_mutex_release(dev); +} + +static int +mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err; + + mt792x_mutex_acquire(dev); + + err = mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, + true); + if (err) + goto out; + + err = mt7925_mcu_set_bss_pm(dev, vif, true); + if (err) + goto out; + + err = mt7925_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); +out: + mt792x_mutex_release(dev); + + return err; +} + +static void +mt7925_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + int err; + + mt792x_mutex_acquire(dev); + + err = mt7925_mcu_set_bss_pm(dev, vif, false); + if (err) + goto out; + + mt7925_mcu_add_bss_info(&dev->phy, mvif->mt76.ctx, vif, NULL, + false); + +out: + mt792x_mutex_release(dev); +} + +static int +mt7925_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) +{ + return 0; +} + +static void +mt7925_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx) +{ +} + +static void mt7925_ctx_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_chanctx_conf *ctx = priv; + + if (ctx != mvif->mt76.ctx) + return; + + if (vif->type == NL80211_IFTYPE_MONITOR) { + mt7925_mcu_set_sniffer(mvif->phy->dev, vif, true); + mt7925_mcu_config_sniffer(mvif, ctx); + } else { + mt7925_mcu_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx); + } +} + +static void +mt7925_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *ctx, + u32 changed) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + mt792x_mutex_acquire(phy->dev); + ieee80211_iterate_active_interfaces(phy->mt76->hw, + IEEE80211_IFACE_ITER_ACTIVE, + mt7925_ctx_iter, ctx); + mt792x_mutex_release(phy->dev); +} + +static void mt7925_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_prep_tx_info *info) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u16 duration = info->duration ? info->duration : + jiffies_to_msecs(HZ); + + mt792x_mutex_acquire(dev); + mt7925_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration, + MT7925_ROC_REQ_JOIN); + mt792x_mutex_release(dev); +} + +static void mt7925_mgd_complete_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_prep_tx_info *info) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + mt7925_abort_roc(mvif->phy, mvif); +} + +const struct ieee80211_ops mt7925_ops = { + .tx = mt792x_tx, + .start = mt7925_start, + .stop = mt792x_stop, + .add_interface = mt7925_add_interface, + .remove_interface = mt792x_remove_interface, + .config = mt7925_config, + .conf_tx = mt792x_conf_tx, + .configure_filter = mt7925_configure_filter, + .bss_info_changed = mt7925_bss_info_changed, + .start_ap = mt7925_start_ap, + .stop_ap = mt7925_stop_ap, + .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, + .set_key = mt7925_set_key, + .sta_set_decap_offload = mt7925_sta_set_decap_offload, +#if IS_ENABLED(CONFIG_IPV6) + .ipv6_addr_change = mt7925_ipv6_addr_change, +#endif /* CONFIG_IPV6 */ + .ampdu_action = mt7925_ampdu_action, + .set_rts_threshold = mt7925_set_rts_threshold, + .wake_tx_queue = mt76_wake_tx_queue, + .release_buffered_frames = mt76_release_buffered_frames, + .channel_switch_beacon = mt7925_channel_switch_beacon, + .get_txpower = mt76_get_txpower, + .get_stats = mt792x_get_stats, + .get_et_sset_count = mt792x_get_et_sset_count, + .get_et_strings = mt792x_get_et_strings, + .get_et_stats = mt792x_get_et_stats, + .get_tsf = mt792x_get_tsf, + .set_tsf = mt792x_set_tsf, + .get_survey = mt76_get_survey, + .get_antenna = mt76_get_antenna, + .set_antenna = mt7925_set_antenna, + .set_coverage_class = mt792x_set_coverage_class, + .hw_scan = mt7925_hw_scan, + .cancel_hw_scan = mt7925_cancel_hw_scan, + .sta_statistics = mt792x_sta_statistics, + .sched_scan_start = mt7925_start_sched_scan, + .sched_scan_stop = mt7925_stop_sched_scan, +#ifdef CONFIG_PM + .suspend = mt7925_suspend, + .resume = mt7925_resume, + .set_wakeup = mt792x_set_wakeup, + .set_rekey_data = mt7925_set_rekey_data, +#endif /* CONFIG_PM */ + .flush = mt792x_flush, + .set_sar_specs = mt7925_set_sar_specs, + .remain_on_channel = mt7925_remain_on_channel, + .cancel_remain_on_channel = mt7925_cancel_remain_on_channel, + .add_chanctx = mt7925_add_chanctx, + .remove_chanctx = mt7925_remove_chanctx, + .change_chanctx = mt7925_change_chanctx, + .assign_vif_chanctx = mt792x_assign_vif_chanctx, + .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, + .mgd_prepare_tx = mt7925_mgd_prepare_tx, + .mgd_complete_tx = mt7925_mgd_complete_tx, +}; +EXPORT_SYMBOL_GPL(mt7925_ops); + +MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c new file mode 100644 index 000000000000..9c0e397537ac --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -0,0 +1,3174 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/fs.h> +#include <linux/firmware.h> +#include "mt7925.h" +#include "mcu.h" +#include "mac.h" + +#define MT_STA_BFER BIT(0) +#define MT_STA_BFEE BIT(1) + +static bool mt7925_disable_clc; +module_param_named(disable_clc, mt7925_disable_clc, bool, 0644); +MODULE_PARM_DESC(disable_clc, "disable CLC support"); + +int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) +{ + int mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); + struct mt7925_mcu_rxd *rxd; + int ret = 0; + + if (!skb) { + dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", cmd, seq); + mt792x_reset(mdev); + + return -ETIMEDOUT; + } + + rxd = (struct mt7925_mcu_rxd *)skb->data; + if (seq != rxd->seq) + return -EAGAIN; + + if (cmd == MCU_CMD(PATCH_SEM_CONTROL) || + cmd == MCU_CMD(PATCH_FINISH_REQ)) { + skb_pull(skb, sizeof(*rxd) - 4); + ret = *skb->data; + } else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) || + cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) || + cmd == MCU_UNI_CMD(STA_REC_UPDATE) || + cmd == MCU_UNI_CMD(HIF_CTRL) || + cmd == MCU_UNI_CMD(OFFLOAD) || + cmd == MCU_UNI_CMD(SUSPEND)) { + struct mt7925_mcu_uni_event *event; + + skb_pull(skb, sizeof(*rxd)); + event = (struct mt7925_mcu_uni_event *)skb->data; + ret = le32_to_cpu(event->status); + /* skip invalid event */ + if (mcu_cmd != event->cid) + ret = -EAGAIN; + } else { + skb_pull(skb, sizeof(*rxd)); + } + + return ret; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_parse_response); + +int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set) +{ +#define MT_RF_REG_HDR GENMASK(31, 24) +#define MT_RF_REG_ANT GENMASK(23, 16) +#define RF_REG_PREFIX 0x99 + struct { + u8 __rsv[4]; + union { + struct uni_cmd_access_reg_basic { + __le16 tag; + __le16 len; + __le32 idx; + __le32 data; + } __packed reg; + struct uni_cmd_access_rf_reg_basic { + __le16 tag; + __le16 len; + __le16 ant; + u8 __rsv[2]; + __le32 idx; + __le32 data; + } __packed rf_reg; + }; + } __packed * res, req; + struct sk_buff *skb; + int ret; + + if (u32_get_bits(regidx, MT_RF_REG_HDR) == RF_REG_PREFIX) { + req.rf_reg.tag = cpu_to_le16(UNI_CMD_ACCESS_RF_REG_BASIC); + req.rf_reg.len = cpu_to_le16(sizeof(req.rf_reg)); + req.rf_reg.ant = cpu_to_le16(u32_get_bits(regidx, MT_RF_REG_ANT)); + req.rf_reg.idx = cpu_to_le32(regidx); + req.rf_reg.data = set ? cpu_to_le32(*val) : 0; + } else { + req.reg.tag = cpu_to_le16(UNI_CMD_ACCESS_REG_BASIC); + req.reg.len = cpu_to_le16(sizeof(req.reg)); + req.reg.idx = cpu_to_le32(regidx); + req.reg.data = set ? cpu_to_le32(*val) : 0; + } + + if (set) + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(REG_ACCESS), + &req, sizeof(req), true); + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, + MCU_WM_UNI_CMD_QUERY(REG_ACCESS), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + res = (void *)skb->data; + if (u32_get_bits(regidx, MT_RF_REG_HDR) == RF_REG_PREFIX) + *val = le32_to_cpu(res->rf_reg.data); + else + *val = le32_to_cpu(res->reg.data); + + dev_kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_regval); + +int mt7925_mcu_update_arp_filter(struct mt76_dev *dev, + struct mt76_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct ieee80211_vif *mvif = container_of(info, struct ieee80211_vif, + bss_conf); + struct sk_buff *skb; + int i, len = min_t(int, mvif->cfg.arp_addr_cnt, + IEEE80211_BSS_ARP_ADDR_LIST_LEN); + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt7925_arpns_tlv arp; + } req = { + .hdr = { + .bss_idx = vif->idx, + }, + .arp = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP), + .len = cpu_to_le16(sizeof(req) - 4 + len * 2 * sizeof(__be32)), + .ips_num = len, + .enable = true, + }, + }; + + skb = mt76_mcu_msg_alloc(dev, NULL, sizeof(req) + len * 2 * sizeof(__be32)); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &req, sizeof(req)); + for (i = 0; i < len; i++) { + skb_put_data(skb, &mvif->cfg.arp_addr_list[i], sizeof(__be32)); + skb_put_zero(skb, sizeof(__be32)); + } + + return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true); +} + +#ifdef CONFIG_PM +static int +mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif, + bool suspend, struct cfg80211_wowlan *wowlan) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt76_dev *dev = phy->dev; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_wow_ctrl_tlv wow_ctrl_tlv; + struct mt76_connac_wow_gpio_param_tlv gpio_tlv; + } req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .wow_ctrl_tlv = { + .tag = cpu_to_le16(UNI_SUSPEND_WOW_CTRL), + .len = cpu_to_le16(sizeof(struct mt76_connac_wow_ctrl_tlv)), + .cmd = suspend ? 1 : 2, + }, + .gpio_tlv = { + .tag = cpu_to_le16(UNI_SUSPEND_WOW_GPIO_PARAM), + .len = cpu_to_le16(sizeof(struct mt76_connac_wow_gpio_param_tlv)), + .gpio_pin = 0xff, /* follow fw about GPIO pin */ + }, + }; + + if (wowlan->magic_pkt) + req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_MAGIC; + if (wowlan->disconnect) + req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT | + UNI_WOW_DETECT_TYPE_BCN_LOST); + if (wowlan->nd_config) { + mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config); + req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT; + mt7925_mcu_sched_scan_enable(phy, vif, suspend); + } + if (wowlan->n_patterns) + req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_BITMAP; + + if (mt76_is_mmio(dev)) + req.wow_ctrl_tlv.wakeup_hif = WOW_PCIE; + else if (mt76_is_usb(dev)) + req.wow_ctrl_tlv.wakeup_hif = WOW_USB; + else if (mt76_is_sdio(dev)) + req.wow_ctrl_tlv.wakeup_hif = WOW_GPIO; + + return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req, + sizeof(req), true); +} + +static int +mt7925_mcu_set_wow_pattern(struct mt76_dev *dev, + struct ieee80211_vif *vif, + u8 index, bool enable, + struct cfg80211_pkt_pattern *pattern) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt7925_wow_pattern_tlv *tlv; + struct sk_buff *skb; + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr = { + .bss_idx = mvif->idx, + }; + + skb = mt76_mcu_msg_alloc(dev, NULL, sizeof(hdr) + sizeof(*tlv)); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &hdr, sizeof(hdr)); + tlv = (struct mt7925_wow_pattern_tlv *)skb_put(skb, sizeof(*tlv)); + tlv->tag = cpu_to_le16(UNI_SUSPEND_WOW_PATTERN); + tlv->len = cpu_to_le16(sizeof(*tlv)); + tlv->bss_idx = 0xF; + tlv->data_len = pattern->pattern_len; + tlv->enable = enable; + tlv->index = index; + tlv->offset = 0; + + memcpy(tlv->pattern, pattern->pattern, pattern->pattern_len); + memcpy(tlv->mask, pattern->mask, DIV_ROUND_UP(pattern->pattern_len, 8)); + + return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true); +} + +void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt76_phy *phy = priv; + bool suspend = !test_bit(MT76_STATE_RUNNING, &phy->state); + struct ieee80211_hw *hw = phy->hw; + struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; + int i; + + mt76_connac_mcu_set_gtk_rekey(phy->dev, vif, suspend); + + mt76_connac_mcu_set_suspend_mode(phy->dev, vif, suspend, 1, true); + + for (i = 0; i < wowlan->n_patterns; i++) + mt7925_mcu_set_wow_pattern(phy->dev, vif, i, suspend, + &wowlan->patterns[i]); + mt7925_connac_mcu_set_wow_ctrl(phy, vif, suspend, wowlan); +} + +#endif /* CONFIG_PM */ + +static void +mt7925_mcu_connection_loss_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt7925_uni_beacon_loss_event *event = priv; + + if (mvif->idx != event->hdr.bss_idx) + return; + + if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) || + vif->type != NL80211_IFTYPE_STATION) + return; + + ieee80211_connection_loss(vif); +} + +static void +mt7925_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct mt7925_uni_beacon_loss_event *event; + struct mt76_phy *mphy = &dev->mt76.phy; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd)); + event = (struct mt7925_uni_beacon_loss_event *)skb->data; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_mcu_connection_loss_iter, event); +} + +static void +mt7925_mcu_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct mt7925_roc_grant_tlv *grant = priv; + + if (mvif->idx != grant->bss_idx) + return; + + mvif->band_idx = grant->dbdcband; +} + +static void +mt7925_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_hw *hw = dev->mt76.hw; + struct mt7925_roc_grant_tlv *grant; + struct mt7925_mcu_rxd *rxd; + int duration; + + rxd = (struct mt7925_mcu_rxd *)skb->data; + grant = (struct mt7925_roc_grant_tlv *)(rxd->tlv + 4); + + /* should never happen */ + WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT)); + + if (grant->reqtype == MT7925_ROC_REQ_ROC) + ieee80211_ready_on_channel(hw); + else if (grant->reqtype == MT7925_ROC_REQ_JOIN) + ieee80211_iterate_active_interfaces_atomic(hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7925_mcu_roc_iter, grant); + dev->phy.roc_grant = true; + wake_up(&dev->phy.roc_wait); + duration = le32_to_cpu(grant->max_interval); + mod_timer(&dev->phy.roc_timer, + jiffies + msecs_to_jiffies(duration)); +} + +static void +mt7925_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; + + spin_lock_bh(&dev->mt76.lock); + __skb_queue_tail(&phy->scan_event_list, skb); + spin_unlock_bh(&dev->mt76.lock); + + ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work, + MT792x_HW_SCAN_TIMEOUT); +} + +static void +mt7925_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ +#define UNI_EVENT_TX_DONE_MSG 0 +#define UNI_EVENT_TX_DONE_RAW 1 + struct mt7925_mcu_txs_event { + u8 ver; + u8 rsv[3]; + u8 data[0]; + } __packed * txs; + struct tlv *tlv; + u32 tlv_len; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + tlv = (struct tlv *)skb->data; + tlv_len = skb->len; + + while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) { + switch (le16_to_cpu(tlv->tag)) { + case UNI_EVENT_TX_DONE_RAW: + txs = (struct mt7925_mcu_txs_event *)tlv->data; + mt7925_mac_add_txs(dev, txs->data); + break; + default: + break; + } + tlv_len -= le16_to_cpu(tlv->len); + tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len)); + } +} + +static void +mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct mt7925_uni_debug_msg { + __le16 tag; + __le16 len; + u8 fmt; + u8 rsv[3]; + u8 id; + u8 type:3; + u8 nr_args:5; + union { + struct idxlog { + __le16 rsv; + __le32 ts; + __le32 idx; + u8 data[]; + } __packed idx; + struct txtlog { + u8 len; + u8 rsv; + __le32 ts; + u8 data[]; + } __packed txt; + }; + } __packed * hdr; + + skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + hdr = (struct mt7925_uni_debug_msg *)skb->data; + + if (hdr->id == 0x28) { + skb_pull(skb, offsetof(struct mt7925_uni_debug_msg, id)); + wiphy_info(mt76_hw(dev)->wiphy, "%.*s", skb->len, skb->data); + return; + } else if (hdr->id != 0xa8) { + return; + } + + if (hdr->type == 0) { /* idx log */ + int i, ret, len = PAGE_SIZE - 1, nr_val; + struct page *page = dev_alloc_pages(get_order(len)); + __le32 *val; + char *buf, *cur; + + if (!page) + return; + + buf = page_address(page); + cur = buf; + + nr_val = (le16_to_cpu(hdr->len) - sizeof(*hdr)) / 4; + val = (__le32 *)hdr->idx.data; + for (i = 0; i < nr_val && len > 0; i++) { + ret = snprintf(cur, len, "0x%x,", le32_to_cpu(val[i])); + if (ret <= 0) + break; + + cur += ret; + len -= ret; + } + if (cur > buf) + wiphy_info(mt76_hw(dev)->wiphy, "idx: 0x%X,%d,%s", + le32_to_cpu(hdr->idx.idx), nr_val, buf); + put_page(page); + } else if (hdr->type == 2) { /* str log */ + wiphy_info(mt76_hw(dev)->wiphy, "%.*s", hdr->txt.len, hdr->txt.data); + } +} + +static void +mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev, + struct sk_buff *skb) +{ + struct mt7925_mcu_rxd *rxd; + + rxd = (struct mt7925_mcu_rxd *)skb->data; + + switch (rxd->eid) { + case MCU_UNI_EVENT_FW_LOG_2_HOST: + mt7925_mcu_uni_debug_msg_event(dev, skb); + break; + case MCU_UNI_EVENT_ROC: + mt7925_mcu_uni_roc_event(dev, skb); + break; + case MCU_UNI_EVENT_SCAN_DONE: + mt7925_mcu_scan_event(dev, skb); + return; + case MCU_UNI_EVENT_TX_DONE: + mt7925_mcu_tx_done_event(dev, skb); + break; + case MCU_UNI_EVENT_BSS_BEACON_LOSS: + mt7925_mcu_connection_loss_event(dev, skb); + break; + case MCU_UNI_EVENT_COREDUMP: + dev->fw_assert = true; + mt76_connac_mcu_coredump_event(&dev->mt76, skb, &dev->coredump); + return; + default: + break; + } + dev_kfree_skb(skb); +} + +void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct mt7925_mcu_rxd *rxd = (struct mt7925_mcu_rxd *)skb->data; + + if (skb_linearize(skb)) + return; + + if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) { + mt7925_mcu_uni_rx_unsolicited_event(dev, skb); + return; + } + + mt76_mcu_rx_event(&dev->mt76, skb); +} + +static int +mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv; + struct sta_rec_ba_uni *ba; + struct sk_buff *skb; + struct tlv *tlv; + int len; + + len = sizeof(struct sta_req_hdr) + sizeof(*ba); + skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, + len); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); + + ba = (struct sta_rec_ba_uni *)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; + + return mt76_mcu_skb_send_msg(dev, skb, + MCU_UNI_CMD(STA_REC_UPDATE), true); +} + +/** starec & wtbl **/ +int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; + struct mt792x_vif *mvif = msta->vif; + + if (enable && !params->amsdu) + msta->wcid.amsdu = false; + + return mt7925_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + enable, true); +} + +int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; + struct mt792x_vif *mvif = msta->vif; + + return mt7925_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + enable, false); +} + +static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) +{ + const struct mt76_connac2_fw_trailer *hdr; + const struct mt76_connac2_fw_region *region; + const struct mt7925_clc *clc; + struct mt76_dev *mdev = &dev->mt76; + struct mt792x_phy *phy = &dev->phy; + const struct firmware *fw; + int ret, i, len, offset = 0; + u8 *clc_base = NULL; + + if (mt7925_disable_clc || + mt76_is_usb(&dev->mt76)) + return 0; + + ret = request_firmware(&fw, fw_name, mdev->dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(mdev->dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + for (i = 0; i < hdr->n_region; i++) { + region = (const void *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); + len = le32_to_cpu(region->len); + + /* check if we have valid buffer size */ + if (offset + len > fw->size) { + dev_err(mdev->dev, "Invalid firmware region\n"); + ret = -EINVAL; + goto out; + } + + if ((region->feature_set & FW_FEATURE_NON_DL) && + region->type == FW_TYPE_CLC) { + clc_base = (u8 *)(fw->data + offset); + break; + } + offset += len; + } + + if (!clc_base) + goto out; + + for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) { + clc = (const struct mt7925_clc *)(clc_base + offset); + + /* do not init buf again if chip reset triggered */ + if (phy->clc[clc->idx]) + continue; + + phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc, + le32_to_cpu(clc->len), + GFP_KERNEL); + + if (!phy->clc[clc->idx]) { + ret = -ENOMEM; + goto out; + } + } + + ret = mt7925_mcu_set_clc(dev, "00", ENVIRON_INDOOR); +out: + release_firmware(fw); + + return ret; +} + +int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) +{ + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + u8 ctrl; + u8 interval; + u8 _rsv2[2]; + } __packed req = { + .tag = cpu_to_le16(UNI_WSYS_CONFIG_FW_LOG_CTRL), + .len = cpu_to_le16(sizeof(req) - 4), + .ctrl = ctrl, + }; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(WSYS_CONFIG), + &req, sizeof(req), false, NULL); + return ret; +} + +static void +mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_dev *mdev = mphy->dev; + struct mt7925_mcu_phy_cap { + u8 ht; + u8 vht; + u8 _5g; + u8 max_bw; + u8 nss; + u8 dbdc; + u8 tx_ldpc; + u8 rx_ldpc; + u8 tx_stbc; + u8 rx_stbc; + u8 hw_path; + u8 he; + u8 eht; + } __packed * cap; + enum { + WF0_24G, + WF0_5G + }; + + cap = (struct mt7925_mcu_phy_cap *)data; + + mdev->phy.antenna_mask = BIT(cap->nss) - 1; + mdev->phy.chainmask = mdev->phy.antenna_mask; + mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G); + mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G); + dev->has_eht = cap->eht; +} + +static int +mt7925_mcu_get_nic_capability(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + } __packed req = { + .tag = cpu_to_le16(UNI_CHIP_CONFIG_NIC_CAPA), + .len = cpu_to_le16(sizeof(req) - 4), + }; + struct mt76_connac_cap_hdr { + __le16 n_element; + u8 rsv[2]; + } __packed * hdr; + struct sk_buff *skb; + int ret, i; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(CHIP_CONFIG), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + hdr = (struct mt76_connac_cap_hdr *)skb->data; + if (skb->len < sizeof(*hdr)) { + ret = -EINVAL; + goto out; + } + + skb_pull(skb, sizeof(*hdr)); + + for (i = 0; i < le16_to_cpu(hdr->n_element); i++) { + struct tlv *tlv = (struct tlv *)skb->data; + int len; + + if (skb->len < sizeof(*tlv)) + break; + + len = le16_to_cpu(tlv->len); + if (skb->len < len) + break; + + switch (le16_to_cpu(tlv->tag)) { + case MT_NIC_CAP_6G: + mphy->cap.has_6ghz = !!tlv->data[0]; + break; + case MT_NIC_CAP_MAC_ADDR: + memcpy(mphy->macaddr, (void *)tlv->data, ETH_ALEN); + break; + case MT_NIC_CAP_PHY: + mt7925_mcu_parse_phy_cap(dev, tlv->data); + break; + default: + break; + } + skb_pull(skb, len); + } +out: + dev_kfree_skb(skb); + return ret; +} + +int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd) +{ + u16 len = strlen(cmd) + 1; + struct { + u8 _rsv[4]; + __le16 tag; + __le16 len; + struct mt76_connac_config config; + } __packed req = { + .tag = cpu_to_le16(UNI_CHIP_CONFIG_CHIP_CFG), + .len = cpu_to_le16(sizeof(req) - 4), + .config = { + .resp_type = 0, + .type = 0, + .data_size = cpu_to_le16(len), + }, + }; + + memcpy(req.config.data, cmd, len); + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(CHIP_CONFIG), + &req, sizeof(req), false); +} + +int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable) +{ + char cmd[16]; + + snprintf(cmd, sizeof(cmd), "KeepFullPwr %d", !enable); + + return mt7925_mcu_chip_config(dev, cmd); +} +EXPORT_SYMBOL_GPL(mt7925_mcu_set_deep_sleep); + +int mt7925_run_firmware(struct mt792x_dev *dev) +{ + int err; + + err = mt792x_load_firmware(dev); + if (err) + return err; + + err = mt7925_mcu_get_nic_capability(dev); + if (err) + return err; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + err = mt7925_load_clc(dev, mt792x_ram_name(dev)); + if (err) + return err; + + return mt7925_mcu_fw_log_2_host(dev, 1); +} +EXPORT_SYMBOL_GPL(mt7925_run_firmware); + +static void +mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct sta_rec_hdr_trans *hdr_trans; + struct mt76_wcid *wcid; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HDR_TRANS, sizeof(*hdr_trans)); + hdr_trans = (struct sta_rec_hdr_trans *)tlv; + hdr_trans->dis_rx_hdr_tran = true; + + if (vif->type == NL80211_IFTYPE_STATION) + hdr_trans->to_ds = true; + else + hdr_trans->from_ds = true; + + wcid = (struct mt76_wcid *)sta->drv_priv; + if (!wcid) + return; + + hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags); + if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) { + hdr_trans->to_ds = true; + hdr_trans->from_ds = true; + } +} + +int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta; + struct sk_buff *skb; + + msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; + + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid, + MT7925_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + /* starec hdr trans */ + mt7925_mcu_sta_hdr_trans_tlv(skb, vif, sta); + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); +} + +int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) +{ +#define MCU_EDCA_AC_PARAM 0 +#define WMM_AIFS_SET BIT(0) +#define WMM_CW_MIN_SET BIT(1) +#define WMM_CW_MAX_SET BIT(2) +#define WMM_TXOP_SET BIT(3) +#define WMM_PARAM_SET (WMM_AIFS_SET | WMM_CW_MIN_SET | \ + WMM_CW_MAX_SET | WMM_TXOP_SET) + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct { + u8 bss_idx; + u8 __rsv[3]; + } __packed hdr = { + .bss_idx = mvif->mt76.idx, + }; + struct sk_buff *skb; + int len = sizeof(hdr) + IEEE80211_NUM_ACS * sizeof(struct edca); + int ac; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &hdr, sizeof(hdr)); + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + struct ieee80211_tx_queue_params *q = &mvif->queue_params[ac]; + struct edca *e; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, MCU_EDCA_AC_PARAM, sizeof(*e)); + + e = (struct edca *)tlv; + e->set = WMM_PARAM_SET; + e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS; + e->aifs = q->aifs; + e->txop = cpu_to_le16(q->txop); + + if (q->cw_min) + e->cw_min = fls(q->cw_min); + else + e->cw_min = 5; + + if (q->cw_max) + e->cw_max = fls(q->cw_max); + else + e->cw_max = 10; + } + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(EDCA_UPDATE), true); +} + +static int +mt7925_mcu_sta_key_tlv(struct mt76_wcid *wcid, + struct mt76_connac_sta_key_conf *sta_key_conf, + struct sk_buff *skb, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + struct sta_rec_sec_uni *sec; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); + sec = (struct sta_rec_sec_uni *)tlv; + sec->add = cmd; + + if (cmd == SET_KEY) { + struct sec_key_uni *sec_key; + u8 cipher; + + cipher = mt76_connac_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->wlan_idx = cpu_to_le16(wcid->idx); + sec_key->cipher_id = MCU_CIPHER_AES_CCMP; + sec_key->key_id = sta_key_conf->keyidx; + sec_key->key_len = 16; + memcpy(sec_key->key, sta_key_conf->key, 16); + + sec_key = &sec->key[1]; + sec_key->wlan_idx = cpu_to_le16(wcid->idx); + 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->wlan_idx = cpu_to_le16(wcid->idx); + 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(sta_key_conf->key, key->key, key->keylen); + sta_key_conf->keyidx = key->keyidx; + } + + sec->n_cipher = 1; + } + } else { + sec->n_cipher = 0; + } + + return 0; +} + +int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct mt76_connac_sta_key_conf *sta_key_conf, + struct ieee80211_key_conf *key, int mcu_cmd, + struct mt76_wcid *wcid, enum set_key_cmd cmd) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct sk_buff *skb; + int ret; + + skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid, + MT7925_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + ret = mt7925_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd); + if (ret) + return ret; + + return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true); +} + +int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, + struct ieee80211_channel *chan, int duration, + enum mt7925_roc_req type, u8 token_id) +{ + int center_ch = ieee80211_frequency_to_channel(chan->center_freq); + struct mt792x_dev *dev = phy->dev; + struct { + struct { + u8 rsv[4]; + } __packed hdr; + struct roc_acquire_tlv { + __le16 tag; + __le16 len; + u8 bss_idx; + u8 tokenid; + u8 control_channel; + u8 sco; + u8 band; + u8 bw; + u8 center_chan; + u8 center_chan2; + u8 bw_from_ap; + u8 center_chan_from_ap; + u8 center_chan2_from_ap; + u8 reqtype; + __le32 maxinterval; + u8 dbdcband; + u8 rsv[3]; + } __packed roc; + } __packed req = { + .roc = { + .tag = cpu_to_le16(UNI_ROC_ACQUIRE), + .len = cpu_to_le16(sizeof(struct roc_acquire_tlv)), + .tokenid = token_id, + .reqtype = type, + .maxinterval = cpu_to_le32(duration), + .bss_idx = vif->mt76.idx, + .control_channel = chan->hw_value, + .bw = CMD_CBW_20MHZ, + .bw_from_ap = CMD_CBW_20MHZ, + .center_chan = center_ch, + .center_chan_from_ap = center_ch, + .dbdcband = 0xff, /* auto */ + }, + }; + + if (chan->hw_value < center_ch) + req.roc.sco = 1; /* SCA */ + else if (chan->hw_value > center_ch) + req.roc.sco = 3; /* SCB */ + + switch (chan->band) { + case NL80211_BAND_6GHZ: + req.roc.band = 3; + break; + case NL80211_BAND_5GHZ: + req.roc.band = 2; + break; + default: + req.roc.band = 1; + break; + } + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC), + &req, sizeof(req), false); +} + +int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, + u8 token_id) +{ + struct mt792x_dev *dev = phy->dev; + struct { + struct { + u8 rsv[4]; + } __packed hdr; + struct roc_abort_tlv { + __le16 tag; + __le16 len; + u8 bss_idx; + u8 tokenid; + u8 dbdcband; + u8 rsv[5]; + } __packed abort; + } __packed req = { + .abort = { + .tag = cpu_to_le16(UNI_ROC_ABORT), + .len = cpu_to_le16(sizeof(struct roc_abort_tlv)), + .tokenid = token_id, + .bss_idx = vif->mt76.idx, + .dbdcband = 0xff, /* auto*/ + }, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC), + &req, sizeof(req), false); +} + +int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag) +{ + static const u8 ch_band[] = { + [NL80211_BAND_2GHZ] = 0, + [NL80211_BAND_5GHZ] = 1, + [NL80211_BAND_6GHZ] = 2, + }; + struct mt792x_dev *dev = phy->dev; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + int freq1 = chandef->center_freq1; + u8 band_idx = chandef->chan->band != NL80211_BAND_2GHZ; + struct { + /* fixed field */ + u8 __rsv[4]; + + __le16 tag; + __le16 len; + u8 control_ch; + u8 center_ch; + u8 bw; + u8 tx_path_num; + u8 rx_path; /* mask or num */ + u8 switch_reason; + u8 band_idx; + u8 center_ch2; /* for 80+80 only */ + __le16 cac_case; + u8 channel_band; + u8 rsv0; + __le32 outband_freq; + u8 txpower_drop; + u8 ap_bw; + u8 ap_center_ch; + u8 rsv1[53]; + } __packed req = { + .tag = cpu_to_le16(tag), + .len = cpu_to_le16(sizeof(req) - 4), + .control_ch = chandef->chan->hw_value, + .center_ch = ieee80211_frequency_to_channel(freq1), + .bw = mt76_connac_chan_bw(chandef), + .tx_path_num = hweight8(phy->mt76->antenna_mask), + .rx_path = phy->mt76->antenna_mask, + .band_idx = band_idx, + .channel_band = ch_band[chandef->chan->band], + }; + + if (chandef->chan->band == NL80211_BAND_6GHZ) + req.channel_band = 2; + else + req.channel_band = chandef->chan->band; + + if (tag == UNI_CHANNEL_RX_PATH || + dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + 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 (!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; + + if (tag == UNI_CHANNEL_SWITCH) + req.rx_path = hweight8(req.rx_path); + + if (chandef->width == NL80211_CHAN_WIDTH_80P80) { + int freq2 = chandef->center_freq2; + + req.center_ch2 = ieee80211_frequency_to_channel(freq2); + } + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(CHANNEL_SWITCH), + &req, sizeof(req), true); +} + +int mt7925_mcu_set_eeprom(struct mt792x_dev *dev) +{ + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + u8 buffer_mode; + u8 format; + __le16 buf_len; + } __packed req = { + .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE), + .len = cpu_to_le16(sizeof(req) - 4), + .buffer_mode = EE_MODE_EFUSE, + .format = EE_FORMAT_WHOLE + }; + + return mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(EFUSE_CTRL), + &req, sizeof(req), false, NULL); +} +EXPORT_SYMBOL_GPL(mt7925_mcu_set_eeprom); + +int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct ps_tlv { + __le16 tag; + __le16 len; + u8 ps_state; /* 0: device awake + * 1: static power save + * 2: dynamic power saving + * 3: enter TWT power saving + * 4: leave TWT power saving + */ + u8 pad[3]; + } __packed ps; + } __packed ps_req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .ps = { + .tag = cpu_to_le16(UNI_BSS_INFO_PS), + .len = cpu_to_le16(sizeof(struct ps_tlv)), + .ps_state = vif->cfg.ps ? 2 : 0, + }, + }; + + if (vif->type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &ps_req, sizeof(ps_req), true); +} + +static int +mt7925_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcnft_tlv { + __le16 tag; + __le16 len; + __le16 bcn_interval; + u8 dtim_period; + u8 bmc_delivered_ac; + u8 bmc_triggered_ac; + u8 pad[3]; + } __packed bcnft; + } __packed bcnft_req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .bcnft = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCNFT), + .len = cpu_to_le16(sizeof(struct bcnft_tlv)), + .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), + .dtim_period = vif->bss_conf.dtim_period, + }, + }; + + if (vif->type != NL80211_IFTYPE_STATION) + return 0; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &bcnft_req, sizeof(bcnft_req), true); +} + +int +mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcnft_tlv { + __le16 tag; + __le16 len; + __le16 bcn_interval; + u8 dtim_period; + u8 bmc_delivered_ac; + u8 bmc_triggered_ac; + u8 pad[3]; + } __packed enable; + } req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .enable = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCNFT), + .len = cpu_to_le16(sizeof(struct bcnft_tlv)), + .dtim_period = vif->bss_conf.dtim_period, + .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), + }, + }; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct pm_disable { + __le16 tag; + __le16 len; + } __packed disable; + } req1 = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .disable = { + .tag = cpu_to_le16(UNI_BSS_INFO_PM_DISABLE), + .len = cpu_to_le16(sizeof(struct pm_disable)) + }, + }; + int err; + + err = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &req1, sizeof(req1), false); + if (err < 0 || !enable) + return err; + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &req, sizeof(req), false); +} + +static void +mt7925_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + if (!sta->deflink.he_cap.has_he) + return; + + mt76_connac_mcu_sta_he_tlv_v2(skb, sta); +} + +static void +mt7925_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct sta_rec_he_6g_capa *he_6g; + struct tlv *tlv; + + if (!sta->deflink.he_6ghz_capa.capa) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G, sizeof(*he_6g)); + + he_6g = (struct sta_rec_he_6g_capa *)tlv; + he_6g->capa = sta->deflink.he_6ghz_capa.capa; +} + +static void +mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct ieee80211_eht_mcs_nss_supp *mcs_map; + struct ieee80211_eht_cap_elem_fixed *elem; + struct sta_rec_eht *eht; + struct tlv *tlv; + + if (!sta->deflink.eht_cap.has_eht) + return; + + mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp; + elem = &sta->deflink.eht_cap.eht_cap_elem; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht)); + + eht = (struct sta_rec_eht *)tlv; + eht->tid_bitmap = 0xff; + eht->mac_cap = cpu_to_le16(*(u16 *)elem->mac_cap_info); + eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info); + eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]); + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20)); + memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80)); + memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160)); +} + +static void +mt7925_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct sta_rec_ht *ht; + struct tlv *tlv; + + if (!sta->deflink.ht_cap.ht_supported) + return; + + 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->deflink.ht_cap.cap); +} + +static void +mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct sta_rec_vht *vht; + struct tlv *tlv; + + /* For 6G band, this tlv is necessary to let hw work normally */ + if (!sta->deflink.he_6ghz_capa.capa && !sta->deflink.vht_cap.vht_supported) + return; + + 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->deflink.vht_cap.cap); + vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map; +} + +static void +mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct sta_rec_amsdu *amsdu; + struct tlv *tlv; + + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP) + return; + + if (!sta->deflink.agg.max_amsdu_len) + return; + + 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; + msta->wcid.amsdu = true; + + switch (sta->deflink.agg.max_amsdu_len) { + case IEEE80211_MAX_MPDU_LEN_VHT_11454: + amsdu->max_mpdu_size = + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; + return; + 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; + } +} + +static void +mt7925_mcu_sta_phy_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &mvif->mt76.ctx->def; + struct sta_rec_phy *phy; + struct tlv *tlv; + u8 af = 0, mm = 0; + + if (!sta->deflink.ht_cap.ht_supported && !sta->deflink.he_6ghz_capa.capa) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy)); + phy = (struct sta_rec_phy *)tlv; + phy->phy_type = mt76_connac_get_phy_mode_v2(mvif->phy->mt76, vif, chandef->chan->band, sta); + if (sta->deflink.ht_cap.ht_supported) { + af = sta->deflink.ht_cap.ampdu_factor; + mm = sta->deflink.ht_cap.ampdu_density; + } + + if (sta->deflink.vht_cap.vht_supported) { + u8 vht_af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, + sta->deflink.vht_cap.cap); + + af = max_t(u8, af, vht_af); + } + + if (sta->deflink.he_6ghz_capa.capa) { + af = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); + mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa, + IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); + } + + phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR, af) | + FIELD_PREP(IEEE80211_HT_AMPDU_PARM_DENSITY, mm); + phy->max_ampdu_len = af; +} + +static void +mt7925_mcu_sta_state_v2_tlv(struct mt76_phy *mphy, struct sk_buff *skb, + struct ieee80211_sta *sta, + struct ieee80211_vif *vif, + u8 rcpi, u8 sta_state) +{ + struct sta_rec_state_v2 { + __le16 tag; + __le16 len; + u8 state; + u8 rsv[3]; + __le32 flags; + u8 vht_opmode; + u8 action; + u8 rsv2[2]; + } __packed * state; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state)); + state = (struct sta_rec_state_v2 *)tlv; + state->state = sta_state; + + if (sta->deflink.vht_cap.vht_supported) { + state->vht_opmode = sta->deflink.bandwidth; + state->vht_opmode |= sta->deflink.rx_nss << + IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; + } +} + +static void +mt7925_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &mvif->mt76.ctx->def; + enum nl80211_band band = chandef->chan->band; + struct sta_rec_ra_info *ra_info; + struct tlv *tlv; + u16 supp_rates; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); + ra_info = (struct sta_rec_ra_info *)tlv; + + supp_rates = sta->deflink.supp_rates[band]; + if (band == NL80211_BAND_2GHZ) + supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) | + FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf); + else + supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates); + + ra_info->legacy = cpu_to_le16(supp_rates); + + if (sta->deflink.ht_cap.ht_supported) + memcpy(ra_info->rx_mcs_bitmask, + sta->deflink.ht_cap.mcs.rx_mask, + HT_MCS_MASK_NUM); +} + +static void +mt7925_mcu_sta_mld_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + struct sta_rec_mld *mld; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld)); + mld = (struct sta_rec_mld *)tlv; + memcpy(mld->mac_addr, vif->addr, ETH_ALEN); + mld->primary_id = cpu_to_le16(wcid->idx); + mld->wlan_id = cpu_to_le16(wcid->idx); + + /* TODO: 0 means deflink only, add secondary link(1) later */ + mld->link_num = !!(hweight8(vif->active_links) > 1); + WARN_ON_ONCE(mld->link_num); +} + +static int +mt7925_mcu_sta_cmd(struct mt76_phy *phy, + struct mt76_sta_cmd_info *info) +{ + struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv; + struct mt76_dev *dev = phy->dev; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid, + MT7925_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + if (info->sta || !info->offload_fw) + mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta, + info->enable, info->newly); + if (info->sta && info->enable) { + mt7925_mcu_sta_phy_tlv(skb, info->vif, info->sta); + mt7925_mcu_sta_ht_tlv(skb, info->sta); + mt7925_mcu_sta_vht_tlv(skb, info->sta); + mt76_connac_mcu_sta_uapsd(skb, info->vif, info->sta); + mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->sta); + mt7925_mcu_sta_he_tlv(skb, info->sta); + mt7925_mcu_sta_he_6g_tlv(skb, info->sta); + mt7925_mcu_sta_eht_tlv(skb, info->sta); + mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif, info->sta); + mt7925_mcu_sta_state_v2_tlv(phy, skb, info->sta, + info->vif, info->rcpi, + info->state); + mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->sta); + mt7925_mcu_sta_mld_tlv(skb, info->vif, info->sta); + } + + sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, + sizeof(struct tlv)); + + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid, + WTBL_RESET_AND_SET, + sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + if (info->enable) { + mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif, + info->sta, sta_wtbl, + wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid, + sta_wtbl, wtbl_hdr); + if (info->sta) + mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, + sta_wtbl, wtbl_hdr, + true, true); + } + + return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); +} + +int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, + struct ieee80211_vif *vif, bool enable, + enum mt76_sta_info_state state) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + int rssi = -ewma_rssi_read(&mvif->rssi); + struct mt76_sta_cmd_info info = { + .sta = sta, + .vif = vif, + .enable = enable, + .cmd = MCU_UNI_CMD(STA_REC_UPDATE), + .state = state, + .offload_fw = true, + .rcpi = to_rcpi(rssi), + }; + struct mt792x_sta *msta; + + msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL; + info.wcid = msta ? &msta->wcid : &mvif->sta.wcid; + info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true; + + return mt7925_mcu_sta_cmd(&dev->mphy, &info); +} + +int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, + struct ieee80211_vif *vif, + bool enable) +{ +#define MT7925_FIF_BIT_CLR BIT(1) +#define MT7925_FIF_BIT_SET BIT(0) + int err = 0; + + if (enable) { + err = mt7925_mcu_uni_bss_bcnft(dev, vif, true); + if (err) + return err; + + return mt7925_mcu_set_rxfilter(dev, 0, + MT7925_FIF_BIT_SET, + MT_WF_RFCR_DROP_OTHER_BEACON); + } + + err = mt7925_mcu_set_bss_pm(dev, vif, false); + if (err) + return err; + + return mt7925_mcu_set_rxfilter(dev, 0, + MT7925_FIF_BIT_CLR, + MT_WF_RFCR_DROP_OTHER_BEACON); +} + +int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, struct mt7925_txpwr *txpwr) +{ +#define TX_POWER_SHOW_INFO 0x7 +#define TXPOWER_ALL_RATE_POWER_INFO 0x2 + struct mt7925_txpwr_event *event; + struct mt7925_txpwr_req req = { + .tag = cpu_to_le16(TX_POWER_SHOW_INFO), + .len = cpu_to_le16(sizeof(req) - 4), + .catg = TXPOWER_ALL_RATE_POWER_INFO, + .band_idx = band_idx, + }; + struct sk_buff *skb; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(TXPOWER), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + event = (struct mt7925_txpwr_event *)skb->data; + memcpy(txpwr, &event->txpwr, sizeof(event->txpwr)); + + dev_kfree_skb(skb); + + return 0; +} + +int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + struct { + struct { + u8 band_idx; + u8 pad[3]; + } __packed hdr; + struct sniffer_enable_tlv { + __le16 tag; + __le16 len; + u8 enable; + u8 pad[3]; + } __packed enable; + } __packed req = { + .hdr = { + .band_idx = mvif->mt76.band_idx, + }, + .enable = { + .tag = cpu_to_le16(UNI_SNIFFER_ENABLE), + .len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)), + .enable = enable, + }, + }; + + mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true); + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), + true); +} + +int mt7925_mcu_config_sniffer(struct mt792x_vif *vif, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt76_phy *mphy = vif->phy->mt76; + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &mphy->chandef; + int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; + + const u8 ch_band[] = { + [NL80211_BAND_2GHZ] = 1, + [NL80211_BAND_5GHZ] = 2, + [NL80211_BAND_6GHZ] = 3, + }; + const u8 ch_width[] = { + [NL80211_CHAN_WIDTH_20_NOHT] = 0, + [NL80211_CHAN_WIDTH_20] = 0, + [NL80211_CHAN_WIDTH_40] = 0, + [NL80211_CHAN_WIDTH_80] = 1, + [NL80211_CHAN_WIDTH_160] = 2, + [NL80211_CHAN_WIDTH_80P80] = 3, + [NL80211_CHAN_WIDTH_5] = 4, + [NL80211_CHAN_WIDTH_10] = 5, + [NL80211_CHAN_WIDTH_320] = 6, + }; + + struct { + struct { + u8 band_idx; + u8 pad[3]; + } __packed hdr; + struct config_tlv { + __le16 tag; + __le16 len; + u16 aid; + u8 ch_band; + u8 bw; + u8 control_ch; + u8 sco; + u8 center_ch; + u8 center_ch2; + u8 drop_err; + u8 pad[3]; + } __packed tlv; + } __packed req = { + .hdr = { + .band_idx = vif->mt76.band_idx, + }, + .tlv = { + .tag = cpu_to_le16(UNI_SNIFFER_CONFIG), + .len = cpu_to_le16(sizeof(req.tlv)), + .control_ch = chandef->chan->hw_value, + .center_ch = ieee80211_frequency_to_channel(freq1), + .drop_err = 1, + }, + }; + + if (chandef->chan->band < ARRAY_SIZE(ch_band)) + req.tlv.ch_band = ch_band[chandef->chan->band]; + if (chandef->width < ARRAY_SIZE(ch_width)) + req.tlv.bw = ch_width[chandef->width]; + + if (freq2) + req.tlv.center_ch2 = ieee80211_frequency_to_channel(freq2); + + if (req.tlv.control_ch < req.tlv.center_ch) + req.tlv.sco = 1; /* SCA */ + else if (req.tlv.control_ch > req.tlv.center_ch) + req.tlv.sco = 3; /* SCB */ + + return mt76_mcu_send_msg(mphy->dev, MCU_UNI_CMD(SNIFFER), + &req, sizeof(req), true); +} + +int +mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_mutable_offsets offs; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcn_content_tlv { + __le16 tag; + __le16 len; + __le16 tim_ie_pos; + __le16 csa_ie_pos; + __le16 bcc_ie_pos; + /* 0: disable beacon offload + * 1: enable beacon offload + * 2: update probe respond offload + */ + u8 enable; + /* 0: legacy format (TXD + payload) + * 1: only cap field IE + */ + u8 type; + __le16 pkt_len; + u8 pkt[512]; + } __packed beacon_tlv; + } req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .beacon_tlv = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), + .len = cpu_to_le16(sizeof(struct bcn_content_tlv)), + .enable = enable, + .type = 1, + }, + }; + struct sk_buff *skb; + u8 cap_offs; + + /* support enable/update process only + * disable flow would be handled in bss stop handler automatically + */ + if (!enable) + return -EOPNOTSUPP; + + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs, 0); + if (!skb) + return -EINVAL; + + cap_offs = offsetof(struct ieee80211_mgmt, u.beacon.capab_info); + if (!skb_pull(skb, cap_offs)) { + dev_err(dev->mt76.dev, "beacon format err\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + if (skb->len > 512) { + dev_err(dev->mt76.dev, "beacon size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + memcpy(req.beacon_tlv.pkt, skb->data, skb->len); + req.beacon_tlv.pkt_len = cpu_to_le16(skb->len); + offs.tim_offset -= cap_offs; + req.beacon_tlv.tim_ie_pos = cpu_to_le16(offs.tim_offset); + + if (offs.cntdwn_counter_offs[0]) { + u16 csa_offs; + + csa_offs = offs.cntdwn_counter_offs[0] - cap_offs - 4; + req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs); + } + dev_kfree_skb(skb); + + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &req, sizeof(req), true); +} + +int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif, + struct ieee80211_chanctx_conf *ctx) +{ + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; + int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; + enum nl80211_band band = chandef->chan->band; + struct mt76_dev *mdev = phy->dev; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct rlm_tlv { + __le16 tag; + __le16 len; + u8 control_channel; + u8 center_chan; + u8 center_chan2; + u8 bw; + u8 tx_streams; + u8 rx_streams; + u8 ht_op_info; + u8 sco; + u8 band; + u8 pad[3]; + } __packed rlm; + } __packed rlm_req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .rlm = { + .tag = cpu_to_le16(UNI_BSS_INFO_RLM), + .len = cpu_to_le16(sizeof(struct rlm_tlv)), + .control_channel = chandef->chan->hw_value, + .center_chan = ieee80211_frequency_to_channel(freq1), + .center_chan2 = ieee80211_frequency_to_channel(freq2), + .tx_streams = hweight8(phy->antenna_mask), + .ht_op_info = 4, /* set HT 40M allowed */ + .rx_streams = hweight8(phy->antenna_mask), + .band = band, + }, + }; + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_40: + rlm_req.rlm.bw = CMD_CBW_40MHZ; + break; + case NL80211_CHAN_WIDTH_80: + rlm_req.rlm.bw = CMD_CBW_80MHZ; + break; + case NL80211_CHAN_WIDTH_80P80: + rlm_req.rlm.bw = CMD_CBW_8080MHZ; + break; + case NL80211_CHAN_WIDTH_160: + rlm_req.rlm.bw = CMD_CBW_160MHZ; + break; + case NL80211_CHAN_WIDTH_5: + rlm_req.rlm.bw = CMD_CBW_5MHZ; + break; + case NL80211_CHAN_WIDTH_10: + rlm_req.rlm.bw = CMD_CBW_10MHZ; + break; + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + default: + rlm_req.rlm.bw = CMD_CBW_20MHZ; + rlm_req.rlm.ht_op_info = 0; + break; + } + + if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan) + rlm_req.rlm.sco = 1; /* SCA */ + else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan) + rlm_req.rlm.sco = 3; /* SCB */ + + return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req, + sizeof(rlm_req), true); +} + +static struct sk_buff * +__mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif *mvif, int len) +{ + struct bss_req_hdr hdr = { + .bss_idx = mvif->idx, + }; + struct sk_buff *skb; + + skb = mt76_mcu_msg_alloc(dev, NULL, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + skb_put_data(skb, &hdr, sizeof(hdr)); + + return skb; +} + +static u8 +mt7925_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta) +{ + struct ieee80211_he_6ghz_capa *he_6ghz_capa; + const struct ieee80211_sta_eht_cap *eht_cap; + __le16 capa = 0; + u8 mode = 0; + + if (sta) { + he_6ghz_capa = &sta->deflink.he_6ghz_capa; + eht_cap = &sta->deflink.eht_cap; + } else { + struct ieee80211_supported_band *sband; + + sband = phy->hw->wiphy->bands[band]; + capa = ieee80211_get_he_6ghz_capa(sband, vif->type); + he_6ghz_capa = (struct ieee80211_he_6ghz_capa *)&capa; + + eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type); + } + + switch (band) { + case NL80211_BAND_2GHZ: + if (eht_cap && eht_cap->has_eht) + mode |= PHY_MODE_BE_24G; + break; + case NL80211_BAND_5GHZ: + if (eht_cap && eht_cap->has_eht) + mode |= PHY_MODE_BE_5G; + break; + case NL80211_BAND_6GHZ: + if (he_6ghz_capa && he_6ghz_capa->capa) + mode |= PHY_MODE_AX_6G; + + if (eht_cap && eht_cap->has_eht) + mode |= PHY_MODE_BE_6G; + break; + default: + break; + } + + return mode; +} + +static void +mt7925_mcu_bss_basic_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_chanctx_conf *ctx, + struct mt76_phy *phy, u16 wlan_idx, + bool enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : + &mvif->sta; + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef; + enum nl80211_band band = chandef->chan->band; + struct mt76_connac_bss_basic_tlv *basic_req; + u8 idx, basic_phy; + struct tlv *tlv; + int conn_type; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*basic_req)); + basic_req = (struct mt76_connac_bss_basic_tlv *)tlv; + + idx = mvif->mt76.omac_idx > EXT_BSSID_START ? HW_BSSID_0 : + mvif->mt76.omac_idx; + basic_req->hw_bss_idx = idx; + + basic_req->phymode_ext = mt7925_get_phy_mode_ext(phy, vif, band, sta); + + basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, sta); + basic_req->nonht_basic_phy = cpu_to_le16(basic_phy); + + memcpy(basic_req->bssid, vif->bss_conf.bssid, ETH_ALEN); + basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, sta); + basic_req->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + basic_req->dtim_period = vif->bss_conf.dtim_period; + basic_req->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); + basic_req->sta_idx = cpu_to_le16(msta->wcid.idx); + basic_req->omac_idx = mvif->mt76.omac_idx; + basic_req->band_idx = mvif->mt76.band_idx; + basic_req->wmm_idx = mvif->mt76.wmm_idx; + basic_req->conn_state = !enable; + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + if (vif->p2p) + conn_type = CONNECTION_P2P_GO; + else + conn_type = CONNECTION_INFRA_AP; + basic_req->conn_type = cpu_to_le32(conn_type); + basic_req->active = enable; + break; + case NL80211_IFTYPE_STATION: + if (vif->p2p) + conn_type = CONNECTION_P2P_GC; + else + conn_type = CONNECTION_INFRA_STA; + basic_req->conn_type = cpu_to_le32(conn_type); + basic_req->active = true; + break; + case NL80211_IFTYPE_ADHOC: + basic_req->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); + basic_req->active = true; + break; + default: + WARN_ON(1); + break; + } +} + +static void +mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct bss_sec_tlv { + __le16 tag; + __le16 len; + u8 mode; + u8 status; + u8 cipher; + u8 __rsv; + } __packed * sec; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_SEC, sizeof(*sec)); + sec = (struct bss_sec_tlv *)tlv; + + switch (mvif->cipher) { + case MCU_CIPHER_GCMP_256: + case MCU_CIPHER_GCMP: + sec->mode = MODE_WPA3_SAE; + sec->status = 8; + break; + case MCU_CIPHER_AES_CCMP: + sec->mode = MODE_WPA2_PSK; + sec->status = 6; + break; + case MCU_CIPHER_TKIP: + sec->mode = MODE_WPA2_PSK; + sec->status = 4; + break; + case MCU_CIPHER_WEP104: + case MCU_CIPHER_WEP40: + sec->mode = MODE_SHARED; + sec->status = 0; + break; + default: + sec->mode = MODE_OPEN; + sec->status = 1; + break; + } + + sec->cipher = mvif->cipher; +} + +static void +mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy, + struct ieee80211_chanctx_conf *ctx, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->mt76->chandef; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + enum nl80211_band band = chandef->chan->band; + struct bss_rate_tlv *bmc; + struct tlv *tlv; + u8 idx = mvif->mcast_rates_idx ? + mvif->mcast_rates_idx : mvif->basic_rates_idx; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc)); + + bmc = (struct bss_rate_tlv *)tlv; + + bmc->short_preamble = (band == NL80211_BAND_2GHZ); + bmc->bc_fixed_rate = idx; + bmc->mc_fixed_rate = idx; +} + +static void +mt7925_mcu_bss_mld_tlv(struct sk_buff *skb, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + bool is_mld = ieee80211_vif_is_mld(vif); + struct bss_mld_tlv *mld; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_MLD, sizeof(*mld)); + mld = (struct bss_mld_tlv *)tlv; + + mld->link_id = sta ? (is_mld ? vif->bss_conf.link_id : 0) : 0xff; + mld->group_mld_id = is_mld ? mvif->mt76.idx : 0xff; + mld->own_mld_id = mvif->mt76.idx + 32; + mld->remap_idx = 0xff; + + if (sta) + memcpy(mld->mac_addr, sta->addr, ETH_ALEN); +} + +static void +mt7925_mcu_bss_qos_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt76_connac_bss_qos_tlv *qos; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_QBSS, sizeof(*qos)); + qos = (struct mt76_connac_bss_qos_tlv *)tlv; + qos->qos = vif->bss_conf.qos; +} + +static void +mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt792x_phy *phy) +{ +#define DEFAULT_HE_PE_DURATION 4 +#define DEFAULT_HE_DURATION_RTS_THRES 1023 + const struct ieee80211_sta_he_cap *cap; + struct bss_info_uni_he *he; + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; + if (!he->he_pe_duration) + he->he_pe_duration = DEFAULT_HE_PE_DURATION; + + he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th); + if (!he->he_rts_thres) + he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES); + + he->max_nss_mcs[CMD_HE_MCS_BW80] = cap->he_mcs_nss_supp.tx_mcs_80; + he->max_nss_mcs[CMD_HE_MCS_BW160] = cap->he_mcs_nss_supp.tx_mcs_160; + he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80; +} + +static void +mt7925_mcu_bss_color_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + bool enable) +{ + struct bss_info_uni_bss_color *color; + struct tlv *tlv; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BSS_COLOR, sizeof(*color)); + color = (struct bss_info_uni_bss_color *)tlv; + + color->enable = enable ? + vif->bss_conf.he_bss_color.enabled : 0; + color->bss_color = enable ? + vif->bss_conf.he_bss_color.color : 0; +} + +int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, + struct ieee80211_chanctx_conf *ctx, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + int enable) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = phy->dev; + struct sk_buff *skb; + int err; + + skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + MT7925_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + /* bss_basic must be first */ + mt7925_mcu_bss_basic_tlv(skb, vif, sta, ctx, phy->mt76, + mvif->sta.wcid.idx, enable); + mt7925_mcu_bss_sec_tlv(skb, vif); + + mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, vif, sta); + mt7925_mcu_bss_qos_tlv(skb, vif); + mt7925_mcu_bss_mld_tlv(skb, vif, sta); + + if (vif->bss_conf.he_support) { + mt7925_mcu_bss_he_tlv(skb, vif, phy); + mt7925_mcu_bss_color_tlv(skb, vif, enable); + } + + err = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(BSS_INFO_UPDATE), true); + if (err < 0) + return err; + + return mt7925_mcu_set_chctx(phy->mt76, &mvif->mt76, ctx); +} + +int mt7925_mcu_set_dbdc(struct mt76_phy *phy) +{ + struct mt76_dev *mdev = phy->dev; + + struct mbmc_conf_tlv *conf; + struct mbmc_set_req *hdr; + struct sk_buff *skb; + struct tlv *tlv; + int max_len, err; + + max_len = sizeof(*hdr) + sizeof(*conf); + skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); + if (!skb) + return -ENOMEM; + + hdr = (struct mbmc_set_req *)skb_put(skb, sizeof(*hdr)); + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_MBMC_SETTING, sizeof(*conf)); + conf = (struct mbmc_conf_tlv *)tlv; + + conf->mbmc_en = 1; + conf->band = 0; /* unused */ + + err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SET_DBDC_PARMS), + false); + + return err; +} + +#define MT76_CONNAC_SCAN_CHANNEL_TIME 60 + +int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_scan_request *scan_req) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct cfg80211_scan_request *sreq = &scan_req->req; + int n_ssids = 0, err, i, duration; + struct ieee80211_channel **scan_list = sreq->channels; + struct mt76_dev *mdev = phy->dev; + struct mt76_connac_mcu_scan_channel *chan; + struct sk_buff *skb; + + struct scan_hdr_tlv *hdr; + struct scan_req_tlv *req; + struct scan_ssid_tlv *ssid; + struct scan_bssid_tlv *bssid; + struct scan_chan_info_tlv *chan_info; + struct scan_ie_tlv *ie; + struct scan_misc_tlv *misc; + struct tlv *tlv; + int max_len; + + max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) + + sizeof(*bssid) + sizeof(*chan_info) + + sizeof(*misc) + sizeof(*ie); + + skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); + if (!skb) + return -ENOMEM; + + set_bit(MT76_HW_SCANNING, &phy->state); + mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f; + + hdr = (struct scan_hdr_tlv *)skb_put(skb, sizeof(*hdr)); + hdr->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; + hdr->bss_idx = mvif->idx; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_REQ, sizeof(*req)); + req = (struct scan_req_tlv *)tlv; + req->scan_type = sreq->n_ssids ? 1 : 0; + req->probe_req_num = sreq->n_ssids ? 2 : 0; + + duration = MT76_CONNAC_SCAN_CHANNEL_TIME; + /* increase channel time for passive scan */ + if (!sreq->n_ssids) + duration *= 2; + req->timeout_value = cpu_to_le16(sreq->n_channels * duration); + req->channel_min_dwell_time = cpu_to_le16(duration); + req->channel_dwell_time = cpu_to_le16(duration); + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SSID, sizeof(*ssid)); + ssid = (struct scan_ssid_tlv *)tlv; + for (i = 0; i < sreq->n_ssids; i++) { + if (!sreq->ssids[i].ssid_len) + continue; + + ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); + memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid, + sreq->ssids[i].ssid_len); + n_ssids++; + } + ssid->ssid_type = n_ssids ? BIT(2) : BIT(0); + ssid->ssids_num = n_ssids; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid)); + bssid = (struct scan_bssid_tlv *)tlv; + + memcpy(bssid->bssid, sreq->bssid, ETH_ALEN); + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_CHANNEL, sizeof(*chan_info)); + chan_info = (struct scan_chan_info_tlv *)tlv; + chan_info->channels_num = min_t(u8, sreq->n_channels, + ARRAY_SIZE(chan_info->channels)); + for (i = 0; i < chan_info->channels_num; i++) { + chan = &chan_info->channels[i]; + + switch (scan_list[i]->band) { + case NL80211_BAND_2GHZ: + chan->band = 1; + break; + case NL80211_BAND_6GHZ: + chan->band = 3; + break; + default: + chan->band = 2; + break; + } + chan->channel_num = scan_list[i]->hw_value; + } + chan_info->channel_type = sreq->n_channels ? 4 : 0; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); + ie = (struct scan_ie_tlv *)tlv; + if (sreq->ie_len > 0) { + memcpy(ie->ies, sreq->ie, sreq->ie_len); + ie->ies_len = cpu_to_le16(sreq->ie_len); + } + + req->scan_func |= SCAN_FUNC_SPLIT_SCAN; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc)); + misc = (struct scan_misc_tlv *)tlv; + if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + get_random_mask_addr(misc->random_mac, sreq->mac_addr, + sreq->mac_addr_mask); + req->scan_func |= SCAN_FUNC_RANDOM_MAC; + } + + err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), + false); + if (err < 0) + clear_bit(MT76_HW_SCANNING, &phy->state); + + return err; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan); + +int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *sreq) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct ieee80211_channel **scan_list = sreq->channels; + struct mt76_connac_mcu_scan_channel *chan; + struct mt76_dev *mdev = phy->dev; + struct cfg80211_match_set *cfg_match; + struct cfg80211_ssid *cfg_ssid; + + struct scan_hdr_tlv *hdr; + struct scan_sched_req *req; + struct scan_ssid_tlv *ssid; + struct scan_chan_info_tlv *chan_info; + struct scan_ie_tlv *ie; + struct scan_sched_ssid_match_sets *match; + struct sk_buff *skb; + struct tlv *tlv; + int i, max_len; + + max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) + + sizeof(*chan_info) + sizeof(*ie) + + sizeof(*match); + + skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); + if (!skb) + return -ENOMEM; + + mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f; + + hdr = (struct scan_hdr_tlv *)skb_put(skb, sizeof(*hdr)); + hdr->seq_num = mvif->scan_seq_num | mvif->band_idx << 7; + hdr->bss_idx = mvif->idx; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SCHED_REQ, sizeof(*req)); + req = (struct scan_sched_req *)tlv; + req->version = 1; + + if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + req->scan_func |= SCAN_FUNC_RANDOM_MAC; + + req->intervals_num = sreq->n_scan_plans; + for (i = 0; i < req->intervals_num; i++) + req->intervals[i] = cpu_to_le16(sreq->scan_plans[i].interval); + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SSID, sizeof(*ssid)); + ssid = (struct scan_ssid_tlv *)tlv; + + ssid->ssids_num = sreq->n_ssids; + ssid->ssid_type = BIT(2); + for (i = 0; i < ssid->ssids_num; i++) { + cfg_ssid = &sreq->ssids[i]; + memcpy(ssid->ssids[i].ssid, cfg_ssid->ssid, cfg_ssid->ssid_len); + ssid->ssids[i].ssid_len = cpu_to_le32(cfg_ssid->ssid_len); + } + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SSID_MATCH_SETS, sizeof(*match)); + match = (struct scan_sched_ssid_match_sets *)tlv; + match->match_num = sreq->n_match_sets; + for (i = 0; i < match->match_num; i++) { + cfg_match = &sreq->match_sets[i]; + memcpy(match->match[i].ssid, cfg_match->ssid.ssid, + cfg_match->ssid.ssid_len); + match->match[i].rssi_th = cpu_to_le32(cfg_match->rssi_thold); + match->match[i].ssid_len = cfg_match->ssid.ssid_len; + } + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_CHANNEL, sizeof(*chan_info)); + chan_info = (struct scan_chan_info_tlv *)tlv; + chan_info->channels_num = min_t(u8, sreq->n_channels, + ARRAY_SIZE(chan_info->channels)); + for (i = 0; i < chan_info->channels_num; i++) { + chan = &chan_info->channels[i]; + + switch (scan_list[i]->band) { + case NL80211_BAND_2GHZ: + chan->band = 1; + break; + case NL80211_BAND_6GHZ: + chan->band = 3; + break; + default: + chan->band = 2; + break; + } + chan->channel_num = scan_list[i]->hw_value; + } + chan_info->channel_type = sreq->n_channels ? 4 : 0; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); + ie = (struct scan_ie_tlv *)tlv; + if (sreq->ie_len > 0) { + memcpy(ie->ies, sreq->ie, sreq->ie_len); + ie->ies_len = cpu_to_le16(sreq->ie_len); + } + + return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), + false); +} +EXPORT_SYMBOL_GPL(mt7925_mcu_sched_scan_req); + +int +mt7925_mcu_sched_scan_enable(struct mt76_phy *phy, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt76_dev *mdev = phy->dev; + struct scan_sched_enable *req; + struct scan_hdr_tlv *hdr; + struct sk_buff *skb; + struct tlv *tlv; + int max_len; + + max_len = sizeof(*hdr) + sizeof(*req); + + skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); + if (!skb) + return -ENOMEM; + + hdr = (struct scan_hdr_tlv *)skb_put(skb, sizeof(*hdr)); + hdr->seq_num = 0; + hdr->bss_idx = 0; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_SCHED_ENABLE, sizeof(*req)); + req = (struct scan_sched_enable *)tlv; + req->active = !enable; + + if (enable) + set_bit(MT76_HW_SCHED_SCANNING, &phy->state); + else + clear_bit(MT76_HW_SCHED_SCANNING, &phy->state); + + return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), + false); +} + +int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy, + struct ieee80211_vif *vif) +{ + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; + struct { + struct scan_hdr { + u8 seq_num; + u8 bss_idx; + u8 pad[2]; + } __packed hdr; + struct scan_cancel_tlv { + __le16 tag; + __le16 len; + u8 is_ext_channel; + u8 rsv[3]; + } __packed cancel; + } req = { + .hdr = { + .seq_num = mvif->scan_seq_num, + .bss_idx = mvif->idx, + }, + .cancel = { + .tag = cpu_to_le16(UNI_SCAN_CANCEL), + .len = cpu_to_le16(sizeof(struct scan_cancel_tlv)), + }, + }; + + if (test_and_clear_bit(MT76_HW_SCANNING, &phy->state)) { + struct cfg80211_scan_info info = { + .aborted = true, + }; + + ieee80211_scan_completed(phy->hw, &info); + } + + return mt76_mcu_send_msg(phy->dev, MCU_UNI_CMD(SCAN_REQ), + &req, sizeof(req), false); +} +EXPORT_SYMBOL_GPL(mt7925_mcu_cancel_hw_scan); + +int mt7925_mcu_set_channel_domain(struct mt76_phy *phy) +{ + int len, i, n_max_channels, n_2ch = 0, n_5ch = 0, n_6ch = 0; + struct { + struct { + u8 alpha2[4]; /* regulatory_request.alpha2 */ + u8 bw_2g; /* BW_20_40M 0 + * BW_20M 1 + * BW_20_40_80M 2 + * BW_20_40_80_160M 3 + * BW_20_40_80_8080M 4 + */ + u8 bw_5g; + u8 bw_6g; + u8 pad; + } __packed hdr; + struct n_chan { + __le16 tag; + __le16 len; + u8 n_2ch; + u8 n_5ch; + u8 n_6ch; + u8 pad; + } __packed n_ch; + } req = { + .hdr = { + .bw_2g = 0, + .bw_5g = 3, /* BW_20_40_80_160M */ + .bw_6g = 3, + }, + .n_ch = { + .tag = cpu_to_le16(2), + }, + }; + struct mt76_connac_mcu_chan { + __le16 hw_value; + __le16 pad; + __le32 flags; + } __packed channel; + struct mt76_dev *dev = phy->dev; + struct ieee80211_channel *chan; + struct sk_buff *skb; + + n_max_channels = phy->sband_2g.sband.n_channels + + phy->sband_5g.sband.n_channels + + phy->sband_6g.sband.n_channels; + len = sizeof(req) + n_max_channels * sizeof(channel); + + skb = mt76_mcu_msg_alloc(dev, NULL, len); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, sizeof(req)); + + for (i = 0; i < phy->sband_2g.sband.n_channels; i++) { + chan = &phy->sband_2g.sband.channels[i]; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + channel.hw_value = cpu_to_le16(chan->hw_value); + channel.flags = cpu_to_le32(chan->flags); + channel.pad = 0; + + skb_put_data(skb, &channel, sizeof(channel)); + n_2ch++; + } + for (i = 0; i < phy->sband_5g.sband.n_channels; i++) { + chan = &phy->sband_5g.sband.channels[i]; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + channel.hw_value = cpu_to_le16(chan->hw_value); + channel.flags = cpu_to_le32(chan->flags); + channel.pad = 0; + + skb_put_data(skb, &channel, sizeof(channel)); + n_5ch++; + } + for (i = 0; i < phy->sband_6g.sband.n_channels; i++) { + chan = &phy->sband_6g.sband.channels[i]; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + channel.hw_value = cpu_to_le16(chan->hw_value); + channel.flags = cpu_to_le32(chan->flags); + channel.pad = 0; + + skb_put_data(skb, &channel, sizeof(channel)); + n_6ch++; + } + + BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(req.hdr.alpha2)); + memcpy(req.hdr.alpha2, dev->alpha2, sizeof(dev->alpha2)); + req.n_ch.n_2ch = n_2ch; + req.n_ch.n_5ch = n_5ch; + req.n_ch.n_6ch = n_6ch; + len = sizeof(struct n_chan) + (n_2ch + n_5ch + n_6ch) * sizeof(channel); + req.n_ch.len = cpu_to_le16(len); + memcpy(__skb_push(skb, sizeof(req)), &req, sizeof(req)); + + return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SET_DOMAIN_INFO), + false); +} +EXPORT_SYMBOL_GPL(mt7925_mcu_set_channel_domain); + +static int +__mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, + enum environment_cap env_cap, + struct mt7925_clc *clc, u8 idx) +{ + struct mt7925_clc_segment *seg; + struct sk_buff *skb; + struct { + u8 rsv[4]; + __le16 tag; + __le16 len; + + u8 ver; + u8 pad0; + __le16 size; + u8 idx; + u8 env; + u8 acpi_conf; + u8 pad1; + u8 alpha2[2]; + u8 type[2]; + u8 rsvd[64]; + } __packed req = { + .tag = cpu_to_le16(0x3), + .len = cpu_to_le16(sizeof(req) - 4), + + .idx = idx, + .env = env_cap, + .acpi_conf = mt792x_acpi_get_flags(&dev->phy), + }; + int ret, valid_cnt = 0; + u8 i, *pos; + + if (!clc) + return 0; + + pos = clc->data + sizeof(*seg) * clc->nr_seg; + for (i = 0; i < clc->nr_country; i++) { + struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos; + + pos += sizeof(*rule); + if (rule->alpha2[0] != alpha2[0] || + rule->alpha2[1] != alpha2[1]) + continue; + + seg = (struct mt7925_clc_segment *)clc->data + + rule->seg_idx - 1; + + memcpy(req.alpha2, rule->alpha2, 2); + memcpy(req.type, rule->type, 2); + + req.size = cpu_to_le16(seg->len); + skb = __mt76_mcu_msg_alloc(&dev->mt76, &req, + le16_to_cpu(req.size) + sizeof(req), + sizeof(req), GFP_KERNEL); + if (!skb) + return -ENOMEM; + skb_put_data(skb, clc->data + seg->offset, seg->len); + + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(SET_POWER_LIMIT), + true); + if (ret < 0) + return ret; + valid_cnt++; + } + + if (!valid_cnt) + return -ENOENT; + + return 0; +} + +int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, + enum environment_cap env_cap) +{ + struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy; + int i, ret; + + /* submit all clc config */ + for (i = 0; i < ARRAY_SIZE(phy->clc); i++) { + ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap, + phy->clc[i], i); + + /* If no country found, set "00" as default */ + if (ret == -ENOENT) + ret = __mt7925_mcu_set_clc(dev, "00", + ENVIRON_INDOOR, + phy->clc[i], i); + if (ret < 0) + return ret; + } + return 0; +} + +int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd); + struct mt76_connac2_mcu_uni_txd *uni_txd; + struct mt76_connac2_mcu_txd *mcu_txd; + __le32 *txd; + u32 val; + u8 seq; + + /* TODO: make dynamic based on msg type */ + mdev->mcu.timeout = 20 * HZ; + + seq = ++mdev->mcu.msg_seq & 0xf; + if (!seq) + seq = ++mdev->mcu.msg_seq & 0xf; + + if (cmd == MCU_CMD(FW_SCATTER)) + goto exit; + + txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd); + txd = (__le32 *)skb_push(skb, txd_len); + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | + FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) | + FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0); + txd[0] = cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD); + txd[1] = cpu_to_le32(val); + + if (cmd & __MCU_CMD_FIELD_UNI) { + uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd; + uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + uni_txd->cid = cpu_to_le16(mcu_cmd); + uni_txd->s2d_index = MCU_S2D_H2N; + uni_txd->pkt_type = MCU_PKT_ID; + uni_txd->seq = seq; + + goto exit; + } + + mcu_txd = (struct mt76_connac2_mcu_txd *)txd; + mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); + mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, + MT_TX_MCU_PORT_RX_Q0)); + mcu_txd->pkt_type = MCU_PKT_ID; + mcu_txd->seq = seq; + mcu_txd->cid = mcu_cmd; + mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd); + + if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) { + if (cmd & __MCU_CMD_FIELD_QUERY) + mcu_txd->set_query = MCU_Q_QUERY; + else + mcu_txd->set_query = MCU_Q_SET; + mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid; + } else { + mcu_txd->set_query = MCU_Q_NA; + } + + if (cmd & __MCU_CMD_FIELD_WA) + mcu_txd->s2d_index = MCU_S2D_H2C; + else + mcu_txd->s2d_index = MCU_S2D_H2N; + +exit: + if (wait_seq) + *wait_seq = seq; + + return 0; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_fill_message); + +int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val) +{ + struct { + u8 band_idx; + u8 _rsv[3]; + + __le16 tag; + __le16 len; + __le32 len_thresh; + __le32 pkt_thresh; + } __packed req = { + .band_idx = phy->mt76->band_idx, + .tag = cpu_to_le16(UNI_BAND_CONFIG_RTS_THRESHOLD), + .len = cpu_to_le16(sizeof(req) - 4), + .len_thresh = cpu_to_le32(val), + .pkt_thresh = cpu_to_le32(0x2), + }; + + return mt76_mcu_send_msg(&phy->dev->mt76, MCU_UNI_CMD(BAND_CONFIG), + &req, sizeof(req), true); +} + +int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable) +{ + struct { + u8 band_idx; + u8 _rsv[3]; + + __le16 tag; + __le16 len; + u8 enable; + u8 _rsv2[3]; + } __packed req = { + .band_idx = phy->mt76->band_idx, + .tag = cpu_to_le16(UNI_BAND_CONFIG_RADIO_ENABLE), + .len = cpu_to_le16(sizeof(req) - 4), + .enable = enable, + }; + + return mt76_mcu_send_msg(&phy->dev->mt76, MCU_UNI_CMD(BAND_CONFIG), + &req, sizeof(req), true); +} + +static void +mt7925_mcu_build_sku(struct mt76_dev *dev, s8 *sku, + struct mt76_power_limits *limits, + enum nl80211_band band) +{ + int i, offset = sizeof(limits->cck); + + memset(sku, 127, MT_CONNAC3_SKU_POWER_LIMIT); + + if (band == NL80211_BAND_2GHZ) { + /* cck */ + memcpy(sku, limits->cck, sizeof(limits->cck)); + } + + /* ofdm */ + memcpy(&sku[offset], limits->ofdm, sizeof(limits->ofdm)); + offset += (sizeof(limits->ofdm) * 5); + + /* ht */ + for (i = 0; i < 2; i++) { + memcpy(&sku[offset], limits->mcs[i], 8); + offset += 8; + } + sku[offset++] = limits->mcs[0][0]; + + /* vht */ + for (i = 0; i < ARRAY_SIZE(limits->mcs); i++) { + memcpy(&sku[offset], limits->mcs[i], + ARRAY_SIZE(limits->mcs[i])); + offset += 12; + } + + /* he */ + for (i = 0; i < ARRAY_SIZE(limits->ru); i++) { + memcpy(&sku[offset], limits->ru[i], ARRAY_SIZE(limits->ru[i])); + offset += ARRAY_SIZE(limits->ru[i]); + } + + /* eht */ + for (i = 0; i < ARRAY_SIZE(limits->eht); i++) { + memcpy(&sku[offset], limits->eht[i], ARRAY_SIZE(limits->eht[i])); + offset += ARRAY_SIZE(limits->eht[i]); + } +} + +static int +mt7925_mcu_rate_txpower_band(struct mt76_phy *phy, + enum nl80211_band band) +{ + int tx_power, n_chan, last_ch, err = 0, idx = 0; + int i, sku_len, batch_size, batch_len = 3; + struct mt76_dev *dev = phy->dev; + static const u8 chan_list_2ghz[] = { + 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14 + }; + static const u8 chan_list_5ghz[] = { + 36, 38, 40, 42, 44, 46, 48, + 50, 52, 54, 56, 58, 60, 62, + 64, 100, 102, 104, 106, 108, 110, + 112, 114, 116, 118, 120, 122, 124, + 126, 128, 132, 134, 136, 138, 140, + 142, 144, 149, 151, 153, 155, 157, + 159, 161, 165, 167 + }; + static const u8 chan_list_6ghz[] = { + 1, 3, 5, 7, 9, 11, 13, + 15, 17, 19, 21, 23, 25, 27, + 29, 33, 35, 37, 39, 41, 43, + 45, 47, 49, 51, 53, 55, 57, + 59, 61, 65, 67, 69, 71, 73, + 75, 77, 79, 81, 83, 85, 87, + 89, 91, 93, 97, 99, 101, 103, + 105, 107, 109, 111, 113, 115, 117, + 119, 121, 123, 125, 129, 131, 133, + 135, 137, 139, 141, 143, 145, 147, + 149, 151, 153, 155, 157, 161, 163, + 165, 167, 169, 171, 173, 175, 177, + 179, 181, 183, 185, 187, 189, 193, + 195, 197, 199, 201, 203, 205, 207, + 209, 211, 213, 215, 217, 219, 221, + 225, 227, 229, 233 + }; + struct mt76_power_limits *limits; + struct mt7925_sku_tlv *sku_tlbv; + const u8 *ch_list; + + sku_len = sizeof(*sku_tlbv); + tx_power = 2 * phy->hw->conf.power_level; + if (!tx_power) + tx_power = 127; + + if (band == NL80211_BAND_2GHZ) { + n_chan = ARRAY_SIZE(chan_list_2ghz); + ch_list = chan_list_2ghz; + last_ch = chan_list_2ghz[ARRAY_SIZE(chan_list_2ghz) - 1]; + } else if (band == NL80211_BAND_6GHZ) { + n_chan = ARRAY_SIZE(chan_list_6ghz); + ch_list = chan_list_6ghz; + last_ch = chan_list_6ghz[ARRAY_SIZE(chan_list_6ghz) - 1]; + } else { + n_chan = ARRAY_SIZE(chan_list_5ghz); + ch_list = chan_list_5ghz; + last_ch = chan_list_5ghz[ARRAY_SIZE(chan_list_5ghz) - 1]; + } + batch_size = DIV_ROUND_UP(n_chan, batch_len); + + limits = devm_kmalloc(dev->dev, sizeof(*limits), GFP_KERNEL); + if (!limits) + return -ENOMEM; + + sku_tlbv = devm_kmalloc(dev->dev, sku_len, GFP_KERNEL); + if (!sku_tlbv) { + devm_kfree(dev->dev, limits); + return -ENOMEM; + } + + for (i = 0; i < batch_size; i++) { + struct mt7925_tx_power_limit_tlv *tx_power_tlv; + int j, msg_len, num_ch; + struct sk_buff *skb; + + num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len; + msg_len = sizeof(*tx_power_tlv) + num_ch * sku_len; + skb = mt76_mcu_msg_alloc(dev, NULL, msg_len); + if (!skb) { + err = -ENOMEM; + goto out; + } + + tx_power_tlv = (struct mt7925_tx_power_limit_tlv *) + skb_put(skb, sizeof(*tx_power_tlv)); + + BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv->alpha2)); + memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2)); + tx_power_tlv->n_chan = num_ch; + tx_power_tlv->tag = cpu_to_le16(0x1); + tx_power_tlv->len = cpu_to_le16(sizeof(*tx_power_tlv)); + + switch (band) { + case NL80211_BAND_2GHZ: + tx_power_tlv->band = 1; + break; + case NL80211_BAND_6GHZ: + tx_power_tlv->band = 3; + break; + default: + tx_power_tlv->band = 2; + break; + } + + for (j = 0; j < num_ch; j++, idx++) { + struct ieee80211_channel chan = { + .hw_value = ch_list[idx], + .band = band, + }; + s8 reg_power, sar_power; + + reg_power = mt76_connac_get_ch_power(phy, &chan, + tx_power); + sar_power = mt76_get_sar_power(phy, &chan, reg_power); + + mt76_get_rate_power_limits(phy, &chan, limits, + sar_power); + + tx_power_tlv->last_msg = ch_list[idx] == last_ch; + sku_tlbv->channel = ch_list[idx]; + + mt7925_mcu_build_sku(dev, sku_tlbv->pwr_limit, + limits, band); + skb_put_data(skb, sku_tlbv, sku_len); + } + err = mt76_mcu_skb_send_msg(dev, skb, + MCU_UNI_CMD(SET_POWER_LIMIT), + true); + if (err < 0) + goto out; + } + +out: + devm_kfree(dev->dev, sku_tlbv); + devm_kfree(dev->dev, limits); + return err; +} + +int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy) +{ + int err; + + if (phy->cap.has_2ghz) { + err = mt7925_mcu_rate_txpower_band(phy, + NL80211_BAND_2GHZ); + if (err < 0) + return err; + } + + if (phy->cap.has_5ghz) { + err = mt7925_mcu_rate_txpower_band(phy, + NL80211_BAND_5GHZ); + if (err < 0) + return err; + } + + if (phy->cap.has_6ghz) { + err = mt7925_mcu_rate_txpower_band(phy, + NL80211_BAND_6GHZ); + if (err < 0) + return err; + } + + return 0; +} + +int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, + u8 bit_op, u32 bit_map) +{ + struct mt792x_phy *phy = &dev->phy; + struct { + u8 band_idx; + u8 rsv1[3]; + + __le16 tag; + __le16 len; + u8 mode; + u8 rsv2[3]; + __le32 fif; + __le32 bit_map; /* bit_* for bitmap update */ + u8 bit_op; + u8 pad[51]; + } __packed req = { + .band_idx = phy->mt76->band_idx, + .tag = cpu_to_le16(UNI_BAND_CONFIG_SET_MAC80211_RX_FILTER), + .len = cpu_to_le16(sizeof(req) - 4), + + .mode = fif ? 0 : 1, + .fif = cpu_to_le32(fif), + .bit_map = cpu_to_le32(bit_map), + .bit_op = bit_op, + }; + + return mt76_mcu_send_msg(&phy->dev->mt76, MCU_UNI_CMD(BAND_CONFIG), + &req, sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h new file mode 100644 index 000000000000..3c41e21303b1 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h @@ -0,0 +1,537 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7925_MCU_H +#define __MT7925_MCU_H + +#include "../mt76_connac_mcu.h" + +/* ext event table */ +enum { + MCU_EXT_EVENT_RATE_REPORT = 0x87, +}; + +struct mt7925_mcu_eeprom_info { + __le32 addr; + __le32 valid; + u8 data[MT7925_EEPROM_BLOCK_SIZE]; +} __packed; + +#define MT_RA_RATE_NSS GENMASK(8, 6) +#define MT_RA_RATE_MCS GENMASK(3, 0) +#define MT_RA_RATE_TX_MODE GENMASK(12, 9) +#define MT_RA_RATE_DCM_EN BIT(4) +#define MT_RA_RATE_BW GENMASK(14, 13) + +struct mt7925_mcu_rxd { + __le32 rxd[8]; + + __le16 len; + __le16 pkt_type_id; + + u8 eid; + u8 seq; + u8 option; + u8 __rsv; + + u8 ext_eid; + u8 __rsv1[2]; + u8 s2d_index; + + u8 tlv[]; +}; + +struct mt7925_mcu_uni_event { + u8 cid; + u8 pad[3]; + __le32 status; /* 0: success, others: fail */ +} __packed; + +enum { + MT_EBF = BIT(0), /* explicit beamforming */ + MT_IBF = BIT(1) /* implicit beamforming */ +}; + +struct mt7925_mcu_reg_event { + __le32 reg; + __le32 val; +} __packed; + +struct mt7925_mcu_ant_id_config { + u8 ant_id[4]; +} __packed; + +struct mt7925_txpwr_req { + u8 _rsv[4]; + __le16 tag; + __le16 len; + + u8 format_id; + u8 catg; + u8 band_idx; + u8 _rsv1; +} __packed; + +struct mt7925_txpwr_event { + u8 rsv[4]; + __le16 tag; + __le16 len; + + u8 catg; + u8 band_idx; + u8 ch_band; + u8 format; /* 0:Legacy, 1:HE */ + + /* Rate power info */ + struct mt7925_txpwr txpwr; + + s8 pwr_max; + s8 pwr_min; + u8 rsv1; +} __packed; + +enum { + TM_SWITCH_MODE, + TM_SET_AT_CMD, + TM_QUERY_AT_CMD, +}; + +enum { + MT7925_TM_NORMAL, + MT7925_TM_TESTMODE, + MT7925_TM_ICAP, + MT7925_TM_ICAP_OVERLAP, + MT7925_TM_WIFISPECTRUM, +}; + +struct mt7925_rftest_cmd { + u8 action; + u8 rsv[3]; + __le32 param0; + __le32 param1; +} __packed; + +struct mt7925_rftest_evt { + __le32 param0; + __le32 param1; +} __packed; + +enum { + UNI_CHANNEL_SWITCH, + UNI_CHANNEL_RX_PATH, +}; + +enum { + UNI_CHIP_CONFIG_CHIP_CFG = 0x2, + UNI_CHIP_CONFIG_NIC_CAPA = 0x3, +}; + +enum { + UNI_BAND_CONFIG_RADIO_ENABLE, + UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08, + UNI_BAND_CONFIG_SET_MAC80211_RX_FILTER = 0x0C, +}; + +enum { + UNI_WSYS_CONFIG_FW_LOG_CTRL, + UNI_WSYS_CONFIG_FW_DBG_CTRL, +}; + +enum { + UNI_EFUSE_ACCESS = 1, + UNI_EFUSE_BUFFER_MODE, + UNI_EFUSE_FREE_BLOCK, + UNI_EFUSE_BUFFER_RD, +}; + +enum { + UNI_CMD_ACCESS_REG_BASIC = 0x0, + UNI_CMD_ACCESS_RF_REG_BASIC, +}; + +enum { + UNI_MBMC_SETTING, +}; + +enum { + UNI_EVENT_SCAN_DONE_BASIC = 0, + UNI_EVENT_SCAN_DONE_CHNLINFO = 2, + UNI_EVENT_SCAN_DONE_NLO = 3, +}; + +struct mt7925_mcu_scan_chinfo_event { + u8 nr_chan; + u8 alpha2[3]; +} __packed; + +enum { + UNI_SCAN_REQ = 1, + UNI_SCAN_CANCEL = 2, + UNI_SCAN_SCHED_REQ = 3, + UNI_SCAN_SCHED_ENABLE = 4, + UNI_SCAN_SSID = 10, + UNI_SCAN_BSSID, + UNI_SCAN_CHANNEL, + UNI_SCAN_IE, + UNI_SCAN_MISC, + UNI_SCAN_SSID_MATCH_SETS, +}; + +enum { + UNI_SNIFFER_ENABLE, + UNI_SNIFFER_CONFIG, +}; + +struct scan_hdr_tlv { + /* fixed field */ + u8 seq_num; + u8 bss_idx; + u8 pad[2]; + /* tlv */ + u8 data[]; +} __packed; + +struct scan_req_tlv { + __le16 tag; + __le16 len; + + u8 scan_type; /* 0: PASSIVE SCAN + * 1: ACTIVE SCAN + */ + u8 probe_req_num; /* Number of probe request for each SSID */ + u8 scan_func; /* BIT(0) Enable random MAC scan + * BIT(1) Disable DBDC scan type 1~3. + * BIT(2) Use DBDC scan type 3 (dedicated one RF to scan). + */ + u8 src_mask; + __le16 channel_min_dwell_time; + __le16 channel_dwell_time; /* channel Dwell interval */ + __le16 timeout_value; + __le16 probe_delay_time; + u8 func_mask_ext; +}; + +struct scan_ssid_tlv { + __le16 tag; + __le16 len; + + u8 ssid_type; /* BIT(0) wildcard SSID + * BIT(1) P2P wildcard SSID + * BIT(2) specified SSID + wildcard SSID + * BIT(2) + ssid_type_ext BIT(0) specified SSID only + */ + u8 ssids_num; + u8 pad[2]; + struct mt76_connac_mcu_scan_ssid ssids[4]; +}; + +struct scan_bssid_tlv { + __le16 tag; + __le16 len; + + u8 bssid[ETH_ALEN]; + u8 match_ch; + u8 match_ssid_ind; + u8 rcpi; + u8 pad[3]; +}; + +struct scan_chan_info_tlv { + __le16 tag; + __le16 len; + + u8 channel_type; /* 0: Full channels + * 1: Only 2.4GHz channels + * 2: Only 5GHz channels + * 3: P2P social channel only (channel #1, #6 and #11) + * 4: Specified channels + * Others: Reserved + */ + u8 channels_num; /* valid when channel_type is 4 */ + u8 pad[2]; + struct mt76_connac_mcu_scan_channel channels[64]; +}; + +struct scan_ie_tlv { + __le16 tag; + __le16 len; + + __le16 ies_len; + u8 band; + u8 pad; + u8 ies[MT76_CONNAC_SCAN_IE_LEN]; +}; + +struct scan_misc_tlv { + __le16 tag; + __le16 len; + + u8 random_mac[ETH_ALEN]; + u8 rsv[2]; +}; + +struct scan_sched_req { + __le16 tag; + __le16 len; + + u8 version; + u8 stop_on_match; + u8 intervals_num; + u8 scan_func; + __le16 intervals[MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL]; +}; + +struct scan_sched_ssid_match_sets { + __le16 tag; + __le16 len; + + u8 match_num; + u8 rsv[3]; + + struct mt76_connac_mcu_scan_match match[MT76_CONNAC_MAX_SCAN_MATCH]; +}; + +struct scan_sched_enable { + __le16 tag; + __le16 len; + + u8 active; + u8 rsv[3]; +}; + +struct mbmc_set_req { + u8 pad[4]; + u8 data[]; +} __packed; + +struct mbmc_conf_tlv { + __le16 tag; + __le16 len; + + u8 mbmc_en; + u8 band; + u8 pad[2]; +} __packed; + +struct edca { + __le16 tag; + __le16 len; + + u8 queue; + u8 set; + u8 cw_min; + u8 cw_max; + __le16 txop; + u8 aifs; + u8 __rsv; +}; + +struct bss_req_hdr { + u8 bss_idx; + u8 __rsv[3]; +} __packed; + +struct bss_rate_tlv { + __le16 tag; + __le16 len; + u8 __rsv1[4]; + __le16 bc_trans; + __le16 mc_trans; + u8 short_preamble; + u8 bc_fixed_rate; + u8 mc_fixed_rate; + u8 __rsv2; +} __packed; + +struct bss_mld_tlv { + __le16 tag; + __le16 len; + u8 group_mld_id; + u8 own_mld_id; + u8 mac_addr[ETH_ALEN]; + u8 remap_idx; + u8 link_id; + u8 __rsv[2]; +} __packed; + +struct sta_rec_ba_uni { + __le16 tag; + __le16 len; + u8 tid; + u8 ba_type; + u8 amsdu; + u8 ba_en; + __le16 ssn; + __le16 winsize; + u8 ba_rdd_rro; + u8 __rsv[3]; +} __packed; + +struct sta_rec_eht { + __le16 tag; + __le16 len; + u8 tid_bitmap; + u8 _rsv; + __le16 mac_cap; + __le64 phy_cap; + __le64 phy_cap_ext; + u8 mcs_map_bw20[4]; + u8 mcs_map_bw80[3]; + u8 mcs_map_bw160[3]; + u8 mcs_map_bw320[3]; + u8 _rsv2[3]; +} __packed; + +struct sec_key_uni { + __le16 wlan_idx; + u8 mgmt_prot; + u8 cipher_id; + u8 cipher_len; + u8 key_id; + u8 key_len; + u8 need_resp; + u8 key[32]; +} __packed; + +struct sta_rec_sec_uni { + __le16 tag; + __le16 len; + u8 add; + u8 n_cipher; + u8 rsv[2]; + + struct sec_key_uni key[2]; +} __packed; + +struct sta_rec_hdr_trans { + __le16 tag; + __le16 len; + u8 from_ds; + u8 to_ds; + u8 dis_rx_hdr_tran; + u8 rsv; +} __packed; + +struct sta_rec_mld { + __le16 tag; + __le16 len; + u8 mac_addr[ETH_ALEN]; + __le16 primary_id; + __le16 secondary_id; + __le16 wlan_id; + u8 link_num; + u8 rsv[3]; + struct { + __le16 wlan_id; + u8 bss_idx; + u8 rsv; + } __packed link[2]; +} __packed; + +#define MT7925_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_bf) + \ + sizeof(struct sta_rec_ht) + \ + sizeof(struct sta_rec_he_v2) + \ + sizeof(struct sta_rec_ba_uni) + \ + sizeof(struct sta_rec_vht) + \ + sizeof(struct sta_rec_uapsd) + \ + sizeof(struct sta_rec_amsdu) + \ + sizeof(struct sta_rec_bfee) + \ + sizeof(struct sta_rec_phy) + \ + sizeof(struct sta_rec_ra) + \ + sizeof(struct sta_rec_sec) + \ + sizeof(struct sta_rec_ra_fixed) + \ + sizeof(struct sta_rec_he_6g_capa) + \ + sizeof(struct sta_rec_eht) + \ + sizeof(struct sta_rec_hdr_trans) + \ + sizeof(struct sta_rec_mld) + \ + sizeof(struct tlv)) + +#define MT7925_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \ + sizeof(struct mt76_connac_bss_basic_tlv) + \ + sizeof(struct mt76_connac_bss_qos_tlv) + \ + sizeof(struct bss_rate_tlv) + \ + sizeof(struct bss_mld_tlv) + \ + sizeof(struct bss_info_uni_he) + \ + sizeof(struct bss_info_uni_bss_color) + \ + sizeof(struct tlv)) + +#define MT_CONNAC3_SKU_POWER_LIMIT 449 +struct mt7925_sku_tlv { + u8 channel; + s8 pwr_limit[MT_CONNAC3_SKU_POWER_LIMIT]; +} __packed; + +struct mt7925_tx_power_limit_tlv { + u8 rsv[4]; + + __le16 tag; + __le16 len; + + /* DW0 - common info*/ + u8 ver; + u8 pad0; + __le16 rsv1; + /* DW1 - cmd hint */ + u8 n_chan; /* # channel */ + u8 band; /* 2.4GHz - 5GHz - 6GHz */ + u8 last_msg; + u8 limit_type; + /* DW3 */ + u8 alpha2[4]; /* regulatory_request.alpha2 */ + u8 pad2[32]; + + u8 data[]; +} __packed; + +struct mt7925_arpns_tlv { + __le16 tag; + __le16 len; + + u8 enable; + u8 ips_num; + u8 rsv[2]; +} __packed; + +struct mt7925_wow_pattern_tlv { + __le16 tag; + __le16 len; + u8 bss_idx; + u8 index; /* pattern index */ + u8 enable; /* 0: disable + * 1: enable + */ + u8 data_len; /* pattern length */ + u8 offset; + u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN]; + u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN]; + u8 rsv[4]; +} __packed; + +int mt7925_mcu_set_dbdc(struct mt76_phy *phy); +int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_scan_request *scan_req); +int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy, + struct ieee80211_vif *vif); +int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, + struct ieee80211_vif *vif, + struct cfg80211_sched_scan_request *sreq); +int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy, + struct ieee80211_vif *vif, + bool enable); +int mt7925_mcu_add_bss_info(struct mt792x_phy *phy, + struct ieee80211_chanctx_conf *ctx, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + int enable); +int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable); +int mt7925_mcu_set_channel_domain(struct mt76_phy *phy); +int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable); +int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif, + struct ieee80211_chanctx_conf *ctx); +int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy); +int mt7925_mcu_update_arp_filter(struct mt76_dev *dev, + struct mt76_vif *vif, + struct ieee80211_bss_conf *info); +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h new file mode 100644 index 000000000000..33785f526acf --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7925_H +#define __MT7925_H + +#include "../mt792x.h" +#include "regs.h" + +#define MT7925_BEACON_RATES_TBL 25 + +#define MT7925_TX_RING_SIZE 2048 +#define MT7925_TX_MCU_RING_SIZE 256 +#define MT7925_TX_FWDL_RING_SIZE 128 + +#define MT7925_RX_RING_SIZE 1536 +#define MT7925_RX_MCU_RING_SIZE 512 + +#define MT7925_EEPROM_SIZE 3584 +#define MT7925_TOKEN_SIZE 8192 + +#define MT7925_EEPROM_BLOCK_SIZE 16 + +#define MT7925_SKU_RATE_NUM 161 +#define MT7925_SKU_MAX_DELTA_IDX MT7925_SKU_RATE_NUM +#define MT7925_SKU_TABLE_SIZE (MT7925_SKU_RATE_NUM + 1) + +#define MCU_UNI_EVENT_ROC 0x27 + +enum { + UNI_ROC_ACQUIRE, + UNI_ROC_ABORT, + UNI_ROC_NUM +}; + +enum mt7925_roc_req { + MT7925_ROC_REQ_JOIN, + MT7925_ROC_REQ_ROC, + MT7925_ROC_REQ_NUM +}; + +enum { + UNI_EVENT_ROC_GRANT = 0, + UNI_EVENT_ROC_TAG_NUM +}; + +struct mt7925_roc_grant_tlv { + __le16 tag; + __le16 len; + u8 bss_idx; + u8 tokenid; + u8 status; + u8 primarychannel; + u8 rfsco; + u8 rfband; + u8 channelwidth; + u8 centerfreqseg1; + u8 centerfreqseg2; + u8 reqtype; + u8 dbdcband; + u8 rsv[1]; + __le32 max_interval; +} __packed; + +struct mt7925_beacon_loss_tlv { + __le16 tag; + __le16 len; + u8 reason; + u8 nr_btolink; + u8 pad[2]; +} __packed; + +struct mt7925_uni_beacon_loss_event { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt7925_beacon_loss_tlv beacon_loss; +} __packed; + +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) +#define to_rcpi(rssi) (2 * (rssi) + 220) + +enum mt7925_txq_id { + MT7925_TXQ_BAND0, + MT7925_TXQ_BAND1, + MT7925_TXQ_MCU_WM = 15, + MT7925_TXQ_FWDL, +}; + +enum mt7925_rxq_id { + MT7925_RXQ_BAND0 = 2, + MT7925_RXQ_BAND1, + MT7925_RXQ_MCU_WM = 0, + MT7925_RXQ_MCU_WM2, /* for tx done */ +}; + +enum { + MODE_OPEN = 0, + MODE_SHARED = 1, + MODE_WPA = 3, + MODE_WPA_PSK = 4, + MODE_WPA_NONE = 5, + MODE_WPA2 = 6, + MODE_WPA2_PSK = 7, + MODE_WPA3_SAE = 11, +}; + +enum { + MT7925_CLC_POWER, + MT7925_CLC_CHAN, + MT7925_CLC_MAX_NUM, +}; + +struct mt7925_clc_rule { + u8 alpha2[2]; + u8 type[2]; + u8 seg_idx; + u8 rsv[3]; +} __packed; + +struct mt7925_clc_segment { + u8 idx; + u8 rsv1[3]; + u32 offset; + u32 len; + u8 rsv2[4]; +} __packed; + +struct mt7925_clc { + __le32 len; + u8 idx; + u8 ver; + u8 nr_country; + u8 type; + u8 nr_seg; + u8 rsv[7]; + u8 data[]; +} __packed; + +enum mt7925_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, + __MT_EE_MAX = 0x9ff +}; + +enum { + TXPWR_USER, + TXPWR_EEPROM, + TXPWR_MAC, + TXPWR_MAX_NUM, +}; + +struct mt7925_txpwr { + s8 cck[4][2]; + s8 ofdm[8][2]; + s8 ht20[8][2]; + s8 ht40[9][2]; + s8 vht20[12][2]; + s8 vht40[12][2]; + s8 vht80[12][2]; + s8 vht160[12][2]; + s8 he26[12][2]; + s8 he52[12][2]; + s8 he106[12][2]; + s8 he242[12][2]; + s8 he484[12][2]; + s8 he996[12][2]; + s8 he996x2[12][2]; + s8 eht26[16][2]; + s8 eht52[16][2]; + s8 eht106[16][2]; + s8 eht242[16][2]; + s8 eht484[16][2]; + s8 eht996[16][2]; + s8 eht996x2[16][2]; + s8 eht996x4[16][2]; + s8 eht26_52[16][2]; + s8 eht26_106[16][2]; + s8 eht484_242[16][2]; + s8 eht996_484[16][2]; + s8 eht996_484_242[16][2]; + s8 eht996x2_484[16][2]; + s8 eht996x3[16][2]; + s8 eht996x3_484[16][2]; +}; + +extern const struct ieee80211_ops mt7925_ops; + +int __mt7925_start(struct mt792x_phy *phy); +int mt7925_register_device(struct mt792x_dev *dev); +void mt7925_unregister_device(struct mt792x_dev *dev); +int mt7925_run_firmware(struct mt792x_dev *dev); +int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, + bool enable); +int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, + struct ieee80211_vif *vif, bool enable, + enum mt76_sta_info_state state); +int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag); +int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif); +int mt7925_mcu_set_eeprom(struct mt792x_dev *dev); +int mt7925_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate); +int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl); +void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb); +int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd); +int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, + u8 bit_op, u32 bit_map); + +int mt7925_mac_init(struct mt792x_dev *dev); +int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); +void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7925_mac_reset_work(struct work_struct *work); +int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); + +void mt7925_tx_token_put(struct mt792x_dev *dev); +bool mt7925_rx_check(struct mt76_dev *mdev, void *data, int len); +void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb, u32 *info); +void mt7925_stats_work(struct work_struct *work); +void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy); +int mt7925_init_debugfs(struct mt792x_dev *dev); + +int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, + struct ieee80211_vif *vif, + bool enable); +int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable); +int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable); +void mt7925_scan_work(struct work_struct *work); +void mt7925_roc_work(struct work_struct *work); +int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); +void mt7925_coredump_work(struct work_struct *work); +int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx, + struct mt7925_txpwr *txpwr); +void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev, + u8 tbl_idx, u16 rate_idx); +void mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, int pid, + enum mt76_txq_id qid, u32 changed); +void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, bool clear_status, + struct list_head *free_list); +int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq); + +int mt7925e_mac_reset(struct mt792x_dev *dev); +int mt7925e_mcu_init(struct mt792x_dev *dev); +void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data); +void mt7925_set_runtime_pm(struct mt792x_dev *dev); +void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif); +void mt7925_connac_mcu_set_suspend_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif); +void mt7925_set_ipv6_ns_work(struct work_struct *work); + +int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, + bool enable); +int mt7925_mcu_config_sniffer(struct mt792x_vif *vif, + struct ieee80211_chanctx_conf *ctx); + +int mt7925_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); +void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, + struct mt76_queue_entry *e); +bool mt7925_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); + +int mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable); +int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw, + const struct cfg80211_sar_specs *sar); + +int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set); +int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, + enum environment_cap env_cap); +int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, + struct ieee80211_channel *chan, int duration, + enum mt7925_roc_req type, u8 token_id); +int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, + u8 token_id); +int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *wait_seq); +int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct mt76_connac_sta_key_conf *sta_key_conf, + struct ieee80211_key_conf *key, int mcu_cmd, + struct mt76_wcid *wcid, enum set_key_cmd cmd); +int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val); +int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c new file mode 100644 index 000000000000..08ef75e24e1c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c @@ -0,0 +1,586 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include "mt7925.h" +#include "mac.h" +#include "mcu.h" +#include "../dma.h" + +static const struct pci_device_id mt7925_pci_device_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7925), + .driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0717), + .driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM }, + { }, +}; + +static bool mt7925_disable_aspm; +module_param_named(disable_aspm, mt7925_disable_aspm, bool, 0644); +MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support"); + +static int mt7925e_init_reset(struct mt792x_dev *dev) +{ + return mt792x_wpdma_reset(dev, true); +} + +static void mt7925e_unregister_device(struct mt792x_dev *dev) +{ + int i; + struct mt76_connac_pm *pm = &dev->pm; + + cancel_work_sync(&dev->init_work); + mt76_unregister_device(&dev->mt76); + mt76_for_each_q_rx(&dev->mt76, i) + napi_disable(&dev->mt76.napi[i]); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + cancel_work_sync(&dev->reset_work); + + mt7925_tx_token_put(dev); + __mt792x_mcu_drv_pmctrl(dev); + mt792x_dma_cleanup(dev); + mt792x_wfsys_reset(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); + + tasklet_disable(&dev->mt76.irq_tasklet); +} + +static void mt7925_reg_remap_restore(struct mt792x_dev *dev) +{ + /* remap to ori status */ + if (unlikely(dev->backup_l1)) { + dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->backup_l1); + dev->backup_l1 = 0; + } + + if (dev->backup_l2) { + dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->backup_l2); + dev->backup_l2 = 0; + } +} + +static u32 mt7925_reg_map_l1(struct mt792x_dev *dev, u32 addr) +{ + u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); + + dev->backup_l1 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1); + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1, + MT_HIF_REMAP_L1_MASK, + FIELD_PREP(MT_HIF_REMAP_L1_MASK, base)); + + /* use read to push write */ + dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1); + + return MT_HIF_REMAP_BASE_L1 + offset; +} + +static u32 mt7925_reg_map_l2(struct mt792x_dev *dev, u32 addr) +{ + u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, MT_HIF_REMAP_BASE_L2); + + dev->backup_l2 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1); + + dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1, + MT_HIF_REMAP_L1_MASK, + FIELD_PREP(MT_HIF_REMAP_L1_MASK, base)); + + dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, addr); + /* use read to push write */ + dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1); + + return MT_HIF_REMAP_BASE_L1; +} + +static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr) +{ + static const struct mt76_connac_reg_map fixed_map[] = { + { 0x830c0000, 0x000000, 0x0001000 }, /* WF_MCU_BUS_CR_REMAP */ + { 0x54000000, 0x002000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA0 */ + { 0x55000000, 0x003000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA1 */ + { 0x56000000, 0x004000, 0x0001000 }, /* WFDMA reserved */ + { 0x57000000, 0x005000, 0x0001000 }, /* WFDMA MCU wrap CR */ + { 0x58000000, 0x006000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */ + { 0x59000000, 0x007000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA1 */ + { 0x820c0000, 0x008000, 0x0004000 }, /* WF_UMAC_TOP (PLE) */ + { 0x820c8000, 0x00c000, 0x0002000 }, /* WF_UMAC_TOP (PSE) */ + { 0x820cc000, 0x00e000, 0x0002000 }, /* WF_UMAC_TOP (PP) */ + { 0x74030000, 0x010000, 0x0001000 }, /* PCIe MAC */ + { 0x820e0000, 0x020000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */ + { 0x820e1000, 0x020400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */ + { 0x820e2000, 0x020800, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */ + { 0x820e3000, 0x020c00, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */ + { 0x820e4000, 0x021000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */ + { 0x820e5000, 0x021400, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */ + { 0x820ce000, 0x021c00, 0x0000200 }, /* WF_LMAC_TOP (WF_SEC) */ + { 0x820e7000, 0x021e00, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */ + { 0x820cf000, 0x022000, 0x0001000 }, /* WF_LMAC_TOP (WF_PF) */ + { 0x820e9000, 0x023400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */ + { 0x820ea000, 0x024000, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */ + { 0x820eb000, 0x024200, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */ + { 0x820ec000, 0x024600, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_INT) */ + { 0x820ed000, 0x024800, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */ + { 0x820ca000, 0x026000, 0x0002000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */ + { 0x820d0000, 0x030000, 0x0010000 }, /* WF_LMAC_TOP (WF_WTBLON) */ + { 0x40000000, 0x070000, 0x0010000 }, /* WF_UMAC_SYSRAM */ + { 0x00400000, 0x080000, 0x0010000 }, /* WF_MCU_SYSRAM */ + { 0x00410000, 0x090000, 0x0010000 }, /* WF_MCU_SYSRAM (configure register) */ + { 0x820f0000, 0x0a0000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */ + { 0x820f1000, 0x0a0600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */ + { 0x820f2000, 0x0a0800, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */ + { 0x820f3000, 0x0a0c00, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */ + { 0x820f4000, 0x0a1000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */ + { 0x820f5000, 0x0a1400, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */ + { 0x820f7000, 0x0a1e00, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */ + { 0x820f9000, 0x0a3400, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */ + { 0x820fa000, 0x0a4000, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */ + { 0x820fb000, 0x0a4200, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */ + { 0x820fc000, 0x0a4600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_INT) */ + { 0x820fd000, 0x0a4800, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */ + { 0x820c4000, 0x0a8000, 0x0004000 }, /* WF_LMAC_TOP BN1 (WF_MUCOP) */ + { 0x820b0000, 0x0ae000, 0x0001000 }, /* [APB2] WFSYS_ON */ + { 0x80020000, 0x0b0000, 0x0010000 }, /* WF_TOP_MISC_OFF */ + { 0x81020000, 0x0c0000, 0x0010000 }, /* WF_TOP_MISC_ON */ + { 0x7c020000, 0x0d0000, 0x0010000 }, /* CONN_INFRA, wfdma */ + { 0x7c060000, 0x0e0000, 0x0010000 }, /* CONN_INFRA, conn_host_csr_top */ + { 0x7c000000, 0x0f0000, 0x0010000 }, /* CONN_INFRA */ + { 0x70020000, 0x1f0000, 0x0010000 }, /* Reserved for CBTOP, can't switch */ + { 0x7c500000, 0x060000, 0x2000000 }, /* remap */ + { 0x0, 0x0, 0x0 } /* End */ + }; + int i; + + if (addr < 0x200000) + return addr; + + mt7925_reg_remap_restore(dev); + + for (i = 0; i < ARRAY_SIZE(fixed_map); i++) { + u32 ofs; + + if (addr < fixed_map[i].phys) + continue; + + ofs = addr - fixed_map[i].phys; + if (ofs > fixed_map[i].size) + continue; + + return fixed_map[i].maps + ofs; + } + + if ((addr >= 0x18000000 && addr < 0x18c00000) || + (addr >= 0x70000000 && addr < 0x78000000) || + (addr >= 0x7c000000 && addr < 0x7c400000)) + return mt7925_reg_map_l1(dev, addr); + + return mt7925_reg_map_l2(dev, addr); +} + +static u32 mt7925_rr(struct mt76_dev *mdev, u32 offset) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + u32 addr = __mt7925_reg_addr(dev, offset); + + return dev->bus_ops->rr(mdev, addr); +} + +static void mt7925_wr(struct mt76_dev *mdev, u32 offset, u32 val) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + u32 addr = __mt7925_reg_addr(dev, offset); + + dev->bus_ops->wr(mdev, addr, val); +} + +static u32 mt7925_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + u32 addr = __mt7925_reg_addr(dev, offset); + + return dev->bus_ops->rmw(mdev, addr, mask, val); +} + +static int mt7925_dma_init(struct mt792x_dev *dev) +{ + int ret; + + mt76_dma_attach(&dev->mt76); + + ret = mt792x_dma_disable(dev, true); + if (ret) + return ret; + + /* init tx queue */ + ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0, + MT7925_TX_RING_SIZE, + MT_TX_RING_BASE, 0); + if (ret) + return ret; + + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4); + + /* command to WM */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7925_TXQ_MCU_WM, + MT7925_TX_MCU_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* firmware download */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7925_TXQ_FWDL, + MT7925_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* rx event */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], + MT7925_RXQ_MCU_WM, MT7925_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + if (ret) + return ret; + + /* rx data */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], + MT7925_RXQ_BAND0, MT7925_RX_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); + if (ret) + return ret; + + ret = mt76_init_queues(dev, mt792x_poll_rx); + if (ret < 0) + return ret; + + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt792x_poll_tx); + napi_enable(&dev->mt76.tx_napi); + + return mt792x_dma_enable(dev); +} + +static int mt7925_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp), + .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ | + MT_DRV_AMSDU_OFFLOAD, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .token_size = MT7925_TOKEN_SIZE, + .tx_prepare_skb = mt7925e_tx_prepare_skb, + .tx_complete_skb = mt76_connac_tx_complete_skb, + .rx_check = mt7925_rx_check, + .rx_skb = mt7925_queue_rx_skb, + .rx_poll_complete = mt792x_rx_poll_complete, + .sta_add = mt7925_mac_sta_add, + .sta_assoc = mt7925_mac_sta_assoc, + .sta_remove = mt7925_mac_sta_remove, + .update_survey = mt792x_update_channel, + }; + static const struct mt792x_hif_ops mt7925_pcie_ops = { + .init_reset = mt7925e_init_reset, + .reset = mt7925e_mac_reset, + .mcu_init = mt7925e_mcu_init, + .drv_own = mt792xe_mcu_drv_pmctrl, + .fw_own = mt792xe_mcu_fw_pmctrl, + }; + static const struct mt792x_irq_map irq_map = { + .host_irq_enable = MT_WFDMA0_HOST_INT_ENA, + .tx = { + .all_complete_mask = MT_INT_TX_DONE_ALL, + .mcu_complete_mask = MT_INT_TX_DONE_MCU, + }, + .rx = { + .data_complete_mask = HOST_RX_DONE_INT_ENA2, + .wm_complete_mask = HOST_RX_DONE_INT_ENA0, + }, + }; + struct ieee80211_ops *ops; + struct mt76_bus_ops *bus_ops; + struct mt792x_dev *dev; + struct mt76_dev *mdev; + u8 features; + int ret; + u16 cmd; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); + if (ret) + return ret; + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY)) { + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + } + pci_set_master(pdev); + + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return ret; + + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) + goto err_free_pci_vec; + + if (mt7925_disable_aspm) + mt76_pci_disable_aspm(pdev); + + ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7925_ops, + (void *)id->driver_data, &features); + if (!ops) { + ret = -ENOMEM; + goto err_free_pci_vec; + } + + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops); + if (!mdev) { + ret = -ENOMEM; + goto err_free_pci_vec; + } + + pci_set_drvdata(pdev, mdev); + + dev = container_of(mdev, struct mt792x_dev, mt76); + dev->fw_features = features; + dev->hif_ops = &mt7925_pcie_ops; + dev->irq_map = &irq_map; + mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev); + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + dev->bus_ops = dev->mt76.bus; + bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), + GFP_KERNEL); + if (!bus_ops) { + ret = -ENOMEM; + goto err_free_dev; + } + + bus_ops->rr = mt7925_rr; + bus_ops->wr = mt7925_wr; + bus_ops->rmw = mt7925_rmw; + dev->mt76.bus = bus_ops; + + ret = __mt792x_mcu_fw_pmctrl(dev); + if (ret) + goto err_free_dev; + + ret = __mt792xe_mcu_drv_pmctrl(dev); + if (ret) + goto err_free_dev; + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + + dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = mt792x_wfsys_reset(dev); + if (ret) + goto err_free_dev; + + mt76_wr(dev, irq_map.host_irq_enable, 0); + + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + + ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto err_free_dev; + + ret = mt7925_dma_init(dev); + if (ret) + goto err_free_irq; + + ret = mt7925_register_device(dev); + if (ret) + goto err_free_irq; + + return 0; + +err_free_irq: + devm_free_irq(&pdev->dev, pdev->irq, dev); +err_free_dev: + mt76_free_device(&dev->mt76); +err_free_pci_vec: + pci_free_irq_vectors(pdev); + + return ret; +} + +static void mt7925_pci_remove(struct pci_dev *pdev) +{ + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + + mt7925e_unregister_device(dev); + devm_free_irq(&pdev->dev, pdev->irq, dev); + mt76_free_device(&dev->mt76); + pci_free_irq_vectors(pdev); +} + +static int mt7925_pci_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt76_connac_pm *pm = &dev->pm; + int i, err; + + pm->suspended = true; + flush_work(&dev->reset_work); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + + err = mt792x_mcu_drv_pmctrl(dev); + if (err < 0) + goto restore_suspend; + + /* always enable deep sleep during suspend to reduce + * power consumption + */ + mt7925_mcu_set_deep_sleep(dev, true); + + err = mt76_connac_mcu_set_hif_suspend(mdev, true); + if (err) + goto restore_suspend; + + napi_disable(&mdev->tx_napi); + mt76_worker_disable(&mdev->tx_worker); + + mt76_for_each_q_rx(mdev, i) { + napi_disable(&mdev->napi[i]); + } + + /* wait until dma is idle */ + mt76_poll(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000); + + /* put dma disabled */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + /* disable interrupt */ + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); + mt76_wr(dev, MT_WFDMA0_HOST_INT_DIS, + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); + + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); + + synchronize_irq(pdev->irq); + tasklet_kill(&mdev->irq_tasklet); + + err = mt792x_mcu_fw_pmctrl(dev); + if (err) + goto restore_napi; + + return 0; + +restore_napi: + mt76_for_each_q_rx(mdev, i) { + napi_enable(&mdev->napi[i]); + } + napi_enable(&mdev->tx_napi); + + if (!pm->ds_enable) + mt7925_mcu_set_deep_sleep(dev, false); + + mt76_connac_mcu_set_hif_suspend(mdev, false); + +restore_suspend: + pm->suspended = false; + + if (err < 0) + mt792x_reset(&dev->mt76); + + return err; +} + +static int mt7925_pci_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt76_connac_pm *pm = &dev->pm; + int i, err; + + err = mt792x_mcu_drv_pmctrl(dev); + if (err < 0) + goto failed; + + mt792x_wpdma_reinit_cond(dev); + + /* enable interrupt */ + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + mt76_connac_irq_enable(&dev->mt76, + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); + mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); + + /* put dma enabled */ + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + mt76_worker_enable(&mdev->tx_worker); + + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) { + napi_enable(&mdev->napi[i]); + napi_schedule(&mdev->napi[i]); + } + napi_enable(&mdev->tx_napi); + napi_schedule(&mdev->tx_napi); + local_bh_enable(); + + err = mt76_connac_mcu_set_hif_suspend(mdev, false); + + /* restore previous ds setting */ + if (!pm->ds_enable) + mt7925_mcu_set_deep_sleep(dev, false); + +failed: + pm->suspended = false; + + if (err < 0) + mt792x_reset(&dev->mt76); + + return err; +} + +static void mt7925_pci_shutdown(struct pci_dev *pdev) +{ + mt7925_pci_remove(pdev); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(mt7925_pm_ops, mt7925_pci_suspend, mt7925_pci_resume); + +static struct pci_driver mt7925_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7925_pci_device_table, + .probe = mt7925_pci_probe, + .remove = mt7925_pci_remove, + .shutdown = mt7925_pci_shutdown, + .driver.pm = pm_sleep_ptr(&mt7925_pm_ops), +}; + +module_pci_driver(mt7925_pci_driver); + +MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table); +MODULE_FIRMWARE(MT7925_FIRMWARE_WM); +MODULE_FIRMWARE(MT7925_ROM_PATCH); +MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c new file mode 100644 index 000000000000..9fca887977d2 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt7925.h" +#include "../dma.h" +#include "mac.h" + +int mt7925e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct mt76_connac_hw_txp *txp; + struct mt76_txwi_cache *t; + int id, pid; + u8 *txwi = (u8 *)txwi_ptr; + + if (unlikely(tx_info->skb->len <= ETH_HLEN)) + return -EINVAL; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; + + id = mt76_token_consume(mdev, &t); + if (id < 0) + return id; + + if (sta) { + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + + if (time_after(jiffies, msta->last_txs + HZ / 4)) { + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + msta->last_txs = jiffies; + } + } + + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + mt7925_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key, + pid, qid, 0); + + txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE); + memset(txp, 0, sizeof(struct mt76_connac_hw_txp)); + mt76_connac_write_hw_txp(mdev, tx_info, txp, id); + + tx_info->skb = NULL; + + return 0; +} + +void mt7925_tx_token_put(struct mt792x_dev *dev) +{ + struct mt76_txwi_cache *txwi; + int id; + + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { + mt7925_txwi_free(dev, txwi, NULL, false, NULL); + dev->mt76.token_count--; + } + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); +} + +int mt7925e_mac_reset(struct mt792x_dev *dev) +{ + const struct mt792x_irq_map *irq_map = dev->irq_map; + int i, err; + + mt792xe_mcu_drv_pmctrl(dev); + + mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); + + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76_txq_schedule_all(&dev->mphy); + + mt76_worker_disable(&dev->mt76.tx_worker); + if (irq_map->rx.data_complete_mask) + napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]); + if (irq_map->rx.wm_complete_mask) + napi_disable(&dev->mt76.napi[MT_RXQ_MCU]); + if (irq_map->rx.wm2_complete_mask) + napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); + if (irq_map->tx.all_complete_mask) + napi_disable(&dev->mt76.tx_napi); + + mt7925_tx_token_put(dev); + idr_init(&dev->mt76.token); + + mt792x_wpdma_reset(dev, true); + + local_bh_disable(); + mt76_for_each_q_rx(&dev->mt76, i) { + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); + } + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); + local_bh_enable(); + + dev->fw_assert = false; + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + + mt76_wr(dev, dev->irq_map->host_irq_enable, + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + + err = mt792xe_mcu_fw_pmctrl(dev); + if (err) + return err; + + err = __mt792xe_mcu_drv_pmctrl(dev); + if (err) + goto out; + + err = mt7925_run_firmware(dev); + if (err) + goto out; + + err = mt7925_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7925_mac_init(dev); + if (err) + goto out; + + err = __mt7925_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c new file mode 100644 index 000000000000..f95bc5dcd830 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt7925.h" +#include "mcu.h" + +static int +mt7925_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *seq) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + enum mt76_mcuq_id txq = MT_MCUQ_WM; + int ret; + + ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq); + if (ret) + return ret; + + mdev->mcu.timeout = 3 * HZ; + + if (cmd == MCU_CMD(FW_SCATTER)) + txq = MT_MCUQ_FWDL; + + return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); +} + +int mt7925e_mcu_init(struct mt792x_dev *dev) +{ + static const struct mt76_mcu_ops mt7925_mcu_ops = { + .headroom = sizeof(struct mt76_connac2_mcu_txd), + .mcu_skb_send_msg = mt7925_mcu_send_message, + .mcu_parse_response = mt7925_mcu_parse_response, + }; + int err; + + dev->mt76.mcu_ops = &mt7925_mcu_ops; + + err = mt792xe_mcu_fw_pmctrl(dev); + if (err) + return err; + + err = __mt792xe_mcu_drv_pmctrl(dev); + if (err) + return err; + + mt76_rmw_field(dev, MT_PCIE_MAC_PM, MT_PCIE_MAC_PM_L0S_DIS, 1); + + err = mt7925_run_firmware(dev); + + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false); + + return err; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h new file mode 100644 index 000000000000..985794a40c1a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7925_REGS_H +#define __MT7925_REGS_H + +#include "../mt792x_regs.h" + +#define MT_MDP_BASE 0x820cc800 +#define MT_MDP(ofs) (MT_MDP_BASE + (ofs)) + +#define MT_MDP_DCR0 MT_MDP(0x000) +#define MT_MDP_DCR0_DAMSDU_EN BIT(15) +#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19) + +#define MT_MDP_DCR1 MT_MDP(0x004) +#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3) + +#define MT_MDP_BNRCFR0(_band) MT_MDP(0x090 + ((_band) << 8)) +#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4) +#define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6) +#define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8) + +#define MT_MDP_BNRCFR1(_band) MT_MDP(0x094 + ((_band) << 8)) +#define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22) +#define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27) +#define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29) +#define MT_MDP_TO_HIF 0 +#define MT_MDP_TO_WM 1 + +#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x228) +#define MT_WFDMA0_HOST_INT_DIS MT_WFDMA0(0x22c) +#define HOST_RX_DONE_INT_ENA4 BIT(12) +#define HOST_RX_DONE_INT_ENA5 BIT(13) +#define HOST_RX_DONE_INT_ENA6 BIT(14) +#define HOST_RX_DONE_INT_ENA7 BIT(15) +#define HOST_RX_DONE_INT_ENA8 BIT(16) +#define HOST_RX_DONE_INT_ENA9 BIT(17) +#define HOST_RX_DONE_INT_ENA10 BIT(18) +#define HOST_RX_DONE_INT_ENA11 BIT(19) +#define HOST_TX_DONE_INT_ENA15 BIT(25) +#define HOST_TX_DONE_INT_ENA16 BIT(26) +#define HOST_TX_DONE_INT_ENA17 BIT(27) + +/* WFDMA interrupt */ +#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2 +#define MT_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0 +#define MT_INT_RX_DONE_WM2 HOST_RX_DONE_INT_ENA1 +#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_DATA | \ + MT_INT_RX_DONE_WM | \ + MT_INT_RX_DONE_WM2) + +#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \ + HOST_TX_DONE_INT_ENA17) + +#define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16 +#define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0 + +#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \ + MT_INT_TX_DONE_FWDL) +#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \ + MT_INT_TX_DONE_BAND0 | \ + GENMASK(18, 4)) + +#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x500) + +#define MT_INFRA_CFG_BASE 0xd1000 +#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) + +#define MT_HIF_REMAP_L1 0x155024 +#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16) +#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0) +#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) +#define MT_HIF_REMAP_BASE_L1 0x130000 + +#define MT_HIF_REMAP_L2 0x0120 +#if IS_ENABLED(CONFIG_MT76_DEV) +#define MT_HIF_REMAP_BASE_L2 (0x7c500000 - (0x7c000000 - 0x18000000)) +#else +#define MT_HIF_REMAP_BASE_L2 0x18500000 +#endif + +#define MT_WFSYS_SW_RST_B 0x7c000140 + +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370) +#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0) + +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14) + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/usb.c b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c new file mode 100644 index 000000000000..9b885c5b3ed5 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7925/usb.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> + +#include "mt7925.h" +#include "mcu.h" +#include "mac.h" + +static const struct usb_device_id mt7925u_device_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7925, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM }, + { }, +}; + +static int +mt7925u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, int *seq) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + u32 pad, ep; + int ret; + + ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq); + if (ret) + return ret; + + mdev->mcu.timeout = 3 * HZ; + + if (cmd != MCU_CMD(FW_SCATTER)) + ep = MT_EP_OUT_INBAND_CMD; + else + ep = MT_EP_OUT_AC_BE; + + mt792x_skb_add_usb_sdio_hdr(dev, skb, 0); + pad = round_up(skb->len, 4) + 4 - skb->len; + __skb_put_zero(skb, pad); + + ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL, + 1000, ep); + dev_kfree_skb(skb); + + return ret; +} + +static int mt7925u_mcu_init(struct mt792x_dev *dev) +{ + static const struct mt76_mcu_ops mcu_ops = { + .headroom = MT_SDIO_HDR_SIZE + + sizeof(struct mt76_connac2_mcu_txd), + .tailroom = MT_USB_TAIL_SIZE, + .mcu_skb_send_msg = mt7925u_mcu_send_message, + .mcu_parse_response = mt7925_mcu_parse_response, + }; + int ret; + + dev->mt76.mcu_ops = &mcu_ops; + + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + ret = mt7925_run_firmware(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + return 0; +} + +static int mt7925u_mac_reset(struct mt792x_dev *dev) +{ + int err; + + mt76_txq_schedule_all(&dev->mphy); + mt76_worker_disable(&dev->mt76.tx_worker); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt792xu_wfsys_reset(dev); + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + err = mt76u_resume_rx(&dev->mt76); + if (err) + goto out; + + err = mt792xu_mcu_power_on(dev); + if (err) + goto out; + + err = mt792xu_dma_init(dev, false); + if (err) + goto out; + + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7925_run_firmware(dev); + if (err) + goto out; + + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7925_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7925_mac_init(dev); + if (err) + goto out; + + err = __mt7925_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; +} + +static int mt7925u_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + .txwi_size = MT_SDIO_TXD_SIZE, + .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ | + MT_DRV_AMSDU_OFFLOAD, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7925_usb_sdio_tx_prepare_skb, + .tx_complete_skb = mt7925_usb_sdio_tx_complete_skb, + .tx_status_data = mt7925_usb_sdio_tx_status_data, + .rx_skb = mt7925_queue_rx_skb, + .rx_check = mt7925_rx_check, + .sta_add = mt7925_mac_sta_add, + .sta_assoc = mt7925_mac_sta_assoc, + .sta_remove = mt7925_mac_sta_remove, + .update_survey = mt792x_update_channel, + }; + static const struct mt792x_hif_ops hif_ops = { + .mcu_init = mt7925u_mcu_init, + .init_reset = mt792xu_init_reset, + .reset = mt7925u_mac_reset, + }; + static struct mt76_bus_ops bus_ops = { + .rr = mt792xu_rr, + .wr = mt792xu_wr, + .rmw = mt792xu_rmw, + .read_copy = mt76u_read_copy, + .write_copy = mt792xu_copy, + .type = MT76_BUS_USB, + }; + struct usb_device *udev = interface_to_usbdev(usb_intf); + struct ieee80211_ops *ops; + struct ieee80211_hw *hw; + struct mt792x_dev *dev; + struct mt76_dev *mdev; + u8 features; + int ret; + + ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7925_ops, + (void *)id->driver_info, &features); + if (!ops) + return -ENOMEM; + + ops->stop = mt792xu_stop; + + mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt792x_dev, mt76); + dev->fw_features = features; + dev->hif_ops = &hif_ops; + + udev = usb_get_dev(udev); + usb_reset_device(udev); + + usb_set_intfdata(usb_intf, dev); + + ret = __mt76u_init(mdev, usb_intf, &bus_ops); + if (ret < 0) + goto error; + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) { + ret = mt792xu_wfsys_reset(dev); + if (ret) + goto error; + } + + ret = mt792xu_mcu_power_on(dev); + if (ret) + goto error; + + ret = mt76u_alloc_mcu_queue(&dev->mt76); + if (ret) + goto error; + + ret = mt76u_alloc_queues(&dev->mt76); + if (ret) + goto error; + + ret = mt792xu_dma_init(dev, false); + if (ret) + goto error; + + hw = mt76_hw(dev); + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1; + + ret = mt7925_register_device(dev); + if (ret) + goto error; + + return 0; + +error: + mt76u_queues_deinit(&dev->mt76); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); + + return ret; +} + +#ifdef CONFIG_PM +static int mt7925u_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct mt792x_dev *dev = usb_get_intfdata(intf); + struct mt76_connac_pm *pm = &dev->pm; + int err; + + pm->suspended = true; + flush_work(&dev->reset_work); + + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + if (err) + goto failed; + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + return 0; + +failed: + pm->suspended = false; + + if (err < 0) + mt792x_reset(&dev->mt76); + + return err; +} + +static int mt7925u_resume(struct usb_interface *intf) +{ + struct mt792x_dev *dev = usb_get_intfdata(intf); + struct mt76_connac_pm *pm = &dev->pm; + bool reinit = true; + int err, i; + + for (i = 0; i < 10; i++) { + u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT); + + if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) { + reinit = false; + break; + } + if (val & MT_WF_SW_SER_DONE_SUSPEND) { + mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0); + break; + } + + msleep(20); + } + + if (reinit || mt792x_dma_need_reinit(dev)) { + err = mt792xu_dma_init(dev, true); + if (err) + goto failed; + } + + err = mt76u_resume_rx(&dev->mt76); + if (err < 0) + goto failed; + + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); +failed: + pm->suspended = false; + + if (err < 0) + mt792x_reset(&dev->mt76); + + return err; +} +#endif /* CONFIG_PM */ + +MODULE_DEVICE_TABLE(usb, mt7925u_device_table); +MODULE_FIRMWARE(MT7925_FIRMWARE_WM); +MODULE_FIRMWARE(MT7925_ROM_PATCH); + +static struct usb_driver mt7925u_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7925u_device_table, + .probe = mt7925u_probe, + .disconnect = mt792xu_disconnect, +#ifdef CONFIG_PM + .suspend = mt7925u_suspend, + .resume = mt7925u_resume, + .reset_resume = mt7925u_resume, +#endif /* CONFIG_PM */ + .soft_unbind = 1, + .disable_hub_initiated_lpm = 1, +}; +module_usb_driver(mt7925u_driver); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h index 5d5ab8630041..36fae736dd19 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -25,6 +25,8 @@ #define MT792x_FW_TAG_FEATURE 4 #define MT792x_FW_CAP_CNM BIT(7) +#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0) + /* NOTE: used to map mt76_rates. idx may change if firmware expands table */ #define MT792x_BASIC_RATES_TBL 11 @@ -36,9 +38,14 @@ #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" #define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin" +#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin" #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" #define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin" +#define MT7925_ROM_PATCH "mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin" + +#define MT792x_SDIO_HDR_TX_BYTES GENMASK(15, 0) +#define MT792x_SDIO_HDR_PKT_TYPE GENMASK(17, 16) struct mt792x_vif; struct mt792x_sta; @@ -61,6 +68,14 @@ enum { MT792x_CLC_MAX_NUM, }; +enum mt792x_reg_power_type { + MT_AP_UNSET = 0, + MT_AP_DEFAULT, + MT_AP_LPI, + MT_AP_SP, + MT_AP_VLP, +}; + DECLARE_EWMA(avg_signal, 10, 8) struct mt792x_sta { @@ -91,7 +106,6 @@ struct mt792x_vif { struct ewma_rssi rssi; struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; - struct ieee80211_chanctx_conf *ctx; }; struct mt792x_phy { @@ -113,6 +127,8 @@ struct mt792x_phy { struct mt76_mib_stats mib; u8 sta_work_count; + u8 clc_chan_conf; + enum mt792x_reg_power_type power_type; struct sk_buff_head scan_event_list; struct delayed_work scan_work; @@ -120,6 +136,7 @@ struct mt792x_phy { void *acpisar; #endif void *clc[MT792x_CLC_MAX_NUM]; + u64 chip_cap; struct work_struct roc_work; struct timer_list roc_timer; @@ -229,6 +246,7 @@ static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev) #define mt792x_mutex_release(dev) \ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) +void mt792x_stop(struct ieee80211_hw *hw); void mt792x_pm_wake_work(struct work_struct *work); void mt792x_pm_power_save_work(struct work_struct *work); void mt792x_reset(struct mt76_dev *mdev); @@ -308,6 +326,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev) switch (mt76_chip(&dev->mt76)) { case 0x7922: return MT7922_FIRMWARE_WM; + case 0x7925: + return MT7925_FIRMWARE_WM; default: return MT7921_FIRMWARE_WM; } @@ -318,6 +338,8 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev) switch (mt76_chip(&dev->mt76)) { case 0x7922: return MT7922_ROM_PATCH; + case 0x7925: + return MT7925_ROM_PATCH; default: return MT7921_ROM_PATCH; } @@ -337,6 +359,20 @@ void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val); u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val); void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len); void mt792xu_disconnect(struct usb_interface *usb_intf); +void mt792xu_stop(struct ieee80211_hw *hw); + +static inline void +mt792x_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, + int type) +{ + u32 hdr, len; + + len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr); + hdr = FIELD_PREP(MT792x_SDIO_HDR_TX_BYTES, len) | + FIELD_PREP(MT792x_SDIO_HDR_PKT_TYPE, type); + + put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr))); +} int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index 46be7f996c7e..502be22dbe36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -91,6 +91,28 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, } EXPORT_SYMBOL_GPL(mt792x_tx); +void mt792x_stop(struct ieee80211_hw *hw) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + + cancel_delayed_work_sync(&phy->mt76->mac_work); + + cancel_delayed_work_sync(&dev->pm.ps_work); + cancel_work_sync(&dev->pm.wake_work); + cancel_work_sync(&dev->reset_work); + mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); + + if (is_mt7921(&dev->mt76)) { + mt792x_mutex_acquire(dev); + mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); + mt792x_mutex_release(dev); + } + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); +} +EXPORT_SYMBOL_GPL(mt792x_stop); + void mt792x_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -115,7 +137,7 @@ void mt792x_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); } EXPORT_SYMBOL_GPL(mt792x_remove_interface); @@ -243,7 +265,7 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->ctx = ctx; + mvif->mt76.ctx = ctx; mutex_unlock(&dev->mt76.mutex); return 0; @@ -259,7 +281,7 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->ctx = NULL; + mvif->mt76.ctx = NULL; mutex_unlock(&dev->mt76.mutex); } EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx); @@ -358,7 +380,7 @@ void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (sset != ETH_SS_STATS) return; - memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats)); + memcpy(data, mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats)); data += sizeof(mt792x_gstrings_stats); page_pool_ethtool_stats_get_strings(data); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c index a3dbd3865b2f..488326ce5ed4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c @@ -88,25 +88,44 @@ EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete); #define PREFETCH(base, depth) ((base) << 16 | (depth)) static void mt792x_dma_prefetch(struct mt792x_dev *dev) { - mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4)); - mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4)); - - mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4)); - mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); + if (is_mt7925(&dev->mt76)) { + /* rx ring */ + mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4)); + /* tx ring */ + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x10)); + mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0200, 0x10)); + mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0300, 0x10)); + mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10)); + mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4)); + } else { + /* rx ring */ + mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4)); + /* tx ring */ + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4)); + mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); + } } int mt792x_dma_enable(struct mt792x_dev *dev) { + if (is_mt7925(&dev->mt76)) + mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28)); + /* configure perfetch settings */ mt792x_dma_prefetch(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c index 20e7f9c7c88c..2dd283caed36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c @@ -287,6 +287,15 @@ int mt792xu_init_reset(struct mt792x_dev *dev) } EXPORT_SYMBOL_GPL(mt792xu_init_reset); +void mt792xu_stop(struct ieee80211_hw *hw) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt76u_stop_tx(&dev->mt76); + mt792x_stop(hw); +} +EXPORT_SYMBOL_GPL(mt792xu_stop); + void mt792xu_disconnect(struct usb_interface *usb_intf) { struct mt792x_dev *dev = usb_get_intfdata(usb_intf); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index 0d6cc214ce10..55cb1770fa34 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) @@ -733,16 +754,17 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; + val = max_t(u8, sts - 1, 3); eht_cap_elem->phy_cap_info[0] |= - u8_encode_bits(u8_get_bits(sts - 1, BIT(0)), + u8_encode_bits(u8_get_bits(val, BIT(0)), IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK); eht_cap_elem->phy_cap_info[1] = - u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)), + u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)), IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) | - u8_encode_bits(sts - 1, + u8_encode_bits(val, IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) | - u8_encode_bits(sts - 1, + u8_encode_bits(val, IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK); eht_cap_elem->phy_cap_info[2] = @@ -869,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 ac8759febe48..04540833485f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -433,7 +433,9 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, case IEEE80211_STA_RX_BW_160: status->bw = RATE_INFO_BW_160; break; + /* rxv reports bw 320-1 and 320-2 separately */ case IEEE80211_STA_RX_BW_320: + case IEEE80211_STA_RX_BW_320 + 1: status->bw = RATE_INFO_BW_320; break; default: @@ -948,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; @@ -991,11 +984,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, } txp->fw.token = cpu_to_le16(id); - if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) - txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx); - else - txp->fw.rept_wds_wcid = cpu_to_le16(0xfff); - tx_info->skb = DMA_DUMMY_DATA; + txp->fw.rept_wds_wcid = cpu_to_le16(sta ? wcid->idx : 0xfff); + + tx_info->skb = NULL; /* pass partial skb header to fw */ tx_info->buf[1].len = MT_CT_PARSE_LEN; @@ -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,9 +1053,9 @@ 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[1], MT_TXD1_WLAN_IDX); + wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX); } __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); @@ -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; 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 (!wcid) + continue; - if (info & MT_TXFREE_INFO_HEADER) + 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->status.ampdu_len = 1; + info->status.ampdu_ack_len = + !!(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.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 c3a479dc3f53..09c7a28a3d51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -190,7 +190,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, mvif->mt76.omac_idx = idx; mvif->phy = phy; mvif->mt76.band_idx = band_idx; - mvif->mt76.wmm_idx = band_idx; + mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; ret = mt7996_mcu_add_dev_info(phy, vif, true); if (ret) @@ -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) @@ -414,10 +414,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct ieee80211_tx_queue_params *params) { struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + const u8 mq_to_aci[] = { + [IEEE80211_AC_VO] = 3, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_BE] = 0, + [IEEE80211_AC_BK] = 1, + }; + /* firmware uses access class index */ + mvif->queue_params[mq_to_aci[queue]] = *params; /* no need to update right away, we'll get BSS_CHANGED_QOS */ - queue = mt76_connac_lmac_mapping(queue); - mvif->queue_params[queue] = *params; return 0; } @@ -564,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); @@ -595,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); @@ -618,8 +615,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, mt7996_mcu_add_beacon(hw, vif, info->enable_beacon); } - if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || - changed & BSS_CHANGED_FILS_DISCOVERY) + if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) mt7996_mcu_beacon_inband_discov(dev, vif, changed); if (changed & BSS_CHANGED_MU_GROUPS) @@ -660,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); @@ -972,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; @@ -992,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) @@ -1192,7 +1209,7 @@ void mt7996_get_et_strings(struct ieee80211_hw *hw, u32 sset, u8 *data) { if (sset == ETH_SS_STATS) - memcpy(data, *mt7996_gstrings_stats, + memcpy(data, mt7996_gstrings_stats, sizeof(mt7996_gstrings_stats)); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 4a30db49ef33..bf917beb9439 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -324,8 +324,10 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3) static void mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (vif->bss_conf.csa_active) - ieee80211_csa_finish(vif); + if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION) + return; + + ieee80211_csa_finish(vif); } static void @@ -399,7 +401,7 @@ out: static void mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { - if (!vif->bss_conf.color_change_active) + if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION) return; ieee80211_color_change_finish(vif); @@ -448,6 +450,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb) } static void +mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb) +{ + struct mt7996_mcu_all_sta_info_event *res; + u16 i; + + skb_pull(skb, sizeof(struct mt7996_mcu_rxd)); + + res = (struct mt7996_mcu_all_sta_info_event *)skb->data; + + for (i = 0; i < le16_to_cpu(res->sta_num); i++) { + u8 ac; + u16 wlan_idx; + struct mt76_wcid *wcid; + + switch (le16_to_cpu(res->tag)) { + case UNI_ALL_STA_TXRX_ADM_STAT: + wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx); + wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); + + if (!wcid) + break; + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + wcid->stats.tx_bytes += + le32_to_cpu(res->adm_stat[i].tx_bytes[ac]); + wcid->stats.rx_bytes += + le32_to_cpu(res->adm_stat[i].rx_bytes[ac]); + } + break; + case UNI_ALL_STA_TXRX_MSDU_COUNT: + wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx); + wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); + + if (!wcid) + break; + + wcid->stats.tx_packets += + le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt); + wcid->stats.rx_packets += + le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt); + break; + default: + break; + } + } +} + +static void mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb) { struct mt7996_mcu_rxd *rxd = (struct mt7996_mcu_rxd *)skb->data; @@ -491,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb) case MCU_UNI_EVENT_RDD_REPORT: mt7996_mcu_rx_radar_detected(dev, skb); break; + case MCU_UNI_EVENT_ALL_STA_INFO: + mt7996_mcu_rx_all_sta_info_event(dev, skb); + break; default: break; } @@ -601,6 +654,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void +mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7996_phy *phy, int enable) +{ + struct bss_info_uni_mbssid *mbssid; + struct tlv *tlv; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid)); + + mbssid = (struct bss_info_uni_mbssid *)tlv; + + if (enable && vif->bss_conf.bssid_indicator) { + mbssid->max_indicator = vif->bss_conf.bssid_indicator; + mbssid->mbss_idx = vif->bss_conf.bssid_index; + mbssid->tx_bss_omac_idx = 0; + } +} + +static void mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7996_phy *phy) { @@ -866,6 +937,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, /* this tag is necessary no matter if the vif is MLD */ mt7996_mcu_bss_mld_tlv(skb, vif); } + + mt7996_mcu_bss_mbssid_tlv(skb, vif, phy, enable); + out: return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); @@ -1152,6 +1226,8 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]); muru->ofdma_ul.uo_ra = HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]); + muru->ofdma_ul.rx_ctrl_frame_to_mbss = + HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]); } static inline bool @@ -1624,6 +1700,132 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, MCU_WM_UNI_CMD(RA), true); } +static int +mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *data, u32 field) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct sta_phy *phy = data; + struct sta_rec_ra_fixed *ra; + struct sk_buff *skb; + struct tlv *tlv; + + skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, + &msta->wcid, + MT7996_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); + ra = (struct sta_rec_ra_fixed *)tlv; + + switch (field) { + case RATE_PARAM_AUTO: + break; + case RATE_PARAM_FIXED: + case RATE_PARAM_FIXED_MCS: + case RATE_PARAM_FIXED_GI: + case RATE_PARAM_FIXED_HE_LTF: + if (phy) + ra->phy = *phy; + break; + default: + break; + } + ra->field = cpu_to_le32(field); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); +} + +static int +mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; + struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask; + enum nl80211_band band = chandef->chan->band; + struct sta_phy phy = {}; + int ret, nrates = 0; + +#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \ + do { \ + u8 i, gi = mask->control[band]._gi; \ + gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \ + phy.sgi = gi; \ + phy.he_ltf = mask->control[band].he_ltf; \ + for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \ + if (!mask->control[band]._mcs[i]) \ + continue; \ + nrates += hweight16(mask->control[band]._mcs[i]); \ + phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \ + if (_ht) \ + phy.mcs += 8 * i; \ + } \ + } while (0) + + if (sta->deflink.he_cap.has_he) { + __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1); + } else if (sta->deflink.vht_cap.vht_supported) { + __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0); + } else if (sta->deflink.ht_cap.ht_supported) { + __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0); + } else { + nrates = hweight32(mask->control[band].legacy); + phy.mcs = ffs(mask->control[band].legacy) - 1; + } +#undef __sta_phy_bitrate_mask_check + + /* fall back to auto rate control */ + if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI && + mask->control[band].he_gi == GENMASK(7, 0) && + mask->control[band].he_ltf == GENMASK(7, 0) && + nrates != 1) + return 0; + + /* fixed single rate */ + if (nrates == 1) { + ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy, + RATE_PARAM_FIXED_MCS); + if (ret) + return ret; + } + + /* fixed GI */ + if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI || + mask->control[band].he_gi != GENMASK(7, 0)) { + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + u32 addr; + + /* firmware updates only TXCMD but doesn't take WTBL into + * account, so driver should update here to reflect the + * actual txrate hardware sends out. + */ + addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7); + if (sta->deflink.he_cap.has_he) + mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi); + else + mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); + + ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy, + RATE_PARAM_FIXED_GI); + if (ret) + return ret; + } + + /* fixed HE_LTF */ + if (mask->control[band].he_ltf != GENMASK(7, 0)) { + ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy, + RATE_PARAM_FIXED_HE_LTF); + if (ret) + return ret; + } + + return 0; +} + static void mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -1733,6 +1935,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif, struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct sk_buff *skb; + int ret; skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &msta->wcid, @@ -1752,8 +1955,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif, */ mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); + if (ret) + return ret; + + return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta); } static int @@ -1996,6 +2203,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb, } static void +mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, + struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn, + struct ieee80211_mutable_offsets *offs) +{ + struct bss_bcn_mbss_tlv *mbss; + const struct element *elem; + struct tlv *tlv; + + if (!vif->bss_conf.bssid_indicator) + return; + + tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss)); + + mbss = (struct bss_bcn_mbss_tlv *)tlv; + mbss->offset[0] = cpu_to_le16(offs->tim_offset); + mbss->bitmap = cpu_to_le32(1); + + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, + &skb->data[offs->mbssid_off], + skb->len - offs->mbssid_off) { + const struct element *sub_elem; + + if (elem->datalen < 2) + continue; + + for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) { + const struct ieee80211_bssid_index *idx; + const u8 *idx_ie; + + /* not a valid BSS profile */ + if (sub_elem->id || sub_elem->datalen < 4) + continue; + + /* Find WLAN_EID_MULTI_BSSID_IDX + * in the merged nontransmitted profile + */ + idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, + sub_elem->data, sub_elem->datalen); + if (!idx_ie || idx_ie[1] < sizeof(*idx)) + continue; + + idx = (void *)(idx_ie + 2); + if (!idx->bssid_index || idx->bssid_index > 31) + continue; + + mbss->offset[idx->bssid_index] = cpu_to_le16(idx_ie - + skb->data); + mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index)); + } + } +} + +static void mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, struct sk_buff *rskb, struct sk_buff *skb, struct bss_bcn_content_tlv *bcn, @@ -2016,7 +2276,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif, bcn->bcc_ie_pos = cpu_to_le16(offset - 3); } - buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE; + buf = (u8 *)bcn + sizeof(*bcn); mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, BSS_CHANGED_BEACON); @@ -2034,26 +2294,25 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct sk_buff *skb, *rskb; struct tlv *tlv; struct bss_bcn_content_tlv *bcn; + int len; + + if (vif->bss_conf.nontransmitted) + return 0; rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, - MT7996_BEACON_UPDATE_SIZE); + MT7996_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) return PTR_ERR(rskb); - tlv = mt7996_mcu_add_uni_tlv(rskb, - UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn)); - bcn = (struct bss_bcn_content_tlv *)tlv; - bcn->enable = en; - - if (!en) - goto out; - skb = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!skb) + if (!skb) { + dev_kfree_skb(rskb); return -EINVAL; + } - if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) { + if (skb->len > MT7996_MAX_BEACON_SIZE) { dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(rskb); dev_kfree_skb(skb); return -EINVAL; } @@ -2061,11 +2320,18 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); + len = sizeof(*bcn) + MT_TXD_SIZE + skb->len; + tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len); + bcn = (struct bss_bcn_content_tlv *)tlv; + bcn->enable = en; + if (!en) + goto out; + mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); - /* TODO: subtag - 11v MBSSID */ + mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs); mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs); - dev_kfree_skb(skb); out: + dev_kfree_skb(skb); return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } @@ -2086,9 +2352,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, struct sk_buff *rskb, *skb = NULL; struct tlv *tlv; u8 *buf, interval; + int len; + + if (vif->bss_conf.nontransmitted) + return 0; rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, - MT7996_INBAND_FRAME_SIZE); + MT7996_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) return PTR_ERR(rskb); @@ -2102,11 +2372,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); } - if (!skb) + if (!skb) { + dev_kfree_skb(rskb); return -EINVAL; + } - if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) { + if (skb->len > MT7996_MAX_BEACON_SIZE) { dev_err(dev->mt76.dev, "inband discovery size limit exceed\n"); + dev_kfree_skb(rskb); dev_kfree_skb(skb); return -EINVAL; } @@ -2116,7 +2389,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, info->band = band; info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx); - tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov)); + len = sizeof(*discov) + MT_TXD_SIZE + skb->len; + + tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len); discov = (struct bss_inband_discovery_tlv *)tlv; discov->tx_mode = OFFLOAD_TX_MODE_SU; @@ -2127,7 +2402,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev, discov->enable = true; discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED); - buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE; + buf = (u8 *)tlv + sizeof(*discov); mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed); @@ -2679,7 +2954,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif) e = (struct edca *)tlv; e->set = WMM_PARAM_SET; - e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS; + e->queue = ac; e->aifs = q->aifs; e->txop = cpu_to_le16(q->txop); @@ -2960,10 +3235,10 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag) .channel_band = ch_band[chandef->chan->band], }; - if (tag == UNI_CHANNEL_RX_PATH || - dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR) + if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR) req.switch_reason = CH_SWITCH_NORMAL; - else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL || + phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef, NL80211_IFTYPE_AP)) @@ -3307,8 +3582,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action) tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en)); req_mod_en = (struct bf_mod_en_ctrl *)tlv; - req_mod_en->bf_num = 2; - req_mod_en->bf_bitmap = GENMASK(0, 0); + req_mod_en->bf_num = 3; + req_mod_en->bf_bitmap = GENMASK(2, 0); break; } default: @@ -3548,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, int cmd) { struct { - u8 _rsv[4]; + /* fixed field */ + u8 bss; + u8 _rsv[3]; __le16 tag; __le16 len; @@ -3566,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, u8 exponent; u8 is_ap; u8 agrt_params; - u8 __rsv2[135]; + u8 __rsv2[23]; } __packed req = { .tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE), .len = cpu_to_le16(sizeof(req) - 4), @@ -3576,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev, .flowid = flow->id, .peer_id = cpu_to_le16(flow->wcid), .duration = flow->duration, + .bss = mvif->mt76.idx, .bss_idx = mvif->mt76.idx, .start_tsf = cpu_to_le64(flow->tsf), .mantissa = flow->mantissa, @@ -3786,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val) return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req, sizeof(req), true); } + +int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag) +{ + struct mt7996_dev *dev = phy->dev; + struct { + u8 _rsv[4]; + + __le16 tag; + __le16 len; + } __packed req = { + .tag = cpu_to_le16(tag), + .len = cpu_to_le16(sizeof(req) - 4), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO), + &req, sizeof(req), false); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index 078f82858621..a88f6af323da 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[2]; + + union { + struct { + __le16 wlan_idx; + u8 rsv[2]; + __le32 tx_bytes[IEEE80211_NUM_ACS]; + __le32 rx_bytes[IEEE80211_NUM_ACS]; + } adm_stat[0]; + + struct { + __le16 wlan_idx; + u8 rsv[2]; + __le32 tx_msdu_cnt; + __le32 rx_msdu_cnt; + } msdu_cnt[0]; + }; +} __packed; + enum mt7996_chan_mib_offs { UNI_MIB_OBSS_AIRTIME = 26, UNI_MIB_NON_WIFI_TIME = 27, @@ -270,8 +296,6 @@ struct bss_inband_discovery_tlv { u8 enable; __le16 wcid; __le16 prob_rsp_len; -#define MAX_INBAND_FRAME_SIZE 512 - u8 pkt[MAX_INBAND_FRAME_SIZE]; } __packed; struct bss_bcn_content_tlv { @@ -283,8 +307,6 @@ struct bss_bcn_content_tlv { u8 enable; u8 type; __le16 pkt_len; -#define MAX_BEACON_SIZE 512 - u8 pkt[MAX_BEACON_SIZE]; } __packed; struct bss_bcn_cntdwn_tlv { @@ -591,13 +613,14 @@ enum { sizeof(struct sta_rec_hdr_trans) + \ sizeof(struct tlv)) +#define MT7996_MAX_BEACON_SIZE 1342 #define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \ sizeof(struct bss_bcn_content_tlv) + \ + MT_TXD_SIZE + \ sizeof(struct bss_bcn_cntdwn_tlv) + \ sizeof(struct bss_bcn_mbss_tlv)) - -#define MT7996_INBAND_FRAME_SIZE (sizeof(struct bss_req_hdr) + \ - sizeof(struct bss_inband_discovery_tlv)) +#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \ + MT7996_BEACON_UPDATE_SIZE) enum { UNI_BAND_CONFIG_RADIO_ENABLE, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 7354e5cf8e67..e53cf6a3704c 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/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index 97beab924517..0086a7866657 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) diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 6cc26cc6c517..1809b03292c3 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -329,40 +329,32 @@ void mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb) { - struct mt76_dev *dev = phy->dev; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct mt76_queue *q; - int qid = skb_get_queue_mapping(skb); if (mt76_testmode_enabled(phy)) { ieee80211_free_txskb(phy->hw, skb); return; } - if (WARN_ON(qid >= MT_TXQ_PSD)) { - qid = MT_TXQ_BE; - skb_set_queue_mapping(skb, qid); - } - - if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && - !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && - !ieee80211_is_data(hdr->frame_control) && - !ieee80211_is_bufferable_mmpdu(skb)) { - qid = MT_TXQ_PSD; - } + if (WARN_ON(skb_get_queue_mapping(skb) >= MT_TXQ_PSD)) + skb_set_queue_mapping(skb, MT_TXQ_BE); if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(info->control.vif, sta, skb, info->control.rates, 1); info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); - q = phy->q_tx[qid]; - spin_lock_bh(&q->lock); - __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL); - dev->queue_ops->kick(dev, q); - spin_unlock_bh(&q->lock); + spin_lock_bh(&wcid->tx_pending.lock); + __skb_queue_tail(&wcid->tx_pending, skb); + spin_unlock_bh(&wcid->tx_pending.lock); + + spin_lock_bh(&phy->tx_lock); + if (list_empty(&wcid->tx_list)) + list_add_tail(&wcid->tx_list, &phy->tx_list); + spin_unlock_bh(&phy->tx_lock); + + mt76_worker_schedule(&phy->dev->tx_worker); } EXPORT_SYMBOL_GPL(mt76_tx); @@ -593,10 +585,86 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) } EXPORT_SYMBOL_GPL(mt76_txq_schedule); +static int +mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid) +{ + struct mt76_dev *dev = phy->dev; + struct ieee80211_sta *sta; + struct mt76_queue *q; + struct sk_buff *skb; + int ret = 0; + + spin_lock(&wcid->tx_pending.lock); + while ((skb = skb_peek(&wcid->tx_pending)) != NULL) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int qid = skb_get_queue_mapping(skb); + + if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && + !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + !ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_bufferable_mmpdu(skb)) + qid = MT_TXQ_PSD; + + q = phy->q_tx[qid]; + if (mt76_txq_stopped(q)) { + ret = -1; + break; + } + + __skb_unlink(skb, &wcid->tx_pending); + spin_unlock(&wcid->tx_pending.lock); + + sta = wcid_to_sta(wcid); + spin_lock(&q->lock); + __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL); + dev->queue_ops->kick(dev, q); + spin_unlock(&q->lock); + + spin_lock(&wcid->tx_pending.lock); + } + spin_unlock(&wcid->tx_pending.lock); + + return ret; +} + +static void mt76_txq_schedule_pending(struct mt76_phy *phy) +{ + if (list_empty(&phy->tx_list)) + return; + + local_bh_disable(); + rcu_read_lock(); + + spin_lock(&phy->tx_lock); + while (!list_empty(&phy->tx_list)) { + struct mt76_wcid *wcid = NULL; + int ret; + + wcid = list_first_entry(&phy->tx_list, struct mt76_wcid, tx_list); + list_del_init(&wcid->tx_list); + + spin_unlock(&phy->tx_lock); + ret = mt76_txq_schedule_pending_wcid(phy, wcid); + spin_lock(&phy->tx_lock); + + if (ret) { + if (list_empty(&wcid->tx_list)) + list_add_tail(&wcid->tx_list, &phy->tx_list); + break; + } + } + spin_unlock(&phy->tx_lock); + + rcu_read_unlock(); + local_bh_enable(); +} + void mt76_txq_schedule_all(struct mt76_phy *phy) { int i; + mt76_txq_schedule_pending(phy); for (i = 0; i <= MT_TXQ_BK; i++) mt76_txq_schedule(phy, i); } diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 3835b639d453..cc9b2a459386 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1897,7 +1897,7 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) /*this is wrong, fill_tx_cmddesc needs update*/ pdesc = &ring->desc[0]; - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb); __skb_queue_tail(&ring->queue, skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 65ebe52883d3..d094163a9a71 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -665,9 +665,8 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -687,8 +686,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, } clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); - if (firstseg) - set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); set_tx_desc_tx_rate(pdesc, DESC92C_RATE1M); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index e17f70b4d199..aae654b0e3ba 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -797,6 +797,5 @@ bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 5376bb34251f..50e139186a93 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -518,9 +518,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -540,9 +539,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, } clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); - if (firstseg) - set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); - + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); set_tx_desc_tx_rate(pdesc, DESC_RATE1M); set_tx_desc_seq(pdesc, 0); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index b45b05a6a523..f3ffe3d9883c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -527,6 +527,5 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index a040c07791d1..5ec0eb8773a5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1539,7 +1539,7 @@ static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) * if its "here". * * This is maybe necessary: - * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb); + * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, skb); */ dev_kfree_skb(skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index b70767e72f3d..9969e9d1fc4b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -626,9 +626,8 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc8, _rtl_tx_desc_checksum(pdesc); } -void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 fw_queue = QSLT_BEACON; @@ -637,8 +636,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, __le32 *pdesc = (__le32 *)pdesc8; memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); - if (firstseg) - set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE); + set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE); set_tx_desc_tx_rate(pdesc, DESC_RATE1M); set_tx_desc_seq(pdesc, 0); set_tx_desc_linip(pdesc, 0); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index 171fe39dfb0c..cc4ef2bfd2e7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -396,8 +396,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_tcb_desc *tcb_desc); void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc, u32 buffer_len, bool ispspoll); -void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool b_firstseg, - bool b_lastseg, struct sk_buff *skb); +void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 9ddb8478784b..e1fb29962801 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -469,7 +469,7 @@ static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw, pdesc = &ring->desc[idx]; /* discard output from call below */ rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN); - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb); __skb_queue_tail(&ring->queue, skb); spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index c09c0c312665..02ac69c08ed3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -655,9 +655,8 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -678,8 +677,7 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, return; } clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); - if (firstseg) - set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); /* 5G have no CCK rate * Caution: The macros below are multi-line expansions. * The braces are needed no matter what checkpatch says diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h index d01578875cd5..2992668c156c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h @@ -564,7 +564,6 @@ bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c index 997ff115b9ab..5a828a934fe9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c @@ -936,8 +936,7 @@ void rtl92ee_dm_init(struct ieee80211_hw *hw) static void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *drv_priv; - u8 cnt = 0; + u8 cnt; rtlpriv->dm.one_entry_only = false; @@ -951,9 +950,7 @@ static void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw) rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - cnt++; - } + cnt = list_count_nodes(&rtlpriv->entry_list); spin_unlock_bh(&rtlpriv->locks.entry_list_lock); if (cnt == 1) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index a182cdeb58e2..67388e0b3fa0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -827,9 +827,8 @@ void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -846,8 +845,7 @@ void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, } clear_pci_tx_desc_content(pdesc, txdesc_len); - if (firstseg) - set_tx_desc_offset(pdesc, txdesc_len); + set_tx_desc_offset(pdesc, txdesc_len); set_tx_desc_tx_rate(pdesc, DESC_RATE1M); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h index 967cef3a9cbf..3852a50a688b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h @@ -743,6 +743,5 @@ u64 rtl92ee_get_desc(struct ieee80211_hw *hw, bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index f570495af044..579b1789d6d1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c @@ -122,7 +122,7 @@ static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; pdesc = &ring->desc[idx]; - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb); __skb_queue_tail(&ring->queue, skb); spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c index a5853a170b58..f104cdb649f8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c @@ -492,7 +492,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, } void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, - bool firstseg, bool lastseg, struct sk_buff *skb) + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h index 90aa12fc6a7f..40291a6a15d0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h @@ -10,8 +10,8 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb); +void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + struct sk_buff *skb); bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, u8 *pdesc, struct sk_buff *skb); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index 53af0d209b11..b34dffc6a30c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c @@ -1122,7 +1122,7 @@ static void rtl8723e_dm_bt_2_ant_hid_sco_esco(struct ieee80211_hw *hw) /* Always ignore WlanAct if bHid|bSCOBusy|bSCOeSCO */ rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", + "[BTCoex], BT btInqPageStartTime = 0x%lx, btTxRxCntLvl = %d\n", hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); if ((hal_coex_8723.bt_inq_page_start_time) || (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) { @@ -1335,7 +1335,7 @@ static void rtl8723e_dm_bt_2_ant_ftp_a2dp(struct ieee80211_hw *hw) btdm8723.dec_bt_pwr = true; rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", + "[BTCoex], BT btInqPageStartTime = 0x%lx, btTxRxCntLvl = %d\n", hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); if ((hal_coex_8723.bt_inq_page_start_time) || @@ -1358,9 +1358,8 @@ static void rtl8723e_dm_bt_2_ant_ftp_a2dp(struct ieee80211_hw *hw) static void rtl8723e_dm_bt_inq_page_monitor(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cur_time; + unsigned long cur_time = jiffies; - cur_time = jiffies; if (hal_coex_8723.c2h_bt_inquiry_page) { /* bt inquiry or page is started. */ if (hal_coex_8723.bt_inq_page_start_time == 0) { @@ -1368,18 +1367,17 @@ static void rtl8723e_dm_bt_inq_page_monitor(struct ieee80211_hw *hw) BT_COEX_STATE_BT_INQ_PAGE; hal_coex_8723.bt_inq_page_start_time = cur_time; rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT Inquiry/page is started at time : 0x%x\n", + "[BTCoex], BT Inquiry/page is started at time : 0x%lx\n", hal_coex_8723.bt_inq_page_start_time); } } rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT Inquiry/page started time : 0x%x, cur_time : 0x%x\n", + "[BTCoex], BT Inquiry/page started time : 0x%lx, cur_time : 0x%lx\n", hal_coex_8723.bt_inq_page_start_time, cur_time); if (hal_coex_8723.bt_inq_page_start_time) { - if ((((long)cur_time - - (long)hal_coex_8723.bt_inq_page_start_time) / HZ) - >= 10) { + if (jiffies_to_msecs(cur_time - + hal_coex_8723.bt_inq_page_start_time) >= 10000) { rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "[BTCoex], BT Inquiry/page >= 10sec!!!\n"); hal_coex_8723.bt_inq_page_start_time = 0; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index 7f294e698994..d9823ddab7be 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -519,9 +519,8 @@ void rtl8723e_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -541,8 +540,7 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, } clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE); - if (firstseg) - set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); + set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN); set_tx_desc_tx_rate(pdesc, DESC92C_RATE1M); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h index 2d25f62a4d52..f352fddfff32 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h @@ -530,6 +530,5 @@ bool rtl8723e_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c index c3c990cc032f..c53f95144812 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c @@ -1210,8 +1210,7 @@ static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw) static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 cnt = 0; - struct rtl_sta_info *drv_priv; + u8 cnt; rtlpriv->dm.one_entry_only = false; @@ -1225,9 +1224,7 @@ static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw) rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - cnt++; - } + cnt = list_count_nodes(&rtlpriv->entry_list); spin_unlock_bh(&rtlpriv->locks.entry_list_lock); if (cnt == 1) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 24ef7cc52e99..8b6352f7f93b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c @@ -585,7 +585,6 @@ void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, } void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, - bool firstseg, bool lastseg, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h index 174aca20c7e1..da027f915cf4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h @@ -642,6 +642,5 @@ bool rtl8723be_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index f3fe16798c59..76b5395539d0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -827,8 +827,7 @@ static void rtl8821ae_dm_dig(struct ieee80211_hw *hw) static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 cnt = 0; - struct rtl_sta_info *drv_priv; + u8 cnt; rtlpriv->dm.tx_rate = 0xff; @@ -844,8 +843,7 @@ static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw) rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) - cnt++; + cnt = list_count_nodes(&rtlpriv->entry_list); spin_unlock_bh(&rtlpriv->locks.entry_list_lock); if (cnt == 1) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index d7cb3319d885..bd71592fe26a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c @@ -828,9 +828,8 @@ void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw, rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); } -void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc8, bool firstseg, - bool lastseg, struct sk_buff *skb) +void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h index a9ed6fd41089..1155365348f3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h @@ -648,6 +648,5 @@ bool rtl8821ae_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 0f99e3446796..b60169196eab 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1597,7 +1597,7 @@ struct bt_coexist_8723 { u8 c2h_bt_info; bool c2h_bt_info_req_sent; bool c2h_bt_inquiry_page; - u32 bt_inq_page_start_time; + unsigned long bt_inq_page_start_time; u8 bt_retry_cnt; u8 c2h_bt_info_original; u8 bt_inquiry_page_cnt; @@ -2249,7 +2249,6 @@ struct rtl_hal_ops { void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, u32 buffer_len, bool bsspspoll); void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb); void (*fill_tx_special_desc)(struct ieee80211_hw *hw, u8 *pdesc, u8 *pbd_desc, diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index c42ef8294d59..86dc1516effa 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -342,8 +342,10 @@ enum rtw_regulatory_domains { RTW_REGD_UKRAINE = 7, RTW_REGD_MEXICO = 8, RTW_REGD_CN = 9, - RTW_REGD_WW, + RTW_REGD_QATAR = 10, + RTW_REGD_UK = 11, + RTW_REGD_WW, RTW_REGD_MAX }; diff --git a/drivers/net/wireless/realtek/rtw88/regd.c b/drivers/net/wireless/realtek/rtw88/regd.c index 2f547cbcf6da..7f3b2ea3f2a5 100644 --- a/drivers/net/wireless/realtek/rtw88/regd.c +++ b/drivers/net/wireless/realtek/rtw88/regd.c @@ -70,16 +70,16 @@ static const struct rtw_regulatory rtw_reg_map[] = { COUNTRY_REGD_ENT("BY", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("BZ", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("CA", RTW_REGD_IC, RTW_REGD_IC), - COUNTRY_REGD_ENT("CC", RTW_REGD_ETSI, RTW_REGD_ETSI), + COUNTRY_REGD_ENT("CC", RTW_REGD_ACMA, RTW_REGD_ACMA), COUNTRY_REGD_ENT("CD", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("CF", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("CG", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("CH", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("CI", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("CK", RTW_REGD_ETSI, RTW_REGD_ETSI), - COUNTRY_REGD_ENT("CL", RTW_REGD_FCC, RTW_REGD_FCC), + COUNTRY_REGD_ENT("CL", RTW_REGD_CHILE, RTW_REGD_CHILE), COUNTRY_REGD_ENT("CM", RTW_REGD_ETSI, RTW_REGD_ETSI), - COUNTRY_REGD_ENT("CN", RTW_REGD_ETSI, RTW_REGD_ETSI), + COUNTRY_REGD_ENT("CN", RTW_REGD_CN, RTW_REGD_CN), COUNTRY_REGD_ENT("CO", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("CR", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("CV", RTW_REGD_ETSI, RTW_REGD_ETSI), @@ -106,7 +106,7 @@ static const struct rtw_regulatory rtw_reg_map[] = { COUNTRY_REGD_ENT("FO", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("FR", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("GA", RTW_REGD_ETSI, RTW_REGD_ETSI), - COUNTRY_REGD_ENT("GB", RTW_REGD_ETSI, RTW_REGD_ETSI), + COUNTRY_REGD_ENT("GB", RTW_REGD_UK, RTW_REGD_UK), COUNTRY_REGD_ENT("GD", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("GE", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("GF", RTW_REGD_ETSI, RTW_REGD_ETSI), @@ -214,7 +214,7 @@ static const struct rtw_regulatory rtw_reg_map[] = { COUNTRY_REGD_ENT("PT", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("PW", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("PY", RTW_REGD_FCC, RTW_REGD_FCC), - COUNTRY_REGD_ENT("QA", RTW_REGD_ETSI, RTW_REGD_ETSI), + COUNTRY_REGD_ENT("QA", RTW_REGD_QATAR, RTW_REGD_QATAR), COUNTRY_REGD_ENT("RE", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("RO", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("RS", RTW_REGD_ETSI, RTW_REGD_ETSI), @@ -234,7 +234,7 @@ static const struct rtw_regulatory rtw_reg_map[] = { COUNTRY_REGD_ENT("SN", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("SO", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("SR", RTW_REGD_FCC, RTW_REGD_FCC), - COUNTRY_REGD_ENT("ST", RTW_REGD_FCC, RTW_REGD_FCC), + COUNTRY_REGD_ENT("ST", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("SV", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("SX", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("SZ", RTW_REGD_ETSI, RTW_REGD_ETSI), @@ -253,7 +253,7 @@ static const struct rtw_regulatory rtw_reg_map[] = { COUNTRY_REGD_ENT("TV", RTW_REGD_ETSI, RTW_REGD_WW), COUNTRY_REGD_ENT("TW", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("TZ", RTW_REGD_ETSI, RTW_REGD_ETSI), - COUNTRY_REGD_ENT("UA", RTW_REGD_ETSI, RTW_REGD_ETSI), + COUNTRY_REGD_ENT("UA", RTW_REGD_UKRAINE, RTW_REGD_UKRAINE), COUNTRY_REGD_ENT("UG", RTW_REGD_ETSI, RTW_REGD_ETSI), COUNTRY_REGD_ENT("US", RTW_REGD_FCC, RTW_REGD_FCC), COUNTRY_REGD_ENT("UY", RTW_REGD_FCC, RTW_REGD_FCC), @@ -502,6 +502,14 @@ u8 rtw_regd_get(struct rtw_dev *rtwdev) } EXPORT_SYMBOL(rtw_regd_get); +bool rtw_regd_srrc(struct rtw_dev *rtwdev) +{ + struct rtw_regd *regd = &rtwdev->regd; + + return rtw_reg_match(regd->regulatory, "CN"); +} +EXPORT_SYMBOL(rtw_regd_srrc); + struct rtw_regd_alternative_t { bool set; u8 alt; @@ -519,6 +527,8 @@ rtw_regd_alt[RTW_REGD_MAX] = { DECL_REGD_ALT(RTW_REGD_UKRAINE, RTW_REGD_ETSI), DECL_REGD_ALT(RTW_REGD_MEXICO, RTW_REGD_FCC), DECL_REGD_ALT(RTW_REGD_CN, RTW_REGD_ETSI), + DECL_REGD_ALT(RTW_REGD_QATAR, RTW_REGD_ETSI), + DECL_REGD_ALT(RTW_REGD_UK, RTW_REGD_ETSI), }; bool rtw_regd_has_alt(u8 regd, u8 *regd_alt) diff --git a/drivers/net/wireless/realtek/rtw88/regd.h b/drivers/net/wireless/realtek/rtw88/regd.h index 34cb13d0cd9e..3c5a6fd8e6dd 100644 --- a/drivers/net/wireless/realtek/rtw88/regd.h +++ b/drivers/net/wireless/realtek/rtw88/regd.h @@ -68,4 +68,6 @@ int rtw_regd_init(struct rtw_dev *rtwdev); int rtw_regd_hint(struct rtw_dev *rtwdev); u8 rtw_regd_get(struct rtw_dev *rtwdev); bool rtw_regd_has_alt(u8 regd, u8 *regd_alt); +bool rtw_regd_srrc(struct rtw_dev *rtwdev); + #endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index adf224618a2a..429bb420b056 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -381,6 +381,65 @@ static void rtw8821c_set_channel_rxdfir(struct rtw_dev *rtwdev, u8 bw) } } +static void rtw8821c_cck_tx_filter_srrc(struct rtw_dev *rtwdev, u8 channel, u8 bw) +{ + struct rtw_hal *hal = &rtwdev->hal; + + if (channel == 14) { + rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xe82c); + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x0000b81c); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x0000); + rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x00003667); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000); + } else if (channel == 13 || + (channel == 11 && bw == RTW_CHANNEL_WIDTH_40)) { + rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xf8fe); + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x64b80c1c); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x8810); + rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x01235667); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00027); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00027); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00029); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00026); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000); + } else { + rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xe82c); + rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, + hal->ch_param[0]); + rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, + hal->ch_param[1] & MASKLWORD); + rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, + hal->ch_param[2]); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000); + } +} + static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, u8 primary_ch_idx) { @@ -395,6 +454,13 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 0x0); rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x96a); + + if (rtw_regd_srrc(rtwdev)) { + rtw8821c_cck_tx_filter_srrc(rtwdev, channel, bw); + goto set_bw; + } + + /* CCK TX filter parameters for default case */ if (channel == 14) { rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x0000b81c); rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x0000); @@ -430,6 +496,7 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x412); } +set_bw: switch (bw) { case RTW_CHANNEL_WIDTH_20: default: diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h index fcff31688c45..91ed921407bb 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h @@ -238,6 +238,7 @@ extern const struct rtw_chip_info rtw8821c_hw_spec; #define REG_RXSB 0xa00 #define REG_ADCINI 0xa04 #define REG_PWRTH 0xa08 +#define REG_CCA_FLTR 0xa20 #define REG_TXSF2 0xa24 #define REG_TXSF6 0xa28 #define REG_FA_CCK 0xa5c diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c index 6c82c4383497..0393b9a0c1a3 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c_table.c @@ -6013,996 +6013,1492 @@ RTW_DECL_TABLE_RF_RADIO(rtw8821c_rf_a, A); static const struct rtw_txpwr_lmt_cfg_pair rtw8821c_txpwr_lmt_type0[] = { { 0, 0, 0, 0, 1, 30, }, { 2, 0, 0, 0, 1, 30, }, - { 0, 0, 0, 0, 2, 32, }, - { 2, 0, 0, 0, 2, 30, }, - { 0, 0, 0, 0, 3, 32, }, - { 2, 0, 0, 0, 3, 30, }, - { 0, 0, 0, 0, 4, 32, }, - { 2, 0, 0, 0, 4, 30, }, - { 0, 0, 0, 0, 5, 32, }, - { 2, 0, 0, 0, 5, 30, }, - { 0, 0, 0, 0, 6, 32, }, - { 2, 0, 0, 0, 6, 30, }, - { 0, 0, 0, 0, 7, 32, }, - { 2, 0, 0, 0, 7, 30, }, - { 0, 0, 0, 0, 8, 32, }, - { 2, 0, 0, 0, 8, 30, }, - { 0, 0, 0, 0, 9, 32, }, - { 2, 0, 0, 0, 9, 30, }, - { 0, 0, 0, 0, 10, 32, }, - { 2, 0, 0, 0, 10, 30, }, - { 0, 0, 0, 0, 11, 32, }, - { 2, 0, 0, 0, 11, 30, }, - { 0, 0, 0, 0, 12, 24, }, - { 2, 0, 0, 0, 12, 30, }, - { 0, 0, 0, 0, 13, 16, }, - { 2, 0, 0, 0, 13, 30, }, - { 0, 0, 0, 0, 14, 63, }, - { 2, 0, 0, 0, 14, 63, }, - { 0, 0, 0, 1, 1, 30, }, - { 2, 0, 0, 1, 1, 30, }, - { 0, 0, 0, 1, 2, 32, }, - { 2, 0, 0, 1, 2, 30, }, - { 0, 0, 0, 1, 3, 34, }, - { 2, 0, 0, 1, 3, 30, }, - { 0, 0, 0, 1, 4, 34, }, - { 2, 0, 0, 1, 4, 30, }, - { 0, 0, 0, 1, 5, 34, }, - { 2, 0, 0, 1, 5, 30, }, - { 0, 0, 0, 1, 6, 34, }, - { 2, 0, 0, 1, 6, 30, }, - { 0, 0, 0, 1, 7, 34, }, - { 2, 0, 0, 1, 7, 30, }, - { 0, 0, 0, 1, 8, 34, }, - { 2, 0, 0, 1, 8, 30, }, - { 0, 0, 0, 1, 9, 34, }, - { 2, 0, 0, 1, 9, 30, }, - { 0, 0, 0, 1, 10, 32, }, - { 2, 0, 0, 1, 10, 30, }, - { 0, 0, 0, 1, 11, 30, }, - { 2, 0, 0, 1, 11, 30, }, - { 0, 0, 0, 1, 12, 28, }, - { 2, 0, 0, 1, 12, 30, }, - { 0, 0, 0, 1, 13, 16, }, - { 2, 0, 0, 1, 13, 30, }, - { 0, 0, 0, 1, 14, 63, }, - { 2, 0, 0, 1, 14, 63, }, - { 0, 0, 0, 2, 1, 26, }, - { 2, 0, 0, 2, 1, 30, }, - { 0, 0, 0, 2, 2, 30, }, - { 2, 0, 0, 2, 2, 30, }, - { 0, 0, 0, 2, 3, 32, }, - { 2, 0, 0, 2, 3, 30, }, - { 0, 0, 0, 2, 4, 34, }, - { 2, 0, 0, 2, 4, 30, }, - { 0, 0, 0, 2, 5, 34, }, - { 2, 0, 0, 2, 5, 30, }, - { 0, 0, 0, 2, 6, 34, }, - { 2, 0, 0, 2, 6, 30, }, - { 0, 0, 0, 2, 7, 34, }, - { 2, 0, 0, 2, 7, 30, }, - { 0, 0, 0, 2, 8, 34, }, - { 2, 0, 0, 2, 8, 30, }, - { 0, 0, 0, 2, 9, 32, }, - { 2, 0, 0, 2, 9, 30, }, - { 0, 0, 0, 2, 10, 30, }, - { 2, 0, 0, 2, 10, 30, }, - { 0, 0, 0, 2, 11, 28, }, - { 2, 0, 0, 2, 11, 30, }, - { 0, 0, 0, 2, 12, 26, }, - { 2, 0, 0, 2, 12, 30, }, - { 0, 0, 0, 2, 13, 12, }, - { 2, 0, 0, 2, 13, 30, }, - { 0, 0, 0, 2, 14, 63, }, - { 2, 0, 0, 2, 14, 63, }, - { 0, 0, 1, 2, 1, 63, }, - { 2, 0, 1, 2, 1, 63, }, - { 0, 0, 1, 2, 2, 63, }, - { 2, 0, 1, 2, 2, 63, }, - { 0, 0, 1, 2, 3, 26, }, - { 2, 0, 1, 2, 3, 30, }, - { 0, 0, 1, 2, 4, 26, }, - { 2, 0, 1, 2, 4, 30, }, - { 0, 0, 1, 2, 5, 30, }, - { 2, 0, 1, 2, 5, 30, }, - { 0, 0, 1, 2, 6, 30, }, - { 2, 0, 1, 2, 6, 30, }, - { 0, 0, 1, 2, 7, 30, }, - { 2, 0, 1, 2, 7, 30, }, - { 0, 0, 1, 2, 8, 26, }, - { 2, 0, 1, 2, 8, 30, }, - { 0, 0, 1, 2, 9, 26, }, - { 2, 0, 1, 2, 9, 30, }, - { 0, 0, 1, 2, 10, 28, }, - { 2, 0, 1, 2, 10, 30, }, - { 0, 0, 1, 2, 11, 20, }, - { 2, 0, 1, 2, 11, 30, }, - { 0, 0, 1, 2, 12, 63, }, - { 2, 0, 1, 2, 12, 63, }, - { 0, 0, 1, 2, 13, 63, }, - { 2, 0, 1, 2, 13, 63, }, - { 0, 0, 1, 2, 14, 63, }, - { 2, 0, 1, 2, 14, 63, }, - { 0, 1, 0, 1, 36, 31, }, - { 2, 1, 0, 1, 36, 32, }, - { 0, 1, 0, 1, 40, 33, }, - { 2, 1, 0, 1, 40, 32, }, - { 0, 1, 0, 1, 44, 33, }, - { 2, 1, 0, 1, 44, 32, }, - { 0, 1, 0, 1, 48, 31, }, - { 2, 1, 0, 1, 48, 32, }, - { 0, 1, 0, 1, 52, 33, }, - { 2, 1, 0, 1, 52, 32, }, - { 0, 1, 0, 1, 56, 33, }, - { 2, 1, 0, 1, 56, 32, }, - { 0, 1, 0, 1, 60, 33, }, - { 2, 1, 0, 1, 60, 32, }, - { 0, 1, 0, 1, 64, 30, }, - { 2, 1, 0, 1, 64, 32, }, - { 0, 1, 0, 1, 100, 30, }, - { 2, 1, 0, 1, 100, 32, }, - { 0, 1, 0, 1, 104, 33, }, - { 2, 1, 0, 1, 104, 32, }, - { 0, 1, 0, 1, 108, 33, }, - { 2, 1, 0, 1, 108, 32, }, - { 0, 1, 0, 1, 112, 33, }, - { 2, 1, 0, 1, 112, 32, }, - { 0, 1, 0, 1, 116, 33, }, - { 2, 1, 0, 1, 116, 32, }, - { 0, 1, 0, 1, 120, 33, }, - { 2, 1, 0, 1, 120, 32, }, - { 0, 1, 0, 1, 124, 33, }, - { 2, 1, 0, 1, 124, 32, }, - { 0, 1, 0, 1, 128, 33, }, - { 2, 1, 0, 1, 128, 32, }, - { 0, 1, 0, 1, 132, 33, }, - { 2, 1, 0, 1, 132, 32, }, - { 0, 1, 0, 1, 136, 33, }, - { 2, 1, 0, 1, 136, 32, }, - { 0, 1, 0, 1, 140, 31, }, - { 2, 1, 0, 1, 140, 32, }, - { 0, 1, 0, 1, 144, 30, }, - { 2, 1, 0, 1, 144, 63, }, - { 0, 1, 0, 1, 149, 33, }, - { 2, 1, 0, 1, 149, 63, }, - { 0, 1, 0, 1, 153, 33, }, - { 2, 1, 0, 1, 153, 63, }, - { 0, 1, 0, 1, 157, 33, }, - { 2, 1, 0, 1, 157, 63, }, - { 0, 1, 0, 1, 161, 33, }, - { 2, 1, 0, 1, 161, 63, }, - { 0, 1, 0, 1, 165, 33, }, - { 2, 1, 0, 1, 165, 63, }, - { 0, 1, 0, 2, 36, 30, }, - { 2, 1, 0, 2, 36, 32, }, - { 0, 1, 0, 2, 40, 33, }, - { 2, 1, 0, 2, 40, 32, }, - { 0, 1, 0, 2, 44, 33, }, - { 2, 1, 0, 2, 44, 32, }, - { 0, 1, 0, 2, 48, 33, }, - { 2, 1, 0, 2, 48, 32, }, - { 0, 1, 0, 2, 52, 33, }, - { 2, 1, 0, 2, 52, 32, }, - { 0, 1, 0, 2, 56, 33, }, - { 2, 1, 0, 2, 56, 32, }, - { 0, 1, 0, 2, 60, 33, }, - { 2, 1, 0, 2, 60, 32, }, - { 0, 1, 0, 2, 64, 30, }, - { 2, 1, 0, 2, 64, 32, }, - { 0, 1, 0, 2, 100, 30, }, - { 2, 1, 0, 2, 100, 32, }, - { 0, 1, 0, 2, 104, 33, }, - { 2, 1, 0, 2, 104, 32, }, - { 0, 1, 0, 2, 108, 33, }, - { 2, 1, 0, 2, 108, 32, }, - { 0, 1, 0, 2, 112, 33, }, - { 2, 1, 0, 2, 112, 32, }, - { 0, 1, 0, 2, 116, 33, }, - { 2, 1, 0, 2, 116, 32, }, - { 0, 1, 0, 2, 120, 33, }, - { 2, 1, 0, 2, 120, 32, }, - { 0, 1, 0, 2, 124, 33, }, - { 2, 1, 0, 2, 124, 32, }, - { 0, 1, 0, 2, 128, 33, }, - { 2, 1, 0, 2, 128, 32, }, - { 0, 1, 0, 2, 132, 33, }, - { 2, 1, 0, 2, 132, 32, }, - { 0, 1, 0, 2, 136, 33, }, - { 2, 1, 0, 2, 136, 32, }, - { 0, 1, 0, 2, 140, 29, }, - { 2, 1, 0, 2, 140, 32, }, - { 0, 1, 0, 2, 144, 27, }, - { 2, 1, 0, 2, 144, 63, }, - { 0, 1, 0, 2, 149, 33, }, - { 2, 1, 0, 2, 149, 63, }, - { 0, 1, 0, 2, 153, 33, }, - { 2, 1, 0, 2, 153, 63, }, - { 0, 1, 0, 2, 157, 33, }, - { 2, 1, 0, 2, 157, 63, }, - { 0, 1, 0, 2, 161, 33, }, - { 2, 1, 0, 2, 161, 63, }, - { 0, 1, 0, 2, 165, 33, }, - { 2, 1, 0, 2, 165, 63, }, - { 0, 1, 1, 2, 38, 22, }, - { 2, 1, 1, 2, 38, 32, }, - { 0, 1, 1, 2, 46, 32, }, - { 2, 1, 1, 2, 46, 32, }, - { 0, 1, 1, 2, 54, 32, }, - { 2, 1, 1, 2, 54, 32, }, - { 0, 1, 1, 2, 62, 23, }, - { 2, 1, 1, 2, 62, 32, }, - { 0, 1, 1, 2, 102, 21, }, - { 2, 1, 1, 2, 102, 32, }, - { 0, 1, 1, 2, 110, 32, }, - { 2, 1, 1, 2, 110, 32, }, - { 0, 1, 1, 2, 118, 32, }, - { 2, 1, 1, 2, 118, 32, }, - { 0, 1, 1, 2, 126, 32, }, - { 2, 1, 1, 2, 126, 32, }, - { 0, 1, 1, 2, 134, 32, }, - { 2, 1, 1, 2, 134, 32, }, - { 0, 1, 1, 2, 142, 29, }, - { 2, 1, 1, 2, 142, 63, }, - { 0, 1, 1, 2, 151, 32, }, - { 2, 1, 1, 2, 151, 63, }, - { 0, 1, 1, 2, 159, 32, }, - { 2, 1, 1, 2, 159, 63, }, - { 0, 1, 2, 4, 42, 19, }, - { 2, 1, 2, 4, 42, 32, }, - { 0, 1, 2, 4, 58, 22, }, - { 2, 1, 2, 4, 58, 32, }, - { 0, 1, 2, 4, 106, 18, }, - { 2, 1, 2, 4, 106, 32, }, - { 0, 1, 2, 4, 122, 32, }, - { 2, 1, 2, 4, 122, 32, }, - { 0, 1, 2, 4, 138, 28, }, - { 2, 1, 2, 4, 138, 63, }, - { 0, 1, 2, 4, 155, 32, }, - { 2, 1, 2, 4, 155, 63, }, { 1, 0, 0, 0, 1, 34, }, { 3, 0, 0, 0, 1, 30, }, { 4, 0, 0, 0, 1, 34, }, { 5, 0, 0, 0, 1, 30, }, { 6, 0, 0, 0, 1, 30, }, { 7, 0, 0, 0, 1, 30, }, + { 8, 0, 0, 0, 1, 30, }, + { 9, 0, 0, 0, 1, 28, }, + { 10, 0, 0, 0, 1, 30, }, + { 11, 0, 0, 0, 1, 30, }, + { 0, 0, 0, 0, 2, 32, }, + { 2, 0, 0, 0, 2, 30, }, { 1, 0, 0, 0, 2, 34, }, { 3, 0, 0, 0, 2, 32, }, { 4, 0, 0, 0, 2, 34, }, { 5, 0, 0, 0, 2, 30, }, { 6, 0, 0, 0, 2, 32, }, { 7, 0, 0, 0, 2, 30, }, + { 8, 0, 0, 0, 2, 32, }, + { 9, 0, 0, 0, 2, 28, }, + { 10, 0, 0, 0, 2, 30, }, + { 11, 0, 0, 0, 2, 30, }, + { 0, 0, 0, 0, 3, 32, }, + { 2, 0, 0, 0, 3, 30, }, { 1, 0, 0, 0, 3, 34, }, { 3, 0, 0, 0, 3, 32, }, { 4, 0, 0, 0, 3, 34, }, { 5, 0, 0, 0, 3, 30, }, { 6, 0, 0, 0, 3, 32, }, { 7, 0, 0, 0, 3, 30, }, + { 8, 0, 0, 0, 3, 32, }, + { 9, 0, 0, 0, 3, 28, }, + { 10, 0, 0, 0, 3, 30, }, + { 11, 0, 0, 0, 3, 30, }, + { 0, 0, 0, 0, 4, 32, }, + { 2, 0, 0, 0, 4, 30, }, { 1, 0, 0, 0, 4, 34, }, { 3, 0, 0, 0, 4, 32, }, { 4, 0, 0, 0, 4, 34, }, { 5, 0, 0, 0, 4, 30, }, { 6, 0, 0, 0, 4, 32, }, { 7, 0, 0, 0, 4, 30, }, + { 8, 0, 0, 0, 4, 32, }, + { 9, 0, 0, 0, 4, 28, }, + { 10, 0, 0, 0, 4, 30, }, + { 11, 0, 0, 0, 4, 30, }, + { 0, 0, 0, 0, 5, 32, }, + { 2, 0, 0, 0, 5, 30, }, { 1, 0, 0, 0, 5, 34, }, { 3, 0, 0, 0, 5, 32, }, { 4, 0, 0, 0, 5, 34, }, { 5, 0, 0, 0, 5, 30, }, { 6, 0, 0, 0, 5, 32, }, { 7, 0, 0, 0, 5, 30, }, + { 8, 0, 0, 0, 5, 32, }, + { 9, 0, 0, 0, 5, 28, }, + { 10, 0, 0, 0, 5, 30, }, + { 11, 0, 0, 0, 5, 30, }, + { 0, 0, 0, 0, 6, 32, }, + { 2, 0, 0, 0, 6, 30, }, { 1, 0, 0, 0, 6, 34, }, { 3, 0, 0, 0, 6, 32, }, { 4, 0, 0, 0, 6, 34, }, { 5, 0, 0, 0, 6, 30, }, { 6, 0, 0, 0, 6, 32, }, { 7, 0, 0, 0, 6, 30, }, + { 8, 0, 0, 0, 6, 32, }, + { 9, 0, 0, 0, 6, 28, }, + { 10, 0, 0, 0, 6, 30, }, + { 11, 0, 0, 0, 6, 30, }, + { 0, 0, 0, 0, 7, 32, }, + { 2, 0, 0, 0, 7, 30, }, { 1, 0, 0, 0, 7, 34, }, { 3, 0, 0, 0, 7, 32, }, { 4, 0, 0, 0, 7, 34, }, { 5, 0, 0, 0, 7, 30, }, { 6, 0, 0, 0, 7, 32, }, { 7, 0, 0, 0, 7, 30, }, + { 8, 0, 0, 0, 7, 32, }, + { 9, 0, 0, 0, 7, 28, }, + { 10, 0, 0, 0, 7, 30, }, + { 11, 0, 0, 0, 7, 30, }, + { 0, 0, 0, 0, 8, 32, }, + { 2, 0, 0, 0, 8, 30, }, { 1, 0, 0, 0, 8, 34, }, { 3, 0, 0, 0, 8, 32, }, { 4, 0, 0, 0, 8, 34, }, { 5, 0, 0, 0, 8, 30, }, { 6, 0, 0, 0, 8, 32, }, { 7, 0, 0, 0, 8, 30, }, + { 8, 0, 0, 0, 8, 32, }, + { 9, 0, 0, 0, 8, 28, }, + { 10, 0, 0, 0, 8, 30, }, + { 11, 0, 0, 0, 8, 30, }, + { 0, 0, 0, 0, 9, 32, }, + { 2, 0, 0, 0, 9, 30, }, { 1, 0, 0, 0, 9, 34, }, { 3, 0, 0, 0, 9, 32, }, { 4, 0, 0, 0, 9, 34, }, { 5, 0, 0, 0, 9, 30, }, { 6, 0, 0, 0, 9, 32, }, { 7, 0, 0, 0, 9, 30, }, + { 8, 0, 0, 0, 9, 32, }, + { 9, 0, 0, 0, 9, 28, }, + { 10, 0, 0, 0, 9, 30, }, + { 11, 0, 0, 0, 9, 30, }, + { 0, 0, 0, 0, 10, 32, }, + { 2, 0, 0, 0, 10, 30, }, { 1, 0, 0, 0, 10, 34, }, { 3, 0, 0, 0, 10, 32, }, { 4, 0, 0, 0, 10, 34, }, { 5, 0, 0, 0, 10, 30, }, { 6, 0, 0, 0, 10, 32, }, { 7, 0, 0, 0, 10, 30, }, + { 8, 0, 0, 0, 10, 32, }, + { 9, 0, 0, 0, 10, 28, }, + { 10, 0, 0, 0, 10, 30, }, + { 11, 0, 0, 0, 10, 30, }, + { 0, 0, 0, 0, 11, 32, }, + { 2, 0, 0, 0, 11, 30, }, { 1, 0, 0, 0, 11, 34, }, { 3, 0, 0, 0, 11, 32, }, { 4, 0, 0, 0, 11, 34, }, { 5, 0, 0, 0, 11, 30, }, { 6, 0, 0, 0, 11, 32, }, { 7, 0, 0, 0, 11, 30, }, + { 8, 0, 0, 0, 11, 32, }, + { 9, 0, 0, 0, 11, 28, }, + { 10, 0, 0, 0, 11, 30, }, + { 11, 0, 0, 0, 11, 30, }, + { 0, 0, 0, 0, 12, 24, }, + { 2, 0, 0, 0, 12, 30, }, { 1, 0, 0, 0, 12, 34, }, { 3, 0, 0, 0, 12, 24, }, { 4, 0, 0, 0, 12, 34, }, { 5, 0, 0, 0, 12, 30, }, { 6, 0, 0, 0, 12, 24, }, { 7, 0, 0, 0, 12, 30, }, + { 8, 0, 0, 0, 12, 24, }, + { 9, 0, 0, 0, 12, 24, }, + { 10, 0, 0, 0, 12, 30, }, + { 11, 0, 0, 0, 12, 30, }, + { 0, 0, 0, 0, 13, 16, }, + { 2, 0, 0, 0, 13, 30, }, { 1, 0, 0, 0, 13, 34, }, { 3, 0, 0, 0, 13, 16, }, { 4, 0, 0, 0, 13, 34, }, { 5, 0, 0, 0, 13, 30, }, { 6, 0, 0, 0, 13, 16, }, { 7, 0, 0, 0, 13, 30, }, + { 8, 0, 0, 0, 13, 16, }, + { 9, 0, 0, 0, 13, 18, }, + { 10, 0, 0, 0, 13, 30, }, + { 11, 0, 0, 0, 13, 30, }, + { 0, 0, 0, 0, 14, 63, }, + { 2, 0, 0, 0, 14, 63, }, { 1, 0, 0, 0, 14, 34, }, { 3, 0, 0, 0, 14, 63, }, { 4, 0, 0, 0, 14, 63, }, { 5, 0, 0, 0, 14, 63, }, { 6, 0, 0, 0, 14, 63, }, { 7, 0, 0, 0, 14, 63, }, + { 8, 0, 0, 0, 14, 63, }, + { 9, 0, 0, 0, 14, 63, }, + { 10, 0, 0, 0, 14, 63, }, + { 11, 0, 0, 0, 14, 63, }, + { 0, 0, 0, 1, 1, 30, }, + { 2, 0, 0, 1, 1, 30, }, { 1, 0, 0, 1, 1, 34, }, { 3, 0, 0, 1, 1, 30, }, { 4, 0, 0, 1, 1, 32, }, { 5, 0, 0, 1, 1, 30, }, { 6, 0, 0, 1, 1, 30, }, { 7, 0, 0, 1, 1, 30, }, + { 8, 0, 0, 1, 1, 30, }, + { 9, 0, 0, 1, 1, 30, }, + { 10, 0, 0, 1, 1, 30, }, + { 11, 0, 0, 1, 1, 30, }, + { 0, 0, 0, 1, 2, 32, }, + { 2, 0, 0, 1, 2, 30, }, { 1, 0, 0, 1, 2, 34, }, { 3, 0, 0, 1, 2, 32, }, { 4, 0, 0, 1, 2, 34, }, { 5, 0, 0, 1, 2, 30, }, { 6, 0, 0, 1, 2, 32, }, { 7, 0, 0, 1, 2, 30, }, + { 8, 0, 0, 1, 2, 32, }, + { 9, 0, 0, 1, 2, 30, }, + { 10, 0, 0, 1, 2, 30, }, + { 11, 0, 0, 1, 2, 30, }, + { 0, 0, 0, 1, 3, 34, }, + { 2, 0, 0, 1, 3, 30, }, { 1, 0, 0, 1, 3, 34, }, { 3, 0, 0, 1, 3, 34, }, { 4, 0, 0, 1, 3, 34, }, { 5, 0, 0, 1, 3, 30, }, { 6, 0, 0, 1, 3, 34, }, { 7, 0, 0, 1, 3, 30, }, + { 8, 0, 0, 1, 3, 34, }, + { 9, 0, 0, 1, 3, 30, }, + { 10, 0, 0, 1, 3, 30, }, + { 11, 0, 0, 1, 3, 30, }, + { 0, 0, 0, 1, 4, 34, }, + { 2, 0, 0, 1, 4, 30, }, { 1, 0, 0, 1, 4, 34, }, { 3, 0, 0, 1, 4, 34, }, { 4, 0, 0, 1, 4, 34, }, { 5, 0, 0, 1, 4, 30, }, { 6, 0, 0, 1, 4, 34, }, { 7, 0, 0, 1, 4, 30, }, + { 8, 0, 0, 1, 4, 34, }, + { 9, 0, 0, 1, 4, 30, }, + { 10, 0, 0, 1, 4, 30, }, + { 11, 0, 0, 1, 4, 30, }, + { 0, 0, 0, 1, 5, 34, }, + { 2, 0, 0, 1, 5, 30, }, { 1, 0, 0, 1, 5, 34, }, { 3, 0, 0, 1, 5, 34, }, { 4, 0, 0, 1, 5, 34, }, { 5, 0, 0, 1, 5, 30, }, { 6, 0, 0, 1, 5, 34, }, { 7, 0, 0, 1, 5, 30, }, + { 8, 0, 0, 1, 5, 34, }, + { 9, 0, 0, 1, 5, 30, }, + { 10, 0, 0, 1, 5, 30, }, + { 11, 0, 0, 1, 5, 30, }, + { 0, 0, 0, 1, 6, 34, }, + { 2, 0, 0, 1, 6, 30, }, { 1, 0, 0, 1, 6, 34, }, { 3, 0, 0, 1, 6, 34, }, { 4, 0, 0, 1, 6, 34, }, { 5, 0, 0, 1, 6, 30, }, { 6, 0, 0, 1, 6, 34, }, { 7, 0, 0, 1, 6, 30, }, + { 8, 0, 0, 1, 6, 34, }, + { 9, 0, 0, 1, 6, 30, }, + { 10, 0, 0, 1, 6, 30, }, + { 11, 0, 0, 1, 6, 30, }, + { 0, 0, 0, 1, 7, 34, }, + { 2, 0, 0, 1, 7, 30, }, { 1, 0, 0, 1, 7, 34, }, { 3, 0, 0, 1, 7, 34, }, { 4, 0, 0, 1, 7, 34, }, { 5, 0, 0, 1, 7, 30, }, { 6, 0, 0, 1, 7, 34, }, { 7, 0, 0, 1, 7, 30, }, + { 8, 0, 0, 1, 7, 34, }, + { 9, 0, 0, 1, 7, 30, }, + { 10, 0, 0, 1, 7, 30, }, + { 11, 0, 0, 1, 7, 30, }, + { 0, 0, 0, 1, 8, 34, }, + { 2, 0, 0, 1, 8, 30, }, { 1, 0, 0, 1, 8, 34, }, { 3, 0, 0, 1, 8, 34, }, { 4, 0, 0, 1, 8, 34, }, { 5, 0, 0, 1, 8, 30, }, { 6, 0, 0, 1, 8, 34, }, { 7, 0, 0, 1, 8, 30, }, + { 8, 0, 0, 1, 8, 34, }, + { 9, 0, 0, 1, 8, 30, }, + { 10, 0, 0, 1, 8, 30, }, + { 11, 0, 0, 1, 8, 30, }, + { 0, 0, 0, 1, 9, 34, }, + { 2, 0, 0, 1, 9, 30, }, { 1, 0, 0, 1, 9, 34, }, { 3, 0, 0, 1, 9, 34, }, { 4, 0, 0, 1, 9, 34, }, { 5, 0, 0, 1, 9, 30, }, { 6, 0, 0, 1, 9, 34, }, { 7, 0, 0, 1, 9, 30, }, + { 8, 0, 0, 1, 9, 34, }, + { 9, 0, 0, 1, 9, 30, }, + { 10, 0, 0, 1, 9, 30, }, + { 11, 0, 0, 1, 9, 30, }, + { 0, 0, 0, 1, 10, 32, }, + { 2, 0, 0, 1, 10, 30, }, { 1, 0, 0, 1, 10, 34, }, { 3, 0, 0, 1, 10, 32, }, { 4, 0, 0, 1, 10, 34, }, { 5, 0, 0, 1, 10, 30, }, { 6, 0, 0, 1, 10, 32, }, { 7, 0, 0, 1, 10, 30, }, + { 8, 0, 0, 1, 10, 32, }, + { 9, 0, 0, 1, 10, 26, }, + { 10, 0, 0, 1, 10, 30, }, + { 11, 0, 0, 1, 10, 30, }, + { 0, 0, 0, 1, 11, 30, }, + { 2, 0, 0, 1, 11, 30, }, { 1, 0, 0, 1, 11, 34, }, { 3, 0, 0, 1, 11, 30, }, { 4, 0, 0, 1, 11, 34, }, { 5, 0, 0, 1, 11, 30, }, { 6, 0, 0, 1, 11, 30, }, { 7, 0, 0, 1, 11, 30, }, + { 8, 0, 0, 1, 11, 30, }, + { 9, 0, 0, 1, 11, 22, }, + { 10, 0, 0, 1, 11, 30, }, + { 11, 0, 0, 1, 11, 30, }, + { 0, 0, 0, 1, 12, 28, }, + { 2, 0, 0, 1, 12, 30, }, { 1, 0, 0, 1, 12, 34, }, { 3, 0, 0, 1, 12, 28, }, { 4, 0, 0, 1, 12, 34, }, { 5, 0, 0, 1, 12, 30, }, { 6, 0, 0, 1, 12, 28, }, { 7, 0, 0, 1, 12, 30, }, + { 8, 0, 0, 1, 12, 28, }, + { 9, 0, 0, 1, 12, 18, }, + { 10, 0, 0, 1, 12, 30, }, + { 11, 0, 0, 1, 12, 30, }, + { 0, 0, 0, 1, 13, 16, }, + { 2, 0, 0, 1, 13, 30, }, { 1, 0, 0, 1, 13, 34, }, { 3, 0, 0, 1, 13, 16, }, { 4, 0, 0, 1, 13, 32, }, { 5, 0, 0, 1, 13, 30, }, { 6, 0, 0, 1, 13, 16, }, { 7, 0, 0, 1, 13, 30, }, + { 8, 0, 0, 1, 13, 16, }, + { 9, 0, 0, 1, 13, 2, }, + { 10, 0, 0, 1, 13, 30, }, + { 11, 0, 0, 1, 13, 30, }, + { 0, 0, 0, 1, 14, 63, }, + { 2, 0, 0, 1, 14, 63, }, { 1, 0, 0, 1, 14, 63, }, { 3, 0, 0, 1, 14, 63, }, { 4, 0, 0, 1, 14, 63, }, { 5, 0, 0, 1, 14, 63, }, { 6, 0, 0, 1, 14, 63, }, { 7, 0, 0, 1, 14, 63, }, + { 8, 0, 0, 1, 14, 63, }, + { 9, 0, 0, 1, 14, 63, }, + { 10, 0, 0, 1, 14, 63, }, + { 11, 0, 0, 1, 14, 63, }, + { 0, 0, 0, 2, 1, 26, }, + { 2, 0, 0, 2, 1, 30, }, { 1, 0, 0, 2, 1, 34, }, { 3, 0, 0, 2, 1, 26, }, { 4, 0, 0, 2, 1, 32, }, { 5, 0, 0, 2, 1, 30, }, { 6, 0, 0, 2, 1, 26, }, { 7, 0, 0, 2, 1, 30, }, + { 8, 0, 0, 2, 1, 26, }, + { 9, 0, 0, 2, 1, 30, }, + { 10, 0, 0, 2, 1, 30, }, + { 11, 0, 0, 2, 1, 30, }, + { 0, 0, 0, 2, 2, 30, }, + { 2, 0, 0, 2, 2, 30, }, { 1, 0, 0, 2, 2, 34, }, { 3, 0, 0, 2, 2, 30, }, { 4, 0, 0, 2, 2, 34, }, { 5, 0, 0, 2, 2, 30, }, { 6, 0, 0, 2, 2, 30, }, { 7, 0, 0, 2, 2, 30, }, + { 8, 0, 0, 2, 2, 30, }, + { 9, 0, 0, 2, 2, 30, }, + { 10, 0, 0, 2, 2, 30, }, + { 11, 0, 0, 2, 2, 30, }, + { 0, 0, 0, 2, 3, 32, }, + { 2, 0, 0, 2, 3, 30, }, { 1, 0, 0, 2, 3, 34, }, { 3, 0, 0, 2, 3, 32, }, { 4, 0, 0, 2, 3, 34, }, { 5, 0, 0, 2, 3, 30, }, { 6, 0, 0, 2, 3, 32, }, { 7, 0, 0, 2, 3, 30, }, + { 8, 0, 0, 2, 3, 32, }, + { 9, 0, 0, 2, 3, 30, }, + { 10, 0, 0, 2, 3, 30, }, + { 11, 0, 0, 2, 3, 30, }, + { 0, 0, 0, 2, 4, 34, }, + { 2, 0, 0, 2, 4, 30, }, { 1, 0, 0, 2, 4, 34, }, { 3, 0, 0, 2, 4, 34, }, { 4, 0, 0, 2, 4, 34, }, { 5, 0, 0, 2, 4, 30, }, { 6, 0, 0, 2, 4, 34, }, { 7, 0, 0, 2, 4, 30, }, + { 8, 0, 0, 2, 4, 34, }, + { 9, 0, 0, 2, 4, 30, }, + { 10, 0, 0, 2, 4, 30, }, + { 11, 0, 0, 2, 4, 30, }, + { 0, 0, 0, 2, 5, 34, }, + { 2, 0, 0, 2, 5, 30, }, { 1, 0, 0, 2, 5, 34, }, { 3, 0, 0, 2, 5, 34, }, { 4, 0, 0, 2, 5, 34, }, { 5, 0, 0, 2, 5, 30, }, { 6, 0, 0, 2, 5, 34, }, { 7, 0, 0, 2, 5, 30, }, + { 8, 0, 0, 2, 5, 34, }, + { 9, 0, 0, 2, 5, 30, }, + { 10, 0, 0, 2, 5, 30, }, + { 11, 0, 0, 2, 5, 30, }, + { 0, 0, 0, 2, 6, 34, }, + { 2, 0, 0, 2, 6, 30, }, { 1, 0, 0, 2, 6, 34, }, { 3, 0, 0, 2, 6, 34, }, { 4, 0, 0, 2, 6, 34, }, { 5, 0, 0, 2, 6, 30, }, { 6, 0, 0, 2, 6, 34, }, { 7, 0, 0, 2, 6, 30, }, + { 8, 0, 0, 2, 6, 34, }, + { 9, 0, 0, 2, 6, 30, }, + { 10, 0, 0, 2, 6, 30, }, + { 11, 0, 0, 2, 6, 30, }, + { 0, 0, 0, 2, 7, 34, }, + { 2, 0, 0, 2, 7, 30, }, { 1, 0, 0, 2, 7, 34, }, { 3, 0, 0, 2, 7, 34, }, { 4, 0, 0, 2, 7, 34, }, { 5, 0, 0, 2, 7, 30, }, { 6, 0, 0, 2, 7, 34, }, { 7, 0, 0, 2, 7, 30, }, + { 8, 0, 0, 2, 7, 34, }, + { 9, 0, 0, 2, 7, 30, }, + { 10, 0, 0, 2, 7, 30, }, + { 11, 0, 0, 2, 7, 30, }, + { 0, 0, 0, 2, 8, 34, }, + { 2, 0, 0, 2, 8, 30, }, { 1, 0, 0, 2, 8, 34, }, { 3, 0, 0, 2, 8, 34, }, { 4, 0, 0, 2, 8, 34, }, { 5, 0, 0, 2, 8, 30, }, { 6, 0, 0, 2, 8, 34, }, { 7, 0, 0, 2, 8, 30, }, + { 8, 0, 0, 2, 8, 34, }, + { 9, 0, 0, 2, 8, 30, }, + { 10, 0, 0, 2, 8, 30, }, + { 11, 0, 0, 2, 8, 30, }, + { 0, 0, 0, 2, 9, 32, }, + { 2, 0, 0, 2, 9, 30, }, { 1, 0, 0, 2, 9, 34, }, { 3, 0, 0, 2, 9, 32, }, { 4, 0, 0, 2, 9, 34, }, { 5, 0, 0, 2, 9, 30, }, { 6, 0, 0, 2, 9, 32, }, { 7, 0, 0, 2, 9, 30, }, + { 8, 0, 0, 2, 9, 32, }, + { 9, 0, 0, 2, 9, 30, }, + { 10, 0, 0, 2, 9, 30, }, + { 11, 0, 0, 2, 9, 30, }, + { 0, 0, 0, 2, 10, 30, }, + { 2, 0, 0, 2, 10, 30, }, { 1, 0, 0, 2, 10, 34, }, { 3, 0, 0, 2, 10, 30, }, { 4, 0, 0, 2, 10, 34, }, { 5, 0, 0, 2, 10, 30, }, { 6, 0, 0, 2, 10, 30, }, { 7, 0, 0, 2, 10, 30, }, + { 8, 0, 0, 2, 10, 30, }, + { 9, 0, 0, 2, 10, 24, }, + { 10, 0, 0, 2, 10, 30, }, + { 11, 0, 0, 2, 10, 30, }, + { 0, 0, 0, 2, 11, 28, }, + { 2, 0, 0, 2, 11, 30, }, { 1, 0, 0, 2, 11, 34, }, { 3, 0, 0, 2, 11, 28, }, { 4, 0, 0, 2, 11, 34, }, { 5, 0, 0, 2, 11, 30, }, { 6, 0, 0, 2, 11, 28, }, { 7, 0, 0, 2, 11, 30, }, + { 8, 0, 0, 2, 11, 28, }, + { 9, 0, 0, 2, 11, 20, }, + { 10, 0, 0, 2, 11, 30, }, + { 11, 0, 0, 2, 11, 30, }, + { 0, 0, 0, 2, 12, 26, }, + { 2, 0, 0, 2, 12, 30, }, { 1, 0, 0, 2, 12, 34, }, { 3, 0, 0, 2, 12, 26, }, { 4, 0, 0, 2, 12, 34, }, { 5, 0, 0, 2, 12, 30, }, { 6, 0, 0, 2, 12, 26, }, { 7, 0, 0, 2, 12, 30, }, + { 8, 0, 0, 2, 12, 26, }, + { 9, 0, 0, 2, 12, 16, }, + { 10, 0, 0, 2, 12, 30, }, + { 11, 0, 0, 2, 12, 30, }, + { 0, 0, 0, 2, 13, 12, }, + { 2, 0, 0, 2, 13, 30, }, { 1, 0, 0, 2, 13, 34, }, { 3, 0, 0, 2, 13, 12, }, { 4, 0, 0, 2, 13, 32, }, { 5, 0, 0, 2, 13, 30, }, { 6, 0, 0, 2, 13, 12, }, { 7, 0, 0, 2, 13, 30, }, + { 8, 0, 0, 2, 13, 12, }, + { 9, 0, 0, 2, 13, 0, }, + { 10, 0, 0, 2, 13, 30, }, + { 11, 0, 0, 2, 13, 30, }, + { 0, 0, 0, 2, 14, 63, }, + { 2, 0, 0, 2, 14, 63, }, { 1, 0, 0, 2, 14, 63, }, { 3, 0, 0, 2, 14, 63, }, { 4, 0, 0, 2, 14, 63, }, { 5, 0, 0, 2, 14, 63, }, { 6, 0, 0, 2, 14, 63, }, { 7, 0, 0, 2, 14, 63, }, + { 8, 0, 0, 2, 14, 63, }, + { 9, 0, 0, 2, 14, 63, }, + { 10, 0, 0, 2, 14, 63, }, + { 11, 0, 0, 2, 14, 63, }, + { 0, 0, 1, 2, 1, 63, }, + { 2, 0, 1, 2, 1, 63, }, { 1, 0, 1, 2, 1, 63, }, { 3, 0, 1, 2, 1, 63, }, { 4, 0, 1, 2, 1, 63, }, { 5, 0, 1, 2, 1, 63, }, { 6, 0, 1, 2, 1, 63, }, { 7, 0, 1, 2, 1, 63, }, + { 8, 0, 1, 2, 1, 63, }, + { 9, 0, 1, 2, 1, 63, }, + { 10, 0, 1, 2, 1, 63, }, + { 11, 0, 1, 2, 1, 63, }, + { 0, 0, 1, 2, 2, 63, }, + { 2, 0, 1, 2, 2, 63, }, { 1, 0, 1, 2, 2, 63, }, { 3, 0, 1, 2, 2, 63, }, { 4, 0, 1, 2, 2, 63, }, { 5, 0, 1, 2, 2, 63, }, { 6, 0, 1, 2, 2, 63, }, { 7, 0, 1, 2, 2, 63, }, + { 8, 0, 1, 2, 2, 63, }, + { 9, 0, 1, 2, 2, 63, }, + { 10, 0, 1, 2, 2, 63, }, + { 11, 0, 1, 2, 2, 63, }, + { 0, 0, 1, 2, 3, 26, }, + { 2, 0, 1, 2, 3, 30, }, { 1, 0, 1, 2, 3, 30, }, { 3, 0, 1, 2, 3, 26, }, { 4, 0, 1, 2, 3, 30, }, { 5, 0, 1, 2, 3, 30, }, { 6, 0, 1, 2, 3, 26, }, { 7, 0, 1, 2, 3, 30, }, + { 8, 0, 1, 2, 3, 26, }, + { 9, 0, 1, 2, 3, 29, }, + { 10, 0, 1, 2, 3, 30, }, + { 11, 0, 1, 2, 3, 30, }, + { 0, 0, 1, 2, 4, 26, }, + { 2, 0, 1, 2, 4, 30, }, { 1, 0, 1, 2, 4, 30, }, { 3, 0, 1, 2, 4, 26, }, { 4, 0, 1, 2, 4, 30, }, { 5, 0, 1, 2, 4, 30, }, { 6, 0, 1, 2, 4, 26, }, { 7, 0, 1, 2, 4, 30, }, + { 8, 0, 1, 2, 4, 26, }, + { 9, 0, 1, 2, 4, 29, }, + { 10, 0, 1, 2, 4, 30, }, + { 11, 0, 1, 2, 4, 30, }, + { 0, 0, 1, 2, 5, 30, }, + { 2, 0, 1, 2, 5, 30, }, { 1, 0, 1, 2, 5, 30, }, { 3, 0, 1, 2, 5, 30, }, { 4, 0, 1, 2, 5, 30, }, { 5, 0, 1, 2, 5, 30, }, { 6, 0, 1, 2, 5, 30, }, { 7, 0, 1, 2, 5, 30, }, + { 8, 0, 1, 2, 5, 30, }, + { 9, 0, 1, 2, 5, 29, }, + { 10, 0, 1, 2, 5, 30, }, + { 11, 0, 1, 2, 5, 30, }, + { 0, 0, 1, 2, 6, 30, }, + { 2, 0, 1, 2, 6, 30, }, { 1, 0, 1, 2, 6, 30, }, { 3, 0, 1, 2, 6, 30, }, { 4, 0, 1, 2, 6, 30, }, { 5, 0, 1, 2, 6, 30, }, { 6, 0, 1, 2, 6, 30, }, { 7, 0, 1, 2, 6, 30, }, + { 8, 0, 1, 2, 6, 30, }, + { 9, 0, 1, 2, 6, 29, }, + { 10, 0, 1, 2, 6, 30, }, + { 11, 0, 1, 2, 6, 30, }, + { 0, 0, 1, 2, 7, 30, }, + { 2, 0, 1, 2, 7, 30, }, { 1, 0, 1, 2, 7, 30, }, { 3, 0, 1, 2, 7, 30, }, { 4, 0, 1, 2, 7, 30, }, { 5, 0, 1, 2, 7, 30, }, { 6, 0, 1, 2, 7, 30, }, { 7, 0, 1, 2, 7, 30, }, + { 8, 0, 1, 2, 7, 30, }, + { 9, 0, 1, 2, 7, 29, }, + { 10, 0, 1, 2, 7, 30, }, + { 11, 0, 1, 2, 7, 30, }, + { 0, 0, 1, 2, 8, 26, }, + { 2, 0, 1, 2, 8, 30, }, { 1, 0, 1, 2, 8, 30, }, { 3, 0, 1, 2, 8, 26, }, { 4, 0, 1, 2, 8, 30, }, { 5, 0, 1, 2, 8, 30, }, { 6, 0, 1, 2, 8, 26, }, { 7, 0, 1, 2, 8, 30, }, + { 8, 0, 1, 2, 8, 26, }, + { 9, 0, 1, 2, 8, 25, }, + { 10, 0, 1, 2, 8, 30, }, + { 11, 0, 1, 2, 8, 30, }, + { 0, 0, 1, 2, 9, 26, }, + { 2, 0, 1, 2, 9, 30, }, { 1, 0, 1, 2, 9, 30, }, { 3, 0, 1, 2, 9, 26, }, { 4, 0, 1, 2, 9, 30, }, { 5, 0, 1, 2, 9, 30, }, { 6, 0, 1, 2, 9, 26, }, { 7, 0, 1, 2, 9, 30, }, + { 8, 0, 1, 2, 9, 26, }, + { 9, 0, 1, 2, 9, 21, }, + { 10, 0, 1, 2, 9, 30, }, + { 11, 0, 1, 2, 9, 30, }, + { 0, 0, 1, 2, 10, 28, }, + { 2, 0, 1, 2, 10, 30, }, { 1, 0, 1, 2, 10, 30, }, { 3, 0, 1, 2, 10, 28, }, { 4, 0, 1, 2, 10, 30, }, { 5, 0, 1, 2, 10, 30, }, { 6, 0, 1, 2, 10, 28, }, { 7, 0, 1, 2, 10, 30, }, + { 8, 0, 1, 2, 10, 28, }, + { 9, 0, 1, 2, 10, 17, }, + { 10, 0, 1, 2, 10, 30, }, + { 11, 0, 1, 2, 10, 30, }, + { 0, 0, 1, 2, 11, 20, }, + { 2, 0, 1, 2, 11, 30, }, { 1, 0, 1, 2, 11, 30, }, { 3, 0, 1, 2, 11, 20, }, { 4, 0, 1, 2, 11, 30, }, { 5, 0, 1, 2, 11, 30, }, { 6, 0, 1, 2, 11, 20, }, { 7, 0, 1, 2, 11, 30, }, + { 8, 0, 1, 2, 11, 20, }, + { 9, 0, 1, 2, 11, 5, }, + { 10, 0, 1, 2, 11, 30, }, + { 11, 0, 1, 2, 11, 30, }, + { 0, 0, 1, 2, 12, 63, }, + { 2, 0, 1, 2, 12, 63, }, { 1, 0, 1, 2, 12, 63, }, { 3, 0, 1, 2, 12, 63, }, { 4, 0, 1, 2, 12, 63, }, { 5, 0, 1, 2, 12, 63, }, { 6, 0, 1, 2, 12, 63, }, { 7, 0, 1, 2, 12, 63, }, + { 8, 0, 1, 2, 12, 63, }, + { 9, 0, 1, 2, 12, 63, }, + { 10, 0, 1, 2, 12, 63, }, + { 11, 0, 1, 2, 12, 63, }, + { 0, 0, 1, 2, 13, 63, }, + { 2, 0, 1, 2, 13, 63, }, { 1, 0, 1, 2, 13, 63, }, { 3, 0, 1, 2, 13, 63, }, { 4, 0, 1, 2, 13, 63, }, { 5, 0, 1, 2, 13, 63, }, { 6, 0, 1, 2, 13, 63, }, { 7, 0, 1, 2, 13, 63, }, + { 8, 0, 1, 2, 13, 63, }, + { 9, 0, 1, 2, 13, 63, }, + { 10, 0, 1, 2, 13, 63, }, + { 11, 0, 1, 2, 13, 63, }, + { 0, 0, 1, 2, 14, 63, }, + { 2, 0, 1, 2, 14, 63, }, { 1, 0, 1, 2, 14, 63, }, { 3, 0, 1, 2, 14, 63, }, { 4, 0, 1, 2, 14, 63, }, { 5, 0, 1, 2, 14, 63, }, { 6, 0, 1, 2, 14, 63, }, { 7, 0, 1, 2, 14, 63, }, + { 8, 0, 1, 2, 14, 63, }, + { 9, 0, 1, 2, 14, 63, }, + { 10, 0, 1, 2, 14, 63, }, + { 11, 0, 1, 2, 14, 63, }, + { 0, 1, 0, 1, 36, 31, }, + { 2, 1, 0, 1, 36, 32, }, { 1, 1, 0, 1, 36, 33, }, { 3, 1, 0, 1, 36, 31, }, { 4, 1, 0, 1, 36, 29, }, { 5, 1, 0, 1, 36, 32, }, - { 6, 1, 0, 1, 36, 29, }, + { 6, 1, 0, 1, 36, 31, }, { 7, 1, 0, 1, 36, 27, }, + { 8, 1, 0, 1, 36, 31, }, + { 9, 1, 0, 1, 36, 29, }, + { 10, 1, 0, 1, 36, 63, }, + { 11, 1, 0, 1, 36, 32, }, + { 0, 1, 0, 1, 40, 33, }, + { 2, 1, 0, 1, 40, 32, }, { 1, 1, 0, 1, 40, 33, }, { 3, 1, 0, 1, 40, 31, }, { 4, 1, 0, 1, 40, 28, }, { 5, 1, 0, 1, 40, 32, }, - { 6, 1, 0, 1, 40, 29, }, + { 6, 1, 0, 1, 40, 33, }, { 7, 1, 0, 1, 40, 27, }, + { 8, 1, 0, 1, 40, 31, }, + { 9, 1, 0, 1, 40, 29, }, + { 10, 1, 0, 1, 40, 63, }, + { 11, 1, 0, 1, 40, 32, }, + { 0, 1, 0, 1, 44, 33, }, + { 2, 1, 0, 1, 44, 32, }, { 1, 1, 0, 1, 44, 33, }, { 3, 1, 0, 1, 44, 31, }, { 4, 1, 0, 1, 44, 28, }, { 5, 1, 0, 1, 44, 32, }, - { 6, 1, 0, 1, 44, 30, }, + { 6, 1, 0, 1, 44, 33, }, { 7, 1, 0, 1, 44, 27, }, + { 8, 1, 0, 1, 44, 31, }, + { 9, 1, 0, 1, 44, 29, }, + { 10, 1, 0, 1, 44, 63, }, + { 11, 1, 0, 1, 44, 32, }, + { 0, 1, 0, 1, 48, 31, }, + { 2, 1, 0, 1, 48, 32, }, { 1, 1, 0, 1, 48, 33, }, { 3, 1, 0, 1, 48, 31, }, { 4, 1, 0, 1, 48, 27, }, { 5, 1, 0, 1, 48, 32, }, - { 6, 1, 0, 1, 48, 30, }, + { 6, 1, 0, 1, 48, 31, }, { 7, 1, 0, 1, 48, 27, }, + { 8, 1, 0, 1, 48, 31, }, + { 9, 1, 0, 1, 48, 29, }, + { 10, 1, 0, 1, 48, 63, }, + { 11, 1, 0, 1, 48, 32, }, + { 0, 1, 0, 1, 52, 33, }, + { 2, 1, 0, 1, 52, 32, }, { 1, 1, 0, 1, 52, 33, }, { 3, 1, 0, 1, 52, 32, }, { 4, 1, 0, 1, 52, 16, }, { 5, 1, 0, 1, 52, 32, }, - { 6, 1, 0, 1, 52, 30, }, + { 6, 1, 0, 1, 52, 33, }, { 7, 1, 0, 1, 52, 27, }, + { 8, 1, 0, 1, 52, 33, }, + { 9, 1, 0, 1, 52, 29, }, + { 10, 1, 0, 1, 52, 63, }, + { 11, 1, 0, 1, 52, 32, }, + { 0, 1, 0, 1, 56, 33, }, + { 2, 1, 0, 1, 56, 32, }, { 1, 1, 0, 1, 56, 33, }, { 3, 1, 0, 1, 56, 32, }, { 4, 1, 0, 1, 56, 33, }, { 5, 1, 0, 1, 56, 32, }, - { 6, 1, 0, 1, 56, 30, }, + { 6, 1, 0, 1, 56, 33, }, { 7, 1, 0, 1, 56, 27, }, + { 8, 1, 0, 1, 56, 33, }, + { 9, 1, 0, 1, 56, 29, }, + { 10, 1, 0, 1, 56, 63, }, + { 11, 1, 0, 1, 56, 32, }, + { 0, 1, 0, 1, 60, 33, }, + { 2, 1, 0, 1, 60, 32, }, { 1, 1, 0, 1, 60, 33, }, { 3, 1, 0, 1, 60, 32, }, { 4, 1, 0, 1, 60, 33, }, { 5, 1, 0, 1, 60, 32, }, - { 6, 1, 0, 1, 60, 30, }, + { 6, 1, 0, 1, 60, 33, }, { 7, 1, 0, 1, 60, 27, }, + { 8, 1, 0, 1, 60, 33, }, + { 9, 1, 0, 1, 60, 29, }, + { 10, 1, 0, 1, 60, 63, }, + { 11, 1, 0, 1, 60, 32, }, + { 0, 1, 0, 1, 64, 30, }, + { 2, 1, 0, 1, 64, 32, }, { 1, 1, 0, 1, 64, 33, }, { 3, 1, 0, 1, 64, 30, }, { 4, 1, 0, 1, 64, 33, }, { 5, 1, 0, 1, 64, 32, }, - { 6, 1, 0, 1, 64, 29, }, + { 6, 1, 0, 1, 64, 30, }, { 7, 1, 0, 1, 64, 27, }, + { 8, 1, 0, 1, 64, 30, }, + { 9, 1, 0, 1, 64, 29, }, + { 10, 1, 0, 1, 64, 63, }, + { 11, 1, 0, 1, 64, 32, }, + { 0, 1, 0, 1, 100, 30, }, + { 2, 1, 0, 1, 100, 32, }, { 1, 1, 0, 1, 100, 33, }, { 3, 1, 0, 1, 100, 30, }, { 4, 1, 0, 1, 100, 33, }, { 5, 1, 0, 1, 100, 32, }, - { 6, 1, 0, 1, 100, 30, }, + { 6, 1, 0, 1, 100, 33, }, { 7, 1, 0, 1, 100, 27, }, + { 8, 1, 0, 1, 100, 30, }, + { 9, 1, 0, 1, 100, 63, }, + { 10, 1, 0, 1, 100, 63, }, + { 11, 1, 0, 1, 100, 32, }, + { 0, 1, 0, 1, 104, 33, }, + { 2, 1, 0, 1, 104, 32, }, { 1, 1, 0, 1, 104, 33, }, { 3, 1, 0, 1, 104, 33, }, { 4, 1, 0, 1, 104, 33, }, { 5, 1, 0, 1, 104, 32, }, - { 6, 1, 0, 1, 104, 30, }, + { 6, 1, 0, 1, 104, 33, }, { 7, 1, 0, 1, 104, 27, }, + { 8, 1, 0, 1, 104, 33, }, + { 9, 1, 0, 1, 104, 63, }, + { 10, 1, 0, 1, 104, 63, }, + { 11, 1, 0, 1, 104, 32, }, + { 0, 1, 0, 1, 108, 33, }, + { 2, 1, 0, 1, 108, 32, }, { 1, 1, 0, 1, 108, 33, }, { 3, 1, 0, 1, 108, 33, }, { 4, 1, 0, 1, 108, 33, }, { 5, 1, 0, 1, 108, 32, }, - { 6, 1, 0, 1, 108, 30, }, + { 6, 1, 0, 1, 108, 33, }, { 7, 1, 0, 1, 108, 27, }, + { 8, 1, 0, 1, 108, 33, }, + { 9, 1, 0, 1, 108, 63, }, + { 10, 1, 0, 1, 108, 63, }, + { 11, 1, 0, 1, 108, 32, }, + { 0, 1, 0, 1, 112, 33, }, + { 2, 1, 0, 1, 112, 32, }, { 1, 1, 0, 1, 112, 33, }, { 3, 1, 0, 1, 112, 33, }, { 4, 1, 0, 1, 112, 33, }, { 5, 1, 0, 1, 112, 32, }, - { 6, 1, 0, 1, 112, 30, }, + { 6, 1, 0, 1, 112, 33, }, { 7, 1, 0, 1, 112, 27, }, + { 8, 1, 0, 1, 112, 33, }, + { 9, 1, 0, 1, 112, 63, }, + { 10, 1, 0, 1, 112, 63, }, + { 11, 1, 0, 1, 112, 32, }, + { 0, 1, 0, 1, 116, 33, }, + { 2, 1, 0, 1, 116, 32, }, { 1, 1, 0, 1, 116, 33, }, { 3, 1, 0, 1, 116, 33, }, { 4, 1, 0, 1, 116, 33, }, { 5, 1, 0, 1, 116, 32, }, - { 6, 1, 0, 1, 116, 30, }, + { 6, 1, 0, 1, 116, 33, }, { 7, 1, 0, 1, 116, 27, }, + { 8, 1, 0, 1, 116, 33, }, + { 9, 1, 0, 1, 116, 63, }, + { 10, 1, 0, 1, 116, 63, }, + { 11, 1, 0, 1, 116, 32, }, + { 0, 1, 0, 1, 120, 33, }, + { 2, 1, 0, 1, 120, 32, }, { 1, 1, 0, 1, 120, 33, }, { 3, 1, 0, 1, 120, 63, }, { 4, 1, 0, 1, 120, 33, }, { 5, 1, 0, 1, 120, 63, }, - { 6, 1, 0, 1, 120, 30, }, + { 6, 1, 0, 1, 120, 33, }, { 7, 1, 0, 1, 120, 27, }, + { 8, 1, 0, 1, 120, 33, }, + { 9, 1, 0, 1, 120, 63, }, + { 10, 1, 0, 1, 120, 63, }, + { 11, 1, 0, 1, 120, 32, }, + { 0, 1, 0, 1, 124, 33, }, + { 2, 1, 0, 1, 124, 32, }, { 1, 1, 0, 1, 124, 33, }, { 3, 1, 0, 1, 124, 63, }, { 4, 1, 0, 1, 124, 33, }, { 5, 1, 0, 1, 124, 63, }, - { 6, 1, 0, 1, 124, 30, }, + { 6, 1, 0, 1, 124, 33, }, { 7, 1, 0, 1, 124, 27, }, + { 8, 1, 0, 1, 124, 33, }, + { 9, 1, 0, 1, 124, 63, }, + { 10, 1, 0, 1, 124, 63, }, + { 11, 1, 0, 1, 124, 32, }, + { 0, 1, 0, 1, 128, 33, }, + { 2, 1, 0, 1, 128, 32, }, { 1, 1, 0, 1, 128, 33, }, { 3, 1, 0, 1, 128, 63, }, - { 4, 1, 0, 1, 128, 63, }, + { 4, 1, 0, 1, 128, 33, }, { 5, 1, 0, 1, 128, 63, }, - { 6, 1, 0, 1, 128, 30, }, + { 6, 1, 0, 1, 128, 33, }, { 7, 1, 0, 1, 128, 27, }, + { 8, 1, 0, 1, 128, 33, }, + { 9, 1, 0, 1, 128, 63, }, + { 10, 1, 0, 1, 128, 63, }, + { 11, 1, 0, 1, 128, 32, }, + { 0, 1, 0, 1, 132, 33, }, + { 2, 1, 0, 1, 132, 32, }, { 1, 1, 0, 1, 132, 33, }, { 3, 1, 0, 1, 132, 33, }, - { 4, 1, 0, 1, 132, 63, }, + { 4, 1, 0, 1, 132, 33, }, { 5, 1, 0, 1, 132, 32, }, - { 6, 1, 0, 1, 132, 30, }, + { 6, 1, 0, 1, 132, 33, }, { 7, 1, 0, 1, 132, 27, }, + { 8, 1, 0, 1, 132, 33, }, + { 9, 1, 0, 1, 132, 63, }, + { 10, 1, 0, 1, 132, 63, }, + { 11, 1, 0, 1, 132, 32, }, + { 0, 1, 0, 1, 136, 33, }, + { 2, 1, 0, 1, 136, 32, }, { 1, 1, 0, 1, 136, 33, }, { 3, 1, 0, 1, 136, 33, }, - { 4, 1, 0, 1, 136, 63, }, + { 4, 1, 0, 1, 136, 33, }, { 5, 1, 0, 1, 136, 32, }, - { 6, 1, 0, 1, 136, 30, }, - { 7, 1, 0, 1, 136, 63, }, + { 6, 1, 0, 1, 136, 33, }, + { 7, 1, 0, 1, 136, 27, }, + { 8, 1, 0, 1, 136, 33, }, + { 9, 1, 0, 1, 136, 63, }, + { 10, 1, 0, 1, 136, 63, }, + { 11, 1, 0, 1, 136, 32, }, + { 0, 1, 0, 1, 140, 31, }, + { 2, 1, 0, 1, 140, 32, }, { 1, 1, 0, 1, 140, 33, }, { 3, 1, 0, 1, 140, 31, }, - { 4, 1, 0, 1, 140, 63, }, + { 4, 1, 0, 1, 140, 33, }, { 5, 1, 0, 1, 140, 32, }, - { 6, 1, 0, 1, 140, 30, }, - { 7, 1, 0, 1, 140, 63, }, + { 6, 1, 0, 1, 140, 33, }, + { 7, 1, 0, 1, 140, 27, }, + { 8, 1, 0, 1, 140, 31, }, + { 9, 1, 0, 1, 140, 63, }, + { 10, 1, 0, 1, 140, 63, }, + { 11, 1, 0, 1, 140, 32, }, + { 0, 1, 0, 1, 144, 30, }, + { 2, 1, 0, 1, 144, 63, }, { 1, 1, 0, 1, 144, 63, }, { 3, 1, 0, 1, 144, 30, }, - { 4, 1, 0, 1, 144, 63, }, + { 4, 1, 0, 1, 144, 33, }, { 5, 1, 0, 1, 144, 63, }, - { 6, 1, 0, 1, 144, 30, }, + { 6, 1, 0, 1, 144, 33, }, { 7, 1, 0, 1, 144, 63, }, + { 8, 1, 0, 1, 144, 30, }, + { 9, 1, 0, 1, 144, 63, }, + { 10, 1, 0, 1, 144, 63, }, + { 11, 1, 0, 1, 144, 32, }, + { 0, 1, 0, 1, 149, 33, }, + { 2, 1, 0, 1, 149, 14, }, { 1, 1, 0, 1, 149, 63, }, { 3, 1, 0, 1, 149, 30, }, { 4, 1, 0, 1, 149, 33, }, { 5, 1, 0, 1, 149, 33, }, - { 6, 1, 0, 1, 149, 30, }, + { 6, 1, 0, 1, 149, 33, }, { 7, 1, 0, 1, 149, 27, }, + { 8, 1, 0, 1, 149, 33, }, + { 9, 1, 0, 1, 149, 30, }, + { 10, 1, 0, 1, 149, 14, }, + { 11, 1, 0, 1, 149, 31, }, + { 0, 1, 0, 1, 153, 33, }, + { 2, 1, 0, 1, 153, 14, }, { 1, 1, 0, 1, 153, 63, }, { 3, 1, 0, 1, 153, 33, }, { 4, 1, 0, 1, 153, 33, }, { 5, 1, 0, 1, 153, 33, }, - { 6, 1, 0, 1, 153, 30, }, + { 6, 1, 0, 1, 153, 33, }, { 7, 1, 0, 1, 153, 27, }, + { 8, 1, 0, 1, 153, 33, }, + { 9, 1, 0, 1, 153, 30, }, + { 10, 1, 0, 1, 153, 14, }, + { 11, 1, 0, 1, 153, 31, }, + { 0, 1, 0, 1, 157, 33, }, + { 2, 1, 0, 1, 157, 14, }, { 1, 1, 0, 1, 157, 63, }, { 3, 1, 0, 1, 157, 33, }, { 4, 1, 0, 1, 157, 33, }, { 5, 1, 0, 1, 157, 33, }, - { 6, 1, 0, 1, 157, 30, }, + { 6, 1, 0, 1, 157, 33, }, { 7, 1, 0, 1, 157, 27, }, + { 8, 1, 0, 1, 157, 33, }, + { 9, 1, 0, 1, 157, 30, }, + { 10, 1, 0, 1, 157, 14, }, + { 11, 1, 0, 1, 157, 31, }, + { 0, 1, 0, 1, 161, 33, }, + { 2, 1, 0, 1, 161, 14, }, { 1, 1, 0, 1, 161, 63, }, { 3, 1, 0, 1, 161, 33, }, { 4, 1, 0, 1, 161, 31, }, { 5, 1, 0, 1, 161, 33, }, - { 6, 1, 0, 1, 161, 30, }, + { 6, 1, 0, 1, 161, 33, }, { 7, 1, 0, 1, 161, 27, }, + { 8, 1, 0, 1, 161, 33, }, + { 9, 1, 0, 1, 161, 30, }, + { 10, 1, 0, 1, 161, 14, }, + { 11, 1, 0, 1, 161, 31, }, + { 0, 1, 0, 1, 165, 33, }, + { 2, 1, 0, 1, 165, 14, }, { 1, 1, 0, 1, 165, 63, }, { 3, 1, 0, 1, 165, 33, }, - { 4, 1, 0, 1, 165, 63, }, + { 4, 1, 0, 1, 165, 33, }, { 5, 1, 0, 1, 165, 33, }, - { 6, 1, 0, 1, 165, 30, }, + { 6, 1, 0, 1, 165, 33, }, { 7, 1, 0, 1, 165, 27, }, + { 8, 1, 0, 1, 165, 30, }, + { 9, 1, 0, 1, 165, 30, }, + { 10, 1, 0, 1, 165, 14, }, + { 11, 1, 0, 1, 165, 31, }, + { 0, 1, 0, 2, 36, 30, }, + { 2, 1, 0, 2, 36, 32, }, { 1, 1, 0, 2, 36, 33, }, { 3, 1, 0, 2, 36, 30, }, { 4, 1, 0, 2, 36, 27, }, { 5, 1, 0, 2, 36, 32, }, { 6, 1, 0, 2, 36, 30, }, { 7, 1, 0, 2, 36, 27, }, + { 8, 1, 0, 2, 36, 30, }, + { 9, 1, 0, 2, 36, 29, }, + { 10, 1, 0, 2, 36, 63, }, + { 11, 1, 0, 2, 36, 32, }, + { 0, 1, 0, 2, 40, 33, }, + { 2, 1, 0, 2, 40, 32, }, { 1, 1, 0, 2, 40, 33, }, { 3, 1, 0, 2, 40, 31, }, { 4, 1, 0, 2, 40, 29, }, { 5, 1, 0, 2, 40, 32, }, - { 6, 1, 0, 2, 40, 30, }, + { 6, 1, 0, 2, 40, 33, }, { 7, 1, 0, 2, 40, 27, }, + { 8, 1, 0, 2, 40, 31, }, + { 9, 1, 0, 2, 40, 29, }, + { 10, 1, 0, 2, 40, 63, }, + { 11, 1, 0, 2, 40, 32, }, + { 0, 1, 0, 2, 44, 33, }, + { 2, 1, 0, 2, 44, 32, }, { 1, 1, 0, 2, 44, 33, }, { 3, 1, 0, 2, 44, 31, }, { 4, 1, 0, 2, 44, 29, }, { 5, 1, 0, 2, 44, 32, }, - { 6, 1, 0, 2, 44, 30, }, + { 6, 1, 0, 2, 44, 33, }, { 7, 1, 0, 2, 44, 27, }, + { 8, 1, 0, 2, 44, 31, }, + { 9, 1, 0, 2, 44, 29, }, + { 10, 1, 0, 2, 44, 63, }, + { 11, 1, 0, 2, 44, 32, }, + { 0, 1, 0, 2, 48, 33, }, + { 2, 1, 0, 2, 48, 32, }, { 1, 1, 0, 2, 48, 33, }, { 3, 1, 0, 2, 48, 31, }, { 4, 1, 0, 2, 48, 26, }, { 5, 1, 0, 2, 48, 32, }, - { 6, 1, 0, 2, 48, 30, }, + { 6, 1, 0, 2, 48, 33, }, { 7, 1, 0, 2, 48, 27, }, + { 8, 1, 0, 2, 48, 31, }, + { 9, 1, 0, 2, 48, 29, }, + { 10, 1, 0, 2, 48, 63, }, + { 11, 1, 0, 2, 48, 32, }, + { 0, 1, 0, 2, 52, 33, }, + { 2, 1, 0, 2, 52, 32, }, { 1, 1, 0, 2, 52, 33, }, { 3, 1, 0, 2, 52, 32, }, { 4, 1, 0, 2, 52, 7, }, { 5, 1, 0, 2, 52, 32, }, - { 6, 1, 0, 2, 52, 30, }, + { 6, 1, 0, 2, 52, 33, }, { 7, 1, 0, 2, 52, 27, }, + { 8, 1, 0, 2, 52, 33, }, + { 9, 1, 0, 2, 52, 29, }, + { 10, 1, 0, 2, 52, 63, }, + { 11, 1, 0, 2, 52, 32, }, + { 0, 1, 0, 2, 56, 33, }, + { 2, 1, 0, 2, 56, 32, }, { 1, 1, 0, 2, 56, 33, }, { 3, 1, 0, 2, 56, 32, }, { 4, 1, 0, 2, 56, 33, }, { 5, 1, 0, 2, 56, 32, }, - { 6, 1, 0, 2, 56, 30, }, + { 6, 1, 0, 2, 56, 33, }, { 7, 1, 0, 2, 56, 27, }, + { 8, 1, 0, 2, 56, 33, }, + { 9, 1, 0, 2, 56, 29, }, + { 10, 1, 0, 2, 56, 63, }, + { 11, 1, 0, 2, 56, 32, }, + { 0, 1, 0, 2, 60, 33, }, + { 2, 1, 0, 2, 60, 32, }, { 1, 1, 0, 2, 60, 33, }, { 3, 1, 0, 2, 60, 32, }, { 4, 1, 0, 2, 60, 33, }, { 5, 1, 0, 2, 60, 32, }, - { 6, 1, 0, 2, 60, 30, }, + { 6, 1, 0, 2, 60, 33, }, { 7, 1, 0, 2, 60, 27, }, + { 8, 1, 0, 2, 60, 33, }, + { 9, 1, 0, 2, 60, 29, }, + { 10, 1, 0, 2, 60, 63, }, + { 11, 1, 0, 2, 60, 32, }, + { 0, 1, 0, 2, 64, 30, }, + { 2, 1, 0, 2, 64, 32, }, { 1, 1, 0, 2, 64, 33, }, { 3, 1, 0, 2, 64, 30, }, { 4, 1, 0, 2, 64, 33, }, { 5, 1, 0, 2, 64, 32, }, { 6, 1, 0, 2, 64, 30, }, { 7, 1, 0, 2, 64, 27, }, + { 8, 1, 0, 2, 64, 30, }, + { 9, 1, 0, 2, 64, 29, }, + { 10, 1, 0, 2, 64, 63, }, + { 11, 1, 0, 2, 64, 32, }, + { 0, 1, 0, 2, 100, 30, }, + { 2, 1, 0, 2, 100, 32, }, { 1, 1, 0, 2, 100, 33, }, { 3, 1, 0, 2, 100, 30, }, { 4, 1, 0, 2, 100, 33, }, { 5, 1, 0, 2, 100, 32, }, - { 6, 1, 0, 2, 100, 30, }, + { 6, 1, 0, 2, 100, 33, }, { 7, 1, 0, 2, 100, 27, }, + { 8, 1, 0, 2, 100, 30, }, + { 9, 1, 0, 2, 100, 63, }, + { 10, 1, 0, 2, 100, 63, }, + { 11, 1, 0, 2, 100, 32, }, + { 0, 1, 0, 2, 104, 33, }, + { 2, 1, 0, 2, 104, 32, }, { 1, 1, 0, 2, 104, 33, }, { 3, 1, 0, 2, 104, 33, }, { 4, 1, 0, 2, 104, 33, }, { 5, 1, 0, 2, 104, 32, }, - { 6, 1, 0, 2, 104, 30, }, + { 6, 1, 0, 2, 104, 33, }, { 7, 1, 0, 2, 104, 27, }, + { 8, 1, 0, 2, 104, 33, }, + { 9, 1, 0, 2, 104, 63, }, + { 10, 1, 0, 2, 104, 63, }, + { 11, 1, 0, 2, 104, 32, }, + { 0, 1, 0, 2, 108, 33, }, + { 2, 1, 0, 2, 108, 32, }, { 1, 1, 0, 2, 108, 33, }, { 3, 1, 0, 2, 108, 33, }, { 4, 1, 0, 2, 108, 33, }, { 5, 1, 0, 2, 108, 32, }, - { 6, 1, 0, 2, 108, 30, }, + { 6, 1, 0, 2, 108, 33, }, { 7, 1, 0, 2, 108, 27, }, + { 8, 1, 0, 2, 108, 33, }, + { 9, 1, 0, 2, 108, 63, }, + { 10, 1, 0, 2, 108, 63, }, + { 11, 1, 0, 2, 108, 32, }, + { 0, 1, 0, 2, 112, 33, }, + { 2, 1, 0, 2, 112, 32, }, { 1, 1, 0, 2, 112, 33, }, { 3, 1, 0, 2, 112, 33, }, { 4, 1, 0, 2, 112, 33, }, { 5, 1, 0, 2, 112, 32, }, - { 6, 1, 0, 2, 112, 30, }, + { 6, 1, 0, 2, 112, 33, }, { 7, 1, 0, 2, 112, 27, }, + { 8, 1, 0, 2, 112, 33, }, + { 9, 1, 0, 2, 112, 63, }, + { 10, 1, 0, 2, 112, 63, }, + { 11, 1, 0, 2, 112, 32, }, + { 0, 1, 0, 2, 116, 33, }, + { 2, 1, 0, 2, 116, 32, }, { 1, 1, 0, 2, 116, 33, }, { 3, 1, 0, 2, 116, 33, }, { 4, 1, 0, 2, 116, 33, }, { 5, 1, 0, 2, 116, 32, }, - { 6, 1, 0, 2, 116, 30, }, + { 6, 1, 0, 2, 116, 33, }, { 7, 1, 0, 2, 116, 27, }, + { 8, 1, 0, 2, 116, 33, }, + { 9, 1, 0, 2, 116, 63, }, + { 10, 1, 0, 2, 116, 63, }, + { 11, 1, 0, 2, 116, 32, }, + { 0, 1, 0, 2, 120, 33, }, + { 2, 1, 0, 2, 120, 32, }, { 1, 1, 0, 2, 120, 33, }, { 3, 1, 0, 2, 120, 63, }, { 4, 1, 0, 2, 120, 33, }, { 5, 1, 0, 2, 120, 63, }, - { 6, 1, 0, 2, 120, 30, }, + { 6, 1, 0, 2, 120, 33, }, { 7, 1, 0, 2, 120, 27, }, + { 8, 1, 0, 2, 120, 33, }, + { 9, 1, 0, 2, 120, 63, }, + { 10, 1, 0, 2, 120, 63, }, + { 11, 1, 0, 2, 120, 32, }, + { 0, 1, 0, 2, 124, 33, }, + { 2, 1, 0, 2, 124, 32, }, { 1, 1, 0, 2, 124, 33, }, { 3, 1, 0, 2, 124, 63, }, { 4, 1, 0, 2, 124, 33, }, { 5, 1, 0, 2, 124, 63, }, - { 6, 1, 0, 2, 124, 30, }, + { 6, 1, 0, 2, 124, 33, }, { 7, 1, 0, 2, 124, 27, }, + { 8, 1, 0, 2, 124, 33, }, + { 9, 1, 0, 2, 124, 63, }, + { 10, 1, 0, 2, 124, 63, }, + { 11, 1, 0, 2, 124, 32, }, + { 0, 1, 0, 2, 128, 33, }, + { 2, 1, 0, 2, 128, 32, }, { 1, 1, 0, 2, 128, 33, }, { 3, 1, 0, 2, 128, 63, }, - { 4, 1, 0, 2, 128, 63, }, + { 4, 1, 0, 2, 128, 33, }, { 5, 1, 0, 2, 128, 63, }, - { 6, 1, 0, 2, 128, 30, }, + { 6, 1, 0, 2, 128, 33, }, { 7, 1, 0, 2, 128, 27, }, + { 8, 1, 0, 2, 128, 33, }, + { 9, 1, 0, 2, 128, 63, }, + { 10, 1, 0, 2, 128, 63, }, + { 11, 1, 0, 2, 128, 32, }, + { 0, 1, 0, 2, 132, 33, }, + { 2, 1, 0, 2, 132, 32, }, { 1, 1, 0, 2, 132, 33, }, { 3, 1, 0, 2, 132, 33, }, - { 4, 1, 0, 2, 132, 63, }, + { 4, 1, 0, 2, 132, 33, }, { 5, 1, 0, 2, 132, 32, }, - { 6, 1, 0, 2, 132, 30, }, + { 6, 1, 0, 2, 132, 33, }, { 7, 1, 0, 2, 132, 27, }, + { 8, 1, 0, 2, 132, 33, }, + { 9, 1, 0, 2, 132, 63, }, + { 10, 1, 0, 2, 132, 63, }, + { 11, 1, 0, 2, 132, 32, }, + { 0, 1, 0, 2, 136, 33, }, + { 2, 1, 0, 2, 136, 32, }, { 1, 1, 0, 2, 136, 33, }, { 3, 1, 0, 2, 136, 33, }, - { 4, 1, 0, 2, 136, 63, }, + { 4, 1, 0, 2, 136, 33, }, { 5, 1, 0, 2, 136, 32, }, - { 6, 1, 0, 2, 136, 30, }, - { 7, 1, 0, 2, 136, 63, }, + { 6, 1, 0, 2, 136, 33, }, + { 7, 1, 0, 2, 136, 27, }, + { 8, 1, 0, 2, 136, 33, }, + { 9, 1, 0, 2, 136, 63, }, + { 10, 1, 0, 2, 136, 63, }, + { 11, 1, 0, 2, 136, 32, }, + { 0, 1, 0, 2, 140, 29, }, + { 2, 1, 0, 2, 140, 32, }, { 1, 1, 0, 2, 140, 33, }, { 3, 1, 0, 2, 140, 29, }, - { 4, 1, 0, 2, 140, 63, }, + { 4, 1, 0, 2, 140, 33, }, { 5, 1, 0, 2, 140, 32, }, - { 6, 1, 0, 2, 140, 30, }, - { 7, 1, 0, 2, 140, 63, }, + { 6, 1, 0, 2, 140, 33, }, + { 7, 1, 0, 2, 140, 27, }, + { 8, 1, 0, 2, 140, 29, }, + { 9, 1, 0, 2, 140, 63, }, + { 10, 1, 0, 2, 140, 63, }, + { 11, 1, 0, 2, 140, 32, }, + { 0, 1, 0, 2, 144, 27, }, + { 2, 1, 0, 2, 144, 63, }, { 1, 1, 0, 2, 144, 63, }, { 3, 1, 0, 2, 144, 27, }, - { 4, 1, 0, 2, 144, 63, }, + { 4, 1, 0, 2, 144, 33, }, { 5, 1, 0, 2, 144, 63, }, - { 6, 1, 0, 2, 144, 30, }, + { 6, 1, 0, 2, 144, 33, }, { 7, 1, 0, 2, 144, 63, }, + { 8, 1, 0, 2, 144, 27, }, + { 9, 1, 0, 2, 144, 63, }, + { 10, 1, 0, 2, 144, 63, }, + { 11, 1, 0, 2, 144, 31, }, + { 0, 1, 0, 2, 149, 33, }, + { 2, 1, 0, 2, 149, 14, }, { 1, 1, 0, 2, 149, 63, }, { 3, 1, 0, 2, 149, 33, }, { 4, 1, 0, 2, 149, 33, }, { 5, 1, 0, 2, 149, 33, }, - { 6, 1, 0, 2, 149, 30, }, + { 6, 1, 0, 2, 149, 33, }, { 7, 1, 0, 2, 149, 27, }, + { 8, 1, 0, 2, 149, 33, }, + { 9, 1, 0, 2, 149, 31, }, + { 10, 1, 0, 2, 149, 14, }, + { 11, 1, 0, 2, 149, 31, }, + { 0, 1, 0, 2, 153, 33, }, + { 2, 1, 0, 2, 153, 14, }, { 1, 1, 0, 2, 153, 63, }, { 3, 1, 0, 2, 153, 33, }, { 4, 1, 0, 2, 153, 33, }, { 5, 1, 0, 2, 153, 33, }, - { 6, 1, 0, 2, 153, 30, }, + { 6, 1, 0, 2, 153, 33, }, { 7, 1, 0, 2, 153, 27, }, + { 8, 1, 0, 2, 153, 33, }, + { 9, 1, 0, 2, 153, 31, }, + { 10, 1, 0, 2, 153, 14, }, + { 11, 1, 0, 2, 153, 31, }, + { 0, 1, 0, 2, 157, 33, }, + { 2, 1, 0, 2, 157, 14, }, { 1, 1, 0, 2, 157, 63, }, { 3, 1, 0, 2, 157, 33, }, { 4, 1, 0, 2, 157, 33, }, { 5, 1, 0, 2, 157, 33, }, - { 6, 1, 0, 2, 157, 30, }, + { 6, 1, 0, 2, 157, 33, }, { 7, 1, 0, 2, 157, 27, }, + { 8, 1, 0, 2, 157, 33, }, + { 9, 1, 0, 2, 157, 31, }, + { 10, 1, 0, 2, 157, 14, }, + { 11, 1, 0, 2, 157, 31, }, + { 0, 1, 0, 2, 161, 33, }, + { 2, 1, 0, 2, 161, 14, }, { 1, 1, 0, 2, 161, 63, }, { 3, 1, 0, 2, 161, 33, }, { 4, 1, 0, 2, 161, 31, }, { 5, 1, 0, 2, 161, 33, }, - { 6, 1, 0, 2, 161, 30, }, + { 6, 1, 0, 2, 161, 33, }, { 7, 1, 0, 2, 161, 27, }, + { 8, 1, 0, 2, 161, 33, }, + { 9, 1, 0, 2, 161, 31, }, + { 10, 1, 0, 2, 161, 14, }, + { 11, 1, 0, 2, 161, 31, }, + { 0, 1, 0, 2, 165, 33, }, + { 2, 1, 0, 2, 165, 14, }, { 1, 1, 0, 2, 165, 63, }, { 3, 1, 0, 2, 165, 33, }, - { 4, 1, 0, 2, 165, 63, }, + { 4, 1, 0, 2, 165, 33, }, { 5, 1, 0, 2, 165, 33, }, - { 6, 1, 0, 2, 165, 30, }, + { 6, 1, 0, 2, 165, 33, }, { 7, 1, 0, 2, 165, 27, }, + { 8, 1, 0, 2, 165, 30, }, + { 9, 1, 0, 2, 165, 31, }, + { 10, 1, 0, 2, 165, 14, }, + { 11, 1, 0, 2, 165, 31, }, + { 0, 1, 1, 2, 38, 22, }, + { 2, 1, 1, 2, 38, 32, }, { 1, 1, 1, 2, 38, 32, }, { 3, 1, 1, 2, 38, 22, }, { 4, 1, 1, 2, 38, 26, }, { 5, 1, 1, 2, 38, 32, }, { 6, 1, 1, 2, 38, 22, }, { 7, 1, 1, 2, 38, 27, }, + { 8, 1, 1, 2, 38, 22, }, + { 9, 1, 1, 2, 38, 29, }, + { 10, 1, 1, 2, 38, 63, }, + { 11, 1, 1, 2, 38, 32, }, + { 0, 1, 1, 2, 46, 32, }, + { 2, 1, 1, 2, 46, 32, }, { 1, 1, 1, 2, 46, 32, }, { 3, 1, 1, 2, 46, 32, }, { 4, 1, 1, 2, 46, 28, }, { 5, 1, 1, 2, 46, 32, }, - { 6, 1, 1, 2, 46, 30, }, + { 6, 1, 1, 2, 46, 32, }, { 7, 1, 1, 2, 46, 27, }, + { 8, 1, 1, 2, 46, 31, }, + { 9, 1, 1, 2, 46, 29, }, + { 10, 1, 1, 2, 46, 63, }, + { 11, 1, 1, 2, 46, 32, }, + { 0, 1, 1, 2, 54, 32, }, + { 2, 1, 1, 2, 54, 32, }, { 1, 1, 1, 2, 54, 32, }, { 3, 1, 1, 2, 54, 32, }, { 4, 1, 1, 2, 54, 22, }, { 5, 1, 1, 2, 54, 32, }, - { 6, 1, 1, 2, 54, 30, }, + { 6, 1, 1, 2, 54, 32, }, { 7, 1, 1, 2, 54, 27, }, + { 8, 1, 1, 2, 54, 32, }, + { 9, 1, 1, 2, 54, 28, }, + { 10, 1, 1, 2, 54, 63, }, + { 11, 1, 1, 2, 54, 32, }, + { 0, 1, 1, 2, 62, 23, }, + { 2, 1, 1, 2, 62, 32, }, { 1, 1, 1, 2, 62, 32, }, { 3, 1, 1, 2, 62, 23, }, { 4, 1, 1, 2, 62, 31, }, { 5, 1, 1, 2, 62, 32, }, { 6, 1, 1, 2, 62, 23, }, { 7, 1, 1, 2, 62, 27, }, + { 8, 1, 1, 2, 62, 23, }, + { 9, 1, 1, 2, 62, 28, }, + { 10, 1, 1, 2, 62, 63, }, + { 11, 1, 1, 2, 62, 32, }, + { 0, 1, 1, 2, 102, 21, }, + { 2, 1, 1, 2, 102, 32, }, { 1, 1, 1, 2, 102, 32, }, { 3, 1, 1, 2, 102, 21, }, { 4, 1, 1, 2, 102, 31, }, { 5, 1, 1, 2, 102, 32, }, - { 6, 1, 1, 2, 102, 30, }, + { 6, 1, 1, 2, 102, 32, }, { 7, 1, 1, 2, 102, 27, }, + { 8, 1, 1, 2, 102, 21, }, + { 9, 1, 1, 2, 102, 63, }, + { 10, 1, 1, 2, 102, 63, }, + { 11, 1, 1, 2, 102, 32, }, + { 0, 1, 1, 2, 110, 32, }, + { 2, 1, 1, 2, 110, 32, }, { 1, 1, 1, 2, 110, 32, }, { 3, 1, 1, 2, 110, 32, }, { 4, 1, 1, 2, 110, 32, }, { 5, 1, 1, 2, 110, 32, }, - { 6, 1, 1, 2, 110, 30, }, + { 6, 1, 1, 2, 110, 32, }, { 7, 1, 1, 2, 110, 27, }, + { 8, 1, 1, 2, 110, 32, }, + { 9, 1, 1, 2, 110, 63, }, + { 10, 1, 1, 2, 110, 63, }, + { 11, 1, 1, 2, 110, 32, }, + { 0, 1, 1, 2, 118, 32, }, + { 2, 1, 1, 2, 118, 32, }, { 1, 1, 1, 2, 118, 32, }, { 3, 1, 1, 2, 118, 63, }, { 4, 1, 1, 2, 118, 32, }, { 5, 1, 1, 2, 118, 63, }, - { 6, 1, 1, 2, 118, 30, }, + { 6, 1, 1, 2, 118, 32, }, { 7, 1, 1, 2, 118, 27, }, + { 8, 1, 1, 2, 118, 32, }, + { 9, 1, 1, 2, 118, 63, }, + { 10, 1, 1, 2, 118, 63, }, + { 11, 1, 1, 2, 118, 32, }, + { 0, 1, 1, 2, 126, 32, }, + { 2, 1, 1, 2, 126, 32, }, { 1, 1, 1, 2, 126, 32, }, { 3, 1, 1, 2, 126, 63, }, - { 4, 1, 1, 2, 126, 63, }, + { 4, 1, 1, 2, 126, 32, }, { 5, 1, 1, 2, 126, 63, }, - { 6, 1, 1, 2, 126, 30, }, + { 6, 1, 1, 2, 126, 32, }, { 7, 1, 1, 2, 126, 27, }, + { 8, 1, 1, 2, 126, 32, }, + { 9, 1, 1, 2, 126, 63, }, + { 10, 1, 1, 2, 126, 63, }, + { 11, 1, 1, 2, 126, 32, }, + { 0, 1, 1, 2, 134, 32, }, + { 2, 1, 1, 2, 134, 32, }, { 1, 1, 1, 2, 134, 32, }, { 3, 1, 1, 2, 134, 32, }, - { 4, 1, 1, 2, 134, 63, }, + { 4, 1, 1, 2, 134, 32, }, { 5, 1, 1, 2, 134, 32, }, - { 6, 1, 1, 2, 134, 30, }, - { 7, 1, 1, 2, 134, 63, }, + { 6, 1, 1, 2, 134, 32, }, + { 7, 1, 1, 2, 134, 27, }, + { 8, 1, 1, 2, 134, 32, }, + { 9, 1, 1, 2, 134, 63, }, + { 10, 1, 1, 2, 134, 63, }, + { 11, 1, 1, 2, 134, 32, }, + { 0, 1, 1, 2, 142, 29, }, + { 2, 1, 1, 2, 142, 63, }, { 1, 1, 1, 2, 142, 63, }, { 3, 1, 1, 2, 142, 29, }, - { 4, 1, 1, 2, 142, 63, }, + { 4, 1, 1, 2, 142, 32, }, { 5, 1, 1, 2, 142, 63, }, - { 6, 1, 1, 2, 142, 30, }, + { 6, 1, 1, 2, 142, 32, }, { 7, 1, 1, 2, 142, 63, }, + { 8, 1, 1, 2, 142, 29, }, + { 9, 1, 1, 2, 142, 63, }, + { 10, 1, 1, 2, 142, 63, }, + { 11, 1, 1, 2, 142, 31, }, + { 0, 1, 1, 2, 151, 32, }, + { 2, 1, 1, 2, 151, 14, }, { 1, 1, 1, 2, 151, 63, }, { 3, 1, 1, 2, 151, 32, }, { 4, 1, 1, 2, 151, 27, }, { 5, 1, 1, 2, 151, 32, }, - { 6, 1, 1, 2, 151, 30, }, + { 6, 1, 1, 2, 151, 32, }, { 7, 1, 1, 2, 151, 27, }, + { 8, 1, 1, 2, 151, 32, }, + { 9, 1, 1, 2, 151, 27, }, + { 10, 1, 1, 2, 151, 14, }, + { 11, 1, 1, 2, 151, 30, }, + { 0, 1, 1, 2, 159, 32, }, + { 2, 1, 1, 2, 159, 14, }, { 1, 1, 1, 2, 159, 63, }, { 3, 1, 1, 2, 159, 32, }, { 4, 1, 1, 2, 159, 26, }, { 5, 1, 1, 2, 159, 32, }, - { 6, 1, 1, 2, 159, 30, }, + { 6, 1, 1, 2, 159, 32, }, { 7, 1, 1, 2, 159, 27, }, + { 8, 1, 1, 2, 159, 32, }, + { 9, 1, 1, 2, 159, 31, }, + { 10, 1, 1, 2, 159, 14, }, + { 11, 1, 1, 2, 159, 30, }, + { 0, 1, 2, 4, 42, 19, }, + { 2, 1, 2, 4, 42, 32, }, { 1, 1, 2, 4, 42, 28, }, { 3, 1, 2, 4, 42, 19, }, { 4, 1, 2, 4, 42, 25, }, { 5, 1, 2, 4, 42, 32, }, { 6, 1, 2, 4, 42, 19, }, { 7, 1, 2, 4, 42, 27, }, + { 8, 1, 2, 4, 42, 19, }, + { 9, 1, 2, 4, 42, 25, }, + { 10, 1, 2, 4, 42, 63, }, + { 11, 1, 2, 4, 42, 32, }, + { 0, 1, 2, 4, 58, 22, }, + { 2, 1, 2, 4, 58, 32, }, { 1, 1, 2, 4, 58, 28, }, { 3, 1, 2, 4, 58, 22, }, { 4, 1, 2, 4, 58, 28, }, { 5, 1, 2, 4, 58, 32, }, { 6, 1, 2, 4, 58, 22, }, { 7, 1, 2, 4, 58, 27, }, + { 8, 1, 2, 4, 58, 22, }, + { 9, 1, 2, 4, 58, 23, }, + { 10, 1, 2, 4, 58, 63, }, + { 11, 1, 2, 4, 58, 32, }, + { 0, 1, 2, 4, 106, 18, }, + { 2, 1, 2, 4, 106, 32, }, { 1, 1, 2, 4, 106, 32, }, { 3, 1, 2, 4, 106, 18, }, { 4, 1, 2, 4, 106, 30, }, { 5, 1, 2, 4, 106, 32, }, - { 6, 1, 2, 4, 106, 30, }, + { 6, 1, 2, 4, 106, 32, }, { 7, 1, 2, 4, 106, 27, }, + { 8, 1, 2, 4, 106, 18, }, + { 9, 1, 2, 4, 106, 63, }, + { 10, 1, 2, 4, 106, 63, }, + { 11, 1, 2, 4, 106, 32, }, + { 0, 1, 2, 4, 122, 32, }, + { 2, 1, 2, 4, 122, 32, }, { 1, 1, 2, 4, 122, 32, }, { 3, 1, 2, 4, 122, 63, }, { 4, 1, 2, 4, 122, 26, }, { 5, 1, 2, 4, 122, 63, }, - { 6, 1, 2, 4, 122, 30, }, + { 6, 1, 2, 4, 122, 32, }, { 7, 1, 2, 4, 122, 27, }, + { 8, 1, 2, 4, 122, 32, }, + { 9, 1, 2, 4, 122, 63, }, + { 10, 1, 2, 4, 122, 63, }, + { 11, 1, 2, 4, 122, 32, }, + { 0, 1, 2, 4, 138, 28, }, + { 2, 1, 2, 4, 138, 63, }, { 1, 1, 2, 4, 138, 63, }, { 3, 1, 2, 4, 138, 28, }, - { 4, 1, 2, 4, 138, 63, }, + { 4, 1, 2, 4, 138, 32, }, { 5, 1, 2, 4, 138, 63, }, - { 6, 1, 2, 4, 138, 30, }, + { 6, 1, 2, 4, 138, 32, }, { 7, 1, 2, 4, 138, 63, }, + { 8, 1, 2, 4, 138, 28, }, + { 9, 1, 2, 4, 138, 63, }, + { 10, 1, 2, 4, 138, 63, }, + { 11, 1, 2, 4, 138, 30, }, + { 0, 1, 2, 4, 155, 32, }, + { 2, 1, 2, 4, 155, 14, }, { 1, 1, 2, 4, 155, 63, }, { 3, 1, 2, 4, 155, 32, }, { 4, 1, 2, 4, 155, 27, }, { 5, 1, 2, 4, 155, 32, }, - { 6, 1, 2, 4, 155, 30, }, + { 6, 1, 2, 4, 155, 32, }, { 7, 1, 2, 4, 155, 27, }, + { 8, 1, 2, 4, 155, 32, }, + { 9, 1, 2, 4, 155, 20, }, + { 10, 1, 2, 4, 155, 14, }, + { 11, 1, 2, 4, 155, 30, }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8821c_txpwr_lmt_type0); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c index f9e3d0779c59..5699846a399b 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c @@ -39832,6 +39832,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 1, 60, }, { 8, 0, 0, 0, 1, 72, }, { 9, 0, 0, 0, 1, 60, }, + { 10, 0, 0, 0, 1, 60, }, + { 11, 0, 0, 0, 1, 60, }, { 0, 0, 0, 0, 2, 72, }, { 2, 0, 0, 0, 2, 60, }, { 1, 0, 0, 0, 2, 68, }, @@ -39842,6 +39844,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 2, 60, }, { 8, 0, 0, 0, 2, 72, }, { 9, 0, 0, 0, 2, 60, }, + { 10, 0, 0, 0, 2, 60, }, + { 11, 0, 0, 0, 2, 60, }, { 0, 0, 0, 0, 3, 76, }, { 2, 0, 0, 0, 3, 60, }, { 1, 0, 0, 0, 3, 68, }, @@ -39852,6 +39856,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 3, 60, }, { 8, 0, 0, 0, 3, 76, }, { 9, 0, 0, 0, 3, 60, }, + { 10, 0, 0, 0, 3, 60, }, + { 11, 0, 0, 0, 3, 60, }, { 0, 0, 0, 0, 4, 76, }, { 2, 0, 0, 0, 4, 60, }, { 1, 0, 0, 0, 4, 68, }, @@ -39862,6 +39868,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 4, 60, }, { 8, 0, 0, 0, 4, 76, }, { 9, 0, 0, 0, 4, 60, }, + { 10, 0, 0, 0, 4, 60, }, + { 11, 0, 0, 0, 4, 60, }, { 0, 0, 0, 0, 5, 76, }, { 2, 0, 0, 0, 5, 60, }, { 1, 0, 0, 0, 5, 68, }, @@ -39872,6 +39880,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 5, 60, }, { 8, 0, 0, 0, 5, 76, }, { 9, 0, 0, 0, 5, 60, }, + { 10, 0, 0, 0, 5, 60, }, + { 11, 0, 0, 0, 5, 60, }, { 0, 0, 0, 0, 6, 76, }, { 2, 0, 0, 0, 6, 60, }, { 1, 0, 0, 0, 6, 68, }, @@ -39882,6 +39892,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 6, 60, }, { 8, 0, 0, 0, 6, 76, }, { 9, 0, 0, 0, 6, 60, }, + { 10, 0, 0, 0, 6, 60, }, + { 11, 0, 0, 0, 6, 60, }, { 0, 0, 0, 0, 7, 76, }, { 2, 0, 0, 0, 7, 60, }, { 1, 0, 0, 0, 7, 68, }, @@ -39892,6 +39904,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 7, 60, }, { 8, 0, 0, 0, 7, 76, }, { 9, 0, 0, 0, 7, 60, }, + { 10, 0, 0, 0, 7, 60, }, + { 11, 0, 0, 0, 7, 60, }, { 0, 0, 0, 0, 8, 76, }, { 2, 0, 0, 0, 8, 60, }, { 1, 0, 0, 0, 8, 68, }, @@ -39902,6 +39916,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 8, 60, }, { 8, 0, 0, 0, 8, 76, }, { 9, 0, 0, 0, 8, 60, }, + { 10, 0, 0, 0, 8, 60, }, + { 11, 0, 0, 0, 8, 60, }, { 0, 0, 0, 0, 9, 76, }, { 2, 0, 0, 0, 9, 60, }, { 1, 0, 0, 0, 9, 68, }, @@ -39912,6 +39928,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 9, 60, }, { 8, 0, 0, 0, 9, 76, }, { 9, 0, 0, 0, 9, 60, }, + { 10, 0, 0, 0, 9, 60, }, + { 11, 0, 0, 0, 9, 60, }, { 0, 0, 0, 0, 10, 72, }, { 2, 0, 0, 0, 10, 60, }, { 1, 0, 0, 0, 10, 68, }, @@ -39922,6 +39940,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 10, 60, }, { 8, 0, 0, 0, 10, 72, }, { 9, 0, 0, 0, 10, 60, }, + { 10, 0, 0, 0, 10, 60, }, + { 11, 0, 0, 0, 10, 60, }, { 0, 0, 0, 0, 11, 72, }, { 2, 0, 0, 0, 11, 60, }, { 1, 0, 0, 0, 11, 68, }, @@ -39932,7 +39952,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 11, 60, }, { 8, 0, 0, 0, 11, 72, }, { 9, 0, 0, 0, 11, 60, }, - { 0, 0, 0, 0, 12, 44, }, + { 10, 0, 0, 0, 11, 60, }, + { 11, 0, 0, 0, 11, 60, }, + { 0, 0, 0, 0, 12, 52, }, { 2, 0, 0, 0, 12, 60, }, { 1, 0, 0, 0, 12, 68, }, { 3, 0, 0, 0, 12, 52, }, @@ -39942,7 +39964,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 12, 60, }, { 8, 0, 0, 0, 12, 52, }, { 9, 0, 0, 0, 12, 60, }, - { 0, 0, 0, 0, 13, 40, }, + { 10, 0, 0, 0, 12, 60, }, + { 11, 0, 0, 0, 12, 60, }, + { 0, 0, 0, 0, 13, 48, }, { 2, 0, 0, 0, 13, 60, }, { 1, 0, 0, 0, 13, 68, }, { 3, 0, 0, 0, 13, 48, }, @@ -39952,6 +39976,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 13, 60, }, { 8, 0, 0, 0, 13, 48, }, { 9, 0, 0, 0, 13, 60, }, + { 10, 0, 0, 0, 13, 60, }, + { 11, 0, 0, 0, 13, 60, }, { 0, 0, 0, 0, 14, 127, }, { 2, 0, 0, 0, 14, 127, }, { 1, 0, 0, 0, 14, 68, }, @@ -39962,6 +39988,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 0, 14, 127, }, { 8, 0, 0, 0, 14, 127, }, { 9, 0, 0, 0, 14, 127, }, + { 10, 0, 0, 0, 14, 127, }, + { 11, 0, 0, 0, 14, 127, }, { 0, 0, 0, 1, 1, 52, }, { 2, 0, 0, 1, 1, 60, }, { 1, 0, 0, 1, 1, 76, }, @@ -39972,6 +40000,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 1, 60, }, { 8, 0, 0, 1, 1, 52, }, { 9, 0, 0, 1, 1, 60, }, + { 10, 0, 0, 1, 1, 60, }, + { 11, 0, 0, 1, 1, 60, }, { 0, 0, 0, 1, 2, 60, }, { 2, 0, 0, 1, 2, 60, }, { 1, 0, 0, 1, 2, 76, }, @@ -39982,6 +40012,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 2, 60, }, { 8, 0, 0, 1, 2, 60, }, { 9, 0, 0, 1, 2, 60, }, + { 10, 0, 0, 1, 2, 60, }, + { 11, 0, 0, 1, 2, 60, }, { 0, 0, 0, 1, 3, 64, }, { 2, 0, 0, 1, 3, 60, }, { 1, 0, 0, 1, 3, 76, }, @@ -39992,6 +40024,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 3, 60, }, { 8, 0, 0, 1, 3, 64, }, { 9, 0, 0, 1, 3, 60, }, + { 10, 0, 0, 1, 3, 60, }, + { 11, 0, 0, 1, 3, 60, }, { 0, 0, 0, 1, 4, 68, }, { 2, 0, 0, 1, 4, 60, }, { 1, 0, 0, 1, 4, 76, }, @@ -40002,6 +40036,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 4, 60, }, { 8, 0, 0, 1, 4, 68, }, { 9, 0, 0, 1, 4, 60, }, + { 10, 0, 0, 1, 4, 60, }, + { 11, 0, 0, 1, 4, 60, }, { 0, 0, 0, 1, 5, 76, }, { 2, 0, 0, 1, 5, 60, }, { 1, 0, 0, 1, 5, 76, }, @@ -40012,6 +40048,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 5, 60, }, { 8, 0, 0, 1, 5, 76, }, { 9, 0, 0, 1, 5, 60, }, + { 10, 0, 0, 1, 5, 60, }, + { 11, 0, 0, 1, 5, 60, }, { 0, 0, 0, 1, 6, 76, }, { 2, 0, 0, 1, 6, 60, }, { 1, 0, 0, 1, 6, 76, }, @@ -40022,6 +40060,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 6, 60, }, { 8, 0, 0, 1, 6, 76, }, { 9, 0, 0, 1, 6, 60, }, + { 10, 0, 0, 1, 6, 60, }, + { 11, 0, 0, 1, 6, 60, }, { 0, 0, 0, 1, 7, 76, }, { 2, 0, 0, 1, 7, 60, }, { 1, 0, 0, 1, 7, 76, }, @@ -40032,6 +40072,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 7, 60, }, { 8, 0, 0, 1, 7, 76, }, { 9, 0, 0, 1, 7, 60, }, + { 10, 0, 0, 1, 7, 60, }, + { 11, 0, 0, 1, 7, 60, }, { 0, 0, 0, 1, 8, 68, }, { 2, 0, 0, 1, 8, 60, }, { 1, 0, 0, 1, 8, 76, }, @@ -40042,6 +40084,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 8, 60, }, { 8, 0, 0, 1, 8, 68, }, { 9, 0, 0, 1, 8, 60, }, + { 10, 0, 0, 1, 8, 60, }, + { 11, 0, 0, 1, 8, 60, }, { 0, 0, 0, 1, 9, 64, }, { 2, 0, 0, 1, 9, 60, }, { 1, 0, 0, 1, 9, 76, }, @@ -40052,6 +40096,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 9, 60, }, { 8, 0, 0, 1, 9, 64, }, { 9, 0, 0, 1, 9, 60, }, + { 10, 0, 0, 1, 9, 60, }, + { 11, 0, 0, 1, 9, 60, }, { 0, 0, 0, 1, 10, 60, }, { 2, 0, 0, 1, 10, 60, }, { 1, 0, 0, 1, 10, 76, }, @@ -40062,6 +40108,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 10, 60, }, { 8, 0, 0, 1, 10, 60, }, { 9, 0, 0, 1, 10, 60, }, + { 10, 0, 0, 1, 10, 60, }, + { 11, 0, 0, 1, 10, 60, }, { 0, 0, 0, 1, 11, 52, }, { 2, 0, 0, 1, 11, 60, }, { 1, 0, 0, 1, 11, 76, }, @@ -40071,8 +40119,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 1, 11, 52, }, { 7, 0, 0, 1, 11, 60, }, { 8, 0, 0, 1, 11, 52, }, - { 9, 0, 0, 1, 11, 60, }, - { 0, 0, 0, 1, 12, 32, }, + { 9, 0, 0, 1, 11, 44, }, + { 10, 0, 0, 1, 11, 60, }, + { 11, 0, 0, 1, 11, 60, }, + { 0, 0, 0, 1, 12, 40, }, { 2, 0, 0, 1, 12, 60, }, { 1, 0, 0, 1, 12, 76, }, { 3, 0, 0, 1, 12, 40, }, @@ -40081,8 +40131,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 1, 12, 40, }, { 7, 0, 0, 1, 12, 60, }, { 8, 0, 0, 1, 12, 40, }, - { 9, 0, 0, 1, 12, 60, }, - { 0, 0, 0, 1, 13, 20, }, + { 9, 0, 0, 1, 12, 44, }, + { 10, 0, 0, 1, 12, 60, }, + { 11, 0, 0, 1, 12, 60, }, + { 0, 0, 0, 1, 13, 28, }, { 2, 0, 0, 1, 13, 60, }, { 1, 0, 0, 1, 13, 76, }, { 3, 0, 0, 1, 13, 28, }, @@ -40091,7 +40143,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 1, 13, 28, }, { 7, 0, 0, 1, 13, 60, }, { 8, 0, 0, 1, 13, 28, }, - { 9, 0, 0, 1, 13, 60, }, + { 9, 0, 0, 1, 13, 36, }, + { 10, 0, 0, 1, 13, 60, }, + { 11, 0, 0, 1, 13, 60, }, { 0, 0, 0, 1, 14, 127, }, { 2, 0, 0, 1, 14, 127, }, { 1, 0, 0, 1, 14, 127, }, @@ -40102,6 +40156,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 1, 14, 127, }, { 8, 0, 0, 1, 14, 127, }, { 9, 0, 0, 1, 14, 127, }, + { 10, 0, 0, 1, 14, 127, }, + { 11, 0, 0, 1, 14, 127, }, { 0, 0, 0, 2, 1, 52, }, { 2, 0, 0, 2, 1, 60, }, { 1, 0, 0, 2, 1, 76, }, @@ -40112,6 +40168,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 1, 60, }, { 8, 0, 0, 2, 1, 52, }, { 9, 0, 0, 2, 1, 60, }, + { 10, 0, 0, 2, 1, 60, }, + { 11, 0, 0, 2, 1, 60, }, { 0, 0, 0, 2, 2, 60, }, { 2, 0, 0, 2, 2, 60, }, { 1, 0, 0, 2, 2, 76, }, @@ -40122,6 +40180,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 2, 60, }, { 8, 0, 0, 2, 2, 60, }, { 9, 0, 0, 2, 2, 60, }, + { 10, 0, 0, 2, 2, 60, }, + { 11, 0, 0, 2, 2, 60, }, { 0, 0, 0, 2, 3, 64, }, { 2, 0, 0, 2, 3, 60, }, { 1, 0, 0, 2, 3, 76, }, @@ -40132,6 +40192,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 3, 60, }, { 8, 0, 0, 2, 3, 64, }, { 9, 0, 0, 2, 3, 60, }, + { 10, 0, 0, 2, 3, 60, }, + { 11, 0, 0, 2, 3, 60, }, { 0, 0, 0, 2, 4, 68, }, { 2, 0, 0, 2, 4, 60, }, { 1, 0, 0, 2, 4, 76, }, @@ -40142,6 +40204,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 4, 60, }, { 8, 0, 0, 2, 4, 68, }, { 9, 0, 0, 2, 4, 60, }, + { 10, 0, 0, 2, 4, 60, }, + { 11, 0, 0, 2, 4, 60, }, { 0, 0, 0, 2, 5, 76, }, { 2, 0, 0, 2, 5, 60, }, { 1, 0, 0, 2, 5, 76, }, @@ -40152,6 +40216,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 5, 60, }, { 8, 0, 0, 2, 5, 76, }, { 9, 0, 0, 2, 5, 60, }, + { 10, 0, 0, 2, 5, 60, }, + { 11, 0, 0, 2, 5, 60, }, { 0, 0, 0, 2, 6, 76, }, { 2, 0, 0, 2, 6, 60, }, { 1, 0, 0, 2, 6, 76, }, @@ -40162,6 +40228,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 6, 60, }, { 8, 0, 0, 2, 6, 76, }, { 9, 0, 0, 2, 6, 60, }, + { 10, 0, 0, 2, 6, 60, }, + { 11, 0, 0, 2, 6, 60, }, { 0, 0, 0, 2, 7, 76, }, { 2, 0, 0, 2, 7, 60, }, { 1, 0, 0, 2, 7, 76, }, @@ -40172,6 +40240,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 7, 60, }, { 8, 0, 0, 2, 7, 76, }, { 9, 0, 0, 2, 7, 60, }, + { 10, 0, 0, 2, 7, 60, }, + { 11, 0, 0, 2, 7, 60, }, { 0, 0, 0, 2, 8, 68, }, { 2, 0, 0, 2, 8, 60, }, { 1, 0, 0, 2, 8, 76, }, @@ -40182,6 +40252,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 8, 60, }, { 8, 0, 0, 2, 8, 68, }, { 9, 0, 0, 2, 8, 60, }, + { 10, 0, 0, 2, 8, 60, }, + { 11, 0, 0, 2, 8, 60, }, { 0, 0, 0, 2, 9, 64, }, { 2, 0, 0, 2, 9, 60, }, { 1, 0, 0, 2, 9, 76, }, @@ -40192,6 +40264,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 9, 60, }, { 8, 0, 0, 2, 9, 64, }, { 9, 0, 0, 2, 9, 60, }, + { 10, 0, 0, 2, 9, 60, }, + { 11, 0, 0, 2, 9, 60, }, { 0, 0, 0, 2, 10, 60, }, { 2, 0, 0, 2, 10, 60, }, { 1, 0, 0, 2, 10, 76, }, @@ -40202,6 +40276,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 10, 60, }, { 8, 0, 0, 2, 10, 60, }, { 9, 0, 0, 2, 10, 60, }, + { 10, 0, 0, 2, 10, 60, }, + { 11, 0, 0, 2, 10, 60, }, { 0, 0, 0, 2, 11, 52, }, { 2, 0, 0, 2, 11, 60, }, { 1, 0, 0, 2, 11, 76, }, @@ -40211,8 +40287,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 2, 11, 52, }, { 7, 0, 0, 2, 11, 60, }, { 8, 0, 0, 2, 11, 52, }, - { 9, 0, 0, 2, 11, 60, }, - { 0, 0, 0, 2, 12, 32, }, + { 9, 0, 0, 2, 11, 46, }, + { 10, 0, 0, 2, 11, 60, }, + { 11, 0, 0, 2, 11, 60, }, + { 0, 0, 0, 2, 12, 40, }, { 2, 0, 0, 2, 12, 60, }, { 1, 0, 0, 2, 12, 76, }, { 3, 0, 0, 2, 12, 40, }, @@ -40221,8 +40299,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 2, 12, 40, }, { 7, 0, 0, 2, 12, 60, }, { 8, 0, 0, 2, 12, 40, }, - { 9, 0, 0, 2, 12, 60, }, - { 0, 0, 0, 2, 13, 20, }, + { 9, 0, 0, 2, 12, 42, }, + { 10, 0, 0, 2, 12, 60, }, + { 11, 0, 0, 2, 12, 60, }, + { 0, 0, 0, 2, 13, 28, }, { 2, 0, 0, 2, 13, 60, }, { 1, 0, 0, 2, 13, 76, }, { 3, 0, 0, 2, 13, 28, }, @@ -40231,7 +40311,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 2, 13, 28, }, { 7, 0, 0, 2, 13, 60, }, { 8, 0, 0, 2, 13, 28, }, - { 9, 0, 0, 2, 13, 60, }, + { 9, 0, 0, 2, 13, 34, }, + { 10, 0, 0, 2, 13, 60, }, + { 11, 0, 0, 2, 13, 60, }, { 0, 0, 0, 2, 14, 127, }, { 2, 0, 0, 2, 14, 127, }, { 1, 0, 0, 2, 14, 127, }, @@ -40242,6 +40324,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 2, 14, 127, }, { 8, 0, 0, 2, 14, 127, }, { 9, 0, 0, 2, 14, 127, }, + { 10, 0, 0, 2, 14, 127, }, + { 11, 0, 0, 2, 14, 127, }, { 0, 0, 0, 3, 1, 52, }, { 2, 0, 0, 3, 1, 36, }, { 1, 0, 0, 3, 1, 66, }, @@ -40252,6 +40336,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 1, 36, }, { 8, 0, 0, 3, 1, 52, }, { 9, 0, 0, 3, 1, 36, }, + { 10, 0, 0, 3, 1, 36, }, + { 11, 0, 0, 3, 1, 36, }, { 0, 0, 0, 3, 2, 60, }, { 2, 0, 0, 3, 2, 36, }, { 1, 0, 0, 3, 2, 66, }, @@ -40262,6 +40348,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 2, 36, }, { 8, 0, 0, 3, 2, 60, }, { 9, 0, 0, 3, 2, 36, }, + { 10, 0, 0, 3, 2, 36, }, + { 11, 0, 0, 3, 2, 36, }, { 0, 0, 0, 3, 3, 64, }, { 2, 0, 0, 3, 3, 36, }, { 1, 0, 0, 3, 3, 66, }, @@ -40272,6 +40360,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 3, 36, }, { 8, 0, 0, 3, 3, 64, }, { 9, 0, 0, 3, 3, 36, }, + { 10, 0, 0, 3, 3, 36, }, + { 11, 0, 0, 3, 3, 36, }, { 0, 0, 0, 3, 4, 68, }, { 2, 0, 0, 3, 4, 36, }, { 1, 0, 0, 3, 4, 66, }, @@ -40282,6 +40372,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 4, 36, }, { 8, 0, 0, 3, 4, 68, }, { 9, 0, 0, 3, 4, 36, }, + { 10, 0, 0, 3, 4, 36, }, + { 11, 0, 0, 3, 4, 36, }, { 0, 0, 0, 3, 5, 76, }, { 2, 0, 0, 3, 5, 36, }, { 1, 0, 0, 3, 5, 66, }, @@ -40292,6 +40384,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 5, 36, }, { 8, 0, 0, 3, 5, 76, }, { 9, 0, 0, 3, 5, 36, }, + { 10, 0, 0, 3, 5, 36, }, + { 11, 0, 0, 3, 5, 36, }, { 0, 0, 0, 3, 6, 76, }, { 2, 0, 0, 3, 6, 36, }, { 1, 0, 0, 3, 6, 66, }, @@ -40302,6 +40396,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 6, 36, }, { 8, 0, 0, 3, 6, 76, }, { 9, 0, 0, 3, 6, 36, }, + { 10, 0, 0, 3, 6, 36, }, + { 11, 0, 0, 3, 6, 36, }, { 0, 0, 0, 3, 7, 76, }, { 2, 0, 0, 3, 7, 36, }, { 1, 0, 0, 3, 7, 66, }, @@ -40312,6 +40408,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 7, 36, }, { 8, 0, 0, 3, 7, 76, }, { 9, 0, 0, 3, 7, 36, }, + { 10, 0, 0, 3, 7, 36, }, + { 11, 0, 0, 3, 7, 36, }, { 0, 0, 0, 3, 8, 68, }, { 2, 0, 0, 3, 8, 36, }, { 1, 0, 0, 3, 8, 66, }, @@ -40322,6 +40420,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 8, 36, }, { 8, 0, 0, 3, 8, 68, }, { 9, 0, 0, 3, 8, 36, }, + { 10, 0, 0, 3, 8, 36, }, + { 11, 0, 0, 3, 8, 36, }, { 0, 0, 0, 3, 9, 64, }, { 2, 0, 0, 3, 9, 36, }, { 1, 0, 0, 3, 9, 66, }, @@ -40332,6 +40432,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 9, 36, }, { 8, 0, 0, 3, 9, 64, }, { 9, 0, 0, 3, 9, 36, }, + { 10, 0, 0, 3, 9, 36, }, + { 11, 0, 0, 3, 9, 36, }, { 0, 0, 0, 3, 10, 60, }, { 2, 0, 0, 3, 10, 36, }, { 1, 0, 0, 3, 10, 66, }, @@ -40342,6 +40444,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 10, 36, }, { 8, 0, 0, 3, 10, 60, }, { 9, 0, 0, 3, 10, 36, }, + { 10, 0, 0, 3, 10, 36, }, + { 11, 0, 0, 3, 10, 36, }, { 0, 0, 0, 3, 11, 52, }, { 2, 0, 0, 3, 11, 36, }, { 1, 0, 0, 3, 11, 66, }, @@ -40352,7 +40456,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 11, 36, }, { 8, 0, 0, 3, 11, 52, }, { 9, 0, 0, 3, 11, 36, }, - { 0, 0, 0, 3, 12, 32, }, + { 10, 0, 0, 3, 11, 36, }, + { 11, 0, 0, 3, 11, 36, }, + { 0, 0, 0, 3, 12, 40, }, { 2, 0, 0, 3, 12, 36, }, { 1, 0, 0, 3, 12, 66, }, { 3, 0, 0, 3, 12, 40, }, @@ -40362,7 +40468,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 12, 36, }, { 8, 0, 0, 3, 12, 40, }, { 9, 0, 0, 3, 12, 36, }, - { 0, 0, 0, 3, 13, 20, }, + { 10, 0, 0, 3, 12, 36, }, + { 11, 0, 0, 3, 12, 36, }, + { 0, 0, 0, 3, 13, 28, }, { 2, 0, 0, 3, 13, 36, }, { 1, 0, 0, 3, 13, 66, }, { 3, 0, 0, 3, 13, 28, }, @@ -40371,7 +40479,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 0, 3, 13, 28, }, { 7, 0, 0, 3, 13, 36, }, { 8, 0, 0, 3, 13, 28, }, - { 9, 0, 0, 3, 13, 36, }, + { 9, 0, 0, 3, 13, 34, }, + { 10, 0, 0, 3, 13, 36, }, + { 11, 0, 0, 3, 13, 36, }, { 0, 0, 0, 3, 14, 127, }, { 2, 0, 0, 3, 14, 127, }, { 1, 0, 0, 3, 14, 127, }, @@ -40382,6 +40492,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 0, 3, 14, 127, }, { 8, 0, 0, 3, 14, 127, }, { 9, 0, 0, 3, 14, 127, }, + { 10, 0, 0, 3, 14, 127, }, + { 11, 0, 0, 3, 14, 127, }, { 0, 0, 1, 2, 1, 127, }, { 2, 0, 1, 2, 1, 127, }, { 1, 0, 1, 2, 1, 127, }, @@ -40392,6 +40504,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 1, 127, }, { 8, 0, 1, 2, 1, 127, }, { 9, 0, 1, 2, 1, 127, }, + { 10, 0, 1, 2, 1, 127, }, + { 11, 0, 1, 2, 1, 127, }, { 0, 0, 1, 2, 2, 127, }, { 2, 0, 1, 2, 2, 127, }, { 1, 0, 1, 2, 2, 127, }, @@ -40402,6 +40516,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 2, 127, }, { 8, 0, 1, 2, 2, 127, }, { 9, 0, 1, 2, 2, 127, }, + { 10, 0, 1, 2, 2, 127, }, + { 11, 0, 1, 2, 2, 127, }, { 0, 0, 1, 2, 3, 52, }, { 2, 0, 1, 2, 3, 60, }, { 1, 0, 1, 2, 3, 72, }, @@ -40412,6 +40528,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 3, 60, }, { 8, 0, 1, 2, 3, 52, }, { 9, 0, 1, 2, 3, 60, }, + { 10, 0, 1, 2, 3, 60, }, + { 11, 0, 1, 2, 3, 60, }, { 0, 0, 1, 2, 4, 52, }, { 2, 0, 1, 2, 4, 60, }, { 1, 0, 1, 2, 4, 72, }, @@ -40422,6 +40540,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 4, 60, }, { 8, 0, 1, 2, 4, 52, }, { 9, 0, 1, 2, 4, 60, }, + { 10, 0, 1, 2, 4, 60, }, + { 11, 0, 1, 2, 4, 60, }, { 0, 0, 1, 2, 5, 60, }, { 2, 0, 1, 2, 5, 60, }, { 1, 0, 1, 2, 5, 72, }, @@ -40432,6 +40552,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 5, 60, }, { 8, 0, 1, 2, 5, 60, }, { 9, 0, 1, 2, 5, 60, }, + { 10, 0, 1, 2, 5, 60, }, + { 11, 0, 1, 2, 5, 60, }, { 0, 0, 1, 2, 6, 64, }, { 2, 0, 1, 2, 6, 60, }, { 1, 0, 1, 2, 6, 72, }, @@ -40442,6 +40564,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 6, 60, }, { 8, 0, 1, 2, 6, 64, }, { 9, 0, 1, 2, 6, 60, }, + { 10, 0, 1, 2, 6, 60, }, + { 11, 0, 1, 2, 6, 60, }, { 0, 0, 1, 2, 7, 60, }, { 2, 0, 1, 2, 7, 60, }, { 1, 0, 1, 2, 7, 72, }, @@ -40452,6 +40576,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 7, 60, }, { 8, 0, 1, 2, 7, 60, }, { 9, 0, 1, 2, 7, 60, }, + { 10, 0, 1, 2, 7, 60, }, + { 11, 0, 1, 2, 7, 60, }, { 0, 0, 1, 2, 8, 52, }, { 2, 0, 1, 2, 8, 60, }, { 1, 0, 1, 2, 8, 72, }, @@ -40462,6 +40588,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 8, 60, }, { 8, 0, 1, 2, 8, 52, }, { 9, 0, 1, 2, 8, 60, }, + { 10, 0, 1, 2, 8, 60, }, + { 11, 0, 1, 2, 8, 60, }, { 0, 0, 1, 2, 9, 52, }, { 2, 0, 1, 2, 9, 60, }, { 1, 0, 1, 2, 9, 72, }, @@ -40471,7 +40599,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 1, 2, 9, 52, }, { 7, 0, 1, 2, 9, 60, }, { 8, 0, 1, 2, 9, 52, }, - { 9, 0, 1, 2, 9, 60, }, + { 9, 0, 1, 2, 9, 44, }, + { 10, 0, 1, 2, 9, 60, }, + { 11, 0, 1, 2, 9, 60, }, { 0, 0, 1, 2, 10, 40, }, { 2, 0, 1, 2, 10, 60, }, { 1, 0, 1, 2, 10, 72, }, @@ -40481,7 +40611,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 1, 2, 10, 40, }, { 7, 0, 1, 2, 10, 60, }, { 8, 0, 1, 2, 10, 40, }, - { 9, 0, 1, 2, 10, 60, }, + { 9, 0, 1, 2, 10, 44, }, + { 10, 0, 1, 2, 10, 60, }, + { 11, 0, 1, 2, 10, 60, }, { 0, 0, 1, 2, 11, 28, }, { 2, 0, 1, 2, 11, 60, }, { 1, 0, 1, 2, 11, 72, }, @@ -40491,7 +40623,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 1, 2, 11, 28, }, { 7, 0, 1, 2, 11, 60, }, { 8, 0, 1, 2, 11, 28, }, - { 9, 0, 1, 2, 11, 60, }, + { 9, 0, 1, 2, 11, 16, }, + { 10, 0, 1, 2, 11, 60, }, + { 11, 0, 1, 2, 11, 60, }, { 0, 0, 1, 2, 12, 127, }, { 2, 0, 1, 2, 12, 127, }, { 1, 0, 1, 2, 12, 127, }, @@ -40502,6 +40636,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 12, 127, }, { 8, 0, 1, 2, 12, 127, }, { 9, 0, 1, 2, 12, 127, }, + { 10, 0, 1, 2, 12, 127, }, + { 11, 0, 1, 2, 12, 127, }, { 0, 0, 1, 2, 13, 127, }, { 2, 0, 1, 2, 13, 127, }, { 1, 0, 1, 2, 13, 127, }, @@ -40512,6 +40648,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 13, 127, }, { 8, 0, 1, 2, 13, 127, }, { 9, 0, 1, 2, 13, 127, }, + { 10, 0, 1, 2, 13, 127, }, + { 11, 0, 1, 2, 13, 127, }, { 0, 0, 1, 2, 14, 127, }, { 2, 0, 1, 2, 14, 127, }, { 1, 0, 1, 2, 14, 127, }, @@ -40522,6 +40660,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 2, 14, 127, }, { 8, 0, 1, 2, 14, 127, }, { 9, 0, 1, 2, 14, 127, }, + { 10, 0, 1, 2, 14, 127, }, + { 11, 0, 1, 2, 14, 127, }, { 0, 0, 1, 3, 1, 127, }, { 2, 0, 1, 3, 1, 127, }, { 1, 0, 1, 3, 1, 127, }, @@ -40532,6 +40672,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 1, 127, }, { 8, 0, 1, 3, 1, 127, }, { 9, 0, 1, 3, 1, 127, }, + { 10, 0, 1, 3, 1, 127, }, + { 11, 0, 1, 3, 1, 127, }, { 0, 0, 1, 3, 2, 127, }, { 2, 0, 1, 3, 2, 127, }, { 1, 0, 1, 3, 2, 127, }, @@ -40542,6 +40684,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 2, 127, }, { 8, 0, 1, 3, 2, 127, }, { 9, 0, 1, 3, 2, 127, }, + { 10, 0, 1, 3, 2, 127, }, + { 11, 0, 1, 3, 2, 127, }, { 0, 0, 1, 3, 3, 48, }, { 2, 0, 1, 3, 3, 36, }, { 1, 0, 1, 3, 3, 66, }, @@ -40552,6 +40696,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 3, 36, }, { 8, 0, 1, 3, 3, 48, }, { 9, 0, 1, 3, 3, 36, }, + { 10, 0, 1, 3, 3, 36, }, + { 11, 0, 1, 3, 3, 36, }, { 0, 0, 1, 3, 4, 48, }, { 2, 0, 1, 3, 4, 36, }, { 1, 0, 1, 3, 4, 66, }, @@ -40562,6 +40708,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 4, 36, }, { 8, 0, 1, 3, 4, 48, }, { 9, 0, 1, 3, 4, 36, }, + { 10, 0, 1, 3, 4, 36, }, + { 11, 0, 1, 3, 4, 36, }, { 0, 0, 1, 3, 5, 60, }, { 2, 0, 1, 3, 5, 36, }, { 1, 0, 1, 3, 5, 66, }, @@ -40572,6 +40720,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 5, 36, }, { 8, 0, 1, 3, 5, 60, }, { 9, 0, 1, 3, 5, 36, }, + { 10, 0, 1, 3, 5, 36, }, + { 11, 0, 1, 3, 5, 36, }, { 0, 0, 1, 3, 6, 64, }, { 2, 0, 1, 3, 6, 36, }, { 1, 0, 1, 3, 6, 66, }, @@ -40582,6 +40732,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 6, 36, }, { 8, 0, 1, 3, 6, 64, }, { 9, 0, 1, 3, 6, 36, }, + { 10, 0, 1, 3, 6, 36, }, + { 11, 0, 1, 3, 6, 36, }, { 0, 0, 1, 3, 7, 60, }, { 2, 0, 1, 3, 7, 36, }, { 1, 0, 1, 3, 7, 66, }, @@ -40592,6 +40744,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 7, 36, }, { 8, 0, 1, 3, 7, 60, }, { 9, 0, 1, 3, 7, 36, }, + { 10, 0, 1, 3, 7, 36, }, + { 11, 0, 1, 3, 7, 36, }, { 0, 0, 1, 3, 8, 52, }, { 2, 0, 1, 3, 8, 36, }, { 1, 0, 1, 3, 8, 66, }, @@ -40602,6 +40756,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 8, 36, }, { 8, 0, 1, 3, 8, 52, }, { 9, 0, 1, 3, 8, 36, }, + { 10, 0, 1, 3, 8, 36, }, + { 11, 0, 1, 3, 8, 36, }, { 0, 0, 1, 3, 9, 52, }, { 2, 0, 1, 3, 9, 36, }, { 1, 0, 1, 3, 9, 66, }, @@ -40612,6 +40768,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 9, 36, }, { 8, 0, 1, 3, 9, 52, }, { 9, 0, 1, 3, 9, 36, }, + { 10, 0, 1, 3, 9, 36, }, + { 11, 0, 1, 3, 9, 36, }, { 0, 0, 1, 3, 10, 40, }, { 2, 0, 1, 3, 10, 36, }, { 1, 0, 1, 3, 10, 66, }, @@ -40622,6 +40780,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 10, 36, }, { 8, 0, 1, 3, 10, 40, }, { 9, 0, 1, 3, 10, 36, }, + { 10, 0, 1, 3, 10, 36, }, + { 11, 0, 1, 3, 10, 36, }, { 0, 0, 1, 3, 11, 26, }, { 2, 0, 1, 3, 11, 36, }, { 1, 0, 1, 3, 11, 66, }, @@ -40631,7 +40791,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 0, 1, 3, 11, 26, }, { 7, 0, 1, 3, 11, 36, }, { 8, 0, 1, 3, 11, 26, }, - { 9, 0, 1, 3, 11, 36, }, + { 9, 0, 1, 3, 11, 16, }, + { 10, 0, 1, 3, 11, 36, }, + { 11, 0, 1, 3, 11, 36, }, { 0, 0, 1, 3, 12, 127, }, { 2, 0, 1, 3, 12, 127, }, { 1, 0, 1, 3, 12, 127, }, @@ -40642,6 +40804,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 12, 127, }, { 8, 0, 1, 3, 12, 127, }, { 9, 0, 1, 3, 12, 127, }, + { 10, 0, 1, 3, 12, 127, }, + { 11, 0, 1, 3, 12, 127, }, { 0, 0, 1, 3, 13, 127, }, { 2, 0, 1, 3, 13, 127, }, { 1, 0, 1, 3, 13, 127, }, @@ -40652,6 +40816,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 13, 127, }, { 8, 0, 1, 3, 13, 127, }, { 9, 0, 1, 3, 13, 127, }, + { 10, 0, 1, 3, 13, 127, }, + { 11, 0, 1, 3, 13, 127, }, { 0, 0, 1, 3, 14, 127, }, { 2, 0, 1, 3, 14, 127, }, { 1, 0, 1, 3, 14, 127, }, @@ -40662,6 +40828,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 0, 1, 3, 14, 127, }, { 8, 0, 1, 3, 14, 127, }, { 9, 0, 1, 3, 14, 127, }, + { 10, 0, 1, 3, 14, 127, }, + { 11, 0, 1, 3, 14, 127, }, { 0, 1, 0, 1, 36, 74, }, { 2, 1, 0, 1, 36, 62, }, { 1, 1, 0, 1, 36, 60, }, @@ -40672,6 +40840,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 36, 54, }, { 8, 1, 0, 1, 36, 62, }, { 9, 1, 0, 1, 36, 62, }, + { 10, 1, 0, 1, 36, 62, }, + { 11, 1, 0, 1, 36, 62, }, { 0, 1, 0, 1, 40, 76, }, { 2, 1, 0, 1, 40, 62, }, { 1, 1, 0, 1, 40, 62, }, @@ -40682,6 +40852,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 40, 54, }, { 8, 1, 0, 1, 40, 62, }, { 9, 1, 0, 1, 40, 62, }, + { 10, 1, 0, 1, 40, 62, }, + { 11, 1, 0, 1, 40, 62, }, { 0, 1, 0, 1, 44, 76, }, { 2, 1, 0, 1, 44, 62, }, { 1, 1, 0, 1, 44, 62, }, @@ -40692,6 +40864,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 44, 54, }, { 8, 1, 0, 1, 44, 62, }, { 9, 1, 0, 1, 44, 62, }, + { 10, 1, 0, 1, 44, 62, }, + { 11, 1, 0, 1, 44, 62, }, { 0, 1, 0, 1, 48, 76, }, { 2, 1, 0, 1, 48, 62, }, { 1, 1, 0, 1, 48, 62, }, @@ -40702,6 +40876,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 48, 54, }, { 8, 1, 0, 1, 48, 62, }, { 9, 1, 0, 1, 48, 62, }, + { 10, 1, 0, 1, 48, 62, }, + { 11, 1, 0, 1, 48, 62, }, { 0, 1, 0, 1, 52, 76, }, { 2, 1, 0, 1, 52, 62, }, { 1, 1, 0, 1, 52, 62, }, @@ -40712,6 +40888,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 52, 54, }, { 8, 1, 0, 1, 52, 76, }, { 9, 1, 0, 1, 52, 62, }, + { 10, 1, 0, 1, 52, 62, }, + { 11, 1, 0, 1, 52, 62, }, { 0, 1, 0, 1, 56, 76, }, { 2, 1, 0, 1, 56, 62, }, { 1, 1, 0, 1, 56, 62, }, @@ -40722,6 +40900,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 56, 54, }, { 8, 1, 0, 1, 56, 76, }, { 9, 1, 0, 1, 56, 62, }, + { 10, 1, 0, 1, 56, 62, }, + { 11, 1, 0, 1, 56, 62, }, { 0, 1, 0, 1, 60, 76, }, { 2, 1, 0, 1, 60, 62, }, { 1, 1, 0, 1, 60, 62, }, @@ -40732,6 +40912,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 60, 54, }, { 8, 1, 0, 1, 60, 76, }, { 9, 1, 0, 1, 60, 62, }, + { 10, 1, 0, 1, 60, 62, }, + { 11, 1, 0, 1, 60, 62, }, { 0, 1, 0, 1, 64, 74, }, { 2, 1, 0, 1, 64, 62, }, { 1, 1, 0, 1, 64, 60, }, @@ -40742,6 +40924,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 64, 54, }, { 8, 1, 0, 1, 64, 74, }, { 9, 1, 0, 1, 64, 62, }, + { 10, 1, 0, 1, 64, 62, }, + { 11, 1, 0, 1, 64, 62, }, { 0, 1, 0, 1, 100, 72, }, { 2, 1, 0, 1, 100, 62, }, { 1, 1, 0, 1, 100, 76, }, @@ -40752,6 +40936,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 100, 54, }, { 8, 1, 0, 1, 100, 72, }, { 9, 1, 0, 1, 100, 127, }, + { 10, 1, 0, 1, 100, 54, }, + { 11, 1, 0, 1, 100, 62, }, { 0, 1, 0, 1, 104, 76, }, { 2, 1, 0, 1, 104, 62, }, { 1, 1, 0, 1, 104, 76, }, @@ -40762,6 +40948,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 104, 54, }, { 8, 1, 0, 1, 104, 76, }, { 9, 1, 0, 1, 104, 127, }, + { 10, 1, 0, 1, 104, 54, }, + { 11, 1, 0, 1, 104, 62, }, { 0, 1, 0, 1, 108, 76, }, { 2, 1, 0, 1, 108, 62, }, { 1, 1, 0, 1, 108, 76, }, @@ -40772,6 +40960,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 108, 54, }, { 8, 1, 0, 1, 108, 76, }, { 9, 1, 0, 1, 108, 127, }, + { 10, 1, 0, 1, 108, 54, }, + { 11, 1, 0, 1, 108, 62, }, { 0, 1, 0, 1, 112, 76, }, { 2, 1, 0, 1, 112, 62, }, { 1, 1, 0, 1, 112, 76, }, @@ -40782,6 +40972,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 112, 54, }, { 8, 1, 0, 1, 112, 76, }, { 9, 1, 0, 1, 112, 127, }, + { 10, 1, 0, 1, 112, 54, }, + { 11, 1, 0, 1, 112, 62, }, { 0, 1, 0, 1, 116, 76, }, { 2, 1, 0, 1, 116, 62, }, { 1, 1, 0, 1, 116, 76, }, @@ -40792,6 +40984,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 116, 54, }, { 8, 1, 0, 1, 116, 76, }, { 9, 1, 0, 1, 116, 127, }, + { 10, 1, 0, 1, 116, 54, }, + { 11, 1, 0, 1, 116, 62, }, { 0, 1, 0, 1, 120, 76, }, { 2, 1, 0, 1, 120, 62, }, { 1, 1, 0, 1, 120, 76, }, @@ -40802,6 +40996,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 120, 54, }, { 8, 1, 0, 1, 120, 76, }, { 9, 1, 0, 1, 120, 127, }, + { 10, 1, 0, 1, 120, 54, }, + { 11, 1, 0, 1, 120, 62, }, { 0, 1, 0, 1, 124, 76, }, { 2, 1, 0, 1, 124, 62, }, { 1, 1, 0, 1, 124, 76, }, @@ -40812,6 +41008,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 124, 54, }, { 8, 1, 0, 1, 124, 76, }, { 9, 1, 0, 1, 124, 127, }, + { 10, 1, 0, 1, 124, 54, }, + { 11, 1, 0, 1, 124, 62, }, { 0, 1, 0, 1, 128, 76, }, { 2, 1, 0, 1, 128, 62, }, { 1, 1, 0, 1, 128, 76, }, @@ -40822,6 +41020,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 128, 54, }, { 8, 1, 0, 1, 128, 76, }, { 9, 1, 0, 1, 128, 127, }, + { 10, 1, 0, 1, 128, 54, }, + { 11, 1, 0, 1, 128, 62, }, { 0, 1, 0, 1, 132, 76, }, { 2, 1, 0, 1, 132, 62, }, { 1, 1, 0, 1, 132, 76, }, @@ -40832,6 +41032,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 132, 54, }, { 8, 1, 0, 1, 132, 76, }, { 9, 1, 0, 1, 132, 127, }, + { 10, 1, 0, 1, 132, 54, }, + { 11, 1, 0, 1, 132, 62, }, { 0, 1, 0, 1, 136, 76, }, { 2, 1, 0, 1, 136, 62, }, { 1, 1, 0, 1, 136, 76, }, @@ -40842,6 +41044,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 136, 54, }, { 8, 1, 0, 1, 136, 76, }, { 9, 1, 0, 1, 136, 127, }, + { 10, 1, 0, 1, 136, 54, }, + { 11, 1, 0, 1, 136, 62, }, { 0, 1, 0, 1, 140, 72, }, { 2, 1, 0, 1, 140, 62, }, { 1, 1, 0, 1, 140, 76, }, @@ -40852,6 +41056,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 140, 54, }, { 8, 1, 0, 1, 140, 72, }, { 9, 1, 0, 1, 140, 127, }, + { 10, 1, 0, 1, 140, 54, }, + { 11, 1, 0, 1, 140, 62, }, { 0, 1, 0, 1, 144, 76, }, { 2, 1, 0, 1, 144, 127, }, { 1, 1, 0, 1, 144, 127, }, @@ -40862,8 +41068,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 1, 144, 127, }, { 8, 1, 0, 1, 144, 76, }, { 9, 1, 0, 1, 144, 127, }, + { 10, 1, 0, 1, 144, 127, }, + { 11, 1, 0, 1, 144, 76, }, { 0, 1, 0, 1, 149, 76, }, - { 2, 1, 0, 1, 149, 54, }, + { 2, 1, 0, 1, 149, 28, }, { 1, 1, 0, 1, 149, 127, }, { 3, 1, 0, 1, 149, 76, }, { 4, 1, 0, 1, 149, 74, }, @@ -40871,9 +41079,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 1, 149, 76, }, { 7, 1, 0, 1, 149, 54, }, { 8, 1, 0, 1, 149, 76, }, - { 9, 1, 0, 1, 149, 54, }, + { 9, 1, 0, 1, 149, 28, }, + { 10, 1, 0, 1, 149, 28, }, + { 11, 1, 0, 1, 149, 58, }, { 0, 1, 0, 1, 153, 76, }, - { 2, 1, 0, 1, 153, 54, }, + { 2, 1, 0, 1, 153, 28, }, { 1, 1, 0, 1, 153, 127, }, { 3, 1, 0, 1, 153, 76, }, { 4, 1, 0, 1, 153, 74, }, @@ -40881,9 +41091,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 1, 153, 76, }, { 7, 1, 0, 1, 153, 54, }, { 8, 1, 0, 1, 153, 76, }, - { 9, 1, 0, 1, 153, 54, }, + { 9, 1, 0, 1, 153, 28, }, + { 10, 1, 0, 1, 153, 28, }, + { 11, 1, 0, 1, 153, 58, }, { 0, 1, 0, 1, 157, 76, }, - { 2, 1, 0, 1, 157, 54, }, + { 2, 1, 0, 1, 157, 28, }, { 1, 1, 0, 1, 157, 127, }, { 3, 1, 0, 1, 157, 76, }, { 4, 1, 0, 1, 157, 74, }, @@ -40891,9 +41103,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 1, 157, 76, }, { 7, 1, 0, 1, 157, 54, }, { 8, 1, 0, 1, 157, 76, }, - { 9, 1, 0, 1, 157, 54, }, + { 9, 1, 0, 1, 157, 28, }, + { 10, 1, 0, 1, 157, 28, }, + { 11, 1, 0, 1, 157, 58, }, { 0, 1, 0, 1, 161, 76, }, - { 2, 1, 0, 1, 161, 54, }, + { 2, 1, 0, 1, 161, 28, }, { 1, 1, 0, 1, 161, 127, }, { 3, 1, 0, 1, 161, 76, }, { 4, 1, 0, 1, 161, 74, }, @@ -40901,9 +41115,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 1, 161, 76, }, { 7, 1, 0, 1, 161, 54, }, { 8, 1, 0, 1, 161, 76, }, - { 9, 1, 0, 1, 161, 54, }, + { 9, 1, 0, 1, 161, 28, }, + { 10, 1, 0, 1, 161, 28, }, + { 11, 1, 0, 1, 161, 58, }, { 0, 1, 0, 1, 165, 76, }, - { 2, 1, 0, 1, 165, 54, }, + { 2, 1, 0, 1, 165, 28, }, { 1, 1, 0, 1, 165, 127, }, { 3, 1, 0, 1, 165, 76, }, { 4, 1, 0, 1, 165, 74, }, @@ -40911,7 +41127,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 1, 165, 76, }, { 7, 1, 0, 1, 165, 54, }, { 8, 1, 0, 1, 165, 76, }, - { 9, 1, 0, 1, 165, 54, }, + { 9, 1, 0, 1, 165, 28, }, + { 10, 1, 0, 1, 165, 28, }, + { 11, 1, 0, 1, 165, 58, }, { 0, 1, 0, 2, 36, 72, }, { 2, 1, 0, 2, 36, 62, }, { 1, 1, 0, 2, 36, 62, }, @@ -40922,6 +41140,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 36, 54, }, { 8, 1, 0, 2, 36, 62, }, { 9, 1, 0, 2, 36, 62, }, + { 10, 1, 0, 2, 36, 62, }, + { 11, 1, 0, 2, 36, 62, }, { 0, 1, 0, 2, 40, 76, }, { 2, 1, 0, 2, 40, 62, }, { 1, 1, 0, 2, 40, 62, }, @@ -40932,6 +41152,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 40, 54, }, { 8, 1, 0, 2, 40, 62, }, { 9, 1, 0, 2, 40, 62, }, + { 10, 1, 0, 2, 40, 62, }, + { 11, 1, 0, 2, 40, 62, }, { 0, 1, 0, 2, 44, 76, }, { 2, 1, 0, 2, 44, 62, }, { 1, 1, 0, 2, 44, 62, }, @@ -40942,6 +41164,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 44, 54, }, { 8, 1, 0, 2, 44, 62, }, { 9, 1, 0, 2, 44, 62, }, + { 10, 1, 0, 2, 44, 62, }, + { 11, 1, 0, 2, 44, 62, }, { 0, 1, 0, 2, 48, 76, }, { 2, 1, 0, 2, 48, 62, }, { 1, 1, 0, 2, 48, 62, }, @@ -40952,6 +41176,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 48, 54, }, { 8, 1, 0, 2, 48, 62, }, { 9, 1, 0, 2, 48, 62, }, + { 10, 1, 0, 2, 48, 62, }, + { 11, 1, 0, 2, 48, 62, }, { 0, 1, 0, 2, 52, 76, }, { 2, 1, 0, 2, 52, 62, }, { 1, 1, 0, 2, 52, 62, }, @@ -40962,6 +41188,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 52, 54, }, { 8, 1, 0, 2, 52, 76, }, { 9, 1, 0, 2, 52, 62, }, + { 10, 1, 0, 2, 52, 62, }, + { 11, 1, 0, 2, 52, 62, }, { 0, 1, 0, 2, 56, 76, }, { 2, 1, 0, 2, 56, 62, }, { 1, 1, 0, 2, 56, 62, }, @@ -40972,6 +41200,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 56, 54, }, { 8, 1, 0, 2, 56, 76, }, { 9, 1, 0, 2, 56, 62, }, + { 10, 1, 0, 2, 56, 62, }, + { 11, 1, 0, 2, 56, 62, }, { 0, 1, 0, 2, 60, 76, }, { 2, 1, 0, 2, 60, 62, }, { 1, 1, 0, 2, 60, 62, }, @@ -40982,6 +41212,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 60, 54, }, { 8, 1, 0, 2, 60, 76, }, { 9, 1, 0, 2, 60, 62, }, + { 10, 1, 0, 2, 60, 62, }, + { 11, 1, 0, 2, 60, 62, }, { 0, 1, 0, 2, 64, 74, }, { 2, 1, 0, 2, 64, 62, }, { 1, 1, 0, 2, 64, 60, }, @@ -40992,6 +41224,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 64, 54, }, { 8, 1, 0, 2, 64, 74, }, { 9, 1, 0, 2, 64, 62, }, + { 10, 1, 0, 2, 64, 62, }, + { 11, 1, 0, 2, 64, 62, }, { 0, 1, 0, 2, 100, 70, }, { 2, 1, 0, 2, 100, 62, }, { 1, 1, 0, 2, 100, 76, }, @@ -41002,6 +41236,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 100, 54, }, { 8, 1, 0, 2, 100, 70, }, { 9, 1, 0, 2, 100, 127, }, + { 10, 1, 0, 2, 100, 54, }, + { 11, 1, 0, 2, 100, 62, }, { 0, 1, 0, 2, 104, 76, }, { 2, 1, 0, 2, 104, 62, }, { 1, 1, 0, 2, 104, 76, }, @@ -41012,6 +41248,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 104, 54, }, { 8, 1, 0, 2, 104, 76, }, { 9, 1, 0, 2, 104, 127, }, + { 10, 1, 0, 2, 104, 54, }, + { 11, 1, 0, 2, 104, 62, }, { 0, 1, 0, 2, 108, 76, }, { 2, 1, 0, 2, 108, 62, }, { 1, 1, 0, 2, 108, 76, }, @@ -41022,6 +41260,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 108, 54, }, { 8, 1, 0, 2, 108, 76, }, { 9, 1, 0, 2, 108, 127, }, + { 10, 1, 0, 2, 108, 54, }, + { 11, 1, 0, 2, 108, 62, }, { 0, 1, 0, 2, 112, 76, }, { 2, 1, 0, 2, 112, 62, }, { 1, 1, 0, 2, 112, 76, }, @@ -41032,6 +41272,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 112, 54, }, { 8, 1, 0, 2, 112, 76, }, { 9, 1, 0, 2, 112, 127, }, + { 10, 1, 0, 2, 112, 54, }, + { 11, 1, 0, 2, 112, 62, }, { 0, 1, 0, 2, 116, 76, }, { 2, 1, 0, 2, 116, 62, }, { 1, 1, 0, 2, 116, 76, }, @@ -41042,6 +41284,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 116, 54, }, { 8, 1, 0, 2, 116, 76, }, { 9, 1, 0, 2, 116, 127, }, + { 10, 1, 0, 2, 116, 54, }, + { 11, 1, 0, 2, 116, 62, }, { 0, 1, 0, 2, 120, 76, }, { 2, 1, 0, 2, 120, 62, }, { 1, 1, 0, 2, 120, 76, }, @@ -41052,6 +41296,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 120, 54, }, { 8, 1, 0, 2, 120, 76, }, { 9, 1, 0, 2, 120, 127, }, + { 10, 1, 0, 2, 120, 54, }, + { 11, 1, 0, 2, 120, 62, }, { 0, 1, 0, 2, 124, 76, }, { 2, 1, 0, 2, 124, 62, }, { 1, 1, 0, 2, 124, 76, }, @@ -41062,6 +41308,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 124, 54, }, { 8, 1, 0, 2, 124, 76, }, { 9, 1, 0, 2, 124, 127, }, + { 10, 1, 0, 2, 124, 54, }, + { 11, 1, 0, 2, 124, 62, }, { 0, 1, 0, 2, 128, 76, }, { 2, 1, 0, 2, 128, 62, }, { 1, 1, 0, 2, 128, 76, }, @@ -41072,6 +41320,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 128, 54, }, { 8, 1, 0, 2, 128, 76, }, { 9, 1, 0, 2, 128, 127, }, + { 10, 1, 0, 2, 128, 54, }, + { 11, 1, 0, 2, 128, 62, }, { 0, 1, 0, 2, 132, 76, }, { 2, 1, 0, 2, 132, 62, }, { 1, 1, 0, 2, 132, 76, }, @@ -41082,6 +41332,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 132, 54, }, { 8, 1, 0, 2, 132, 76, }, { 9, 1, 0, 2, 132, 127, }, + { 10, 1, 0, 2, 132, 54, }, + { 11, 1, 0, 2, 132, 62, }, { 0, 1, 0, 2, 136, 76, }, { 2, 1, 0, 2, 136, 62, }, { 1, 1, 0, 2, 136, 76, }, @@ -41092,6 +41344,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 136, 54, }, { 8, 1, 0, 2, 136, 76, }, { 9, 1, 0, 2, 136, 127, }, + { 10, 1, 0, 2, 136, 54, }, + { 11, 1, 0, 2, 136, 62, }, { 0, 1, 0, 2, 140, 70, }, { 2, 1, 0, 2, 140, 62, }, { 1, 1, 0, 2, 140, 76, }, @@ -41102,6 +41356,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 140, 54, }, { 8, 1, 0, 2, 140, 70, }, { 9, 1, 0, 2, 140, 127, }, + { 10, 1, 0, 2, 140, 54, }, + { 11, 1, 0, 2, 140, 62, }, { 0, 1, 0, 2, 144, 76, }, { 2, 1, 0, 2, 144, 127, }, { 1, 1, 0, 2, 144, 127, }, @@ -41112,8 +41368,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 2, 144, 127, }, { 8, 1, 0, 2, 144, 76, }, { 9, 1, 0, 2, 144, 127, }, + { 10, 1, 0, 2, 144, 127, }, + { 11, 1, 0, 2, 144, 76, }, { 0, 1, 0, 2, 149, 76, }, - { 2, 1, 0, 2, 149, 54, }, + { 2, 1, 0, 2, 149, 28, }, { 1, 1, 0, 2, 149, 127, }, { 3, 1, 0, 2, 149, 76, }, { 4, 1, 0, 2, 149, 74, }, @@ -41121,9 +41379,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 2, 149, 76, }, { 7, 1, 0, 2, 149, 54, }, { 8, 1, 0, 2, 149, 76, }, - { 9, 1, 0, 2, 149, 54, }, + { 9, 1, 0, 2, 149, 28, }, + { 10, 1, 0, 2, 149, 28, }, + { 11, 1, 0, 2, 149, 60, }, { 0, 1, 0, 2, 153, 76, }, - { 2, 1, 0, 2, 153, 54, }, + { 2, 1, 0, 2, 153, 28, }, { 1, 1, 0, 2, 153, 127, }, { 3, 1, 0, 2, 153, 76, }, { 4, 1, 0, 2, 153, 74, }, @@ -41131,9 +41391,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 2, 153, 76, }, { 7, 1, 0, 2, 153, 54, }, { 8, 1, 0, 2, 153, 76, }, - { 9, 1, 0, 2, 153, 54, }, + { 9, 1, 0, 2, 153, 28, }, + { 10, 1, 0, 2, 153, 28, }, + { 11, 1, 0, 2, 153, 60, }, { 0, 1, 0, 2, 157, 76, }, - { 2, 1, 0, 2, 157, 54, }, + { 2, 1, 0, 2, 157, 28, }, { 1, 1, 0, 2, 157, 127, }, { 3, 1, 0, 2, 157, 76, }, { 4, 1, 0, 2, 157, 74, }, @@ -41141,9 +41403,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 2, 157, 76, }, { 7, 1, 0, 2, 157, 54, }, { 8, 1, 0, 2, 157, 76, }, - { 9, 1, 0, 2, 157, 54, }, + { 9, 1, 0, 2, 157, 28, }, + { 10, 1, 0, 2, 157, 28, }, + { 11, 1, 0, 2, 157, 60, }, { 0, 1, 0, 2, 161, 76, }, - { 2, 1, 0, 2, 161, 54, }, + { 2, 1, 0, 2, 161, 28, }, { 1, 1, 0, 2, 161, 127, }, { 3, 1, 0, 2, 161, 76, }, { 4, 1, 0, 2, 161, 74, }, @@ -41151,9 +41415,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 2, 161, 76, }, { 7, 1, 0, 2, 161, 54, }, { 8, 1, 0, 2, 161, 76, }, - { 9, 1, 0, 2, 161, 54, }, + { 9, 1, 0, 2, 161, 28, }, + { 10, 1, 0, 2, 161, 28, }, + { 11, 1, 0, 2, 161, 60, }, { 0, 1, 0, 2, 165, 76, }, - { 2, 1, 0, 2, 165, 54, }, + { 2, 1, 0, 2, 165, 28, }, { 1, 1, 0, 2, 165, 127, }, { 3, 1, 0, 2, 165, 76, }, { 4, 1, 0, 2, 165, 74, }, @@ -41161,7 +41427,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 2, 165, 76, }, { 7, 1, 0, 2, 165, 54, }, { 8, 1, 0, 2, 165, 76, }, - { 9, 1, 0, 2, 165, 54, }, + { 9, 1, 0, 2, 165, 28, }, + { 10, 1, 0, 2, 165, 28, }, + { 11, 1, 0, 2, 165, 60, }, { 0, 1, 0, 3, 36, 68, }, { 2, 1, 0, 3, 36, 38, }, { 1, 1, 0, 3, 36, 50, }, @@ -41172,6 +41440,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 36, 30, }, { 8, 1, 0, 3, 36, 50, }, { 9, 1, 0, 3, 36, 38, }, + { 10, 1, 0, 3, 36, 38, }, + { 11, 1, 0, 3, 36, 38, }, { 0, 1, 0, 3, 40, 68, }, { 2, 1, 0, 3, 40, 38, }, { 1, 1, 0, 3, 40, 50, }, @@ -41182,6 +41452,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 40, 30, }, { 8, 1, 0, 3, 40, 50, }, { 9, 1, 0, 3, 40, 38, }, + { 10, 1, 0, 3, 40, 38, }, + { 11, 1, 0, 3, 40, 38, }, { 0, 1, 0, 3, 44, 68, }, { 2, 1, 0, 3, 44, 38, }, { 1, 1, 0, 3, 44, 50, }, @@ -41192,6 +41464,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 44, 30, }, { 8, 1, 0, 3, 44, 50, }, { 9, 1, 0, 3, 44, 38, }, + { 10, 1, 0, 3, 44, 38, }, + { 11, 1, 0, 3, 44, 38, }, { 0, 1, 0, 3, 48, 68, }, { 2, 1, 0, 3, 48, 38, }, { 1, 1, 0, 3, 48, 50, }, @@ -41202,6 +41476,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 48, 30, }, { 8, 1, 0, 3, 48, 50, }, { 9, 1, 0, 3, 48, 38, }, + { 10, 1, 0, 3, 48, 38, }, + { 11, 1, 0, 3, 48, 38, }, { 0, 1, 0, 3, 52, 68, }, { 2, 1, 0, 3, 52, 38, }, { 1, 1, 0, 3, 52, 50, }, @@ -41212,6 +41488,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 52, 30, }, { 8, 1, 0, 3, 52, 68, }, { 9, 1, 0, 3, 52, 38, }, + { 10, 1, 0, 3, 52, 38, }, + { 11, 1, 0, 3, 52, 38, }, { 0, 1, 0, 3, 56, 68, }, { 2, 1, 0, 3, 56, 38, }, { 1, 1, 0, 3, 56, 50, }, @@ -41222,6 +41500,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 56, 30, }, { 8, 1, 0, 3, 56, 68, }, { 9, 1, 0, 3, 56, 38, }, + { 10, 1, 0, 3, 56, 38, }, + { 11, 1, 0, 3, 56, 38, }, { 0, 1, 0, 3, 60, 66, }, { 2, 1, 0, 3, 60, 38, }, { 1, 1, 0, 3, 60, 50, }, @@ -41232,6 +41512,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 60, 30, }, { 8, 1, 0, 3, 60, 66, }, { 9, 1, 0, 3, 60, 38, }, + { 10, 1, 0, 3, 60, 38, }, + { 11, 1, 0, 3, 60, 38, }, { 0, 1, 0, 3, 64, 68, }, { 2, 1, 0, 3, 64, 38, }, { 1, 1, 0, 3, 64, 50, }, @@ -41242,6 +41524,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 64, 30, }, { 8, 1, 0, 3, 64, 68, }, { 9, 1, 0, 3, 64, 38, }, + { 10, 1, 0, 3, 64, 38, }, + { 11, 1, 0, 3, 64, 38, }, { 0, 1, 0, 3, 100, 60, }, { 2, 1, 0, 3, 100, 38, }, { 1, 1, 0, 3, 100, 70, }, @@ -41252,6 +41536,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 100, 30, }, { 8, 1, 0, 3, 100, 60, }, { 9, 1, 0, 3, 100, 127, }, + { 10, 1, 0, 3, 100, 30, }, + { 11, 1, 0, 3, 100, 38, }, { 0, 1, 0, 3, 104, 68, }, { 2, 1, 0, 3, 104, 38, }, { 1, 1, 0, 3, 104, 70, }, @@ -41262,6 +41548,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 104, 30, }, { 8, 1, 0, 3, 104, 68, }, { 9, 1, 0, 3, 104, 127, }, + { 10, 1, 0, 3, 104, 30, }, + { 11, 1, 0, 3, 104, 38, }, { 0, 1, 0, 3, 108, 68, }, { 2, 1, 0, 3, 108, 38, }, { 1, 1, 0, 3, 108, 70, }, @@ -41272,6 +41560,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 108, 30, }, { 8, 1, 0, 3, 108, 68, }, { 9, 1, 0, 3, 108, 127, }, + { 10, 1, 0, 3, 108, 30, }, + { 11, 1, 0, 3, 108, 38, }, { 0, 1, 0, 3, 112, 68, }, { 2, 1, 0, 3, 112, 38, }, { 1, 1, 0, 3, 112, 70, }, @@ -41282,6 +41572,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 112, 30, }, { 8, 1, 0, 3, 112, 68, }, { 9, 1, 0, 3, 112, 127, }, + { 10, 1, 0, 3, 112, 30, }, + { 11, 1, 0, 3, 112, 38, }, { 0, 1, 0, 3, 116, 68, }, { 2, 1, 0, 3, 116, 38, }, { 1, 1, 0, 3, 116, 70, }, @@ -41292,6 +41584,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 116, 30, }, { 8, 1, 0, 3, 116, 68, }, { 9, 1, 0, 3, 116, 127, }, + { 10, 1, 0, 3, 116, 30, }, + { 11, 1, 0, 3, 116, 38, }, { 0, 1, 0, 3, 120, 68, }, { 2, 1, 0, 3, 120, 38, }, { 1, 1, 0, 3, 120, 70, }, @@ -41302,6 +41596,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 120, 30, }, { 8, 1, 0, 3, 120, 68, }, { 9, 1, 0, 3, 120, 127, }, + { 10, 1, 0, 3, 120, 30, }, + { 11, 1, 0, 3, 120, 38, }, { 0, 1, 0, 3, 124, 68, }, { 2, 1, 0, 3, 124, 38, }, { 1, 1, 0, 3, 124, 70, }, @@ -41312,6 +41608,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 124, 30, }, { 8, 1, 0, 3, 124, 68, }, { 9, 1, 0, 3, 124, 127, }, + { 10, 1, 0, 3, 124, 30, }, + { 11, 1, 0, 3, 124, 38, }, { 0, 1, 0, 3, 128, 68, }, { 2, 1, 0, 3, 128, 38, }, { 1, 1, 0, 3, 128, 70, }, @@ -41322,6 +41620,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 128, 30, }, { 8, 1, 0, 3, 128, 68, }, { 9, 1, 0, 3, 128, 127, }, + { 10, 1, 0, 3, 128, 30, }, + { 11, 1, 0, 3, 128, 38, }, { 0, 1, 0, 3, 132, 68, }, { 2, 1, 0, 3, 132, 38, }, { 1, 1, 0, 3, 132, 70, }, @@ -41332,6 +41632,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 132, 30, }, { 8, 1, 0, 3, 132, 68, }, { 9, 1, 0, 3, 132, 127, }, + { 10, 1, 0, 3, 132, 30, }, + { 11, 1, 0, 3, 132, 38, }, { 0, 1, 0, 3, 136, 68, }, { 2, 1, 0, 3, 136, 38, }, { 1, 1, 0, 3, 136, 70, }, @@ -41342,6 +41644,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 136, 30, }, { 8, 1, 0, 3, 136, 68, }, { 9, 1, 0, 3, 136, 127, }, + { 10, 1, 0, 3, 136, 30, }, + { 11, 1, 0, 3, 136, 38, }, { 0, 1, 0, 3, 140, 60, }, { 2, 1, 0, 3, 140, 38, }, { 1, 1, 0, 3, 140, 70, }, @@ -41352,6 +41656,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 140, 30, }, { 8, 1, 0, 3, 140, 60, }, { 9, 1, 0, 3, 140, 127, }, + { 10, 1, 0, 3, 140, 30, }, + { 11, 1, 0, 3, 140, 38, }, { 0, 1, 0, 3, 144, 68, }, { 2, 1, 0, 3, 144, 127, }, { 1, 1, 0, 3, 144, 127, }, @@ -41362,8 +41668,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 0, 3, 144, 127, }, { 8, 1, 0, 3, 144, 68, }, { 9, 1, 0, 3, 144, 127, }, + { 10, 1, 0, 3, 144, 127, }, + { 11, 1, 0, 3, 144, 60, }, { 0, 1, 0, 3, 149, 76, }, - { 2, 1, 0, 3, 149, 30, }, + { 2, 1, 0, 3, 149, 4, }, { 1, 1, 0, 3, 149, 127, }, { 3, 1, 0, 3, 149, 76, }, { 4, 1, 0, 3, 149, 60, }, @@ -41371,9 +41679,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 3, 149, 76, }, { 7, 1, 0, 3, 149, 30, }, { 8, 1, 0, 3, 149, 72, }, - { 9, 1, 0, 3, 149, 30, }, + { 9, 1, 0, 3, 149, 4, }, + { 10, 1, 0, 3, 149, 4, }, + { 11, 1, 0, 3, 149, 36, }, { 0, 1, 0, 3, 153, 76, }, - { 2, 1, 0, 3, 153, 30, }, + { 2, 1, 0, 3, 153, 4, }, { 1, 1, 0, 3, 153, 127, }, { 3, 1, 0, 3, 153, 76, }, { 4, 1, 0, 3, 153, 60, }, @@ -41381,9 +41691,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 3, 153, 76, }, { 7, 1, 0, 3, 153, 30, }, { 8, 1, 0, 3, 153, 76, }, - { 9, 1, 0, 3, 153, 30, }, + { 9, 1, 0, 3, 153, 4, }, + { 10, 1, 0, 3, 153, 4, }, + { 11, 1, 0, 3, 153, 36, }, { 0, 1, 0, 3, 157, 76, }, - { 2, 1, 0, 3, 157, 30, }, + { 2, 1, 0, 3, 157, 4, }, { 1, 1, 0, 3, 157, 127, }, { 3, 1, 0, 3, 157, 76, }, { 4, 1, 0, 3, 157, 60, }, @@ -41391,9 +41703,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 3, 157, 76, }, { 7, 1, 0, 3, 157, 30, }, { 8, 1, 0, 3, 157, 76, }, - { 9, 1, 0, 3, 157, 30, }, + { 9, 1, 0, 3, 157, 4, }, + { 10, 1, 0, 3, 157, 4, }, + { 11, 1, 0, 3, 157, 36, }, { 0, 1, 0, 3, 161, 76, }, - { 2, 1, 0, 3, 161, 30, }, + { 2, 1, 0, 3, 161, 4, }, { 1, 1, 0, 3, 161, 127, }, { 3, 1, 0, 3, 161, 76, }, { 4, 1, 0, 3, 161, 60, }, @@ -41401,9 +41715,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 3, 161, 76, }, { 7, 1, 0, 3, 161, 30, }, { 8, 1, 0, 3, 161, 76, }, - { 9, 1, 0, 3, 161, 30, }, + { 9, 1, 0, 3, 161, 4, }, + { 10, 1, 0, 3, 161, 4, }, + { 11, 1, 0, 3, 161, 36, }, { 0, 1, 0, 3, 165, 76, }, - { 2, 1, 0, 3, 165, 30, }, + { 2, 1, 0, 3, 165, 4, }, { 1, 1, 0, 3, 165, 127, }, { 3, 1, 0, 3, 165, 76, }, { 4, 1, 0, 3, 165, 60, }, @@ -41411,7 +41727,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 0, 3, 165, 76, }, { 7, 1, 0, 3, 165, 30, }, { 8, 1, 0, 3, 165, 76, }, - { 9, 1, 0, 3, 165, 30, }, + { 9, 1, 0, 3, 165, 4, }, + { 10, 1, 0, 3, 165, 4, }, + { 11, 1, 0, 3, 165, 36, }, { 0, 1, 1, 2, 38, 66, }, { 2, 1, 1, 2, 38, 64, }, { 1, 1, 1, 2, 38, 62, }, @@ -41422,6 +41740,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 38, 54, }, { 8, 1, 1, 2, 38, 62, }, { 9, 1, 1, 2, 38, 64, }, + { 10, 1, 1, 2, 38, 64, }, + { 11, 1, 1, 2, 38, 64, }, { 0, 1, 1, 2, 46, 72, }, { 2, 1, 1, 2, 46, 64, }, { 1, 1, 1, 2, 46, 62, }, @@ -41432,6 +41752,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 46, 54, }, { 8, 1, 1, 2, 46, 62, }, { 9, 1, 1, 2, 46, 64, }, + { 10, 1, 1, 2, 46, 64, }, + { 11, 1, 1, 2, 46, 64, }, { 0, 1, 1, 2, 54, 72, }, { 2, 1, 1, 2, 54, 64, }, { 1, 1, 1, 2, 54, 62, }, @@ -41442,6 +41764,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 54, 54, }, { 8, 1, 1, 2, 54, 72, }, { 9, 1, 1, 2, 54, 64, }, + { 10, 1, 1, 2, 54, 64, }, + { 11, 1, 1, 2, 54, 64, }, { 0, 1, 1, 2, 62, 64, }, { 2, 1, 1, 2, 62, 64, }, { 1, 1, 1, 2, 62, 62, }, @@ -41452,6 +41776,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 62, 54, }, { 8, 1, 1, 2, 62, 64, }, { 9, 1, 1, 2, 62, 64, }, + { 10, 1, 1, 2, 62, 64, }, + { 11, 1, 1, 2, 62, 64, }, { 0, 1, 1, 2, 102, 58, }, { 2, 1, 1, 2, 102, 64, }, { 1, 1, 1, 2, 102, 72, }, @@ -41462,6 +41788,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 102, 54, }, { 8, 1, 1, 2, 102, 58, }, { 9, 1, 1, 2, 102, 127, }, + { 10, 1, 1, 2, 102, 54, }, + { 11, 1, 1, 2, 102, 64, }, { 0, 1, 1, 2, 110, 72, }, { 2, 1, 1, 2, 110, 64, }, { 1, 1, 1, 2, 110, 72, }, @@ -41472,6 +41800,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 110, 54, }, { 8, 1, 1, 2, 110, 72, }, { 9, 1, 1, 2, 110, 127, }, + { 10, 1, 1, 2, 110, 54, }, + { 11, 1, 1, 2, 110, 64, }, { 0, 1, 1, 2, 118, 72, }, { 2, 1, 1, 2, 118, 64, }, { 1, 1, 1, 2, 118, 72, }, @@ -41482,6 +41812,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 118, 54, }, { 8, 1, 1, 2, 118, 72, }, { 9, 1, 1, 2, 118, 127, }, + { 10, 1, 1, 2, 118, 54, }, + { 11, 1, 1, 2, 118, 64, }, { 0, 1, 1, 2, 126, 72, }, { 2, 1, 1, 2, 126, 64, }, { 1, 1, 1, 2, 126, 72, }, @@ -41492,6 +41824,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 126, 54, }, { 8, 1, 1, 2, 126, 72, }, { 9, 1, 1, 2, 126, 127, }, + { 10, 1, 1, 2, 126, 54, }, + { 11, 1, 1, 2, 126, 64, }, { 0, 1, 1, 2, 134, 72, }, { 2, 1, 1, 2, 134, 64, }, { 1, 1, 1, 2, 134, 72, }, @@ -41502,6 +41836,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 134, 54, }, { 8, 1, 1, 2, 134, 72, }, { 9, 1, 1, 2, 134, 127, }, + { 10, 1, 1, 2, 134, 54, }, + { 11, 1, 1, 2, 134, 64, }, { 0, 1, 1, 2, 142, 72, }, { 2, 1, 1, 2, 142, 127, }, { 1, 1, 1, 2, 142, 127, }, @@ -41512,8 +41848,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 2, 142, 127, }, { 8, 1, 1, 2, 142, 72, }, { 9, 1, 1, 2, 142, 127, }, + { 10, 1, 1, 2, 142, 127, }, + { 11, 1, 1, 2, 142, 72, }, { 0, 1, 1, 2, 151, 72, }, - { 2, 1, 1, 2, 151, 54, }, + { 2, 1, 1, 2, 151, 28, }, { 1, 1, 1, 2, 151, 127, }, { 3, 1, 1, 2, 151, 72, }, { 4, 1, 1, 2, 151, 72, }, @@ -41521,9 +41859,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 1, 2, 151, 72, }, { 7, 1, 1, 2, 151, 54, }, { 8, 1, 1, 2, 151, 72, }, - { 9, 1, 1, 2, 151, 54, }, + { 9, 1, 1, 2, 151, 28, }, + { 10, 1, 1, 2, 151, 28, }, + { 11, 1, 1, 2, 151, 64, }, { 0, 1, 1, 2, 159, 72, }, - { 2, 1, 1, 2, 159, 54, }, + { 2, 1, 1, 2, 159, 28, }, { 1, 1, 1, 2, 159, 127, }, { 3, 1, 1, 2, 159, 72, }, { 4, 1, 1, 2, 159, 72, }, @@ -41531,7 +41871,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 1, 2, 159, 72, }, { 7, 1, 1, 2, 159, 54, }, { 8, 1, 1, 2, 159, 72, }, - { 9, 1, 1, 2, 159, 54, }, + { 9, 1, 1, 2, 159, 28, }, + { 10, 1, 1, 2, 159, 28, }, + { 11, 1, 1, 2, 159, 64, }, { 0, 1, 1, 3, 38, 60, }, { 2, 1, 1, 3, 38, 40, }, { 1, 1, 1, 3, 38, 50, }, @@ -41542,6 +41884,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 38, 30, }, { 8, 1, 1, 3, 38, 50, }, { 9, 1, 1, 3, 38, 40, }, + { 10, 1, 1, 3, 38, 40, }, + { 11, 1, 1, 3, 38, 40, }, { 0, 1, 1, 3, 46, 68, }, { 2, 1, 1, 3, 46, 40, }, { 1, 1, 1, 3, 46, 50, }, @@ -41552,6 +41896,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 46, 30, }, { 8, 1, 1, 3, 46, 50, }, { 9, 1, 1, 3, 46, 40, }, + { 10, 1, 1, 3, 46, 40, }, + { 11, 1, 1, 3, 46, 40, }, { 0, 1, 1, 3, 54, 68, }, { 2, 1, 1, 3, 54, 40, }, { 1, 1, 1, 3, 54, 50, }, @@ -41562,6 +41908,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 54, 30, }, { 8, 1, 1, 3, 54, 68, }, { 9, 1, 1, 3, 54, 40, }, + { 10, 1, 1, 3, 54, 40, }, + { 11, 1, 1, 3, 54, 40, }, { 0, 1, 1, 3, 62, 58, }, { 2, 1, 1, 3, 62, 40, }, { 1, 1, 1, 3, 62, 48, }, @@ -41572,6 +41920,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 62, 30, }, { 8, 1, 1, 3, 62, 58, }, { 9, 1, 1, 3, 62, 40, }, + { 10, 1, 1, 3, 62, 40, }, + { 11, 1, 1, 3, 62, 40, }, { 0, 1, 1, 3, 102, 54, }, { 2, 1, 1, 3, 102, 40, }, { 1, 1, 1, 3, 102, 70, }, @@ -41582,6 +41932,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 102, 30, }, { 8, 1, 1, 3, 102, 54, }, { 9, 1, 1, 3, 102, 127, }, + { 10, 1, 1, 3, 102, 30, }, + { 11, 1, 1, 3, 102, 40, }, { 0, 1, 1, 3, 110, 68, }, { 2, 1, 1, 3, 110, 40, }, { 1, 1, 1, 3, 110, 70, }, @@ -41592,6 +41944,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 110, 30, }, { 8, 1, 1, 3, 110, 68, }, { 9, 1, 1, 3, 110, 127, }, + { 10, 1, 1, 3, 110, 30, }, + { 11, 1, 1, 3, 110, 40, }, { 0, 1, 1, 3, 118, 68, }, { 2, 1, 1, 3, 118, 40, }, { 1, 1, 1, 3, 118, 70, }, @@ -41602,6 +41956,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 118, 30, }, { 8, 1, 1, 3, 118, 68, }, { 9, 1, 1, 3, 118, 127, }, + { 10, 1, 1, 3, 118, 30, }, + { 11, 1, 1, 3, 118, 40, }, { 0, 1, 1, 3, 126, 68, }, { 2, 1, 1, 3, 126, 40, }, { 1, 1, 1, 3, 126, 70, }, @@ -41612,6 +41968,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 126, 30, }, { 8, 1, 1, 3, 126, 68, }, { 9, 1, 1, 3, 126, 127, }, + { 10, 1, 1, 3, 126, 30, }, + { 11, 1, 1, 3, 126, 40, }, { 0, 1, 1, 3, 134, 68, }, { 2, 1, 1, 3, 134, 40, }, { 1, 1, 1, 3, 134, 70, }, @@ -41622,6 +41980,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 134, 30, }, { 8, 1, 1, 3, 134, 68, }, { 9, 1, 1, 3, 134, 127, }, + { 10, 1, 1, 3, 134, 30, }, + { 11, 1, 1, 3, 134, 40, }, { 0, 1, 1, 3, 142, 68, }, { 2, 1, 1, 3, 142, 127, }, { 1, 1, 1, 3, 142, 127, }, @@ -41632,8 +41992,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 1, 3, 142, 127, }, { 8, 1, 1, 3, 142, 68, }, { 9, 1, 1, 3, 142, 127, }, + { 10, 1, 1, 3, 142, 127, }, + { 11, 1, 1, 3, 142, 62, }, { 0, 1, 1, 3, 151, 72, }, - { 2, 1, 1, 3, 151, 30, }, + { 2, 1, 1, 3, 151, 4, }, { 1, 1, 1, 3, 151, 127, }, { 3, 1, 1, 3, 151, 72, }, { 4, 1, 1, 3, 151, 66, }, @@ -41641,9 +42003,11 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 1, 3, 151, 72, }, { 7, 1, 1, 3, 151, 30, }, { 8, 1, 1, 3, 151, 68, }, - { 9, 1, 1, 3, 151, 30, }, + { 9, 1, 1, 3, 151, 4, }, + { 10, 1, 1, 3, 151, 4, }, + { 11, 1, 1, 3, 151, 40, }, { 0, 1, 1, 3, 159, 72, }, - { 2, 1, 1, 3, 159, 30, }, + { 2, 1, 1, 3, 159, 4, }, { 1, 1, 1, 3, 159, 127, }, { 3, 1, 1, 3, 159, 72, }, { 4, 1, 1, 3, 159, 66, }, @@ -41651,7 +42015,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 1, 3, 159, 72, }, { 7, 1, 1, 3, 159, 30, }, { 8, 1, 1, 3, 159, 72, }, - { 9, 1, 1, 3, 159, 30, }, + { 9, 1, 1, 3, 159, 4, }, + { 10, 1, 1, 3, 159, 4, }, + { 11, 1, 1, 3, 159, 40, }, { 0, 1, 2, 4, 42, 64, }, { 2, 1, 2, 4, 42, 64, }, { 1, 1, 2, 4, 42, 64, }, @@ -41662,6 +42028,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 4, 42, 54, }, { 8, 1, 2, 4, 42, 62, }, { 9, 1, 2, 4, 42, 64, }, + { 10, 1, 2, 4, 42, 64, }, + { 11, 1, 2, 4, 42, 64, }, { 0, 1, 2, 4, 58, 62, }, { 2, 1, 2, 4, 58, 64, }, { 1, 1, 2, 4, 58, 64, }, @@ -41672,6 +42040,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 4, 58, 54, }, { 8, 1, 2, 4, 58, 62, }, { 9, 1, 2, 4, 58, 64, }, + { 10, 1, 2, 4, 58, 64, }, + { 11, 1, 2, 4, 58, 64, }, { 0, 1, 2, 4, 106, 58, }, { 2, 1, 2, 4, 106, 64, }, { 1, 1, 2, 4, 106, 72, }, @@ -41682,6 +42052,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 4, 106, 54, }, { 8, 1, 2, 4, 106, 58, }, { 9, 1, 2, 4, 106, 127, }, + { 10, 1, 2, 4, 106, 54, }, + { 11, 1, 2, 4, 106, 64, }, { 0, 1, 2, 4, 122, 72, }, { 2, 1, 2, 4, 122, 64, }, { 1, 1, 2, 4, 122, 72, }, @@ -41692,6 +42064,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 4, 122, 54, }, { 8, 1, 2, 4, 122, 72, }, { 9, 1, 2, 4, 122, 127, }, + { 10, 1, 2, 4, 122, 54, }, + { 11, 1, 2, 4, 122, 64, }, { 0, 1, 2, 4, 138, 72, }, { 2, 1, 2, 4, 138, 127, }, { 1, 1, 2, 4, 138, 127, }, @@ -41702,8 +42076,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 4, 138, 127, }, { 8, 1, 2, 4, 138, 72, }, { 9, 1, 2, 4, 138, 127, }, + { 10, 1, 2, 4, 138, 127, }, + { 11, 1, 2, 4, 138, 72, }, { 0, 1, 2, 4, 155, 72, }, - { 2, 1, 2, 4, 155, 54, }, + { 2, 1, 2, 4, 155, 28, }, { 1, 1, 2, 4, 155, 127, }, { 3, 1, 2, 4, 155, 72, }, { 4, 1, 2, 4, 155, 68, }, @@ -41711,7 +42087,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 2, 4, 155, 72, }, { 7, 1, 2, 4, 155, 54, }, { 8, 1, 2, 4, 155, 68, }, - { 9, 1, 2, 4, 155, 54, }, + { 9, 1, 2, 4, 155, 28, }, + { 10, 1, 2, 4, 155, 28, }, + { 11, 1, 2, 4, 155, 64, }, { 0, 1, 2, 5, 42, 54, }, { 2, 1, 2, 5, 42, 40, }, { 1, 1, 2, 5, 42, 50, }, @@ -41722,6 +42100,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 5, 42, 30, }, { 8, 1, 2, 5, 42, 50, }, { 9, 1, 2, 5, 42, 40, }, + { 10, 1, 2, 5, 42, 40, }, + { 11, 1, 2, 5, 42, 40, }, { 0, 1, 2, 5, 58, 52, }, { 2, 1, 2, 5, 58, 40, }, { 1, 1, 2, 5, 58, 50, }, @@ -41732,6 +42112,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 5, 58, 30, }, { 8, 1, 2, 5, 58, 52, }, { 9, 1, 2, 5, 58, 40, }, + { 10, 1, 2, 5, 58, 40, }, + { 11, 1, 2, 5, 58, 40, }, { 0, 1, 2, 5, 106, 50, }, { 2, 1, 2, 5, 106, 40, }, { 1, 1, 2, 5, 106, 72, }, @@ -41742,6 +42124,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 5, 106, 30, }, { 8, 1, 2, 5, 106, 50, }, { 9, 1, 2, 5, 106, 127, }, + { 10, 1, 2, 5, 106, 30, }, + { 11, 1, 2, 5, 106, 40, }, { 0, 1, 2, 5, 122, 66, }, { 2, 1, 2, 5, 122, 40, }, { 1, 1, 2, 5, 122, 72, }, @@ -41752,6 +42136,8 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 5, 122, 30, }, { 8, 1, 2, 5, 122, 66, }, { 9, 1, 2, 5, 122, 127, }, + { 10, 1, 2, 5, 122, 30, }, + { 11, 1, 2, 5, 122, 40, }, { 0, 1, 2, 5, 138, 66, }, { 2, 1, 2, 5, 138, 127, }, { 1, 1, 2, 5, 138, 127, }, @@ -41762,8 +42148,10 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 7, 1, 2, 5, 138, 127, }, { 8, 1, 2, 5, 138, 66, }, { 9, 1, 2, 5, 138, 127, }, + { 10, 1, 2, 5, 138, 127, }, + { 11, 1, 2, 5, 138, 60, }, { 0, 1, 2, 5, 155, 62, }, - { 2, 1, 2, 5, 155, 30, }, + { 2, 1, 2, 5, 155, 4, }, { 1, 1, 2, 5, 155, 127, }, { 3, 1, 2, 5, 155, 62, }, { 4, 1, 2, 5, 155, 58, }, @@ -41771,7 +42159,9 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type0[] = { { 6, 1, 2, 5, 155, 62, }, { 7, 1, 2, 5, 155, 30, }, { 8, 1, 2, 5, 155, 62, }, - { 9, 1, 2, 5, 155, 30, }, + { 9, 1, 2, 5, 155, 4, }, + { 10, 1, 2, 5, 155, 4, }, + { 11, 1, 2, 5, 155, 40, }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type0); @@ -41783,9 +42173,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 1, 72, }, { 4, 0, 0, 0, 1, 76, }, { 5, 0, 0, 0, 1, 56, }, - { 6, 0, 0, 0, 1, 72, }, - { 7, 0, 0, 0, 1, 60, }, - { 8, 0, 0, 0, 1, 72, }, { 9, 0, 0, 0, 1, 60, }, { 0, 0, 0, 0, 2, 72, }, { 2, 0, 0, 0, 2, 56, }, @@ -41793,9 +42180,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 2, 72, }, { 4, 0, 0, 0, 2, 76, }, { 5, 0, 0, 0, 2, 56, }, - { 6, 0, 0, 0, 2, 72, }, - { 7, 0, 0, 0, 2, 60, }, - { 8, 0, 0, 0, 2, 72, }, { 9, 0, 0, 0, 2, 60, }, { 0, 0, 0, 0, 3, 76, }, { 2, 0, 0, 0, 3, 56, }, @@ -41803,9 +42187,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 3, 76, }, { 4, 0, 0, 0, 3, 76, }, { 5, 0, 0, 0, 3, 56, }, - { 6, 0, 0, 0, 3, 76, }, - { 7, 0, 0, 0, 3, 60, }, - { 8, 0, 0, 0, 3, 76, }, { 9, 0, 0, 0, 3, 60, }, { 0, 0, 0, 0, 4, 76, }, { 2, 0, 0, 0, 4, 56, }, @@ -41813,9 +42194,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 4, 76, }, { 4, 0, 0, 0, 4, 76, }, { 5, 0, 0, 0, 4, 56, }, - { 6, 0, 0, 0, 4, 76, }, - { 7, 0, 0, 0, 4, 60, }, - { 8, 0, 0, 0, 4, 76, }, { 9, 0, 0, 0, 4, 60, }, { 0, 0, 0, 0, 5, 76, }, { 2, 0, 0, 0, 5, 56, }, @@ -41823,9 +42201,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 5, 76, }, { 4, 0, 0, 0, 5, 76, }, { 5, 0, 0, 0, 5, 56, }, - { 6, 0, 0, 0, 5, 76, }, - { 7, 0, 0, 0, 5, 60, }, - { 8, 0, 0, 0, 5, 76, }, { 9, 0, 0, 0, 5, 60, }, { 0, 0, 0, 0, 6, 76, }, { 2, 0, 0, 0, 6, 56, }, @@ -41833,9 +42208,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 6, 76, }, { 4, 0, 0, 0, 6, 76, }, { 5, 0, 0, 0, 6, 56, }, - { 6, 0, 0, 0, 6, 76, }, - { 7, 0, 0, 0, 6, 60, }, - { 8, 0, 0, 0, 6, 76, }, { 9, 0, 0, 0, 6, 60, }, { 0, 0, 0, 0, 7, 76, }, { 2, 0, 0, 0, 7, 56, }, @@ -41843,9 +42215,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 7, 76, }, { 4, 0, 0, 0, 7, 76, }, { 5, 0, 0, 0, 7, 56, }, - { 6, 0, 0, 0, 7, 76, }, - { 7, 0, 0, 0, 7, 60, }, - { 8, 0, 0, 0, 7, 76, }, { 9, 0, 0, 0, 7, 60, }, { 0, 0, 0, 0, 8, 76, }, { 2, 0, 0, 0, 8, 56, }, @@ -41853,9 +42222,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 8, 76, }, { 4, 0, 0, 0, 8, 76, }, { 5, 0, 0, 0, 8, 56, }, - { 6, 0, 0, 0, 8, 76, }, - { 7, 0, 0, 0, 8, 60, }, - { 8, 0, 0, 0, 8, 76, }, { 9, 0, 0, 0, 8, 60, }, { 0, 0, 0, 0, 9, 76, }, { 2, 0, 0, 0, 9, 56, }, @@ -41863,9 +42229,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 9, 76, }, { 4, 0, 0, 0, 9, 76, }, { 5, 0, 0, 0, 9, 56, }, - { 6, 0, 0, 0, 9, 76, }, - { 7, 0, 0, 0, 9, 60, }, - { 8, 0, 0, 0, 9, 76, }, { 9, 0, 0, 0, 9, 60, }, { 0, 0, 0, 0, 10, 72, }, { 2, 0, 0, 0, 10, 56, }, @@ -41873,9 +42236,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 10, 72, }, { 4, 0, 0, 0, 10, 76, }, { 5, 0, 0, 0, 10, 56, }, - { 6, 0, 0, 0, 10, 72, }, - { 7, 0, 0, 0, 10, 60, }, - { 8, 0, 0, 0, 10, 72, }, { 9, 0, 0, 0, 10, 60, }, { 0, 0, 0, 0, 11, 72, }, { 2, 0, 0, 0, 11, 56, }, @@ -41883,29 +42243,20 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 11, 72, }, { 4, 0, 0, 0, 11, 76, }, { 5, 0, 0, 0, 11, 56, }, - { 6, 0, 0, 0, 11, 72, }, - { 7, 0, 0, 0, 11, 60, }, - { 8, 0, 0, 0, 11, 72, }, { 9, 0, 0, 0, 11, 60, }, - { 0, 0, 0, 0, 12, 44, }, + { 0, 0, 0, 0, 12, 52, }, { 2, 0, 0, 0, 12, 56, }, { 1, 0, 0, 0, 12, 72, }, { 3, 0, 0, 0, 12, 52, }, { 4, 0, 0, 0, 12, 76, }, { 5, 0, 0, 0, 12, 56, }, - { 6, 0, 0, 0, 12, 52, }, - { 7, 0, 0, 0, 12, 60, }, - { 8, 0, 0, 0, 12, 52, }, { 9, 0, 0, 0, 12, 60, }, - { 0, 0, 0, 0, 13, 40, }, + { 0, 0, 0, 0, 13, 48, }, { 2, 0, 0, 0, 13, 56, }, { 1, 0, 0, 0, 13, 72, }, { 3, 0, 0, 0, 13, 48, }, { 4, 0, 0, 0, 13, 76, }, { 5, 0, 0, 0, 13, 56, }, - { 6, 0, 0, 0, 13, 48, }, - { 7, 0, 0, 0, 13, 60, }, - { 8, 0, 0, 0, 13, 48, }, { 9, 0, 0, 0, 13, 60, }, { 0, 0, 0, 0, 14, 127, }, { 2, 0, 0, 0, 14, 127, }, @@ -41913,9 +42264,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 0, 14, 127, }, { 4, 0, 0, 0, 14, 127, }, { 5, 0, 0, 0, 14, 127, }, - { 6, 0, 0, 0, 14, 127, }, - { 7, 0, 0, 0, 14, 127, }, - { 8, 0, 0, 0, 14, 127, }, { 9, 0, 0, 0, 14, 127, }, { 0, 0, 0, 1, 1, 52, }, { 2, 0, 0, 1, 1, 60, }, @@ -41923,9 +42271,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 1, 52, }, { 4, 0, 0, 1, 1, 76, }, { 5, 0, 0, 1, 1, 60, }, - { 6, 0, 0, 1, 1, 52, }, - { 7, 0, 0, 1, 1, 60, }, - { 8, 0, 0, 1, 1, 52, }, { 9, 0, 0, 1, 1, 60, }, { 0, 0, 0, 1, 2, 60, }, { 2, 0, 0, 1, 2, 60, }, @@ -41933,9 +42278,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 2, 60, }, { 4, 0, 0, 1, 2, 76, }, { 5, 0, 0, 1, 2, 60, }, - { 6, 0, 0, 1, 2, 60, }, - { 7, 0, 0, 1, 2, 60, }, - { 8, 0, 0, 1, 2, 60, }, { 9, 0, 0, 1, 2, 60, }, { 0, 0, 0, 1, 3, 64, }, { 2, 0, 0, 1, 3, 60, }, @@ -41943,9 +42285,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 3, 64, }, { 4, 0, 0, 1, 3, 76, }, { 5, 0, 0, 1, 3, 60, }, - { 6, 0, 0, 1, 3, 64, }, - { 7, 0, 0, 1, 3, 60, }, - { 8, 0, 0, 1, 3, 64, }, { 9, 0, 0, 1, 3, 60, }, { 0, 0, 0, 1, 4, 68, }, { 2, 0, 0, 1, 4, 60, }, @@ -41953,9 +42292,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 4, 68, }, { 4, 0, 0, 1, 4, 76, }, { 5, 0, 0, 1, 4, 60, }, - { 6, 0, 0, 1, 4, 68, }, - { 7, 0, 0, 1, 4, 60, }, - { 8, 0, 0, 1, 4, 68, }, { 9, 0, 0, 1, 4, 60, }, { 0, 0, 0, 1, 5, 76, }, { 2, 0, 0, 1, 5, 60, }, @@ -41963,9 +42299,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 5, 76, }, { 4, 0, 0, 1, 5, 76, }, { 5, 0, 0, 1, 5, 60, }, - { 6, 0, 0, 1, 5, 76, }, - { 7, 0, 0, 1, 5, 60, }, - { 8, 0, 0, 1, 5, 76, }, { 9, 0, 0, 1, 5, 60, }, { 0, 0, 0, 1, 6, 76, }, { 2, 0, 0, 1, 6, 60, }, @@ -41973,9 +42306,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 6, 76, }, { 4, 0, 0, 1, 6, 76, }, { 5, 0, 0, 1, 6, 60, }, - { 6, 0, 0, 1, 6, 76, }, - { 7, 0, 0, 1, 6, 60, }, - { 8, 0, 0, 1, 6, 76, }, { 9, 0, 0, 1, 6, 60, }, { 0, 0, 0, 1, 7, 76, }, { 2, 0, 0, 1, 7, 60, }, @@ -41983,9 +42313,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 7, 76, }, { 4, 0, 0, 1, 7, 76, }, { 5, 0, 0, 1, 7, 60, }, - { 6, 0, 0, 1, 7, 76, }, - { 7, 0, 0, 1, 7, 60, }, - { 8, 0, 0, 1, 7, 76, }, { 9, 0, 0, 1, 7, 60, }, { 0, 0, 0, 1, 8, 68, }, { 2, 0, 0, 1, 8, 60, }, @@ -41993,9 +42320,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 8, 68, }, { 4, 0, 0, 1, 8, 76, }, { 5, 0, 0, 1, 8, 60, }, - { 6, 0, 0, 1, 8, 68, }, - { 7, 0, 0, 1, 8, 60, }, - { 8, 0, 0, 1, 8, 68, }, { 9, 0, 0, 1, 8, 60, }, { 0, 0, 0, 1, 9, 64, }, { 2, 0, 0, 1, 9, 60, }, @@ -42003,9 +42327,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 9, 64, }, { 4, 0, 0, 1, 9, 76, }, { 5, 0, 0, 1, 9, 60, }, - { 6, 0, 0, 1, 9, 64, }, - { 7, 0, 0, 1, 9, 60, }, - { 8, 0, 0, 1, 9, 64, }, { 9, 0, 0, 1, 9, 60, }, { 0, 0, 0, 1, 10, 60, }, { 2, 0, 0, 1, 10, 60, }, @@ -42013,9 +42334,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 10, 60, }, { 4, 0, 0, 1, 10, 76, }, { 5, 0, 0, 1, 10, 60, }, - { 6, 0, 0, 1, 10, 60, }, - { 7, 0, 0, 1, 10, 60, }, - { 8, 0, 0, 1, 10, 60, }, { 9, 0, 0, 1, 10, 60, }, { 0, 0, 0, 1, 11, 52, }, { 2, 0, 0, 1, 11, 60, }, @@ -42023,39 +42341,27 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 1, 11, 52, }, { 4, 0, 0, 1, 11, 76, }, { 5, 0, 0, 1, 11, 60, }, - { 6, 0, 0, 1, 11, 52, }, - { 7, 0, 0, 1, 11, 60, }, - { 8, 0, 0, 1, 11, 52, }, - { 9, 0, 0, 1, 11, 60, }, - { 0, 0, 0, 1, 12, 32, }, + { 9, 0, 0, 1, 11, 52, }, + { 0, 0, 0, 1, 12, 40, }, { 2, 0, 0, 1, 12, 60, }, { 1, 0, 0, 1, 12, 76, }, { 3, 0, 0, 1, 12, 40, }, { 4, 0, 0, 1, 12, 76, }, { 5, 0, 0, 1, 12, 60, }, - { 6, 0, 0, 1, 12, 40, }, - { 7, 0, 0, 1, 12, 60, }, - { 8, 0, 0, 1, 12, 40, }, - { 9, 0, 0, 1, 12, 60, }, - { 0, 0, 0, 1, 13, 20, }, + { 9, 0, 0, 1, 12, 48, }, + { 0, 0, 0, 1, 13, 28, }, { 2, 0, 0, 1, 13, 60, }, { 1, 0, 0, 1, 13, 76, }, { 3, 0, 0, 1, 13, 28, }, { 4, 0, 0, 1, 13, 74, }, { 5, 0, 0, 1, 13, 60, }, - { 6, 0, 0, 1, 13, 28, }, - { 7, 0, 0, 1, 13, 60, }, - { 8, 0, 0, 1, 13, 28, }, - { 9, 0, 0, 1, 13, 60, }, + { 9, 0, 0, 1, 13, 40, }, { 0, 0, 0, 1, 14, 127, }, { 2, 0, 0, 1, 14, 127, }, { 1, 0, 0, 1, 14, 127, }, { 3, 0, 0, 1, 14, 127, }, { 4, 0, 0, 1, 14, 127, }, { 5, 0, 0, 1, 14, 127, }, - { 6, 0, 0, 1, 14, 127, }, - { 7, 0, 0, 1, 14, 127, }, - { 8, 0, 0, 1, 14, 127, }, { 9, 0, 0, 1, 14, 127, }, { 0, 0, 0, 2, 1, 52, }, { 2, 0, 0, 2, 1, 60, }, @@ -42063,9 +42369,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 1, 52, }, { 4, 0, 0, 2, 1, 76, }, { 5, 0, 0, 2, 1, 60, }, - { 6, 0, 0, 2, 1, 52, }, - { 7, 0, 0, 2, 1, 60, }, - { 8, 0, 0, 2, 1, 52, }, { 9, 0, 0, 2, 1, 60, }, { 0, 0, 0, 2, 2, 60, }, { 2, 0, 0, 2, 2, 60, }, @@ -42073,9 +42376,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 2, 60, }, { 4, 0, 0, 2, 2, 76, }, { 5, 0, 0, 2, 2, 60, }, - { 6, 0, 0, 2, 2, 60, }, - { 7, 0, 0, 2, 2, 60, }, - { 8, 0, 0, 2, 2, 60, }, { 9, 0, 0, 2, 2, 60, }, { 0, 0, 0, 2, 3, 64, }, { 2, 0, 0, 2, 3, 60, }, @@ -42083,9 +42383,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 3, 64, }, { 4, 0, 0, 2, 3, 76, }, { 5, 0, 0, 2, 3, 60, }, - { 6, 0, 0, 2, 3, 64, }, - { 7, 0, 0, 2, 3, 60, }, - { 8, 0, 0, 2, 3, 64, }, { 9, 0, 0, 2, 3, 60, }, { 0, 0, 0, 2, 4, 68, }, { 2, 0, 0, 2, 4, 60, }, @@ -42093,9 +42390,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 4, 68, }, { 4, 0, 0, 2, 4, 76, }, { 5, 0, 0, 2, 4, 60, }, - { 6, 0, 0, 2, 4, 68, }, - { 7, 0, 0, 2, 4, 60, }, - { 8, 0, 0, 2, 4, 68, }, { 9, 0, 0, 2, 4, 60, }, { 0, 0, 0, 2, 5, 76, }, { 2, 0, 0, 2, 5, 60, }, @@ -42103,9 +42397,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 5, 76, }, { 4, 0, 0, 2, 5, 76, }, { 5, 0, 0, 2, 5, 60, }, - { 6, 0, 0, 2, 5, 76, }, - { 7, 0, 0, 2, 5, 60, }, - { 8, 0, 0, 2, 5, 76, }, { 9, 0, 0, 2, 5, 60, }, { 0, 0, 0, 2, 6, 76, }, { 2, 0, 0, 2, 6, 60, }, @@ -42113,9 +42404,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 6, 76, }, { 4, 0, 0, 2, 6, 76, }, { 5, 0, 0, 2, 6, 60, }, - { 6, 0, 0, 2, 6, 76, }, - { 7, 0, 0, 2, 6, 60, }, - { 8, 0, 0, 2, 6, 76, }, { 9, 0, 0, 2, 6, 60, }, { 0, 0, 0, 2, 7, 76, }, { 2, 0, 0, 2, 7, 60, }, @@ -42123,9 +42411,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 7, 76, }, { 4, 0, 0, 2, 7, 76, }, { 5, 0, 0, 2, 7, 60, }, - { 6, 0, 0, 2, 7, 76, }, - { 7, 0, 0, 2, 7, 60, }, - { 8, 0, 0, 2, 7, 76, }, { 9, 0, 0, 2, 7, 60, }, { 0, 0, 0, 2, 8, 68, }, { 2, 0, 0, 2, 8, 60, }, @@ -42133,9 +42418,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 8, 68, }, { 4, 0, 0, 2, 8, 76, }, { 5, 0, 0, 2, 8, 60, }, - { 6, 0, 0, 2, 8, 68, }, - { 7, 0, 0, 2, 8, 60, }, - { 8, 0, 0, 2, 8, 68, }, { 9, 0, 0, 2, 8, 60, }, { 0, 0, 0, 2, 9, 64, }, { 2, 0, 0, 2, 9, 60, }, @@ -42143,9 +42425,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 9, 64, }, { 4, 0, 0, 2, 9, 76, }, { 5, 0, 0, 2, 9, 60, }, - { 6, 0, 0, 2, 9, 64, }, - { 7, 0, 0, 2, 9, 60, }, - { 8, 0, 0, 2, 9, 64, }, { 9, 0, 0, 2, 9, 60, }, { 0, 0, 0, 2, 10, 60, }, { 2, 0, 0, 2, 10, 60, }, @@ -42153,9 +42432,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 10, 60, }, { 4, 0, 0, 2, 10, 76, }, { 5, 0, 0, 2, 10, 60, }, - { 6, 0, 0, 2, 10, 60, }, - { 7, 0, 0, 2, 10, 60, }, - { 8, 0, 0, 2, 10, 60, }, { 9, 0, 0, 2, 10, 60, }, { 0, 0, 0, 2, 11, 52, }, { 2, 0, 0, 2, 11, 60, }, @@ -42163,39 +42439,27 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 2, 11, 52, }, { 4, 0, 0, 2, 11, 76, }, { 5, 0, 0, 2, 11, 60, }, - { 6, 0, 0, 2, 11, 52, }, - { 7, 0, 0, 2, 11, 60, }, - { 8, 0, 0, 2, 11, 52, }, - { 9, 0, 0, 2, 11, 60, }, - { 0, 0, 0, 2, 12, 32, }, + { 9, 0, 0, 2, 11, 52, }, + { 0, 0, 0, 2, 12, 40, }, { 2, 0, 0, 2, 12, 60, }, { 1, 0, 0, 2, 12, 76, }, { 3, 0, 0, 2, 12, 40, }, { 4, 0, 0, 2, 12, 76, }, { 5, 0, 0, 2, 12, 60, }, - { 6, 0, 0, 2, 12, 40, }, - { 7, 0, 0, 2, 12, 60, }, - { 8, 0, 0, 2, 12, 40, }, - { 9, 0, 0, 2, 12, 60, }, - { 0, 0, 0, 2, 13, 20, }, + { 9, 0, 0, 2, 12, 48, }, + { 0, 0, 0, 2, 13, 28, }, { 2, 0, 0, 2, 13, 60, }, { 1, 0, 0, 2, 13, 76, }, { 3, 0, 0, 2, 13, 28, }, { 4, 0, 0, 2, 13, 74, }, { 5, 0, 0, 2, 13, 60, }, - { 6, 0, 0, 2, 13, 28, }, - { 7, 0, 0, 2, 13, 60, }, - { 8, 0, 0, 2, 13, 28, }, - { 9, 0, 0, 2, 13, 60, }, + { 9, 0, 0, 2, 13, 40, }, { 0, 0, 0, 2, 14, 127, }, { 2, 0, 0, 2, 14, 127, }, { 1, 0, 0, 2, 14, 127, }, { 3, 0, 0, 2, 14, 127, }, { 4, 0, 0, 2, 14, 127, }, { 5, 0, 0, 2, 14, 127, }, - { 6, 0, 0, 2, 14, 127, }, - { 7, 0, 0, 2, 14, 127, }, - { 8, 0, 0, 2, 14, 127, }, { 9, 0, 0, 2, 14, 127, }, { 0, 0, 0, 3, 1, 52, }, { 2, 0, 0, 3, 1, 36, }, @@ -42203,9 +42467,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 1, 52, }, { 4, 0, 0, 3, 1, 72, }, { 5, 0, 0, 3, 1, 36, }, - { 6, 0, 0, 3, 1, 52, }, - { 7, 0, 0, 3, 1, 36, }, - { 8, 0, 0, 3, 1, 52, }, { 9, 0, 0, 3, 1, 36, }, { 0, 0, 0, 3, 2, 60, }, { 2, 0, 0, 3, 2, 36, }, @@ -42213,9 +42474,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 2, 60, }, { 4, 0, 0, 3, 2, 72, }, { 5, 0, 0, 3, 2, 36, }, - { 6, 0, 0, 3, 2, 60, }, - { 7, 0, 0, 3, 2, 36, }, - { 8, 0, 0, 3, 2, 60, }, { 9, 0, 0, 3, 2, 36, }, { 0, 0, 0, 3, 3, 64, }, { 2, 0, 0, 3, 3, 36, }, @@ -42223,9 +42481,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 3, 64, }, { 4, 0, 0, 3, 3, 72, }, { 5, 0, 0, 3, 3, 36, }, - { 6, 0, 0, 3, 3, 64, }, - { 7, 0, 0, 3, 3, 36, }, - { 8, 0, 0, 3, 3, 64, }, { 9, 0, 0, 3, 3, 36, }, { 0, 0, 0, 3, 4, 68, }, { 2, 0, 0, 3, 4, 36, }, @@ -42233,9 +42488,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 4, 68, }, { 4, 0, 0, 3, 4, 72, }, { 5, 0, 0, 3, 4, 36, }, - { 6, 0, 0, 3, 4, 68, }, - { 7, 0, 0, 3, 4, 36, }, - { 8, 0, 0, 3, 4, 68, }, { 9, 0, 0, 3, 4, 36, }, { 0, 0, 0, 3, 5, 76, }, { 2, 0, 0, 3, 5, 36, }, @@ -42243,9 +42495,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 5, 76, }, { 4, 0, 0, 3, 5, 72, }, { 5, 0, 0, 3, 5, 36, }, - { 6, 0, 0, 3, 5, 76, }, - { 7, 0, 0, 3, 5, 36, }, - { 8, 0, 0, 3, 5, 76, }, { 9, 0, 0, 3, 5, 36, }, { 0, 0, 0, 3, 6, 76, }, { 2, 0, 0, 3, 6, 36, }, @@ -42253,9 +42502,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 6, 76, }, { 4, 0, 0, 3, 6, 72, }, { 5, 0, 0, 3, 6, 36, }, - { 6, 0, 0, 3, 6, 76, }, - { 7, 0, 0, 3, 6, 36, }, - { 8, 0, 0, 3, 6, 76, }, { 9, 0, 0, 3, 6, 36, }, { 0, 0, 0, 3, 7, 76, }, { 2, 0, 0, 3, 7, 36, }, @@ -42263,9 +42509,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 7, 76, }, { 4, 0, 0, 3, 7, 72, }, { 5, 0, 0, 3, 7, 36, }, - { 6, 0, 0, 3, 7, 76, }, - { 7, 0, 0, 3, 7, 36, }, - { 8, 0, 0, 3, 7, 76, }, { 9, 0, 0, 3, 7, 36, }, { 0, 0, 0, 3, 8, 68, }, { 2, 0, 0, 3, 8, 36, }, @@ -42273,9 +42516,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 8, 68, }, { 4, 0, 0, 3, 8, 72, }, { 5, 0, 0, 3, 8, 36, }, - { 6, 0, 0, 3, 8, 68, }, - { 7, 0, 0, 3, 8, 36, }, - { 8, 0, 0, 3, 8, 68, }, { 9, 0, 0, 3, 8, 36, }, { 0, 0, 0, 3, 9, 64, }, { 2, 0, 0, 3, 9, 36, }, @@ -42283,9 +42523,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 9, 64, }, { 4, 0, 0, 3, 9, 72, }, { 5, 0, 0, 3, 9, 36, }, - { 6, 0, 0, 3, 9, 64, }, - { 7, 0, 0, 3, 9, 36, }, - { 8, 0, 0, 3, 9, 64, }, { 9, 0, 0, 3, 9, 36, }, { 0, 0, 0, 3, 10, 60, }, { 2, 0, 0, 3, 10, 36, }, @@ -42293,9 +42530,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 10, 60, }, { 4, 0, 0, 3, 10, 72, }, { 5, 0, 0, 3, 10, 36, }, - { 6, 0, 0, 3, 10, 60, }, - { 7, 0, 0, 3, 10, 36, }, - { 8, 0, 0, 3, 10, 60, }, { 9, 0, 0, 3, 10, 36, }, { 0, 0, 0, 3, 11, 52, }, { 2, 0, 0, 3, 11, 36, }, @@ -42303,39 +42537,27 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 0, 3, 11, 52, }, { 4, 0, 0, 3, 11, 72, }, { 5, 0, 0, 3, 11, 36, }, - { 6, 0, 0, 3, 11, 52, }, - { 7, 0, 0, 3, 11, 36, }, - { 8, 0, 0, 3, 11, 52, }, - { 9, 0, 0, 3, 11, 36, }, - { 0, 0, 0, 3, 12, 32, }, + { 9, 0, 0, 3, 11, 40, }, + { 0, 0, 0, 3, 12, 40, }, { 2, 0, 0, 3, 12, 36, }, { 1, 0, 0, 3, 12, 66, }, { 3, 0, 0, 3, 12, 40, }, { 4, 0, 0, 3, 12, 72, }, { 5, 0, 0, 3, 12, 36, }, - { 6, 0, 0, 3, 12, 40, }, - { 7, 0, 0, 3, 12, 36, }, - { 8, 0, 0, 3, 12, 40, }, { 9, 0, 0, 3, 12, 36, }, - { 0, 0, 0, 3, 13, 20, }, + { 0, 0, 0, 3, 13, 28, }, { 2, 0, 0, 3, 13, 36, }, { 1, 0, 0, 3, 13, 66, }, { 3, 0, 0, 3, 13, 28, }, { 4, 0, 0, 3, 13, 68, }, { 5, 0, 0, 3, 13, 36, }, - { 6, 0, 0, 3, 13, 28, }, - { 7, 0, 0, 3, 13, 36, }, - { 8, 0, 0, 3, 13, 28, }, - { 9, 0, 0, 3, 13, 36, }, + { 9, 0, 0, 3, 13, 28, }, { 0, 0, 0, 3, 14, 127, }, { 2, 0, 0, 3, 14, 127, }, { 1, 0, 0, 3, 14, 127, }, { 3, 0, 0, 3, 14, 127, }, { 4, 0, 0, 3, 14, 127, }, { 5, 0, 0, 3, 14, 127, }, - { 6, 0, 0, 3, 14, 127, }, - { 7, 0, 0, 3, 14, 127, }, - { 8, 0, 0, 3, 14, 127, }, { 9, 0, 0, 3, 14, 127, }, { 0, 0, 1, 2, 1, 127, }, { 2, 0, 1, 2, 1, 127, }, @@ -42343,29 +42565,20 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 1, 127, }, { 4, 0, 1, 2, 1, 127, }, { 5, 0, 1, 2, 1, 127, }, - { 6, 0, 1, 2, 1, 127, }, - { 7, 0, 1, 2, 1, 127, }, - { 8, 0, 1, 2, 1, 127, }, - { 9, 0, 1, 2, 1, 127, }, + { 9, 0, 1, 2, 1, 60, }, { 0, 0, 1, 2, 2, 127, }, { 2, 0, 1, 2, 2, 127, }, { 1, 0, 1, 2, 2, 127, }, { 3, 0, 1, 2, 2, 127, }, { 4, 0, 1, 2, 2, 127, }, { 5, 0, 1, 2, 2, 127, }, - { 6, 0, 1, 2, 2, 127, }, - { 7, 0, 1, 2, 2, 127, }, - { 8, 0, 1, 2, 2, 127, }, - { 9, 0, 1, 2, 2, 127, }, + { 9, 0, 1, 2, 2, 60, }, { 0, 0, 1, 2, 3, 52, }, { 2, 0, 1, 2, 3, 60, }, { 1, 0, 1, 2, 3, 72, }, { 3, 0, 1, 2, 3, 52, }, { 4, 0, 1, 2, 3, 72, }, { 5, 0, 1, 2, 3, 60, }, - { 6, 0, 1, 2, 3, 52, }, - { 7, 0, 1, 2, 3, 60, }, - { 8, 0, 1, 2, 3, 52, }, { 9, 0, 1, 2, 3, 60, }, { 0, 0, 1, 2, 4, 52, }, { 2, 0, 1, 2, 4, 60, }, @@ -42373,9 +42586,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 4, 52, }, { 4, 0, 1, 2, 4, 72, }, { 5, 0, 1, 2, 4, 60, }, - { 6, 0, 1, 2, 4, 52, }, - { 7, 0, 1, 2, 4, 60, }, - { 8, 0, 1, 2, 4, 52, }, { 9, 0, 1, 2, 4, 60, }, { 0, 0, 1, 2, 5, 60, }, { 2, 0, 1, 2, 5, 60, }, @@ -42383,9 +42593,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 5, 60, }, { 4, 0, 1, 2, 5, 72, }, { 5, 0, 1, 2, 5, 60, }, - { 6, 0, 1, 2, 5, 60, }, - { 7, 0, 1, 2, 5, 60, }, - { 8, 0, 1, 2, 5, 60, }, { 9, 0, 1, 2, 5, 60, }, { 0, 0, 1, 2, 6, 64, }, { 2, 0, 1, 2, 6, 60, }, @@ -42393,9 +42600,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 6, 64, }, { 4, 0, 1, 2, 6, 72, }, { 5, 0, 1, 2, 6, 60, }, - { 6, 0, 1, 2, 6, 64, }, - { 7, 0, 1, 2, 6, 60, }, - { 8, 0, 1, 2, 6, 64, }, { 9, 0, 1, 2, 6, 60, }, { 0, 0, 1, 2, 7, 60, }, { 2, 0, 1, 2, 7, 60, }, @@ -42403,9 +42607,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 7, 60, }, { 4, 0, 1, 2, 7, 72, }, { 5, 0, 1, 2, 7, 60, }, - { 6, 0, 1, 2, 7, 60, }, - { 7, 0, 1, 2, 7, 60, }, - { 8, 0, 1, 2, 7, 60, }, { 9, 0, 1, 2, 7, 60, }, { 0, 0, 1, 2, 8, 52, }, { 2, 0, 1, 2, 8, 60, }, @@ -42413,9 +42614,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 8, 52, }, { 4, 0, 1, 2, 8, 72, }, { 5, 0, 1, 2, 8, 60, }, - { 6, 0, 1, 2, 8, 52, }, - { 7, 0, 1, 2, 8, 60, }, - { 8, 0, 1, 2, 8, 52, }, { 9, 0, 1, 2, 8, 60, }, { 0, 0, 1, 2, 9, 52, }, { 2, 0, 1, 2, 9, 60, }, @@ -42423,9 +42621,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 9, 52, }, { 4, 0, 1, 2, 9, 72, }, { 5, 0, 1, 2, 9, 60, }, - { 6, 0, 1, 2, 9, 52, }, - { 7, 0, 1, 2, 9, 60, }, - { 8, 0, 1, 2, 9, 52, }, { 9, 0, 1, 2, 9, 60, }, { 0, 0, 1, 2, 10, 40, }, { 2, 0, 1, 2, 10, 60, }, @@ -42433,9 +42628,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 10, 40, }, { 4, 0, 1, 2, 10, 72, }, { 5, 0, 1, 2, 10, 60, }, - { 6, 0, 1, 2, 10, 40, }, - { 7, 0, 1, 2, 10, 60, }, - { 8, 0, 1, 2, 10, 40, }, { 9, 0, 1, 2, 10, 60, }, { 0, 0, 1, 2, 11, 28, }, { 2, 0, 1, 2, 11, 60, }, @@ -42443,39 +42635,27 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 2, 11, 28, }, { 4, 0, 1, 2, 11, 70, }, { 5, 0, 1, 2, 11, 60, }, - { 6, 0, 1, 2, 11, 28, }, - { 7, 0, 1, 2, 11, 60, }, - { 8, 0, 1, 2, 11, 28, }, - { 9, 0, 1, 2, 11, 60, }, + { 9, 0, 1, 2, 11, 44, }, { 0, 0, 1, 2, 12, 127, }, { 2, 0, 1, 2, 12, 127, }, { 1, 0, 1, 2, 12, 127, }, { 3, 0, 1, 2, 12, 127, }, { 4, 0, 1, 2, 12, 127, }, { 5, 0, 1, 2, 12, 127, }, - { 6, 0, 1, 2, 12, 127, }, - { 7, 0, 1, 2, 12, 127, }, - { 8, 0, 1, 2, 12, 127, }, - { 9, 0, 1, 2, 12, 127, }, + { 9, 0, 1, 2, 12, 44, }, { 0, 0, 1, 2, 13, 127, }, { 2, 0, 1, 2, 13, 127, }, { 1, 0, 1, 2, 13, 127, }, { 3, 0, 1, 2, 13, 127, }, { 4, 0, 1, 2, 13, 127, }, { 5, 0, 1, 2, 13, 127, }, - { 6, 0, 1, 2, 13, 127, }, - { 7, 0, 1, 2, 13, 127, }, - { 8, 0, 1, 2, 13, 127, }, - { 9, 0, 1, 2, 13, 127, }, + { 9, 0, 1, 2, 13, 20, }, { 0, 0, 1, 2, 14, 127, }, { 2, 0, 1, 2, 14, 127, }, { 1, 0, 1, 2, 14, 127, }, { 3, 0, 1, 2, 14, 127, }, { 4, 0, 1, 2, 14, 127, }, { 5, 0, 1, 2, 14, 127, }, - { 6, 0, 1, 2, 14, 127, }, - { 7, 0, 1, 2, 14, 127, }, - { 8, 0, 1, 2, 14, 127, }, { 9, 0, 1, 2, 14, 127, }, { 0, 0, 1, 3, 1, 127, }, { 2, 0, 1, 3, 1, 127, }, @@ -42483,29 +42663,20 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 1, 127, }, { 4, 0, 1, 3, 1, 127, }, { 5, 0, 1, 3, 1, 127, }, - { 6, 0, 1, 3, 1, 127, }, - { 7, 0, 1, 3, 1, 127, }, - { 8, 0, 1, 3, 1, 127, }, - { 9, 0, 1, 3, 1, 127, }, + { 9, 0, 1, 3, 1, 36, }, { 0, 0, 1, 3, 2, 127, }, { 2, 0, 1, 3, 2, 127, }, { 1, 0, 1, 3, 2, 127, }, { 3, 0, 1, 3, 2, 127, }, { 4, 0, 1, 3, 2, 127, }, { 5, 0, 1, 3, 2, 127, }, - { 6, 0, 1, 3, 2, 127, }, - { 7, 0, 1, 3, 2, 127, }, - { 8, 0, 1, 3, 2, 127, }, - { 9, 0, 1, 3, 2, 127, }, + { 9, 0, 1, 3, 2, 36, }, { 0, 0, 1, 3, 3, 48, }, { 2, 0, 1, 3, 3, 36, }, { 1, 0, 1, 3, 3, 66, }, { 3, 0, 1, 3, 3, 48, }, { 4, 0, 1, 3, 3, 68, }, { 5, 0, 1, 3, 3, 36, }, - { 6, 0, 1, 3, 3, 48, }, - { 7, 0, 1, 3, 3, 36, }, - { 8, 0, 1, 3, 3, 48, }, { 9, 0, 1, 3, 3, 36, }, { 0, 0, 1, 3, 4, 48, }, { 2, 0, 1, 3, 4, 36, }, @@ -42513,9 +42684,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 4, 48, }, { 4, 0, 1, 3, 4, 70, }, { 5, 0, 1, 3, 4, 36, }, - { 6, 0, 1, 3, 4, 48, }, - { 7, 0, 1, 3, 4, 36, }, - { 8, 0, 1, 3, 4, 48, }, { 9, 0, 1, 3, 4, 36, }, { 0, 0, 1, 3, 5, 60, }, { 2, 0, 1, 3, 5, 36, }, @@ -42523,9 +42691,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 5, 60, }, { 4, 0, 1, 3, 5, 70, }, { 5, 0, 1, 3, 5, 36, }, - { 6, 0, 1, 3, 5, 60, }, - { 7, 0, 1, 3, 5, 36, }, - { 8, 0, 1, 3, 5, 60, }, { 9, 0, 1, 3, 5, 36, }, { 0, 0, 1, 3, 6, 64, }, { 2, 0, 1, 3, 6, 36, }, @@ -42533,9 +42698,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 6, 64, }, { 4, 0, 1, 3, 6, 70, }, { 5, 0, 1, 3, 6, 36, }, - { 6, 0, 1, 3, 6, 64, }, - { 7, 0, 1, 3, 6, 36, }, - { 8, 0, 1, 3, 6, 64, }, { 9, 0, 1, 3, 6, 36, }, { 0, 0, 1, 3, 7, 60, }, { 2, 0, 1, 3, 7, 36, }, @@ -42543,9 +42705,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 7, 60, }, { 4, 0, 1, 3, 7, 70, }, { 5, 0, 1, 3, 7, 36, }, - { 6, 0, 1, 3, 7, 60, }, - { 7, 0, 1, 3, 7, 36, }, - { 8, 0, 1, 3, 7, 60, }, { 9, 0, 1, 3, 7, 36, }, { 0, 0, 1, 3, 8, 52, }, { 2, 0, 1, 3, 8, 36, }, @@ -42553,9 +42712,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 8, 52, }, { 4, 0, 1, 3, 8, 70, }, { 5, 0, 1, 3, 8, 36, }, - { 6, 0, 1, 3, 8, 52, }, - { 7, 0, 1, 3, 8, 36, }, - { 8, 0, 1, 3, 8, 52, }, { 9, 0, 1, 3, 8, 36, }, { 0, 0, 1, 3, 9, 52, }, { 2, 0, 1, 3, 9, 36, }, @@ -42563,9 +42719,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 9, 52, }, { 4, 0, 1, 3, 9, 70, }, { 5, 0, 1, 3, 9, 36, }, - { 6, 0, 1, 3, 9, 52, }, - { 7, 0, 1, 3, 9, 36, }, - { 8, 0, 1, 3, 9, 52, }, { 9, 0, 1, 3, 9, 36, }, { 0, 0, 1, 3, 10, 40, }, { 2, 0, 1, 3, 10, 36, }, @@ -42573,9 +42726,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 10, 40, }, { 4, 0, 1, 3, 10, 70, }, { 5, 0, 1, 3, 10, 36, }, - { 6, 0, 1, 3, 10, 40, }, - { 7, 0, 1, 3, 10, 36, }, - { 8, 0, 1, 3, 10, 40, }, { 9, 0, 1, 3, 10, 36, }, { 0, 0, 1, 3, 11, 26, }, { 2, 0, 1, 3, 11, 36, }, @@ -42583,39 +42733,27 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 0, 1, 3, 11, 26, }, { 4, 0, 1, 3, 11, 66, }, { 5, 0, 1, 3, 11, 36, }, - { 6, 0, 1, 3, 11, 26, }, - { 7, 0, 1, 3, 11, 36, }, - { 8, 0, 1, 3, 11, 26, }, - { 9, 0, 1, 3, 11, 36, }, + { 9, 0, 1, 3, 11, 32, }, { 0, 0, 1, 3, 12, 127, }, { 2, 0, 1, 3, 12, 127, }, { 1, 0, 1, 3, 12, 127, }, { 3, 0, 1, 3, 12, 127, }, { 4, 0, 1, 3, 12, 127, }, { 5, 0, 1, 3, 12, 127, }, - { 6, 0, 1, 3, 12, 127, }, - { 7, 0, 1, 3, 12, 127, }, - { 8, 0, 1, 3, 12, 127, }, - { 9, 0, 1, 3, 12, 127, }, + { 9, 0, 1, 3, 12, 32, }, { 0, 0, 1, 3, 13, 127, }, { 2, 0, 1, 3, 13, 127, }, { 1, 0, 1, 3, 13, 127, }, { 3, 0, 1, 3, 13, 127, }, { 4, 0, 1, 3, 13, 127, }, { 5, 0, 1, 3, 13, 127, }, - { 6, 0, 1, 3, 13, 127, }, - { 7, 0, 1, 3, 13, 127, }, - { 8, 0, 1, 3, 13, 127, }, - { 9, 0, 1, 3, 13, 127, }, + { 9, 0, 1, 3, 13, 8, }, { 0, 0, 1, 3, 14, 127, }, { 2, 0, 1, 3, 14, 127, }, { 1, 0, 1, 3, 14, 127, }, { 3, 0, 1, 3, 14, 127, }, { 4, 0, 1, 3, 14, 127, }, { 5, 0, 1, 3, 14, 127, }, - { 6, 0, 1, 3, 14, 127, }, - { 7, 0, 1, 3, 14, 127, }, - { 8, 0, 1, 3, 14, 127, }, { 9, 0, 1, 3, 14, 127, }, { 0, 1, 0, 1, 36, 74, }, { 2, 1, 0, 1, 36, 58, }, @@ -42623,89 +42761,62 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 36, 62, }, { 4, 1, 0, 1, 36, 74, }, { 5, 1, 0, 1, 36, 58, }, - { 6, 1, 0, 1, 36, 64, }, - { 7, 1, 0, 1, 36, 54, }, - { 8, 1, 0, 1, 36, 62, }, - { 9, 1, 0, 1, 36, 62, }, + { 9, 1, 0, 1, 36, 64, }, { 0, 1, 0, 1, 40, 76, }, { 2, 1, 0, 1, 40, 58, }, { 1, 1, 0, 1, 40, 62, }, { 3, 1, 0, 1, 40, 62, }, { 4, 1, 0, 1, 40, 76, }, { 5, 1, 0, 1, 40, 58, }, - { 6, 1, 0, 1, 40, 64, }, - { 7, 1, 0, 1, 40, 54, }, - { 8, 1, 0, 1, 40, 62, }, - { 9, 1, 0, 1, 40, 62, }, + { 9, 1, 0, 1, 40, 64, }, { 0, 1, 0, 1, 44, 76, }, { 2, 1, 0, 1, 44, 58, }, { 1, 1, 0, 1, 44, 62, }, { 3, 1, 0, 1, 44, 62, }, { 4, 1, 0, 1, 44, 76, }, { 5, 1, 0, 1, 44, 58, }, - { 6, 1, 0, 1, 44, 64, }, - { 7, 1, 0, 1, 44, 54, }, - { 8, 1, 0, 1, 44, 62, }, - { 9, 1, 0, 1, 44, 62, }, + { 9, 1, 0, 1, 44, 64, }, { 0, 1, 0, 1, 48, 76, }, { 2, 1, 0, 1, 48, 58, }, { 1, 1, 0, 1, 48, 62, }, { 3, 1, 0, 1, 48, 62, }, { 4, 1, 0, 1, 48, 58, }, { 5, 1, 0, 1, 48, 58, }, - { 6, 1, 0, 1, 48, 64, }, - { 7, 1, 0, 1, 48, 54, }, - { 8, 1, 0, 1, 48, 62, }, - { 9, 1, 0, 1, 48, 62, }, + { 9, 1, 0, 1, 48, 64, }, { 0, 1, 0, 1, 52, 76, }, { 2, 1, 0, 1, 52, 58, }, { 1, 1, 0, 1, 52, 62, }, { 3, 1, 0, 1, 52, 64, }, { 4, 1, 0, 1, 52, 76, }, { 5, 1, 0, 1, 52, 58, }, - { 6, 1, 0, 1, 52, 76, }, - { 7, 1, 0, 1, 52, 54, }, - { 8, 1, 0, 1, 52, 76, }, - { 9, 1, 0, 1, 52, 62, }, + { 9, 1, 0, 1, 52, 64, }, { 0, 1, 0, 1, 56, 76, }, { 2, 1, 0, 1, 56, 58, }, { 1, 1, 0, 1, 56, 62, }, { 3, 1, 0, 1, 56, 64, }, { 4, 1, 0, 1, 56, 76, }, { 5, 1, 0, 1, 56, 58, }, - { 6, 1, 0, 1, 56, 76, }, - { 7, 1, 0, 1, 56, 54, }, - { 8, 1, 0, 1, 56, 76, }, - { 9, 1, 0, 1, 56, 62, }, + { 9, 1, 0, 1, 56, 64, }, { 0, 1, 0, 1, 60, 76, }, { 2, 1, 0, 1, 60, 58, }, { 1, 1, 0, 1, 60, 62, }, { 3, 1, 0, 1, 60, 64, }, { 4, 1, 0, 1, 60, 76, }, { 5, 1, 0, 1, 60, 58, }, - { 6, 1, 0, 1, 60, 76, }, - { 7, 1, 0, 1, 60, 54, }, - { 8, 1, 0, 1, 60, 76, }, - { 9, 1, 0, 1, 60, 62, }, + { 9, 1, 0, 1, 60, 64, }, { 0, 1, 0, 1, 64, 76, }, { 2, 1, 0, 1, 64, 58, }, { 1, 1, 0, 1, 64, 62, }, { 3, 1, 0, 1, 64, 64, }, { 4, 1, 0, 1, 64, 76, }, { 5, 1, 0, 1, 64, 58, }, - { 6, 1, 0, 1, 64, 74, }, - { 7, 1, 0, 1, 64, 54, }, - { 8, 1, 0, 1, 64, 74, }, - { 9, 1, 0, 1, 64, 62, }, + { 9, 1, 0, 1, 64, 64, }, { 0, 1, 0, 1, 100, 68, }, { 2, 1, 0, 1, 100, 58, }, { 1, 1, 0, 1, 100, 76, }, { 3, 1, 0, 1, 100, 68, }, { 4, 1, 0, 1, 100, 76, }, { 5, 1, 0, 1, 100, 58, }, - { 6, 1, 0, 1, 100, 72, }, - { 7, 1, 0, 1, 100, 54, }, - { 8, 1, 0, 1, 100, 72, }, { 9, 1, 0, 1, 100, 127, }, { 0, 1, 0, 1, 104, 76, }, { 2, 1, 0, 1, 104, 58, }, @@ -42713,9 +42824,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 104, 76, }, { 4, 1, 0, 1, 104, 76, }, { 5, 1, 0, 1, 104, 58, }, - { 6, 1, 0, 1, 104, 76, }, - { 7, 1, 0, 1, 104, 54, }, - { 8, 1, 0, 1, 104, 76, }, { 9, 1, 0, 1, 104, 127, }, { 0, 1, 0, 1, 108, 76, }, { 2, 1, 0, 1, 108, 58, }, @@ -42723,9 +42831,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 108, 76, }, { 4, 1, 0, 1, 108, 76, }, { 5, 1, 0, 1, 108, 58, }, - { 6, 1, 0, 1, 108, 76, }, - { 7, 1, 0, 1, 108, 54, }, - { 8, 1, 0, 1, 108, 76, }, { 9, 1, 0, 1, 108, 127, }, { 0, 1, 0, 1, 112, 76, }, { 2, 1, 0, 1, 112, 58, }, @@ -42733,9 +42838,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 112, 76, }, { 4, 1, 0, 1, 112, 76, }, { 5, 1, 0, 1, 112, 58, }, - { 6, 1, 0, 1, 112, 76, }, - { 7, 1, 0, 1, 112, 54, }, - { 8, 1, 0, 1, 112, 76, }, { 9, 1, 0, 1, 112, 127, }, { 0, 1, 0, 1, 116, 76, }, { 2, 1, 0, 1, 116, 58, }, @@ -42743,9 +42845,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 116, 76, }, { 4, 1, 0, 1, 116, 76, }, { 5, 1, 0, 1, 116, 58, }, - { 6, 1, 0, 1, 116, 76, }, - { 7, 1, 0, 1, 116, 54, }, - { 8, 1, 0, 1, 116, 76, }, { 9, 1, 0, 1, 116, 127, }, { 0, 1, 0, 1, 120, 76, }, { 2, 1, 0, 1, 120, 58, }, @@ -42753,9 +42852,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 120, 127, }, { 4, 1, 0, 1, 120, 76, }, { 5, 1, 0, 1, 120, 127, }, - { 6, 1, 0, 1, 120, 76, }, - { 7, 1, 0, 1, 120, 54, }, - { 8, 1, 0, 1, 120, 76, }, { 9, 1, 0, 1, 120, 127, }, { 0, 1, 0, 1, 124, 76, }, { 2, 1, 0, 1, 124, 58, }, @@ -42763,9 +42859,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 124, 127, }, { 4, 1, 0, 1, 124, 76, }, { 5, 1, 0, 1, 124, 127, }, - { 6, 1, 0, 1, 124, 76, }, - { 7, 1, 0, 1, 124, 54, }, - { 8, 1, 0, 1, 124, 76, }, { 9, 1, 0, 1, 124, 127, }, { 0, 1, 0, 1, 128, 76, }, { 2, 1, 0, 1, 128, 58, }, @@ -42773,9 +42866,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 128, 127, }, { 4, 1, 0, 1, 128, 76, }, { 5, 1, 0, 1, 128, 127, }, - { 6, 1, 0, 1, 128, 76, }, - { 7, 1, 0, 1, 128, 54, }, - { 8, 1, 0, 1, 128, 76, }, { 9, 1, 0, 1, 128, 127, }, { 0, 1, 0, 1, 132, 76, }, { 2, 1, 0, 1, 132, 58, }, @@ -42783,9 +42873,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 132, 76, }, { 4, 1, 0, 1, 132, 76, }, { 5, 1, 0, 1, 132, 58, }, - { 6, 1, 0, 1, 132, 76, }, - { 7, 1, 0, 1, 132, 54, }, - { 8, 1, 0, 1, 132, 76, }, { 9, 1, 0, 1, 132, 127, }, { 0, 1, 0, 1, 136, 76, }, { 2, 1, 0, 1, 136, 58, }, @@ -42793,9 +42880,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 136, 76, }, { 4, 1, 0, 1, 136, 76, }, { 5, 1, 0, 1, 136, 58, }, - { 6, 1, 0, 1, 136, 76, }, - { 7, 1, 0, 1, 136, 54, }, - { 8, 1, 0, 1, 136, 76, }, { 9, 1, 0, 1, 136, 127, }, { 0, 1, 0, 1, 140, 74, }, { 2, 1, 0, 1, 140, 58, }, @@ -42803,9 +42887,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 140, 74, }, { 4, 1, 0, 1, 140, 76, }, { 5, 1, 0, 1, 140, 58, }, - { 6, 1, 0, 1, 140, 72, }, - { 7, 1, 0, 1, 140, 54, }, - { 8, 1, 0, 1, 140, 72, }, { 9, 1, 0, 1, 140, 127, }, { 0, 1, 0, 1, 144, 76, }, { 2, 1, 0, 1, 144, 127, }, @@ -42813,9 +42894,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 144, 76, }, { 4, 1, 0, 1, 144, 76, }, { 5, 1, 0, 1, 144, 127, }, - { 6, 1, 0, 1, 144, 76, }, - { 7, 1, 0, 1, 144, 127, }, - { 8, 1, 0, 1, 144, 76, }, { 9, 1, 0, 1, 144, 127, }, { 0, 1, 0, 1, 149, 76, }, { 2, 1, 0, 1, 149, 28, }, @@ -42823,139 +42901,97 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 1, 149, 76, }, { 4, 1, 0, 1, 149, 74, }, { 5, 1, 0, 1, 149, 76, }, - { 6, 1, 0, 1, 149, 76, }, - { 7, 1, 0, 1, 149, 54, }, - { 8, 1, 0, 1, 149, 76, }, - { 9, 1, 0, 1, 149, 28, }, + { 9, 1, 0, 1, 149, 76, }, { 0, 1, 0, 1, 153, 76, }, { 2, 1, 0, 1, 153, 28, }, { 1, 1, 0, 1, 153, 127, }, { 3, 1, 0, 1, 153, 76, }, { 4, 1, 0, 1, 153, 74, }, { 5, 1, 0, 1, 153, 76, }, - { 6, 1, 0, 1, 153, 76, }, - { 7, 1, 0, 1, 153, 54, }, - { 8, 1, 0, 1, 153, 76, }, - { 9, 1, 0, 1, 153, 28, }, + { 9, 1, 0, 1, 153, 76, }, { 0, 1, 0, 1, 157, 76, }, { 2, 1, 0, 1, 157, 28, }, { 1, 1, 0, 1, 157, 127, }, { 3, 1, 0, 1, 157, 76, }, { 4, 1, 0, 1, 157, 74, }, { 5, 1, 0, 1, 157, 76, }, - { 6, 1, 0, 1, 157, 76, }, - { 7, 1, 0, 1, 157, 54, }, - { 8, 1, 0, 1, 157, 76, }, - { 9, 1, 0, 1, 157, 28, }, + { 9, 1, 0, 1, 157, 76, }, { 0, 1, 0, 1, 161, 76, }, { 2, 1, 0, 1, 161, 28, }, { 1, 1, 0, 1, 161, 127, }, { 3, 1, 0, 1, 161, 76, }, { 4, 1, 0, 1, 161, 74, }, { 5, 1, 0, 1, 161, 76, }, - { 6, 1, 0, 1, 161, 76, }, - { 7, 1, 0, 1, 161, 54, }, - { 8, 1, 0, 1, 161, 76, }, - { 9, 1, 0, 1, 161, 28, }, + { 9, 1, 0, 1, 161, 76, }, { 0, 1, 0, 1, 165, 76, }, { 2, 1, 0, 1, 165, 28, }, { 1, 1, 0, 1, 165, 127, }, { 3, 1, 0, 1, 165, 76, }, { 4, 1, 0, 1, 165, 74, }, { 5, 1, 0, 1, 165, 76, }, - { 6, 1, 0, 1, 165, 76, }, - { 7, 1, 0, 1, 165, 54, }, - { 8, 1, 0, 1, 165, 76, }, - { 9, 1, 0, 1, 165, 28, }, + { 9, 1, 0, 1, 165, 76, }, { 0, 1, 0, 2, 36, 70, }, { 2, 1, 0, 2, 36, 58, }, { 1, 1, 0, 2, 36, 64, }, { 3, 1, 0, 2, 36, 62, }, { 4, 1, 0, 2, 36, 76, }, { 5, 1, 0, 2, 36, 58, }, - { 6, 1, 0, 2, 36, 64, }, - { 7, 1, 0, 2, 36, 54, }, - { 8, 1, 0, 2, 36, 62, }, - { 9, 1, 0, 2, 36, 62, }, + { 9, 1, 0, 2, 36, 60, }, { 0, 1, 0, 2, 40, 76, }, { 2, 1, 0, 2, 40, 58, }, { 1, 1, 0, 2, 40, 62, }, { 3, 1, 0, 2, 40, 62, }, { 4, 1, 0, 2, 40, 76, }, { 5, 1, 0, 2, 40, 58, }, - { 6, 1, 0, 2, 40, 64, }, - { 7, 1, 0, 2, 40, 54, }, - { 8, 1, 0, 2, 40, 62, }, - { 9, 1, 0, 2, 40, 62, }, + { 9, 1, 0, 2, 40, 60, }, { 0, 1, 0, 2, 44, 76, }, { 2, 1, 0, 2, 44, 58, }, { 1, 1, 0, 2, 44, 62, }, { 3, 1, 0, 2, 44, 62, }, { 4, 1, 0, 2, 44, 76, }, { 5, 1, 0, 2, 44, 58, }, - { 6, 1, 0, 2, 44, 64, }, - { 7, 1, 0, 2, 44, 54, }, - { 8, 1, 0, 2, 44, 62, }, - { 9, 1, 0, 2, 44, 62, }, + { 9, 1, 0, 2, 44, 60, }, { 0, 1, 0, 2, 48, 76, }, { 2, 1, 0, 2, 48, 58, }, { 1, 1, 0, 2, 48, 62, }, { 3, 1, 0, 2, 48, 62, }, { 4, 1, 0, 2, 48, 58, }, { 5, 1, 0, 2, 48, 58, }, - { 6, 1, 0, 2, 48, 64, }, - { 7, 1, 0, 2, 48, 54, }, - { 8, 1, 0, 2, 48, 62, }, - { 9, 1, 0, 2, 48, 62, }, + { 9, 1, 0, 2, 48, 60, }, { 0, 1, 0, 2, 52, 76, }, { 2, 1, 0, 2, 52, 58, }, { 1, 1, 0, 2, 52, 62, }, { 3, 1, 0, 2, 52, 64, }, { 4, 1, 0, 2, 52, 76, }, { 5, 1, 0, 2, 52, 58, }, - { 6, 1, 0, 2, 52, 76, }, - { 7, 1, 0, 2, 52, 54, }, - { 8, 1, 0, 2, 52, 76, }, - { 9, 1, 0, 2, 52, 62, }, + { 9, 1, 0, 2, 52, 60, }, { 0, 1, 0, 2, 56, 76, }, { 2, 1, 0, 2, 56, 58, }, { 1, 1, 0, 2, 56, 62, }, { 3, 1, 0, 2, 56, 64, }, { 4, 1, 0, 2, 56, 76, }, { 5, 1, 0, 2, 56, 58, }, - { 6, 1, 0, 2, 56, 76, }, - { 7, 1, 0, 2, 56, 54, }, - { 8, 1, 0, 2, 56, 76, }, - { 9, 1, 0, 2, 56, 62, }, + { 9, 1, 0, 2, 56, 60, }, { 0, 1, 0, 2, 60, 76, }, { 2, 1, 0, 2, 60, 58, }, { 1, 1, 0, 2, 60, 62, }, { 3, 1, 0, 2, 60, 64, }, { 4, 1, 0, 2, 60, 76, }, { 5, 1, 0, 2, 60, 58, }, - { 6, 1, 0, 2, 60, 76, }, - { 7, 1, 0, 2, 60, 54, }, - { 8, 1, 0, 2, 60, 76, }, - { 9, 1, 0, 2, 60, 62, }, + { 9, 1, 0, 2, 60, 60, }, { 0, 1, 0, 2, 64, 70, }, { 2, 1, 0, 2, 64, 58, }, { 1, 1, 0, 2, 64, 62, }, { 3, 1, 0, 2, 64, 64, }, { 4, 1, 0, 2, 64, 74, }, { 5, 1, 0, 2, 64, 58, }, - { 6, 1, 0, 2, 64, 74, }, - { 7, 1, 0, 2, 64, 54, }, - { 8, 1, 0, 2, 64, 74, }, - { 9, 1, 0, 2, 64, 62, }, + { 9, 1, 0, 2, 64, 60, }, { 0, 1, 0, 2, 100, 66, }, { 2, 1, 0, 2, 100, 58, }, { 1, 1, 0, 2, 100, 76, }, { 3, 1, 0, 2, 100, 66, }, { 4, 1, 0, 2, 100, 76, }, { 5, 1, 0, 2, 100, 58, }, - { 6, 1, 0, 2, 100, 70, }, - { 7, 1, 0, 2, 100, 54, }, - { 8, 1, 0, 2, 100, 70, }, { 9, 1, 0, 2, 100, 127, }, { 0, 1, 0, 2, 104, 76, }, { 2, 1, 0, 2, 104, 58, }, @@ -42963,9 +42999,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 104, 76, }, { 4, 1, 0, 2, 104, 76, }, { 5, 1, 0, 2, 104, 58, }, - { 6, 1, 0, 2, 104, 76, }, - { 7, 1, 0, 2, 104, 54, }, - { 8, 1, 0, 2, 104, 76, }, { 9, 1, 0, 2, 104, 127, }, { 0, 1, 0, 2, 108, 76, }, { 2, 1, 0, 2, 108, 58, }, @@ -42973,9 +43006,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 108, 76, }, { 4, 1, 0, 2, 108, 76, }, { 5, 1, 0, 2, 108, 58, }, - { 6, 1, 0, 2, 108, 76, }, - { 7, 1, 0, 2, 108, 54, }, - { 8, 1, 0, 2, 108, 76, }, { 9, 1, 0, 2, 108, 127, }, { 0, 1, 0, 2, 112, 76, }, { 2, 1, 0, 2, 112, 58, }, @@ -42983,9 +43013,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 112, 76, }, { 4, 1, 0, 2, 112, 76, }, { 5, 1, 0, 2, 112, 58, }, - { 6, 1, 0, 2, 112, 76, }, - { 7, 1, 0, 2, 112, 54, }, - { 8, 1, 0, 2, 112, 76, }, { 9, 1, 0, 2, 112, 127, }, { 0, 1, 0, 2, 116, 76, }, { 2, 1, 0, 2, 116, 58, }, @@ -42993,9 +43020,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 116, 76, }, { 4, 1, 0, 2, 116, 76, }, { 5, 1, 0, 2, 116, 58, }, - { 6, 1, 0, 2, 116, 76, }, - { 7, 1, 0, 2, 116, 54, }, - { 8, 1, 0, 2, 116, 76, }, { 9, 1, 0, 2, 116, 127, }, { 0, 1, 0, 2, 120, 76, }, { 2, 1, 0, 2, 120, 58, }, @@ -43003,9 +43027,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 120, 127, }, { 4, 1, 0, 2, 120, 76, }, { 5, 1, 0, 2, 120, 127, }, - { 6, 1, 0, 2, 120, 76, }, - { 7, 1, 0, 2, 120, 54, }, - { 8, 1, 0, 2, 120, 76, }, { 9, 1, 0, 2, 120, 127, }, { 0, 1, 0, 2, 124, 76, }, { 2, 1, 0, 2, 124, 58, }, @@ -43013,9 +43034,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 124, 127, }, { 4, 1, 0, 2, 124, 76, }, { 5, 1, 0, 2, 124, 127, }, - { 6, 1, 0, 2, 124, 76, }, - { 7, 1, 0, 2, 124, 54, }, - { 8, 1, 0, 2, 124, 76, }, { 9, 1, 0, 2, 124, 127, }, { 0, 1, 0, 2, 128, 76, }, { 2, 1, 0, 2, 128, 58, }, @@ -43023,9 +43041,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 128, 127, }, { 4, 1, 0, 2, 128, 76, }, { 5, 1, 0, 2, 128, 127, }, - { 6, 1, 0, 2, 128, 76, }, - { 7, 1, 0, 2, 128, 54, }, - { 8, 1, 0, 2, 128, 76, }, { 9, 1, 0, 2, 128, 127, }, { 0, 1, 0, 2, 132, 76, }, { 2, 1, 0, 2, 132, 58, }, @@ -43033,9 +43048,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 132, 76, }, { 4, 1, 0, 2, 132, 76, }, { 5, 1, 0, 2, 132, 58, }, - { 6, 1, 0, 2, 132, 76, }, - { 7, 1, 0, 2, 132, 54, }, - { 8, 1, 0, 2, 132, 76, }, { 9, 1, 0, 2, 132, 127, }, { 0, 1, 0, 2, 136, 76, }, { 2, 1, 0, 2, 136, 58, }, @@ -43043,9 +43055,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 136, 76, }, { 4, 1, 0, 2, 136, 76, }, { 5, 1, 0, 2, 136, 58, }, - { 6, 1, 0, 2, 136, 76, }, - { 7, 1, 0, 2, 136, 54, }, - { 8, 1, 0, 2, 136, 76, }, { 9, 1, 0, 2, 136, 127, }, { 0, 1, 0, 2, 140, 66, }, { 2, 1, 0, 2, 140, 58, }, @@ -43053,9 +43062,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 140, 66, }, { 4, 1, 0, 2, 140, 76, }, { 5, 1, 0, 2, 140, 58, }, - { 6, 1, 0, 2, 140, 70, }, - { 7, 1, 0, 2, 140, 54, }, - { 8, 1, 0, 2, 140, 70, }, { 9, 1, 0, 2, 140, 127, }, { 0, 1, 0, 2, 144, 76, }, { 2, 1, 0, 2, 144, 127, }, @@ -43063,9 +43069,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 144, 76, }, { 4, 1, 0, 2, 144, 76, }, { 5, 1, 0, 2, 144, 127, }, - { 6, 1, 0, 2, 144, 76, }, - { 7, 1, 0, 2, 144, 127, }, - { 8, 1, 0, 2, 144, 76, }, { 9, 1, 0, 2, 144, 127, }, { 0, 1, 0, 2, 149, 76, }, { 2, 1, 0, 2, 149, 28, }, @@ -43073,139 +43076,97 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 2, 149, 76, }, { 4, 1, 0, 2, 149, 74, }, { 5, 1, 0, 2, 149, 76, }, - { 6, 1, 0, 2, 149, 76, }, - { 7, 1, 0, 2, 149, 54, }, - { 8, 1, 0, 2, 149, 76, }, - { 9, 1, 0, 2, 149, 28, }, + { 9, 1, 0, 2, 149, 76, }, { 0, 1, 0, 2, 153, 76, }, { 2, 1, 0, 2, 153, 28, }, { 1, 1, 0, 2, 153, 127, }, { 3, 1, 0, 2, 153, 76, }, { 4, 1, 0, 2, 153, 74, }, { 5, 1, 0, 2, 153, 76, }, - { 6, 1, 0, 2, 153, 76, }, - { 7, 1, 0, 2, 153, 54, }, - { 8, 1, 0, 2, 153, 76, }, - { 9, 1, 0, 2, 153, 28, }, + { 9, 1, 0, 2, 153, 76, }, { 0, 1, 0, 2, 157, 76, }, { 2, 1, 0, 2, 157, 28, }, { 1, 1, 0, 2, 157, 127, }, { 3, 1, 0, 2, 157, 76, }, { 4, 1, 0, 2, 157, 74, }, { 5, 1, 0, 2, 157, 76, }, - { 6, 1, 0, 2, 157, 76, }, - { 7, 1, 0, 2, 157, 54, }, - { 8, 1, 0, 2, 157, 76, }, - { 9, 1, 0, 2, 157, 28, }, + { 9, 1, 0, 2, 157, 76, }, { 0, 1, 0, 2, 161, 76, }, { 2, 1, 0, 2, 161, 28, }, { 1, 1, 0, 2, 161, 127, }, { 3, 1, 0, 2, 161, 76, }, { 4, 1, 0, 2, 161, 74, }, { 5, 1, 0, 2, 161, 76, }, - { 6, 1, 0, 2, 161, 76, }, - { 7, 1, 0, 2, 161, 54, }, - { 8, 1, 0, 2, 161, 76, }, - { 9, 1, 0, 2, 161, 28, }, + { 9, 1, 0, 2, 161, 76, }, { 0, 1, 0, 2, 165, 76, }, { 2, 1, 0, 2, 165, 28, }, { 1, 1, 0, 2, 165, 127, }, { 3, 1, 0, 2, 165, 76, }, { 4, 1, 0, 2, 165, 74, }, { 5, 1, 0, 2, 165, 76, }, - { 6, 1, 0, 2, 165, 76, }, - { 7, 1, 0, 2, 165, 54, }, - { 8, 1, 0, 2, 165, 76, }, - { 9, 1, 0, 2, 165, 28, }, + { 9, 1, 0, 2, 165, 76, }, { 0, 1, 0, 3, 36, 64, }, { 2, 1, 0, 3, 36, 36, }, { 1, 1, 0, 3, 36, 50, }, { 3, 1, 0, 3, 36, 38, }, { 4, 1, 0, 3, 36, 66, }, { 5, 1, 0, 3, 36, 36, }, - { 6, 1, 0, 3, 36, 52, }, - { 7, 1, 0, 3, 36, 30, }, - { 8, 1, 0, 3, 36, 50, }, - { 9, 1, 0, 3, 36, 38, }, + { 9, 1, 0, 3, 36, 36, }, { 0, 1, 0, 3, 40, 68, }, { 2, 1, 0, 3, 40, 36, }, { 1, 1, 0, 3, 40, 50, }, { 3, 1, 0, 3, 40, 38, }, { 4, 1, 0, 3, 40, 66, }, { 5, 1, 0, 3, 40, 36, }, - { 6, 1, 0, 3, 40, 52, }, - { 7, 1, 0, 3, 40, 30, }, - { 8, 1, 0, 3, 40, 50, }, - { 9, 1, 0, 3, 40, 38, }, + { 9, 1, 0, 3, 40, 36, }, { 0, 1, 0, 3, 44, 68, }, { 2, 1, 0, 3, 44, 36, }, { 1, 1, 0, 3, 44, 50, }, { 3, 1, 0, 3, 44, 38, }, { 4, 1, 0, 3, 44, 66, }, { 5, 1, 0, 3, 44, 36, }, - { 6, 1, 0, 3, 44, 52, }, - { 7, 1, 0, 3, 44, 30, }, - { 8, 1, 0, 3, 44, 50, }, - { 9, 1, 0, 3, 44, 38, }, + { 9, 1, 0, 3, 44, 36, }, { 0, 1, 0, 3, 48, 68, }, { 2, 1, 0, 3, 48, 36, }, { 1, 1, 0, 3, 48, 50, }, { 3, 1, 0, 3, 48, 38, }, { 4, 1, 0, 3, 48, 42, }, { 5, 1, 0, 3, 48, 36, }, - { 6, 1, 0, 3, 48, 52, }, - { 7, 1, 0, 3, 48, 30, }, - { 8, 1, 0, 3, 48, 50, }, - { 9, 1, 0, 3, 48, 38, }, + { 9, 1, 0, 3, 48, 36, }, { 0, 1, 0, 3, 52, 68, }, { 2, 1, 0, 3, 52, 36, }, { 1, 1, 0, 3, 52, 50, }, { 3, 1, 0, 3, 52, 40, }, { 4, 1, 0, 3, 52, 66, }, { 5, 1, 0, 3, 52, 36, }, - { 6, 1, 0, 3, 52, 68, }, - { 7, 1, 0, 3, 52, 30, }, - { 8, 1, 0, 3, 52, 68, }, - { 9, 1, 0, 3, 52, 38, }, + { 9, 1, 0, 3, 52, 36, }, { 0, 1, 0, 3, 56, 68, }, { 2, 1, 0, 3, 56, 36, }, { 1, 1, 0, 3, 56, 50, }, { 3, 1, 0, 3, 56, 40, }, { 4, 1, 0, 3, 56, 66, }, { 5, 1, 0, 3, 56, 36, }, - { 6, 1, 0, 3, 56, 68, }, - { 7, 1, 0, 3, 56, 30, }, - { 8, 1, 0, 3, 56, 68, }, - { 9, 1, 0, 3, 56, 38, }, + { 9, 1, 0, 3, 56, 36, }, { 0, 1, 0, 3, 60, 68, }, { 2, 1, 0, 3, 60, 36, }, { 1, 1, 0, 3, 60, 50, }, { 3, 1, 0, 3, 60, 40, }, { 4, 1, 0, 3, 60, 66, }, { 5, 1, 0, 3, 60, 36, }, - { 6, 1, 0, 3, 60, 66, }, - { 7, 1, 0, 3, 60, 30, }, - { 8, 1, 0, 3, 60, 66, }, - { 9, 1, 0, 3, 60, 38, }, + { 9, 1, 0, 3, 60, 36, }, { 0, 1, 0, 3, 64, 66, }, { 2, 1, 0, 3, 64, 36, }, { 1, 1, 0, 3, 64, 50, }, { 3, 1, 0, 3, 64, 40, }, { 4, 1, 0, 3, 64, 66, }, { 5, 1, 0, 3, 64, 36, }, - { 6, 1, 0, 3, 64, 68, }, - { 7, 1, 0, 3, 64, 30, }, - { 8, 1, 0, 3, 64, 68, }, - { 9, 1, 0, 3, 64, 38, }, + { 9, 1, 0, 3, 64, 36, }, { 0, 1, 0, 3, 100, 64, }, { 2, 1, 0, 3, 100, 36, }, { 1, 1, 0, 3, 100, 70, }, { 3, 1, 0, 3, 100, 64, }, { 4, 1, 0, 3, 100, 66, }, { 5, 1, 0, 3, 100, 36, }, - { 6, 1, 0, 3, 100, 60, }, - { 7, 1, 0, 3, 100, 30, }, - { 8, 1, 0, 3, 100, 60, }, { 9, 1, 0, 3, 100, 127, }, { 0, 1, 0, 3, 104, 68, }, { 2, 1, 0, 3, 104, 36, }, @@ -43213,9 +43174,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 104, 68, }, { 4, 1, 0, 3, 104, 66, }, { 5, 1, 0, 3, 104, 36, }, - { 6, 1, 0, 3, 104, 68, }, - { 7, 1, 0, 3, 104, 30, }, - { 8, 1, 0, 3, 104, 68, }, { 9, 1, 0, 3, 104, 127, }, { 0, 1, 0, 3, 108, 68, }, { 2, 1, 0, 3, 108, 36, }, @@ -43223,9 +43181,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 108, 68, }, { 4, 1, 0, 3, 108, 66, }, { 5, 1, 0, 3, 108, 36, }, - { 6, 1, 0, 3, 108, 68, }, - { 7, 1, 0, 3, 108, 30, }, - { 8, 1, 0, 3, 108, 68, }, { 9, 1, 0, 3, 108, 127, }, { 0, 1, 0, 3, 112, 68, }, { 2, 1, 0, 3, 112, 36, }, @@ -43233,9 +43188,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 112, 68, }, { 4, 1, 0, 3, 112, 66, }, { 5, 1, 0, 3, 112, 36, }, - { 6, 1, 0, 3, 112, 68, }, - { 7, 1, 0, 3, 112, 30, }, - { 8, 1, 0, 3, 112, 68, }, { 9, 1, 0, 3, 112, 127, }, { 0, 1, 0, 3, 116, 68, }, { 2, 1, 0, 3, 116, 36, }, @@ -43243,9 +43195,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 116, 68, }, { 4, 1, 0, 3, 116, 66, }, { 5, 1, 0, 3, 116, 36, }, - { 6, 1, 0, 3, 116, 68, }, - { 7, 1, 0, 3, 116, 30, }, - { 8, 1, 0, 3, 116, 68, }, { 9, 1, 0, 3, 116, 127, }, { 0, 1, 0, 3, 120, 68, }, { 2, 1, 0, 3, 120, 36, }, @@ -43253,9 +43202,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 120, 127, }, { 4, 1, 0, 3, 120, 66, }, { 5, 1, 0, 3, 120, 127, }, - { 6, 1, 0, 3, 120, 68, }, - { 7, 1, 0, 3, 120, 30, }, - { 8, 1, 0, 3, 120, 68, }, { 9, 1, 0, 3, 120, 127, }, { 0, 1, 0, 3, 124, 68, }, { 2, 1, 0, 3, 124, 36, }, @@ -43263,9 +43209,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 124, 127, }, { 4, 1, 0, 3, 124, 66, }, { 5, 1, 0, 3, 124, 127, }, - { 6, 1, 0, 3, 124, 68, }, - { 7, 1, 0, 3, 124, 30, }, - { 8, 1, 0, 3, 124, 68, }, { 9, 1, 0, 3, 124, 127, }, { 0, 1, 0, 3, 128, 68, }, { 2, 1, 0, 3, 128, 36, }, @@ -43273,9 +43216,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 128, 127, }, { 4, 1, 0, 3, 128, 66, }, { 5, 1, 0, 3, 128, 127, }, - { 6, 1, 0, 3, 128, 68, }, - { 7, 1, 0, 3, 128, 30, }, - { 8, 1, 0, 3, 128, 68, }, { 9, 1, 0, 3, 128, 127, }, { 0, 1, 0, 3, 132, 68, }, { 2, 1, 0, 3, 132, 36, }, @@ -43283,9 +43223,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 132, 68, }, { 4, 1, 0, 3, 132, 66, }, { 5, 1, 0, 3, 132, 36, }, - { 6, 1, 0, 3, 132, 68, }, - { 7, 1, 0, 3, 132, 30, }, - { 8, 1, 0, 3, 132, 68, }, { 9, 1, 0, 3, 132, 127, }, { 0, 1, 0, 3, 136, 68, }, { 2, 1, 0, 3, 136, 36, }, @@ -43293,9 +43230,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 136, 68, }, { 4, 1, 0, 3, 136, 66, }, { 5, 1, 0, 3, 136, 36, }, - { 6, 1, 0, 3, 136, 68, }, - { 7, 1, 0, 3, 136, 30, }, - { 8, 1, 0, 3, 136, 68, }, { 9, 1, 0, 3, 136, 127, }, { 0, 1, 0, 3, 140, 58, }, { 2, 1, 0, 3, 140, 36, }, @@ -43303,9 +43237,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 140, 58, }, { 4, 1, 0, 3, 140, 66, }, { 5, 1, 0, 3, 140, 36, }, - { 6, 1, 0, 3, 140, 60, }, - { 7, 1, 0, 3, 140, 30, }, - { 8, 1, 0, 3, 140, 60, }, { 9, 1, 0, 3, 140, 127, }, { 0, 1, 0, 3, 144, 68, }, { 2, 1, 0, 3, 144, 127, }, @@ -43313,9 +43244,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 144, 68, }, { 4, 1, 0, 3, 144, 66, }, { 5, 1, 0, 3, 144, 127, }, - { 6, 1, 0, 3, 144, 68, }, - { 7, 1, 0, 3, 144, 127, }, - { 8, 1, 0, 3, 144, 68, }, { 9, 1, 0, 3, 144, 127, }, { 0, 1, 0, 3, 149, 76, }, { 2, 1, 0, 3, 149, 4, }, @@ -43323,59 +43251,41 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 0, 3, 149, 76, }, { 4, 1, 0, 3, 149, 62, }, { 5, 1, 0, 3, 149, 76, }, - { 6, 1, 0, 3, 149, 76, }, - { 7, 1, 0, 3, 149, 30, }, - { 8, 1, 0, 3, 149, 72, }, - { 9, 1, 0, 3, 149, 4, }, + { 9, 1, 0, 3, 149, 68, }, { 0, 1, 0, 3, 153, 76, }, { 2, 1, 0, 3, 153, 4, }, { 1, 1, 0, 3, 153, 127, }, { 3, 1, 0, 3, 153, 76, }, { 4, 1, 0, 3, 153, 62, }, { 5, 1, 0, 3, 153, 76, }, - { 6, 1, 0, 3, 153, 76, }, - { 7, 1, 0, 3, 153, 30, }, - { 8, 1, 0, 3, 153, 76, }, - { 9, 1, 0, 3, 153, 4, }, + { 9, 1, 0, 3, 153, 68, }, { 0, 1, 0, 3, 157, 76, }, { 2, 1, 0, 3, 157, 4, }, { 1, 1, 0, 3, 157, 127, }, { 3, 1, 0, 3, 157, 76, }, { 4, 1, 0, 3, 157, 62, }, { 5, 1, 0, 3, 157, 76, }, - { 6, 1, 0, 3, 157, 76, }, - { 7, 1, 0, 3, 157, 30, }, - { 8, 1, 0, 3, 157, 76, }, - { 9, 1, 0, 3, 157, 4, }, + { 9, 1, 0, 3, 157, 68, }, { 0, 1, 0, 3, 161, 76, }, { 2, 1, 0, 3, 161, 4, }, { 1, 1, 0, 3, 161, 127, }, { 3, 1, 0, 3, 161, 76, }, { 4, 1, 0, 3, 161, 62, }, { 5, 1, 0, 3, 161, 76, }, - { 6, 1, 0, 3, 161, 76, }, - { 7, 1, 0, 3, 161, 30, }, - { 8, 1, 0, 3, 161, 76, }, - { 9, 1, 0, 3, 161, 4, }, + { 9, 1, 0, 3, 161, 72, }, { 0, 1, 0, 3, 165, 76, }, { 2, 1, 0, 3, 165, 4, }, { 1, 1, 0, 3, 165, 127, }, { 3, 1, 0, 3, 165, 76, }, { 4, 1, 0, 3, 165, 62, }, { 5, 1, 0, 3, 165, 76, }, - { 6, 1, 0, 3, 165, 76, }, - { 7, 1, 0, 3, 165, 30, }, - { 8, 1, 0, 3, 165, 76, }, - { 9, 1, 0, 3, 165, 4, }, + { 9, 1, 0, 3, 165, 72, }, { 0, 1, 1, 2, 38, 66, }, { 2, 1, 1, 2, 38, 64, }, { 1, 1, 1, 2, 38, 64, }, { 3, 1, 1, 2, 38, 64, }, { 4, 1, 1, 2, 38, 64, }, { 5, 1, 1, 2, 38, 64, }, - { 6, 1, 1, 2, 38, 64, }, - { 7, 1, 1, 2, 38, 54, }, - { 8, 1, 1, 2, 38, 62, }, { 9, 1, 1, 2, 38, 64, }, { 0, 1, 1, 2, 46, 72, }, { 2, 1, 1, 2, 46, 64, }, @@ -43383,9 +43293,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 46, 64, }, { 4, 1, 1, 2, 46, 70, }, { 5, 1, 1, 2, 46, 64, }, - { 6, 1, 1, 2, 46, 64, }, - { 7, 1, 1, 2, 46, 54, }, - { 8, 1, 1, 2, 46, 62, }, { 9, 1, 1, 2, 46, 64, }, { 0, 1, 1, 2, 54, 72, }, { 2, 1, 1, 2, 54, 64, }, @@ -43393,9 +43300,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 54, 64, }, { 4, 1, 1, 2, 54, 72, }, { 5, 1, 1, 2, 54, 64, }, - { 6, 1, 1, 2, 54, 72, }, - { 7, 1, 1, 2, 54, 54, }, - { 8, 1, 1, 2, 54, 72, }, { 9, 1, 1, 2, 54, 64, }, { 0, 1, 1, 2, 62, 60, }, { 2, 1, 1, 2, 62, 64, }, @@ -43403,9 +43307,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 62, 60, }, { 4, 1, 1, 2, 62, 60, }, { 5, 1, 1, 2, 62, 64, }, - { 6, 1, 1, 2, 62, 64, }, - { 7, 1, 1, 2, 62, 54, }, - { 8, 1, 1, 2, 62, 64, }, { 9, 1, 1, 2, 62, 64, }, { 0, 1, 1, 2, 102, 60, }, { 2, 1, 1, 2, 102, 64, }, @@ -43413,9 +43314,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 102, 60, }, { 4, 1, 1, 2, 102, 64, }, { 5, 1, 1, 2, 102, 64, }, - { 6, 1, 1, 2, 102, 58, }, - { 7, 1, 1, 2, 102, 54, }, - { 8, 1, 1, 2, 102, 58, }, { 9, 1, 1, 2, 102, 127, }, { 0, 1, 1, 2, 110, 72, }, { 2, 1, 1, 2, 110, 64, }, @@ -43423,9 +43321,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 110, 72, }, { 4, 1, 1, 2, 110, 72, }, { 5, 1, 1, 2, 110, 64, }, - { 6, 1, 1, 2, 110, 72, }, - { 7, 1, 1, 2, 110, 54, }, - { 8, 1, 1, 2, 110, 72, }, { 9, 1, 1, 2, 110, 127, }, { 0, 1, 1, 2, 118, 72, }, { 2, 1, 1, 2, 118, 64, }, @@ -43433,9 +43328,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 118, 127, }, { 4, 1, 1, 2, 118, 72, }, { 5, 1, 1, 2, 118, 127, }, - { 6, 1, 1, 2, 118, 72, }, - { 7, 1, 1, 2, 118, 54, }, - { 8, 1, 1, 2, 118, 72, }, { 9, 1, 1, 2, 118, 127, }, { 0, 1, 1, 2, 126, 72, }, { 2, 1, 1, 2, 126, 64, }, @@ -43443,9 +43335,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 126, 127, }, { 4, 1, 1, 2, 126, 72, }, { 5, 1, 1, 2, 126, 127, }, - { 6, 1, 1, 2, 126, 72, }, - { 7, 1, 1, 2, 126, 54, }, - { 8, 1, 1, 2, 126, 72, }, { 9, 1, 1, 2, 126, 127, }, { 0, 1, 1, 2, 134, 72, }, { 2, 1, 1, 2, 134, 64, }, @@ -43453,9 +43342,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 134, 72, }, { 4, 1, 1, 2, 134, 72, }, { 5, 1, 1, 2, 134, 64, }, - { 6, 1, 1, 2, 134, 72, }, - { 7, 1, 1, 2, 134, 54, }, - { 8, 1, 1, 2, 134, 72, }, { 9, 1, 1, 2, 134, 127, }, { 0, 1, 1, 2, 142, 72, }, { 2, 1, 1, 2, 142, 127, }, @@ -43463,9 +43349,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 142, 72, }, { 4, 1, 1, 2, 142, 72, }, { 5, 1, 1, 2, 142, 127, }, - { 6, 1, 1, 2, 142, 72, }, - { 7, 1, 1, 2, 142, 127, }, - { 8, 1, 1, 2, 142, 72, }, { 9, 1, 1, 2, 142, 127, }, { 0, 1, 1, 2, 151, 72, }, { 2, 1, 1, 2, 151, 28, }, @@ -43473,29 +43356,20 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 2, 151, 72, }, { 4, 1, 1, 2, 151, 72, }, { 5, 1, 1, 2, 151, 72, }, - { 6, 1, 1, 2, 151, 72, }, - { 7, 1, 1, 2, 151, 54, }, - { 8, 1, 1, 2, 151, 72, }, - { 9, 1, 1, 2, 151, 28, }, + { 9, 1, 1, 2, 151, 72, }, { 0, 1, 1, 2, 159, 72, }, { 2, 1, 1, 2, 159, 28, }, { 1, 1, 1, 2, 159, 127, }, { 3, 1, 1, 2, 159, 72, }, { 4, 1, 1, 2, 159, 72, }, { 5, 1, 1, 2, 159, 72, }, - { 6, 1, 1, 2, 159, 72, }, - { 7, 1, 1, 2, 159, 54, }, - { 8, 1, 1, 2, 159, 72, }, - { 9, 1, 1, 2, 159, 28, }, + { 9, 1, 1, 2, 159, 72, }, { 0, 1, 1, 3, 38, 60, }, { 2, 1, 1, 3, 38, 40, }, { 1, 1, 1, 3, 38, 50, }, { 3, 1, 1, 3, 38, 40, }, { 4, 1, 1, 3, 38, 54, }, { 5, 1, 1, 3, 38, 40, }, - { 6, 1, 1, 3, 38, 52, }, - { 7, 1, 1, 3, 38, 30, }, - { 8, 1, 1, 3, 38, 50, }, { 9, 1, 1, 3, 38, 40, }, { 0, 1, 1, 3, 46, 68, }, { 2, 1, 1, 3, 46, 40, }, @@ -43503,9 +43377,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 46, 40, }, { 4, 1, 1, 3, 46, 54, }, { 5, 1, 1, 3, 46, 40, }, - { 6, 1, 1, 3, 46, 52, }, - { 7, 1, 1, 3, 46, 30, }, - { 8, 1, 1, 3, 46, 50, }, { 9, 1, 1, 3, 46, 40, }, { 0, 1, 1, 3, 54, 68, }, { 2, 1, 1, 3, 54, 40, }, @@ -43513,9 +43384,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 54, 40, }, { 4, 1, 1, 3, 54, 66, }, { 5, 1, 1, 3, 54, 40, }, - { 6, 1, 1, 3, 54, 68, }, - { 7, 1, 1, 3, 54, 30, }, - { 8, 1, 1, 3, 54, 68, }, { 9, 1, 1, 3, 54, 40, }, { 0, 1, 1, 3, 62, 58, }, { 2, 1, 1, 3, 62, 40, }, @@ -43523,9 +43391,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 62, 40, }, { 4, 1, 1, 3, 62, 50, }, { 5, 1, 1, 3, 62, 40, }, - { 6, 1, 1, 3, 62, 58, }, - { 7, 1, 1, 3, 62, 30, }, - { 8, 1, 1, 3, 62, 58, }, { 9, 1, 1, 3, 62, 40, }, { 0, 1, 1, 3, 102, 56, }, { 2, 1, 1, 3, 102, 40, }, @@ -43533,9 +43398,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 102, 56, }, { 4, 1, 1, 3, 102, 54, }, { 5, 1, 1, 3, 102, 40, }, - { 6, 1, 1, 3, 102, 54, }, - { 7, 1, 1, 3, 102, 30, }, - { 8, 1, 1, 3, 102, 54, }, { 9, 1, 1, 3, 102, 127, }, { 0, 1, 1, 3, 110, 68, }, { 2, 1, 1, 3, 110, 40, }, @@ -43543,9 +43405,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 110, 68, }, { 4, 1, 1, 3, 110, 66, }, { 5, 1, 1, 3, 110, 40, }, - { 6, 1, 1, 3, 110, 68, }, - { 7, 1, 1, 3, 110, 30, }, - { 8, 1, 1, 3, 110, 68, }, { 9, 1, 1, 3, 110, 127, }, { 0, 1, 1, 3, 118, 68, }, { 2, 1, 1, 3, 118, 40, }, @@ -43553,9 +43412,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 118, 127, }, { 4, 1, 1, 3, 118, 66, }, { 5, 1, 1, 3, 118, 127, }, - { 6, 1, 1, 3, 118, 68, }, - { 7, 1, 1, 3, 118, 30, }, - { 8, 1, 1, 3, 118, 68, }, { 9, 1, 1, 3, 118, 127, }, { 0, 1, 1, 3, 126, 68, }, { 2, 1, 1, 3, 126, 40, }, @@ -43563,9 +43419,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 126, 127, }, { 4, 1, 1, 3, 126, 66, }, { 5, 1, 1, 3, 126, 127, }, - { 6, 1, 1, 3, 126, 68, }, - { 7, 1, 1, 3, 126, 30, }, - { 8, 1, 1, 3, 126, 68, }, { 9, 1, 1, 3, 126, 127, }, { 0, 1, 1, 3, 134, 68, }, { 2, 1, 1, 3, 134, 40, }, @@ -43573,9 +43426,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 134, 68, }, { 4, 1, 1, 3, 134, 66, }, { 5, 1, 1, 3, 134, 40, }, - { 6, 1, 1, 3, 134, 68, }, - { 7, 1, 1, 3, 134, 30, }, - { 8, 1, 1, 3, 134, 68, }, { 9, 1, 1, 3, 134, 127, }, { 0, 1, 1, 3, 142, 68, }, { 2, 1, 1, 3, 142, 127, }, @@ -43583,9 +43433,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 142, 68, }, { 4, 1, 1, 3, 142, 66, }, { 5, 1, 1, 3, 142, 127, }, - { 6, 1, 1, 3, 142, 68, }, - { 7, 1, 1, 3, 142, 127, }, - { 8, 1, 1, 3, 142, 68, }, { 9, 1, 1, 3, 142, 127, }, { 0, 1, 1, 3, 151, 72, }, { 2, 1, 1, 3, 151, 4, }, @@ -43593,29 +43440,20 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 1, 3, 151, 72, }, { 4, 1, 1, 3, 151, 66, }, { 5, 1, 1, 3, 151, 72, }, - { 6, 1, 1, 3, 151, 72, }, - { 7, 1, 1, 3, 151, 30, }, - { 8, 1, 1, 3, 151, 68, }, - { 9, 1, 1, 3, 151, 4, }, + { 9, 1, 1, 3, 151, 64, }, { 0, 1, 1, 3, 159, 72, }, { 2, 1, 1, 3, 159, 4, }, { 1, 1, 1, 3, 159, 127, }, { 3, 1, 1, 3, 159, 72, }, { 4, 1, 1, 3, 159, 66, }, { 5, 1, 1, 3, 159, 72, }, - { 6, 1, 1, 3, 159, 72, }, - { 7, 1, 1, 3, 159, 30, }, - { 8, 1, 1, 3, 159, 72, }, - { 9, 1, 1, 3, 159, 4, }, + { 9, 1, 1, 3, 159, 72, }, { 0, 1, 2, 4, 42, 68, }, { 2, 1, 2, 4, 42, 64, }, { 1, 1, 2, 4, 42, 64, }, { 3, 1, 2, 4, 42, 64, }, { 4, 1, 2, 4, 42, 60, }, { 5, 1, 2, 4, 42, 64, }, - { 6, 1, 2, 4, 42, 64, }, - { 7, 1, 2, 4, 42, 54, }, - { 8, 1, 2, 4, 42, 62, }, { 9, 1, 2, 4, 42, 64, }, { 0, 1, 2, 4, 58, 60, }, { 2, 1, 2, 4, 58, 64, }, @@ -43623,9 +43461,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 4, 58, 60, }, { 4, 1, 2, 4, 58, 56, }, { 5, 1, 2, 4, 58, 64, }, - { 6, 1, 2, 4, 58, 62, }, - { 7, 1, 2, 4, 58, 54, }, - { 8, 1, 2, 4, 58, 62, }, { 9, 1, 2, 4, 58, 64, }, { 0, 1, 2, 4, 106, 60, }, { 2, 1, 2, 4, 106, 64, }, @@ -43633,9 +43468,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 4, 106, 60, }, { 4, 1, 2, 4, 106, 58, }, { 5, 1, 2, 4, 106, 64, }, - { 6, 1, 2, 4, 106, 58, }, - { 7, 1, 2, 4, 106, 54, }, - { 8, 1, 2, 4, 106, 58, }, { 9, 1, 2, 4, 106, 127, }, { 0, 1, 2, 4, 122, 72, }, { 2, 1, 2, 4, 122, 64, }, @@ -43643,9 +43475,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 4, 122, 127, }, { 4, 1, 2, 4, 122, 68, }, { 5, 1, 2, 4, 122, 127, }, - { 6, 1, 2, 4, 122, 72, }, - { 7, 1, 2, 4, 122, 54, }, - { 8, 1, 2, 4, 122, 72, }, { 9, 1, 2, 4, 122, 127, }, { 0, 1, 2, 4, 138, 72, }, { 2, 1, 2, 4, 138, 127, }, @@ -43653,9 +43482,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 4, 138, 72, }, { 4, 1, 2, 4, 138, 70, }, { 5, 1, 2, 4, 138, 127, }, - { 6, 1, 2, 4, 138, 72, }, - { 7, 1, 2, 4, 138, 127, }, - { 8, 1, 2, 4, 138, 72, }, { 9, 1, 2, 4, 138, 127, }, { 0, 1, 2, 4, 155, 72, }, { 2, 1, 2, 4, 155, 28, }, @@ -43663,19 +43489,13 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 4, 155, 72, }, { 4, 1, 2, 4, 155, 62, }, { 5, 1, 2, 4, 155, 72, }, - { 6, 1, 2, 4, 155, 72, }, - { 7, 1, 2, 4, 155, 54, }, - { 8, 1, 2, 4, 155, 68, }, - { 9, 1, 2, 4, 155, 28, }, + { 9, 1, 2, 4, 155, 72, }, { 0, 1, 2, 5, 42, 56, }, { 2, 1, 2, 5, 42, 40, }, { 1, 1, 2, 5, 42, 50, }, { 3, 1, 2, 5, 42, 40, }, { 4, 1, 2, 5, 42, 50, }, { 5, 1, 2, 5, 42, 40, }, - { 6, 1, 2, 5, 42, 52, }, - { 7, 1, 2, 5, 42, 30, }, - { 8, 1, 2, 5, 42, 50, }, { 9, 1, 2, 5, 42, 40, }, { 0, 1, 2, 5, 58, 54, }, { 2, 1, 2, 5, 58, 40, }, @@ -43683,9 +43503,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 5, 58, 40, }, { 4, 1, 2, 5, 58, 46, }, { 5, 1, 2, 5, 58, 40, }, - { 6, 1, 2, 5, 58, 52, }, - { 7, 1, 2, 5, 58, 30, }, - { 8, 1, 2, 5, 58, 52, }, { 9, 1, 2, 5, 58, 40, }, { 0, 1, 2, 5, 106, 48, }, { 2, 1, 2, 5, 106, 40, }, @@ -43693,9 +43510,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 5, 106, 48, }, { 4, 1, 2, 5, 106, 50, }, { 5, 1, 2, 5, 106, 40, }, - { 6, 1, 2, 5, 106, 50, }, - { 7, 1, 2, 5, 106, 30, }, - { 8, 1, 2, 5, 106, 50, }, { 9, 1, 2, 5, 106, 127, }, { 0, 1, 2, 5, 122, 70, }, { 2, 1, 2, 5, 122, 40, }, @@ -43703,9 +43517,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 5, 122, 127, }, { 4, 1, 2, 5, 122, 62, }, { 5, 1, 2, 5, 122, 127, }, - { 6, 1, 2, 5, 122, 66, }, - { 7, 1, 2, 5, 122, 30, }, - { 8, 1, 2, 5, 122, 66, }, { 9, 1, 2, 5, 122, 127, }, { 0, 1, 2, 5, 138, 70, }, { 2, 1, 2, 5, 138, 127, }, @@ -43713,9 +43524,6 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 5, 138, 70, }, { 4, 1, 2, 5, 138, 62, }, { 5, 1, 2, 5, 138, 127, }, - { 6, 1, 2, 5, 138, 66, }, - { 7, 1, 2, 5, 138, 127, }, - { 8, 1, 2, 5, 138, 66, }, { 9, 1, 2, 5, 138, 127, }, { 0, 1, 2, 5, 155, 72, }, { 2, 1, 2, 5, 155, 4, }, @@ -43723,10 +43531,7 @@ static const struct rtw_txpwr_lmt_cfg_pair rtw8822c_txpwr_lmt_type5[] = { { 3, 1, 2, 5, 155, 72, }, { 4, 1, 2, 5, 155, 52, }, { 5, 1, 2, 5, 155, 72, }, - { 6, 1, 2, 5, 155, 62, }, - { 7, 1, 2, 5, 155, 30, }, - { 8, 1, 2, 5, 155, 62, }, - { 9, 1, 2, 5, 155, 4, }, + { 9, 1, 2, 5, 155, 66, }, }; RTW_DECL_TABLE_TXPWR_LMT(rtw8822c_txpwr_lmt_type5); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index d879d7e3dc81..e6ab1ac6d709 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -611,8 +611,7 @@ static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb) for (i = 0; i < RTW_USB_RXCB_NUM; i++) { rxcb = &rtwusb->rx_cb[i]; - if (rxcb->rx_urb) - usb_kill_urb(rxcb->rx_urb); + usb_kill_urb(rxcb->rx_urb); } } @@ -623,10 +622,8 @@ static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb) for (i = 0; i < RTW_USB_RXCB_NUM; i++) { rxcb = &rtwusb->rx_cb[i]; - if (rxcb->rx_urb) { - usb_kill_urb(rxcb->rx_urb); - usb_free_urb(rxcb->rx_urb); - } + usb_kill_urb(rxcb->rx_urb); + usb_free_urb(rxcb->rx_urb); } } diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index 4ba8b3df70ae..207218cdf2c4 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -237,13 +237,13 @@ struct rtw89_btc_btf_set_report { struct rtw89_btc_btf_set_slot_table { u8 fver; u8 tbl_num; - u8 buf[]; + struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); } __packed; struct rtw89_btc_btf_set_mon_reg { u8 fver; u8 reg_num; - u8 buf[]; + struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); } __packed; enum btc_btf_set_cx_policy { @@ -1821,19 +1821,17 @@ static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num, struct rtw89_btc_fbtc_slot *s) { - struct rtw89_btc_btf_set_slot_table *tbl = NULL; - u8 *ptr = NULL; - u16 n = 0; + struct rtw89_btc_btf_set_slot_table *tbl; + u16 n; - n = sizeof(*s) * num + sizeof(*tbl); + n = struct_size(tbl, tbls, num); tbl = kmalloc(n, GFP_KERNEL); if (!tbl) return; tbl->fver = BTF_SET_SLOT_TABLE_VER; tbl->tbl_num = num; - ptr = &tbl->buf[0]; - memcpy(ptr, s, num * sizeof(*s)); + memcpy(tbl->tbls, s, flex_array_size(tbl, tbls, num)); _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); @@ -1845,7 +1843,7 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_btc_ver *ver = rtwdev->btc.ver; struct rtw89_btc_btf_set_mon_reg *monreg = NULL; - u8 n, *ptr = NULL, ulen, cxmreg_max; + u8 n, ulen, cxmreg_max; u16 sz = 0; n = chip->mon_reg_num; @@ -1866,16 +1864,15 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) return; } - ulen = sizeof(struct rtw89_btc_fbtc_mreg); - sz = (ulen * n) + sizeof(*monreg); + ulen = sizeof(monreg->regs[0]); + sz = struct_size(monreg, regs, n); monreg = kmalloc(sz, GFP_KERNEL); if (!monreg) return; monreg->fver = ver->fcxmreg; monreg->reg_num = n; - ptr = &monreg->buf[0]; - memcpy(ptr, chip->mon_reg, n * ulen); + memcpy(monreg->regs, chip->mon_reg, flex_array_size(monreg, regs, n)); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): sz=%d ulen=%d n=%d\n", __func__, sz, ulen, n); diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index cca18d7ea1dd..4bfb4188de72 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1621,32 +1621,49 @@ static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev, phy_ppdu); } -static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev, - const struct rtw89_rx_desc_info *desc_info, - bool rx_status) +static u8 rtw89_rxdesc_to_nl_he_eht_gi(struct rtw89_dev *rtwdev, + u8 desc_info_gi, + bool rx_status, bool eht) { - switch (desc_info->gi_ltf) { + switch (desc_info_gi) { case RTW89_GILTF_SGI_4XHE08: case RTW89_GILTF_2XHE08: case RTW89_GILTF_1XHE08: - return NL80211_RATE_INFO_HE_GI_0_8; + return eht ? NL80211_RATE_INFO_EHT_GI_0_8 : + NL80211_RATE_INFO_HE_GI_0_8; case RTW89_GILTF_2XHE16: case RTW89_GILTF_1XHE16: - return NL80211_RATE_INFO_HE_GI_1_6; + return eht ? NL80211_RATE_INFO_EHT_GI_1_6 : + NL80211_RATE_INFO_HE_GI_1_6; case RTW89_GILTF_LGI_4XHE32: - return NL80211_RATE_INFO_HE_GI_3_2; + return eht ? NL80211_RATE_INFO_EHT_GI_3_2 : + NL80211_RATE_INFO_HE_GI_3_2; default: - rtw89_warn(rtwdev, "invalid gi_ltf=%d", desc_info->gi_ltf); - return rx_status ? NL80211_RATE_INFO_HE_GI_3_2 : U8_MAX; + rtw89_warn(rtwdev, "invalid gi_ltf=%d", desc_info_gi); + if (rx_status) + return eht ? NL80211_RATE_INFO_EHT_GI_3_2 : + NL80211_RATE_INFO_HE_GI_3_2; + return U8_MAX; } } +static +bool rtw89_check_rx_statu_gi_match(struct ieee80211_rx_status *status, u8 gi_ltf, + bool eht) +{ + if (eht) + return status->eht.gi == gi_ltf; + + return status->he_gi == gi_ltf; +} + static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, struct ieee80211_rx_status *status) { u8 band = desc_info->bb_sel ? RTW89_PHY_1 : RTW89_PHY_0; u8 data_rate_mode, bw, rate_idx = MASKBYTE0, gi_ltf; + bool eht = false; u16 data_rate; bool ret; @@ -1657,19 +1674,20 @@ static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev, /* rate_idx is still hardware value here */ } else if (data_rate_mode == DATA_RATE_MODE_HT) { rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate); - } else if (data_rate_mode == DATA_RATE_MODE_VHT) { - rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); - } else if (data_rate_mode == DATA_RATE_MODE_HE) { + } else if (data_rate_mode == DATA_RATE_MODE_VHT || + data_rate_mode == DATA_RATE_MODE_HE || + data_rate_mode == DATA_RATE_MODE_EHT) { rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } + eht = data_rate_mode == DATA_RATE_MODE_EHT; bw = rtw89_hw_to_rate_info_bw(desc_info->bw); - gi_ltf = rtw89_rxdesc_to_nl_he_gi(rtwdev, desc_info, false); + gi_ltf = rtw89_rxdesc_to_nl_he_eht_gi(rtwdev, desc_info->gi_ltf, false, eht); ret = rtwdev->ppdu_sts.curr_rx_ppdu_cnt[band] == desc_info->ppdu_cnt && status->rate_idx == rate_idx && - status->he_gi == gi_ltf && + rtw89_check_rx_statu_gi_match(status, gi_ltf, eht) && status->bw == bw; return ret; @@ -1889,6 +1907,72 @@ static void rtw89_core_hw_to_sband_rate(struct ieee80211_rx_status *rx_status) rx_status->rate_idx -= 4; } +static const u8 rx_status_bw_to_radiotap_eht_usig[] = { + [RATE_INFO_BW_20] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_20MHZ, + [RATE_INFO_BW_5] = U8_MAX, + [RATE_INFO_BW_10] = U8_MAX, + [RATE_INFO_BW_40] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_40MHZ, + [RATE_INFO_BW_80] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_80MHZ, + [RATE_INFO_BW_160] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_160MHZ, + [RATE_INFO_BW_HE_RU] = U8_MAX, + [RATE_INFO_BW_320] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_320MHZ_1, + [RATE_INFO_BW_EHT_RU] = U8_MAX, +}; + +static void rtw89_core_update_radiotap_eht(struct rtw89_dev *rtwdev, + struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_radiotap_eht_usig *usig; + struct ieee80211_radiotap_eht *eht; + struct ieee80211_radiotap_tlv *tlv; + int eht_len = struct_size(eht, user_info, 1); + int usig_len = sizeof(*usig); + int len; + u8 bw; + + len = sizeof(*tlv) + ALIGN(eht_len, 4) + + sizeof(*tlv) + ALIGN(usig_len, 4); + + rx_status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END; + skb_reset_mac_header(skb); + + /* EHT */ + tlv = skb_push(skb, len); + memset(tlv, 0, len); + tlv->type = cpu_to_le16(IEEE80211_RADIOTAP_EHT); + tlv->len = cpu_to_le16(eht_len); + + eht = (struct ieee80211_radiotap_eht *)tlv->data; + eht->known = cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI); + eht->data[0] = + le32_encode_bits(rx_status->eht.gi, IEEE80211_RADIOTAP_EHT_DATA0_GI); + + eht->user_info[0] = + cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN | + IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O); + eht->user_info[0] |= + le32_encode_bits(rx_status->rate_idx, IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) | + le32_encode_bits(rx_status->nss, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O); + + /* U-SIG */ + tlv = (void *)tlv + sizeof(*tlv) + ALIGN(eht_len, 4); + tlv->type = cpu_to_le16(IEEE80211_RADIOTAP_EHT_USIG); + tlv->len = cpu_to_le16(usig_len); + + if (rx_status->bw >= ARRAY_SIZE(rx_status_bw_to_radiotap_eht_usig)) + return; + + bw = rx_status_bw_to_radiotap_eht_usig[rx_status->bw]; + if (bw == U8_MAX) + return; + + usig = (struct ieee80211_radiotap_eht_usig *)tlv->data; + usig->common = + le32_encode_bits(1, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN) | + le32_encode_bits(bw, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW); +} + static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) @@ -1907,6 +1991,8 @@ static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev, rx_status->flag |= RX_FLAG_RADIOTAP_HE; he = skb_push(skb, sizeof(*he)); *he = known_he; + } else if (rx_status->encoding == RX_ENC_EHT) { + rtw89_core_update_radiotap_eht(rtwdev, skb, rx_status); } } @@ -2168,6 +2254,8 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0); u16 data_rate; u8 data_rate_mode; + bool eht = false; + u8 gi; /* currently using single PHY */ rx_status->freq = chandef->chan->center_freq; @@ -2215,12 +2303,21 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rx_status->encoding = RX_ENC_HE; rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; + } else if (data_rate_mode == DATA_RATE_MODE_EHT) { + rx_status->encoding = RX_ENC_EHT; + rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); + rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; + eht = true; } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } /* he_gi is used to match ppdu, so we always fill it. */ - rx_status->he_gi = rtw89_rxdesc_to_nl_he_gi(rtwdev, desc_info, true); + gi = rtw89_rxdesc_to_nl_he_eht_gi(rtwdev, desc_info->gi_ltf, true, eht); + if (eht) + rx_status->eht.gi = gi; + else + rx_status->he_gi = gi; rx_status->flag |= RX_FLAG_MACTIME_START; rx_status->mactime = desc_info->free_run_cnt; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 5bf18110b379..d5272a82ff8b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -37,7 +37,14 @@ extern const struct ieee80211_ops rtw89_ops; #define RSSI_FACTOR 1 #define RTW89_RSSI_RAW_TO_DBM(rssi) ((s8)((rssi) >> RSSI_FACTOR) - MAX_RSSI) #define RTW89_TX_DIV_RSSI_RAW_TH (2 << RSSI_FACTOR) -#define RTW89_RADIOTAP_ROOM ALIGN(sizeof(struct ieee80211_radiotap_he), 64) +#define RTW89_RADIOTAP_ROOM_HE sizeof(struct ieee80211_radiotap_he) +#define RTW89_RADIOTAP_ROOM_EHT \ + (sizeof(struct ieee80211_radiotap_tlv) + \ + ALIGN(struct_size((struct ieee80211_radiotap_eht *)0, user_info, 1), 4) + \ + sizeof(struct ieee80211_radiotap_tlv) + \ + ALIGN(sizeof(struct ieee80211_radiotap_eht_usig), 4)) +#define RTW89_RADIOTAP_ROOM \ + ALIGN(max(RTW89_RADIOTAP_ROOM_HE, RTW89_RADIOTAP_ROOM_EHT), 64) #define RTW89_HTC_MASK_VARIANT GENMASK(1, 0) #define RTW89_HTC_VARIANT_HE 3 @@ -2734,6 +2741,7 @@ enum rtw89_ra_mode { RTW89_RA_MODE_HT = BIT(2), RTW89_RA_MODE_VHT = BIT(3), RTW89_RA_MODE_HE = BIT(4), + RTW89_RA_MODE_EHT = BIT(5), }; enum rtw89_ra_report_mode { @@ -2741,6 +2749,7 @@ enum rtw89_ra_report_mode { RTW89_RA_RPT_MODE_HT, RTW89_RA_RPT_MODE_VHT, RTW89_RA_RPT_MODE_HE, + RTW89_RA_RPT_MODE_EHT, }; enum rtw89_dig_noisy_level { diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 6990d3679bc0..a3f795d240ea 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3467,6 +3467,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) [NL80211_RATE_INFO_HE_GI_1_6] = "1.6", [NL80211_RATE_INFO_HE_GI_3_2] = "3.2", }; + static const char * const eht_gi_str[] = { + [NL80211_RATE_INFO_EHT_GI_0_8] = "0.8", + [NL80211_RATE_INFO_EHT_GI_1_6] = "1.6", + [NL80211_RATE_INFO_EHT_GI_3_2] = "3.2", + }; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rate_info *rate = &rtwsta->ra_report.txrate; struct ieee80211_rx_status *status = &rtwsta->rx_status; @@ -3492,6 +3497,10 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) seq_printf(m, "HE %dSS MCS-%d GI:%s", rate->nss, rate->mcs, rate->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ? he_gi_str[rate->he_gi] : "N/A"); + else if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) + seq_printf(m, "EHT %dSS MCS-%d GI:%s", rate->nss, rate->mcs, + rate->eht_gi < ARRAY_SIZE(eht_gi_str) ? + eht_gi_str[rate->eht_gi] : "N/A"); else seq_printf(m, "Legacy %d", rate->legacy); seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : ""); @@ -3520,6 +3529,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) status->he_gi <= NL80211_RATE_INFO_HE_GI_3_2 ? he_gi_str[rate->he_gi] : "N/A"); break; + case RX_ENC_EHT: + seq_printf(m, "EHT %dSS MCS-%d GI:%s", status->nss, status->rate_idx, + status->eht.gi < ARRAY_SIZE(eht_gi_str) ? + eht_gi_str[status->eht.gi] : "N/A"); + break; } seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index f1d14e84cda7..0c5768f41d55 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4840,6 +4840,7 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) #define MAC_AX_LEN_TH_MAX 255 #define MAC_AX_TIME_TH_DEF 88 #define MAC_AX_LEN_TH_DEF 4080 + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; u32 rts_threshold = hw->wiphy->rts_threshold; u32 time_th, len_th; @@ -4856,7 +4857,7 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) time_th = min_t(u32, time_th >> MAC_AX_TIME_TH_SH, MAC_AX_TIME_TH_MAX); len_th = min_t(u32, len_th >> MAC_AX_LEN_TH_SH, MAC_AX_LEN_TH_MAX); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AGG_LEN_HT_0, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, mac->agg_len_ht, mac_idx); rtw89_write16_mask(rtwdev, reg, B_AX_RTS_TXTIME_TH_MASK, time_th); rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th); } @@ -5194,6 +5195,9 @@ static void rtw89_mac_bfee_standby_timer(struct rtw89_dev *rtwdev, u8 mac_idx, { u32 reg; + if (rtwdev->chip->chip_gen != RTW89_CHIP_AX) + return; + rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee standby_timer to %d\n", keep); reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx); if (keep) { @@ -5207,14 +5211,14 @@ static void rtw89_mac_bfee_standby_timer(struct rtw89_dev *rtwdev, u8 mac_idx, } } -static void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) +void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u32 reg; - u32 mask = B_AX_BFMEE_HT_NDPA_EN | B_AX_BFMEE_VHT_NDPA_EN | - B_AX_BFMEE_HE_NDPA_EN; + u32 mask = mac->bfee_ctrl.mask; rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee ndpa_en to %d\n", en); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, mac->bfee_ctrl.addr, mac_idx); if (en) { set_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); rtw89_write32_set(rtwdev, reg, mask); @@ -5224,7 +5228,7 @@ static void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) } } -static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx) +static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx) { u32 reg; u32 val32; @@ -5266,9 +5270,9 @@ static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx) return 0; } -static int rtw89_mac_set_csi_para_reg(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u8 mac_idx = rtwvif->mac_idx; @@ -5324,9 +5328,9 @@ static int rtw89_mac_set_csi_para_reg(struct rtw89_dev *rtwdev, return 0; } -static int rtw89_mac_csi_rrsc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); @@ -5363,17 +5367,18 @@ static int rtw89_mac_csi_rrsc(struct rtw89_dev *rtwdev, return 0; } -void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; if (rtw89_sta_has_beamformer_cap(sta)) { rtw89_debug(rtwdev, RTW89_DBG_BF, "initialize bfee for new association\n"); - rtw89_mac_init_bfee(rtwdev, rtwvif->mac_idx); - rtw89_mac_set_csi_para_reg(rtwdev, vif, sta); - rtw89_mac_csi_rrsc(rtwdev, vif, sta); + rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx); + rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta); + rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta); } } @@ -5592,8 +5597,9 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool en) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u8 mac_idx = rtwvif->mac_idx; - u16 set = B_AX_MUEDCA_EN_0 | B_AX_SET_MUEDCATIMER_TF_0; + u16 set = mac->muedca_ctrl.mask; u32 reg; u32 ret; @@ -5601,7 +5607,7 @@ int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, if (ret) return ret; - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MUEDCA_EN, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, mac->muedca_ctrl.addr, mac_idx); if (en) rtw89_write16_set(rtwdev, reg, set); else @@ -5751,6 +5757,19 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .mem_base_addrs = rtw89_mac_mem_base_addrs_ax, .rx_fltr = R_AX_RX_FLTR_OPT, .port_base = &rtw89_port_base_ax, + .agg_len_ht = R_AX_AGG_LEN_HT_0, + + .muedca_ctrl = { + .addr = R_AX_MUEDCA_EN, + .mask = B_AX_MUEDCA_EN_0 | B_AX_SET_MUEDCATIMER_TF_0, + }, + .bfee_ctrl = { + .addr = R_AX_BFMEE_RESP_OPTION, + .mask = B_AX_BFMEE_HT_NDPA_EN | B_AX_BFMEE_VHT_NDPA_EN | + B_AX_BFMEE_HE_NDPA_EN, + }, + + .bf_assoc = rtw89_mac_bf_assoc_ax, .disable_cpu = rtw89_mac_disable_cpu_ax, .fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax, diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 617fd2aea776..c11c904f87fe 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -859,6 +859,13 @@ struct rtw89_mac_gen_def { const u32 *mem_base_addrs; u32 rx_fltr; const struct rtw89_port_reg *port_base; + u32 agg_len_ht; + + struct rtw89_reg_def muedca_ctrl; + struct rtw89_reg_def bfee_ctrl; + + void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void (*disable_cpu)(struct rtw89_dev *rtwdev); int (*fwdl_enable_wcpu)(struct rtw89_dev *rtwdev, u8 boot_reason, @@ -1034,8 +1041,17 @@ int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl); int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl); void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter); void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev); + +static inline void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct ieee80211_sta *sta) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (mac->bf_assoc) + mac->bf_assoc(rtwdev, vif, sta); +} + void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, @@ -1043,6 +1059,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, bool disconnect); void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev); +void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en); int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, @@ -1051,6 +1068,9 @@ int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause); static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) { + if (rtwdev->chip->chip_gen != RTW89_CHIP_AX) + return; + if (!test_bit(RTW89_FLAG_BFEE_MON, rtwdev->flags)) return; diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 16bbb7751197..31d1f7891675 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -328,11 +328,14 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val); } -static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS] = { - [IEEE80211_AC_VO] = R_AX_MUEDCA_VO_PARAM_0, - [IEEE80211_AC_VI] = R_AX_MUEDCA_VI_PARAM_0, - [IEEE80211_AC_BE] = R_AX_MUEDCA_BE_PARAM_0, - [IEEE80211_AC_BK] = R_AX_MUEDCA_BK_PARAM_0, +#define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \ + R_BE_MUEDCA_ ## acs ## _PARAM_0} + +static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = { + [IEEE80211_AC_VO] = R_MUEDCA_ACS_PARAM(VO), + [IEEE80211_AC_VI] = R_MUEDCA_ACS_PARAM(VI), + [IEEE80211_AC_BE] = R_MUEDCA_ACS_PARAM(BE), + [IEEE80211_AC_BK] = R_MUEDCA_ACS_PARAM(BK), }; static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, @@ -340,6 +343,7 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, { struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; struct ieee80211_he_mu_edca_param_ac_rec *mu_edca; + int gen = rtwdev->chip->chip_gen; u8 aifs, aifsn; u16 timer_32us; u32 reg; @@ -356,7 +360,7 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs); - reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx); rtw89_write32(rtwdev, reg, val); rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true); diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 8af71d8a659a..3278f241db6e 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -243,6 +243,167 @@ static bool rtw89_mac_get_txpwr_cr_be(struct rtw89_dev *rtwdev, return true; } +static int rtw89_mac_init_bfee_be(struct rtw89_dev *rtwdev, u8 mac_idx) +{ + u32 reg; + u32 val; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) + return ret; + + rtw89_mac_bfee_ctrl(rtwdev, mac_idx, true); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL | + B_BE_BFMEE_USE_NSTS | + B_BE_BFMEE_CSI_GID_SEL | + B_BE_BFMEE_CSI_FORCE_RETE_EN); + rtw89_write32_mask(rtwdev, reg, B_BE_BFMEE_CSI_RSC_MASK, CSI_RX_BW_CFG); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CSIRPT_OPTION, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_CSIPRT_VHTSU_AID_EN | + B_BE_CSIPRT_HESU_AID_EN | + B_BE_CSIPRT_EHTSU_AID_EN); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_RRSC, mac_idx); + rtw89_write32(rtwdev, reg, CSI_RRSC_BMAP_BE); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_1, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_BE_BFMEE_BE_CSI_RRSC_BITMAP_MASK, + CSI_RRSC_BITMAP_CFG); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_RATE, mac_idx); + val = u32_encode_bits(CSI_INIT_RATE_HT, B_BE_BFMEE_HT_CSI_RATE_MASK) | + u32_encode_bits(CSI_INIT_RATE_VHT, B_BE_BFMEE_VHT_CSI_RATE_MASK) | + u32_encode_bits(CSI_INIT_RATE_HE, B_BE_BFMEE_HE_CSI_RATE_MASK) | + u32_encode_bits(CSI_INIT_RATE_EHT, B_BE_BFMEE_EHT_CSI_RATE_MASK); + + rtw89_write32(rtwdev, reg, val); + + return 0; +} + +static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; + u8 mac_idx = rtwvif->mac_idx; + u8 port_sel = rtwvif->port; + u8 sound_dim = 3, t; + u8 *phy_cap; + u32 reg; + u16 val; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) + return ret; + + phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + + if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || + (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { + ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD); + stbc_en &= !!(phy_cap[2] & IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ); + t = u8_get_bits(phy_cap[5], + IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK); + sound_dim = min(sound_dim, t); + } + + if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + t = u32_get_bits(sta->deflink.vht_cap.cap, + IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK); + sound_dim = min(sound_dim, t); + } + + nc = min(nc, sound_dim); + nr = min(nr, sound_dim); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); + + val = u16_encode_bits(nc, B_BE_BFMEE_CSIINFO0_NC_MASK) | + u16_encode_bits(nr, B_BE_BFMEE_CSIINFO0_NR_MASK) | + u16_encode_bits(ng, B_BE_BFMEE_CSIINFO0_NG_MASK) | + u16_encode_bits(cb, B_BE_BFMEE_CSIINFO0_CB_MASK) | + u16_encode_bits(cs, B_BE_BFMEE_CSIINFO0_CS_MASK) | + u16_encode_bits(ldpc_en, B_BE_BFMEE_CSIINFO0_LDPC_EN) | + u16_encode_bits(stbc_en, B_BE_BFMEE_CSIINFO0_STBC_EN); + + if (port_sel == 0) + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, + mac_idx); + else + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_1, + mac_idx); + + rtw89_write16(rtwdev, reg, val); + + return 0; +} + +static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + u8 mac_idx = rtwvif->mac_idx; + int ret; + u32 reg; + + ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); + if (ret) + return ret; + + if (sta->deflink.he_cap.has_he) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); + } + if (sta->deflink.vht_cap.vht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); + } + if (sta->deflink.ht_cap.ht_supported) { + rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | + BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); + } + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); + rtw89_write32_clr(rtwdev, reg, B_BE_BFMEE_CSI_FORCE_RETE_EN); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_RRSC, mac_idx); + rtw89_write32(rtwdev, reg, rrsc); + + return 0; +} + +static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + + if (rtw89_sta_has_beamformer_cap(sta)) { + rtw89_debug(rtwdev, RTW89_DBG_BF, + "initialize bfee for new association\n"); + rtw89_mac_init_bfee_be(rtwdev, rtwvif->mac_idx); + rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta); + rtw89_mac_csi_rrsc_be(rtwdev, vif, sta); + } +} + const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .band1_offset = RTW89_MAC_BE_BAND_REG_OFFSET, .filter_model_addr = R_BE_FILTER_MODEL_ADDR, @@ -250,6 +411,19 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .mem_base_addrs = rtw89_mac_mem_base_addrs_be, .rx_fltr = R_BE_RX_FLTR_OPT, .port_base = &rtw89_port_base_be, + .agg_len_ht = R_BE_AGG_LEN_HT_0, + + .muedca_ctrl = { + .addr = R_BE_MUEDCA_EN, + .mask = B_BE_MUEDCA_EN_0 | B_BE_SET_MUEDCATIMER_TF_0, + }, + .bfee_ctrl = { + .addr = R_BE_BFMEE_RESP_OPTION, + .mask = B_BE_BFMEE_HT_NDPA_EN | B_BE_BFMEE_VHT_NDPA_EN | + B_BE_BFMEE_HE_NDPA_EN | B_BE_BFMEE_EHT_NDPA_EN, + }, + + .bf_assoc = rtw89_mac_bf_assoc_be, .disable_cpu = rtw89_mac_disable_cpu_be, .fwdl_enable_wcpu = rtw89_mac_fwdl_enable_wcpu_be, diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index d04eaf7c5500..8a306a86f1f0 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -88,6 +88,55 @@ static u64 get_he_ra_mask(struct ieee80211_sta *sta) return get_mcs_ra_mask(mcs_map, 11, 2); } +static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss) +{ + u64 nss_mcs_shift; + u64 nss_mcs_val; + u64 mask = 0; + int i, j; + u8 nss; + + for (i = 0; i < n_nss; i++) { + nss = u8_get_bits(max_nss[i], IEEE80211_EHT_MCS_NSS_RX); + if (!nss) + continue; + + nss_mcs_val = GENMASK_ULL(start_mcs + i * 2, 0); + + for (j = 0, nss_mcs_shift = 12; j < nss; j++, nss_mcs_shift += 16) + mask |= nss_mcs_val << nss_mcs_shift; + } + + return mask; +} + +static u64 get_eht_ra_mask(struct ieee80211_sta *sta) +{ + struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; + struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; + struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_320: + mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320; + /* MCS 9, 11, 13 */ + return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3); + case IEEE80211_STA_RX_BW_160: + mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._160; + /* MCS 9, 11, 13 */ + return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3); + case IEEE80211_STA_RX_BW_80: + default: + mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80; + /* MCS 9, 11, 13 */ + return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3); + case IEEE80211_STA_RX_BW_20: + mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz; + /* MCS 7, 9, 11, 13 */ + return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4); + } +} + #define RA_FLOOR_TABLE_SIZE 7 #define RA_FLOOR_UP_GAP 3 static u64 rtw89_phy_ra_mask_rssi(struct rtw89_dev *rtwdev, u8 rssi, @@ -194,6 +243,9 @@ rtw89_ra_mask_vht_rates[4] = {RA_MASK_VHT_1SS_RATES, RA_MASK_VHT_2SS_RATES, static const u64 rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES, RA_MASK_HE_3SS_RATES, RA_MASK_HE_4SS_RATES}; +static const u64 +rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES, + RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES}; static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, @@ -255,7 +307,11 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, memset(ra, 0, sizeof(*ra)); /* Set the ra mask from sta's capability */ - if (sta->deflink.he_cap.has_he) { + if (sta->deflink.eht_cap.has_eht) { + mode |= RTW89_RA_MODE_EHT; + ra_mask |= get_eht_ra_mask(sta); + high_rate_masks = rtw89_ra_mask_eht_rates; + } else if (sta->deflink.he_cap.has_he) { mode |= RTW89_RA_MODE_HE; csi_mode = RTW89_RA_RPT_MODE_HE; ra_mask |= get_he_ra_mask(sta); @@ -2343,6 +2399,18 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2; mcs = ra_report->txrate.mcs; break; + case RTW89_RA_RPT_MODE_EHT: + ra_report->txrate.flags |= RATE_INFO_FLAGS_EHT_MCS; + ra_report->txrate.mcs = u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1); + ra_report->txrate.nss = u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1; + if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08) + ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_0_8; + else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16) + ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_1_6; + else + ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_3_2; + mcs = ra_report->txrate.mcs; + break; } ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 9473798b9dac..02521d984c9b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -46,6 +46,11 @@ #define RA_MASK_HE_3SS_RATES GENMASK_ULL(47, 36) #define RA_MASK_HE_4SS_RATES GENMASK_ULL(59, 48) #define RA_MASK_HE_RATES GENMASK_ULL(59, 12) +#define RA_MASK_EHT_1SS_RATES GENMASK_ULL(27, 12) +#define RA_MASK_EHT_2SS_RATES GENMASK_ULL(43, 28) +#define RA_MASK_EHT_3SS_RATES GENMASK_ULL(59, 44) +#define RA_MASK_EHT_4SS_RATES GENMASK_ULL(62, 60) +#define RA_MASK_EHT_RATES GENMASK_ULL(62, 12) #define CFO_TRK_ENABLE_TH (2 << 2) #define CFO_TRK_STOP_TH_4 (30 << 2) diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 95cdee52fdc8..2bf3c1bed6a2 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -3780,6 +3780,18 @@ #define B_BE_P0_SYNC_PORT_SRC_SEL_MASK GENMASK(26, 24) #define B_BE_P0_TSFTR_SYNC_OFFSET_MASK GENMASK(18, 0) +#define R_BE_MUEDCA_BE_PARAM_0 0x10350 +#define R_BE_MUEDCA_BK_PARAM_0 0x10354 +#define R_BE_MUEDCA_VI_PARAM_0 0x10358 +#define R_BE_MUEDCA_VO_PARAM_0 0x1035C + +#define R_BE_MUEDCA_EN 0x10370 +#define R_BE_MUEDCA_EN_C1 0x14370 +#define B_BE_MUEDCA_WMM_SEL BIT(8) +#define B_BE_SET_MUEDCATIMER_TF_1 BIT(5) +#define B_BE_SET_MUEDCATIMER_TF_0 BIT(4) +#define B_BE_MUEDCA_EN_0 BIT(0) + #define R_BE_PORT_CFG_P0 0x10400 #define R_BE_PORT_CFG_P0_C1 0x14400 #define B_BE_BCN_ERLY_SORT_EN_P0 BIT(18) @@ -3894,6 +3906,12 @@ #define R_BE_PORT_HGQ_WINDOW_CFG 0x105A0 #define R_BE_PORT_HGQ_WINDOW_CFG_C1 0x145A0 +#define R_BE_AGG_LEN_HT_0 0x10814 +#define R_BE_AGG_LEN_HT_0_C1 0x14814 +#define B_BE_AMPDU_MAX_LEN_HT_MASK GENMASK(31, 16) +#define B_BE_RTS_TXTIME_TH_MASK GENMASK(15, 8) +#define B_BE_RTS_LEN_TH_MASK GENMASK(7, 0) + #define R_BE_MBSSID_DROP_0 0x1083C #define R_BE_MBSSID_DROP_0_C1 0x1483C #define B_BE_GI_LTF_FB_SEL BIT(30) @@ -3919,6 +3937,61 @@ #define B_BE_UPD_HGQMD BIT(1) #define B_BE_UPD_TIMIE BIT(0) +#define R_BE_BFMEE_RESP_OPTION 0x11180 +#define R_BE_BFMEE_RESP_OPTION_C1 0x15180 +#define B_BE_BFMEE_CSI_SEC_TYPE_SH 20 +#define B_BE_BFMEE_CSI_SEC_TYPE_MSK 0xf +#define B_BE_BFMEE_BFRPT_SEG_SIZE_SH 16 +#define B_BE_BFMEE_BFRPT_SEG_SIZE_MSK 0x3 +#define B_BE_BFMEE_MIMO_EN_SEL BIT(8) +#define B_BE_BFMEE_MU_BFEE_DIS BIT(7) +#define B_BE_BFMEE_CHECK_RPTPOLL_MACID_DIS BIT(6) +#define B_BE_BFMEE_NOCHK_BFPOLL_BMP BIT(5) +#define B_BE_BFMEE_VHTBFRPT_CHK BIT(4) +#define B_BE_BFMEE_EHT_NDPA_EN BIT(3) +#define B_BE_BFMEE_HE_NDPA_EN BIT(2) +#define B_BE_BFMEE_VHT_NDPA_EN BIT(1) +#define B_BE_BFMEE_HT_NDPA_EN BIT(0) + +#define R_BE_TRXPTCL_RESP_CSI_CTRL_0 0x11188 +#define R_BE_TRXPTCL_RESP_CSI_CTRL_0_C1 0x15188 +#define B_BE_BFMEE_CSISEQ_SEL BIT(29) +#define B_BE_BFMEE_BFPARAM_SEL BIT(28) +#define B_BE_BFMEE_OFDM_LEN_TH_MASK GENMASK(27, 24) +#define B_BE_BFMEE_BF_PORT_SEL BIT(23) +#define B_BE_BFMEE_USE_NSTS BIT(22) +#define B_BE_BFMEE_CSI_RATE_FB_EN BIT(21) +#define B_BE_BFMEE_CSI_GID_SEL BIT(20) +#define B_BE_BFMEE_CSI_RSC_MASK GENMASK(19, 18) +#define B_BE_BFMEE_CSI_FORCE_RETE_EN BIT(17) +#define B_BE_BFMEE_CSI_USE_NDPARATE BIT(16) +#define B_BE_BFMEE_CSI_WITHHTC_EN BIT(15) +#define B_BE_BFMEE_CSIINFO0_BF_EN BIT(14) +#define B_BE_BFMEE_CSIINFO0_STBC_EN BIT(13) +#define B_BE_BFMEE_CSIINFO0_LDPC_EN BIT(12) +#define B_BE_BFMEE_CSIINFO0_CS_MASK GENMASK(11, 10) +#define B_BE_BFMEE_CSIINFO0_CB_MASK GENMASK(9, 8) +#define B_BE_BFMEE_CSIINFO0_NG_MASK GENMASK(7, 6) +#define B_BE_BFMEE_CSIINFO0_NR_MASK GENMASK(5, 3) +#define B_BE_BFMEE_CSIINFO0_NC_MASK GENMASK(2, 0) +#define CSI_RX_BW_CFG 0x1 +#define R_BE_TRXPTCL_RESP_CSI_CTRL_1 0x11194 +#define R_BE_TRXPTCL_RESP_CSI_CTRL_1_C1 0x15194 +#define B_BE_BFMEE_BE_CSI_RRSC_BITMAP_MASK GENMASK(31, 24) +#define CSI_RRSC_BITMAP_CFG 0x2A + +#define R_BE_TRXPTCL_RESP_CSI_RRSC 0x1118C +#define R_BE_TRXPTCL_RESP_CSI_RRSC_C1 0x1518C +#define CSI_RRSC_BMAP_BE 0x2A2AFF + +#define R_BE_TRXPTCL_RESP_CSI_RATE 0x11190 +#define R_BE_TRXPTCL_RESP_CSI_RATE_C1 0x15190 +#define B_BE_BFMEE_EHT_CSI_RATE_MASK GENMASK(31, 24) +#define B_BE_BFMEE_HE_CSI_RATE_MASK GENMASK(23, 16) +#define B_BE_BFMEE_VHT_CSI_RATE_MASK GENMASK(15, 8) +#define B_BE_BFMEE_HT_CSI_RATE_MASK GENMASK(7, 0) +#define CSI_INIT_RATE_EHT 0x3 + #define R_BE_RX_FLTR_OPT 0x11420 #define R_BE_RX_FLTR_OPT_C1 0x15420 #define B_BE_UID_FILTER_MASK GENMASK(31, 24) @@ -3938,6 +4011,12 @@ #define B_BE_A_A1_MATCH BIT(1) #define B_BE_SNIFFER_MODE BIT(0) +#define R_BE_CSIRPT_OPTION 0x11464 +#define R_BE_CSIRPT_OPTION_C1 0x15464 +#define B_BE_CSIPRT_EHTSU_AID_EN BIT(26) +#define B_BE_CSIPRT_HESU_AID_EN BIT(25) +#define B_BE_CSIPRT_VHTSU_AID_EN BIT(24) + #define R_BE_PWR_MODULE 0x11900 #define R_BE_PWR_MODULE_C1 0x15900 diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c index 6a5e52a96d18..a44a7403ce8d 100644 --- a/drivers/net/wireless/silabs/wfx/data_tx.c +++ b/drivers/net/wireless/silabs/wfx/data_tx.c @@ -208,6 +208,36 @@ static bool wfx_is_action_back(struct ieee80211_hdr *hdr) return true; } +struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info; + + if (!skb) + return NULL; + tx_info = IEEE80211_SKB_CB(skb); + return (struct wfx_tx_priv *)tx_info->rate_driver_data; +} + +struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb) +{ + struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data; + struct wfx_hif_req_tx *req = (struct wfx_hif_req_tx *)hif->body; + + return req; +} + +struct wfx_vif *wfx_skb_wvif(struct wfx_dev *wdev, struct sk_buff *skb) +{ + struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb); + struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data; + + if (tx_priv->vif_id != hif->interface && hif->interface != 2) { + dev_err(wdev->dev, "corrupted skb"); + return wdev_to_wvif(wdev, hif->interface); + } + return wdev_to_wvif(wdev, tx_priv->vif_id); +} + static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr) { @@ -226,53 +256,40 @@ static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) { - int i; - bool finished; + bool has_rate0 = false; + int i, j; - /* Firmware is not able to mix rates with different flags */ - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (rates[0].flags & IEEE80211_TX_RC_SHORT_GI) - rates[i].flags |= IEEE80211_TX_RC_SHORT_GI; - if (!(rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) + for (i = 1, j = 1; j < IEEE80211_TX_MAX_RATES; j++) { + if (rates[j].idx == -1) + break; + /* The device use the rates in descending order, whatever the request from minstrel. + * We have to trade off here. Most important is to respect the primary rate + * requested by minstrel. So, we drops the entries with rate higher than the + * previous. + */ + if (rates[j].idx >= rates[i - 1].idx) { + rates[i - 1].count += rates[j].count; + rates[i - 1].count = min_t(u16, 15, rates[i - 1].count); + } else { + memcpy(rates + i, rates + j, sizeof(rates[i])); + if (rates[i].idx == 0) + has_rate0 = true; + /* The device apply Short GI only on the first rate */ rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; - if (!(rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)) - rates[i].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; - } - - /* Sort rates and remove duplicates */ - do { - finished = true; - for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) { - if (rates[i + 1].idx == rates[i].idx && - rates[i].idx != -1) { - rates[i].count += rates[i + 1].count; - if (rates[i].count > 15) - rates[i].count = 15; - rates[i + 1].idx = -1; - rates[i + 1].count = 0; - - finished = false; - } - if (rates[i + 1].idx > rates[i].idx) { - swap(rates[i + 1], rates[i]); - finished = false; - } + i++; } - } while (!finished); + } /* Ensure that MCS0 or 1Mbps is present at the end of the retry list */ - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (rates[i].idx == 0) - break; - if (rates[i].idx == -1) { - rates[i].idx = 0; - rates[i].count = 8; /* == hw->max_rate_tries */ - rates[i].flags = rates[i - 1].flags & IEEE80211_TX_RC_MCS; - break; - } + if (!has_rate0 && i < IEEE80211_TX_MAX_RATES) { + rates[i].idx = 0; + rates[i].count = 8; /* == hw->max_rate_tries */ + rates[i].flags = rates[0].flags & IEEE80211_TX_RC_MCS; + i++; + } + for (; i < IEEE80211_TX_MAX_RATES; i++) { + memset(rates + i, 0, sizeof(rates[i])); + rates[i].idx = -1; } - /* All retries use long GI */ - for (i = 1; i < IEEE80211_TX_MAX_RATES; i++) - rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; } static u8 wfx_tx_get_retry_policy_id(struct wfx_vif *wvif, struct ieee80211_tx_info *tx_info) @@ -334,6 +351,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct /* Fill tx_priv */ tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data; tx_priv->icv_size = wfx_tx_get_icv_len(hw_key); + tx_priv->vif_id = wvif->id; /* Fill hif_msg */ WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb"); @@ -344,7 +362,10 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct hif_msg = (struct wfx_hif_msg *)skb->data; hif_msg->len = cpu_to_le16(skb->len); hif_msg->id = HIF_REQ_ID_TX; - hif_msg->interface = wvif->id; + if (tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) + hif_msg->interface = 2; + else + hif_msg->interface = wvif->id; if (skb->len > le16_to_cpu(wvif->wdev->hw_caps.size_inp_ch_buf)) { dev_warn(wvif->wdev->dev, "requested frame size (%d) is larger than maximum supported (%d)\n", @@ -365,9 +386,15 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct req->fc_offset = offset; /* Queue index are inverted between firmware and Linux */ req->queue_id = 3 - queue_id; - req->peer_sta_id = wfx_tx_get_link_id(wvif, sta, hdr); - req->retry_policy_index = wfx_tx_get_retry_policy_id(wvif, tx_info); - req->frame_format = wfx_tx_get_frame_format(tx_info); + if (tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { + req->peer_sta_id = HIF_LINK_ID_NOT_ASSOCIATED; + req->retry_policy_index = HIF_TX_RETRY_POLICY_INVALID; + req->frame_format = HIF_FRAME_FORMAT_NON_HT; + } else { + req->peer_sta_id = wfx_tx_get_link_id(wvif, sta, hdr); + req->retry_policy_index = wfx_tx_get_retry_policy_id(wvif, tx_info); + req->frame_format = wfx_tx_get_frame_format(tx_info); + } if (tx_info->driver_rates[0].flags & IEEE80211_TX_RC_SHORT_GI) req->short_gi = 1; if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) @@ -483,7 +510,7 @@ void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct wfx_hif_cnf_tx *arg) } tx_info = IEEE80211_SKB_CB(skb); tx_priv = wfx_skb_tx_priv(skb); - wvif = wdev_to_wvif(wdev, ((struct wfx_hif_msg *)skb->data)->interface); + wvif = wfx_skb_wvif(wdev, skb); WARN_ON(!wvif); if (!wvif) return; @@ -545,7 +572,6 @@ void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, b struct wfx_dev *wdev = hw->priv; struct sk_buff_head dropped; struct wfx_vif *wvif; - struct wfx_hif_msg *hif; struct sk_buff *skb; skb_queue_head_init(&dropped); @@ -561,8 +587,7 @@ void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, b if (wdev->chip_frozen) wfx_pending_drop(wdev, &dropped); while ((skb = skb_dequeue(&dropped)) != NULL) { - hif = (struct wfx_hif_msg *)skb->data; - wvif = wdev_to_wvif(wdev, hif->interface); + wvif = wfx_skb_wvif(wdev, skb); ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb)); wfx_skb_dtor(wvif, skb); } diff --git a/drivers/net/wireless/silabs/wfx/data_tx.h b/drivers/net/wireless/silabs/wfx/data_tx.h index 983470705e4b..0621b82103be 100644 --- a/drivers/net/wireless/silabs/wfx/data_tx.h +++ b/drivers/net/wireless/silabs/wfx/data_tx.h @@ -36,6 +36,7 @@ struct wfx_tx_policy_cache { struct wfx_tx_priv { ktime_t xmit_timestamp; unsigned char icv_size; + unsigned char vif_id; }; void wfx_tx_policy_init(struct wfx_vif *wvif); @@ -45,22 +46,8 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struc void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct wfx_hif_cnf_tx *arg); void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); -static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info; - - if (!skb) - return NULL; - tx_info = IEEE80211_SKB_CB(skb); - return (struct wfx_tx_priv *)tx_info->rate_driver_data; -} - -static inline struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb) -{ - struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data; - struct wfx_hif_req_tx *req = (struct wfx_hif_req_tx *)hif->body; - - return req; -} +struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb); +struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb); +struct wfx_vif *wfx_skb_wvif(struct wfx_dev *wdev, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c index 9402503fbde3..9f403d275cb1 100644 --- a/drivers/net/wireless/silabs/wfx/hif_tx.c +++ b/drivers/net/wireless/silabs/wfx/hif_tx.c @@ -45,6 +45,24 @@ static void *wfx_alloc_hif(size_t body_len, struct wfx_hif_msg **hif) return NULL; } +static u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) +{ + int i; + u32 ret = 0; + /* The device only supports 2GHz */ + struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; + + for (i = 0; i < sband->n_bitrates; i++) { + if (rates & BIT(i)) { + if (i >= sband->n_bitrates) + dev_warn(wdev->dev, "unsupported basic rate\n"); + else + ret |= BIT(sband->bitrates[i].hw_value); + } + } + return ret; +} + int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request, void *reply, size_t reply_len, bool no_reply) { @@ -220,6 +238,31 @@ int wfx_hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, s return ret; } +/* Hijack scan request to implement Remain-On-Channel */ +int wfx_hif_scan_uniq(struct wfx_vif *wvif, struct ieee80211_channel *chan, int duration) +{ + int ret; + struct wfx_hif_msg *hif; + size_t buf_len = sizeof(struct wfx_hif_req_start_scan_alt) + sizeof(u8); + struct wfx_hif_req_start_scan_alt *body = wfx_alloc_hif(buf_len, &hif); + + if (!hif) + return -ENOMEM; + body->num_of_ssids = HIF_API_MAX_NB_SSIDS; + body->maintain_current_bss = 1; + body->disallow_ps = 1; + body->tx_power_level = cpu_to_le32(chan->max_power); + body->num_of_channels = 1; + body->channel_list[0] = chan->hw_value; + body->max_transmit_rate = API_RATE_INDEX_B_1MBPS; + body->min_channel_time = cpu_to_le32(duration); + body->max_channel_time = cpu_to_le32(duration * 110 / 100); + wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len); + ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); + kfree(hif); + return ret; +} + int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req, int chan_start_idx, int chan_num) { diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.h b/drivers/net/wireless/silabs/wfx/hif_tx.h index 71817a6571f0..aab54df6aafa 100644 --- a/drivers/net/wireless/silabs/wfx/hif_tx.h +++ b/drivers/net/wireless/silabs/wfx/hif_tx.h @@ -54,6 +54,7 @@ int wfx_hif_beacon_transmit(struct wfx_vif *wvif, bool enable); int wfx_hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len); int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211, int chan_start, int chan_num); +int wfx_hif_scan_uniq(struct wfx_vif *wvif, struct ieee80211_channel *chan, int duration); int wfx_hif_stop_scan(struct wfx_vif *wvif); int wfx_hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len); int wfx_hif_shutdown(struct wfx_dev *wdev); diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c index ede822d771aa..e7198520bdff 100644 --- a/drivers/net/wireless/silabs/wfx/main.c +++ b/drivers/net/wireless/silabs/wfx/main.c @@ -151,6 +151,8 @@ static const struct ieee80211_ops wfx_ops = { .change_chanctx = wfx_change_chanctx, .assign_vif_chanctx = wfx_assign_vif_chanctx, .unassign_vif_chanctx = wfx_unassign_vif_chanctx, + .remain_on_channel = wfx_remain_on_channel, + .cancel_remain_on_channel = wfx_cancel_remain_on_channel, }; bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor) @@ -246,6 +248,7 @@ static void wfx_free_common(void *data) mutex_destroy(&wdev->tx_power_loop_info_lock); mutex_destroy(&wdev->rx_stats_lock); + mutex_destroy(&wdev->scan_lock); mutex_destroy(&wdev->conf_mutex); ieee80211_free_hw(wdev->hw); } @@ -288,6 +291,7 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_da hw->wiphy->features |= NL80211_FEATURE_AP_SCAN; hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; + hw->wiphy->max_remain_on_channel_duration = 5000; hw->wiphy->max_ap_assoc_sta = HIF_LINK_ID_MAX; hw->wiphy->max_scan_ssids = 2; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; @@ -314,6 +318,7 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_da gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); mutex_init(&wdev->conf_mutex); + mutex_init(&wdev->scan_lock); mutex_init(&wdev->rx_stats_lock); mutex_init(&wdev->tx_power_loop_info_lock); init_completion(&wdev->firmware_ready); diff --git a/drivers/net/wireless/silabs/wfx/queue.c b/drivers/net/wireless/silabs/wfx/queue.c index 37f492e5d3be..e61b86f211e5 100644 --- a/drivers/net/wireless/silabs/wfx/queue.c +++ b/drivers/net/wireless/silabs/wfx/queue.c @@ -68,13 +68,16 @@ void wfx_tx_queues_init(struct wfx_vif *wvif) for (i = 0; i < IEEE80211_NUM_ACS; ++i) { skb_queue_head_init(&wvif->tx_queue[i].normal); skb_queue_head_init(&wvif->tx_queue[i].cab); + skb_queue_head_init(&wvif->tx_queue[i].offchan); wvif->tx_queue[i].priority = priorities[i]; } } bool wfx_tx_queue_empty(struct wfx_vif *wvif, struct wfx_queue *queue) { - return skb_queue_empty_lockless(&queue->normal) && skb_queue_empty_lockless(&queue->cab); + return skb_queue_empty_lockless(&queue->normal) && + skb_queue_empty_lockless(&queue->cab) && + skb_queue_empty_lockless(&queue->offchan); } void wfx_tx_queues_check_empty(struct wfx_vif *wvif) @@ -103,8 +106,9 @@ static void __wfx_tx_queue_drop(struct wfx_vif *wvif, void wfx_tx_queue_drop(struct wfx_vif *wvif, struct wfx_queue *queue, struct sk_buff_head *dropped) { - __wfx_tx_queue_drop(wvif, &queue->cab, dropped); __wfx_tx_queue_drop(wvif, &queue->normal, dropped); + __wfx_tx_queue_drop(wvif, &queue->cab, dropped); + __wfx_tx_queue_drop(wvif, &queue->offchan, dropped); wake_up(&wvif->wdev->tx_dequeue); } @@ -113,7 +117,9 @@ void wfx_tx_queues_put(struct wfx_vif *wvif, struct sk_buff *skb) struct wfx_queue *queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + if (tx_info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) + skb_queue_tail(&queue->offchan, skb); + else if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) skb_queue_tail(&queue->cab, skb); else skb_queue_tail(&queue->normal, skb); @@ -123,13 +129,11 @@ void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped) { struct wfx_queue *queue; struct wfx_vif *wvif; - struct wfx_hif_msg *hif; struct sk_buff *skb; WARN(!wdev->chip_frozen, "%s should only be used to recover a frozen device", __func__); while ((skb = skb_dequeue(&wdev->tx_pending)) != NULL) { - hif = (struct wfx_hif_msg *)skb->data; - wvif = wdev_to_wvif(wdev, hif->interface); + wvif = wfx_skb_wvif(wdev, skb); if (wvif) { queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; WARN_ON(skb_get_queue_mapping(skb) > 3); @@ -155,7 +159,7 @@ struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id) if (req->packet_id != packet_id) continue; spin_unlock_bh(&wdev->tx_pending.lock); - wvif = wdev_to_wvif(wdev, hif->interface); + wvif = wfx_skb_wvif(wdev, skb); if (wvif) { queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; WARN_ON(skb_get_queue_mapping(skb) > 3); @@ -248,6 +252,26 @@ static struct sk_buff *wfx_tx_queues_get_skb(struct wfx_dev *wdev) wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + for (i = 0; i < num_queues; i++) { + skb = skb_dequeue(&queues[i]->offchan); + if (!skb) + continue; + hif = (struct wfx_hif_msg *)skb->data; + /* Offchan frames are assigned to a special interface. + * The only interface allowed to send data during scan. + */ + WARN_ON(hif->interface != 2); + atomic_inc(&queues[i]->pending_frames); + trace_queues_stats(wdev, queues[i]); + return skb; + } + } + + if (mutex_is_locked(&wdev->scan_lock)) + return NULL; + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { if (!wvif->after_dtim_tx_allowed) continue; for (i = 0; i < num_queues; i++) { diff --git a/drivers/net/wireless/silabs/wfx/queue.h b/drivers/net/wireless/silabs/wfx/queue.h index 4731debca93d..6857fbd60fba 100644 --- a/drivers/net/wireless/silabs/wfx/queue.h +++ b/drivers/net/wireless/silabs/wfx/queue.h @@ -17,6 +17,7 @@ struct wfx_vif; struct wfx_queue { struct sk_buff_head normal; struct sk_buff_head cab; /* Content After (DTIM) Beacon */ + struct sk_buff_head offchan; atomic_t pending_frames; int priority; }; diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c index 16f619ed22e0..c3c103ff88cc 100644 --- a/drivers/net/wireless/silabs/wfx/scan.c +++ b/drivers/net/wireless/silabs/wfx/scan.c @@ -95,7 +95,7 @@ void wfx_hw_scan_work(struct work_struct *work) int chan_cur, ret, err; mutex_lock(&wvif->wdev->conf_mutex); - mutex_lock(&wvif->scan_lock); + mutex_lock(&wvif->wdev->scan_lock); if (wvif->join_in_progress) { dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN"); wfx_reset(wvif); @@ -116,7 +116,7 @@ void wfx_hw_scan_work(struct work_struct *work) ret = -ETIMEDOUT; } } while (ret >= 0 && chan_cur < hw_req->req.n_channels); - mutex_unlock(&wvif->scan_lock); + mutex_unlock(&wvif->wdev->scan_lock); mutex_unlock(&wvif->wdev->conf_mutex); wfx_ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); } @@ -145,3 +145,65 @@ void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done) wvif->scan_nb_chan_done = nb_chan_done; complete(&wvif->scan_complete); } + +void wfx_remain_on_channel_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(work, struct wfx_vif, remain_on_channel_work); + struct ieee80211_channel *chan = wvif->remain_on_channel_chan; + int duration = wvif->remain_on_channel_duration; + int ret; + + /* Hijack scan request to implement Remain-On-Channel */ + mutex_lock(&wvif->wdev->conf_mutex); + mutex_lock(&wvif->wdev->scan_lock); + if (wvif->join_in_progress) { + dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN"); + wfx_reset(wvif); + } + wfx_tx_flush(wvif->wdev); + + reinit_completion(&wvif->scan_complete); + ret = wfx_hif_scan_uniq(wvif, chan, duration); + if (ret) + goto end; + ieee80211_ready_on_channel(wvif->wdev->hw); + ret = wait_for_completion_timeout(&wvif->scan_complete, + msecs_to_jiffies(duration * 120 / 100)); + if (!ret) { + wfx_hif_stop_scan(wvif); + ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ); + dev_dbg(wvif->wdev->dev, "roc timeout\n"); + } + if (!ret) + dev_err(wvif->wdev->dev, "roc didn't stop\n"); + ieee80211_remain_on_channel_expired(wvif->wdev->hw); +end: + mutex_unlock(&wvif->wdev->scan_lock); + mutex_unlock(&wvif->wdev->conf_mutex); + wfx_bh_request_tx(wvif->wdev); +} + +int wfx_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration, + enum ieee80211_roc_type type) +{ + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + if (wfx_api_older_than(wdev, 3, 10)) + return -EOPNOTSUPP; + + wvif->remain_on_channel_duration = duration; + wvif->remain_on_channel_chan = chan; + schedule_work(&wvif->remain_on_channel_work); + return 0; +} + +int wfx_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wfx_hif_stop_scan(wvif); + flush_work(&wvif->remain_on_channel_work); + return 0; +} diff --git a/drivers/net/wireless/silabs/wfx/scan.h b/drivers/net/wireless/silabs/wfx/scan.h index 78e3b984f375..995ab8c6cb5e 100644 --- a/drivers/net/wireless/silabs/wfx/scan.h +++ b/drivers/net/wireless/silabs/wfx/scan.h @@ -19,4 +19,10 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done); +void wfx_remain_on_channel_work(struct work_struct *work); +int wfx_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration, + enum ieee80211_roc_type type); +int wfx_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + #endif diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c index 626dfb4b7a55..1b6c158457b4 100644 --- a/drivers/net/wireless/silabs/wfx/sta.c +++ b/drivers/net/wireless/silabs/wfx/sta.c @@ -20,24 +20,6 @@ #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2 -u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) -{ - int i; - u32 ret = 0; - /* The device only supports 2GHz */ - struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]; - - for (i = 0; i < sband->n_bitrates; i++) { - if (rates & BIT(i)) { - if (i >= sband->n_bitrates) - dev_warn(wdev->dev, "unsupported basic rate\n"); - else - ret |= BIT(sband->bitrates[i].hw_value); - } - } - return ret; -} - void wfx_cooling_timeout_work(struct work_struct *work) { struct wfx_dev *wdev = container_of(to_delayed_work(work), struct wfx_dev, @@ -114,10 +96,12 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS | FIF_PROBE_REQ | FIF_PSPOLL; + /* Filters are ignored during the scan. No frames are filtered. */ + if (mutex_is_locked(&wdev->scan_lock)) + return; + mutex_lock(&wdev->conf_mutex); while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - mutex_lock(&wvif->scan_lock); - /* Note: FIF_BCN_PRBRESP_PROMISC covers probe response and * beacons from other BSS */ @@ -144,8 +128,6 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, else filter_prbreq = true; wfx_hif_set_rx_filter(wvif, filter_bssid, filter_prbreq); - - mutex_unlock(&wvif->scan_lock); } mutex_unlock(&wdev->conf_mutex); } @@ -402,7 +384,12 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + struct wfx_dev *wdev = wvif->wdev; + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_update_pm(wvif); + wvif = (struct wfx_vif *)vif->drv_priv; wfx_reset(wvif); } @@ -634,18 +621,14 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) { - struct wfx_vif *wvif_it; - if (notify_cmd != STA_NOTIFY_AWAKE) return; /* Device won't be able to honor CAB if a scan is in progress on any interface. Prefer to * skip this DTIM and wait for the next one. */ - wvif_it = NULL; - while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL) - if (mutex_is_locked(&wvif_it->scan_lock)) - return; + if (mutex_is_locked(&wvif->wdev->scan_lock)) + return; if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed) dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)", @@ -743,9 +726,9 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) complete(&wvif->set_pm_mode_complete); INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); - mutex_init(&wvif->scan_lock); init_completion(&wvif->scan_complete); INIT_WORK(&wvif->scan_work, wfx_hw_scan_work); + INIT_WORK(&wvif->remain_on_channel_work, wfx_remain_on_channel_work); wfx_tx_queues_init(wvif); wfx_tx_policy_init(wvif); diff --git a/drivers/net/wireless/silabs/wfx/sta.h b/drivers/net/wireless/silabs/wfx/sta.h index 888db5cd3206..c478ddcb934b 100644 --- a/drivers/net/wireless/silabs/wfx/sta.h +++ b/drivers/net/wireless/silabs/wfx/sta.h @@ -66,6 +66,5 @@ int wfx_update_pm(struct wfx_vif *wvif); /* Other Helpers */ void wfx_reset(struct wfx_vif *wvif); -u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates); #endif diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h index 13ba84b3b2c3..bd0df2e1ea99 100644 --- a/drivers/net/wireless/silabs/wfx/wfx.h +++ b/drivers/net/wireless/silabs/wfx/wfx.h @@ -43,6 +43,7 @@ struct wfx_dev { struct delayed_work cooling_timeout_work; bool poll_irq; bool chip_frozen; + struct mutex scan_lock; struct mutex conf_mutex; struct wfx_hif_cmd hif_cmd; @@ -69,6 +70,7 @@ struct wfx_vif { bool after_dtim_tx_allowed; bool join_in_progress; + struct completion set_pm_mode_complete; struct delayed_work beacon_loss_work; @@ -80,15 +82,15 @@ struct wfx_vif { unsigned long uapsd_mask; - /* avoid some operations in parallel with scan */ - struct mutex scan_lock; struct work_struct scan_work; struct completion scan_complete; int scan_nb_chan_done; bool scan_abort; struct ieee80211_scan_request *scan_req; - struct completion set_pm_mode_complete; + struct ieee80211_channel *remain_on_channel_chan; + int remain_on_channel_duration; + struct work_struct remain_on_channel_work; }; static inline struct ieee80211_vif *wvif_to_vif(struct wfx_vif *wvif) |