diff options
author | Jakub Kicinski <kuba@kernel.org> | 2022-05-19 13:01:07 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-05-19 13:01:08 -0700 |
commit | d353e1a3bafd468941d42f6aa59bbd8ac42959b6 (patch) | |
tree | 60940f91dcf03319f79b6feeffb4a3846a2ae51e | |
parent | d7e6f5836038eeac561411ed7a74e2a225a6c138 (diff) | |
parent | 78488a64aea94a3336ee97f345c1496e9bc5ebdf (diff) | |
download | linux-d353e1a3bafd468941d42f6aa59bbd8ac42959b6.tar.bz2 |
Merge tag 'wireless-next-2022-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says:
====================
wireless-next patches for v5.19
Second set of patches for v5.19 and most likely the last one. rtw89
got support for 8852ce devices and mt76 now supports Wireless Ethernet
Dispatch.
Major changes:
cfg80211/mac80211
- support disabling EHT mode
rtw89
- add support for Realtek 8852ce devices
mt76
- Wireless Ethernet Dispatch support for flow offload
- non-standard VHT MCS10-11 support
- mt7921 AP mode support
- mt7921 ipv6 NS offload support
ath11k
- enable keepalive during WoWLAN suspend
- implement remain-on-channel support
* tag 'wireless-next-2022-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (135 commits)
iwlwifi: mei: fix potential NULL-ptr deref
iwlwifi: mei: clear the sap data header before sending
iwlwifi: mvm: remove vif_count
iwlwifi: mvm: always tell the firmware to accept MCAST frames in BSS
iwlwifi: mvm: add OTP info in case of init failure
iwlwifi: mvm: fix assert 1F04 upon reconfig
iwlwifi: fw: init SAR GEO table only if data is present
iwlwifi: mvm: clean up authorized condition
iwlwifi: mvm: use NULL instead of ERR_PTR when parsing wowlan status
iwlwifi: pcie: simplify MSI-X cause mapping
rtw89: pci: only mask out INT indicator register for disable interrupt v1
rtw89: convert rtw89_band to nl80211_band precisely
rtw89: 8852c: update txpwr tables to HALRF_027_00_052
rtw89: cfo: check mac_id to avoid out-of-bounds
rtw89: 8852c: set TX antenna path
rtw89: add ieee80211::sta_rc_update ops
wireless: Fix Makefile to be in alphabetical order
mac80211: refactor freeing the next_beacon
cfg80211: fix kernel-doc for cfg80211_beacon_data
mac80211: minstrel_ht: support ieee80211_rate_status
...
====================
Link: https://lore.kernel.org/r/20220519153334.8D051C385AA@smtp.kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
139 files changed, 5325 insertions, 3091 deletions
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 1e74ec1c7f23..fac8ff983aec 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -11,6 +11,8 @@ #include <linux/gpio/driver.h> #include <linux/interrupt.h> #include <linux/export.h> +#include <linux/property.h> + #include <linux/bcma/bcma.h> #include "bcma_private.h" @@ -182,9 +184,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; chip->parent = bus->dev; -#if IS_BUILTIN(CONFIG_OF) - chip->of_node = cc->core->dev.of_node; -#endif + chip->fwnode = dev_fwnode(&cc->core->dev); + switch (bus->chipinfo.id) { case BCMA_CHIP_ID_BCM4707: case BCMA_CHIP_ID_BCM5357: diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index abf3e5c87ca7..a61cf6c90343 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_WLAN_VENDOR_MARVELL) += marvell/ obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) += mediatek/ obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) += microchip/ obj-$(CONFIG_WLAN_VENDOR_PURELIFI) += purelifi/ +obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/ obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/ obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/ obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/ @@ -21,7 +22,6 @@ obj-$(CONFIG_WLAN_VENDOR_SILABS) += silabs/ obj-$(CONFIG_WLAN_VENDOR_ST) += st/ obj-$(CONFIG_WLAN_VENDOR_TI) += ti/ obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ -obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2092bfd02cd1..688177453b07 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1233,6 +1233,7 @@ success: static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type) { const struct firmware *fw; + char boardname[100]; if (bd_ie_type == ATH10K_BD_IE_BOARD) { if (!ar->hw_params.fw.board) { @@ -1240,9 +1241,19 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type) return -EINVAL; } + scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin", + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, - ar->hw_params.fw.board); + boardname); + if (IS_ERR(ar->normal_mode_fw.board)) { + fw = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); + ar->normal_mode_fw.board = fw; + } + if (IS_ERR(ar->normal_mode_fw.board)) return PTR_ERR(ar->normal_mode_fw.board); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 06a51a48c1d9..3570a5895ea8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2692,8 +2692,10 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar, struct ieee80211_sta *sta) { + struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { - switch (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: return MODE_11AC_VHT160; case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: @@ -6926,6 +6928,9 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar, struct ieee80211_sta *sta, u32 rate_ctrl_flag, u8 nss) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; + if (nss > sta->deflink.rx_nss) { ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n", nss, sta->deflink.rx_nss); @@ -6933,19 +6938,19 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar, } if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) { - if (!sta->deflink.vht_cap.vht_supported) { + if (!vht_cap->vht_supported) { ath10k_warn(ar, "Invalid VHT rate for sta %pM\n", sta->addr); return -EINVAL; } } else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) { - if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) { + if (!ht_cap->ht_supported || vht_cap->vht_supported) { ath10k_warn(ar, "Invalid HT rate for sta %pM\n", sta->addr); return -EINVAL; } } else { - if (sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) + if (ht_cap->ht_supported || vht_cap->vht_supported) return -EINVAL; } diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 050bda828966..fa11807f48a9 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -9,6 +9,8 @@ #include <linux/of_device.h> #include <linux/of.h> #include <linux/dma-mapping.h> +#include <linux/of_address.h> +#include <linux/iommu.h> #include "ahb.h" #include "debug.h" #include "hif.h" @@ -757,6 +759,172 @@ static int ath11k_ahb_setup_resources(struct ath11k_base *ab) return 0; } +static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab) +{ + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + struct device *dev = ab->dev; + struct device_node *node; + struct resource r; + int ret; + + node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!node) + return -ENOENT; + + ret = of_address_to_resource(node, 0, &r); + of_node_put(node); + if (ret) { + dev_err(dev, "failed to resolve msa fixed region\n"); + return ret; + } + + ab_ahb->fw.msa_paddr = r.start; + ab_ahb->fw.msa_size = resource_size(&r); + + node = of_parse_phandle(dev->of_node, "memory-region", 1); + if (!node) + return -ENOENT; + + ret = of_address_to_resource(node, 0, &r); + of_node_put(node); + if (ret) { + dev_err(dev, "failed to resolve ce fixed region\n"); + return ret; + } + + ab_ahb->fw.ce_paddr = r.start; + ab_ahb->fw.ce_size = resource_size(&r); + + return 0; +} + +static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab) +{ + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + struct device *host_dev = ab->dev; + struct platform_device_info info = {0}; + struct iommu_domain *iommu_dom; + struct platform_device *pdev; + struct device_node *node; + int ret; + + /* Chipsets not requiring MSA need not initialize + * MSA resources, return success in such cases. + */ + if (!ab->hw_params.fixed_fw_mem) + return 0; + + ret = ath11k_ahb_setup_msa_resources(ab); + if (ret) { + ath11k_err(ab, "failed to setup msa resources\n"); + return ret; + } + + node = of_get_child_by_name(host_dev->of_node, "wifi-firmware"); + if (!node) { + ab_ahb->fw.use_tz = true; + return 0; + } + + info.fwnode = &node->fwnode; + info.parent = host_dev; + info.name = node->name; + info.dma_mask = DMA_BIT_MASK(32); + + pdev = platform_device_register_full(&info); + if (IS_ERR(pdev)) { + of_node_put(node); + return PTR_ERR(pdev); + } + + ret = of_dma_configure(&pdev->dev, node, true); + if (ret) { + ath11k_err(ab, "dma configure fail: %d\n", ret); + goto err_unregister; + } + + ab_ahb->fw.dev = &pdev->dev; + + iommu_dom = iommu_domain_alloc(&platform_bus_type); + if (!iommu_dom) { + ath11k_err(ab, "failed to allocate iommu domain\n"); + ret = -ENOMEM; + goto err_unregister; + } + + ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev); + if (ret) { + ath11k_err(ab, "could not attach device: %d\n", ret); + goto err_iommu_free; + } + + ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr, + ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size, + IOMMU_READ | IOMMU_WRITE); + if (ret) { + ath11k_err(ab, "failed to map firmware region: %d\n", ret); + goto err_iommu_detach; + } + + ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr, + ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size, + IOMMU_READ | IOMMU_WRITE); + if (ret) { + ath11k_err(ab, "failed to map firmware CE region: %d\n", ret); + goto err_iommu_unmap; + } + + ab_ahb->fw.use_tz = false; + ab_ahb->fw.iommu_domain = iommu_dom; + of_node_put(node); + + return 0; + +err_iommu_unmap: + iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); + +err_iommu_detach: + iommu_detach_device(iommu_dom, ab_ahb->fw.dev); + +err_iommu_free: + iommu_domain_free(iommu_dom); + +err_unregister: + platform_device_unregister(pdev); + of_node_put(node); + + return ret; +} + +static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab) +{ + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + struct iommu_domain *iommu; + size_t unmapped_size; + + if (ab_ahb->fw.use_tz) + return 0; + + iommu = ab_ahb->fw.iommu_domain; + + unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size); + if (unmapped_size != ab_ahb->fw.msa_size) + ath11k_err(ab, "failed to unmap firmware: %zu\n", + unmapped_size); + + unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size); + if (unmapped_size != ab_ahb->fw.ce_size) + ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n", + unmapped_size); + + iommu_detach_device(iommu, ab_ahb->fw.dev); + iommu_domain_free(iommu); + + platform_device_unregister(to_platform_device(ab_ahb->fw.dev)); + + return 0; +} + static int ath11k_ahb_probe(struct platform_device *pdev) { struct ath11k_base *ab; @@ -816,10 +984,14 @@ static int ath11k_ahb_probe(struct platform_device *pdev) if (ret) goto err_core_free; - ret = ath11k_hal_srng_init(ab); + ret = ath11k_ahb_fw_resources_init(ab); if (ret) goto err_core_free; + ret = ath11k_hal_srng_init(ab); + if (ret) + goto err_fw_deinit; + ret = ath11k_ce_alloc_pipes(ab); if (ret) { ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret); @@ -856,6 +1028,9 @@ err_ce_free: err_hal_srng_deinit: ath11k_hal_srng_deinit(ab); +err_fw_deinit: + ath11k_ahb_fw_resource_deinit(ab); + err_core_free: ath11k_core_free(ab); platform_set_drvdata(pdev, NULL); @@ -891,6 +1066,7 @@ static int ath11k_ahb_remove(struct platform_device *pdev) qmi_fail: ath11k_ahb_free_irq(ab); ath11k_hal_srng_deinit(ab); + ath11k_ahb_fw_resource_deinit(ab); ath11k_ce_free_pipes(ab); ath11k_core_free(ab); platform_set_drvdata(pdev, NULL); diff --git a/drivers/net/wireless/ath/ath11k/ahb.h b/drivers/net/wireless/ath/ath11k/ahb.h index 51e6e4a5f686..58a945411c5b 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.h +++ b/drivers/net/wireless/ath/ath11k/ahb.h @@ -12,6 +12,15 @@ struct ath11k_base; struct ath11k_ahb { struct rproc *tgt_rproc; + struct { + struct device *dev; + struct iommu_domain *iommu_domain; + dma_addr_t msa_paddr; + u32 msa_size; + dma_addr_t ce_paddr; + u32 ce_size; + bool use_tz; + } fw; }; static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 01e1d494b527..1e98ff9ff288 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -110,6 +110,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, @@ -185,6 +186,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .name = "qca6390 hw2.0", @@ -259,6 +261,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "qcn9074 hw1.0", @@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 3, .ce_window_idx = 2, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .name = "wcn6855 hw2.0", @@ -407,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "wcn6855 hw2.1", @@ -480,6 +485,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "wcn6750 hw1.0", @@ -553,6 +559,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 1, .ce_window_idx = 2, .fixed_fw_mem = true, + .support_off_channel_tx = false, }, }; @@ -1620,9 +1627,11 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) ieee80211_stop_queues(ar->hw); ath11k_mac_drain_tx(ar); + ar->state_11d = ATH11K_11D_IDLE; complete(&ar->completed_11d_scan); complete(&ar->scan.started); complete(&ar->scan.completed); + complete(&ar->scan.on_channel); complete(&ar->peer_assoc_done); complete(&ar->peer_delete_done); complete(&ar->install_key_done); @@ -1768,7 +1777,6 @@ static void ath11k_core_reset(struct work_struct *work) ATH11K_RECOVER_START_TIMEOUT_HZ); ath11k_hif_power_down(ab); - ath11k_qmi_free_resource(ab); ath11k_hif_power_up(ab); ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n"); diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 00a45819907e..c17a2620aad7 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -520,6 +520,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, struct hal_tx_status *ts) { struct ieee80211_tx_status status = { 0 }; + struct ieee80211_rate_status status_rate = { 0 }; struct ath11k_base *ab = ar->ab; struct ieee80211_tx_info *info; struct ath11k_skb_cb *skb_cb; @@ -603,7 +604,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar, status.skb = msdu; status.info = info; rate = arsta->last_txrate; - status.rate = &rate; + + status_rate.rate_idx = rate; + status_rate.try_count = 1; + + status.rates = &status_rate; + status.n_rates = 1; spin_unlock_bh(&ab->base_lock); diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h index 1aadb1566df8..110c337ddf33 100644 --- a/drivers/net/wireless/ath/ath11k/hal.h +++ b/drivers/net/wireless/ath/ath11k/hal.h @@ -121,7 +121,7 @@ struct ath11k_base; #define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008 #define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c #define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010 -#define HAL_REO1_MISC_CTL 0x00000630 +#define HAL_REO1_MISC_CTL(ab) ab->hw_params.regs->hal_reo1_misc_ctl #define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb #define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb #define HAL_REO1_RING_ID(ab) ab->hw_params.regs->hal_reo1_ring_id diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index 09ce357f0f0d..96db85c55585 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -771,10 +771,10 @@ static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab) FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); - val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL); + val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab)); val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING; val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, HAL_SRNG_RING_ID_REO2SW1); - ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val); + ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val); ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), HAL_DEFAULT_REO_TIMEOUT_USEC); @@ -1983,6 +1983,9 @@ const struct ath11k_hw_regs ipq8074_regs = { /* Shadow register area */ .hal_shadow_base_addr = 0x0, + + /* REO misc control register, not used in IPQ8074 */ + .hal_reo1_misc_ctl = 0x0, }; const struct ath11k_hw_regs qca6390_regs = { @@ -2065,6 +2068,9 @@ const struct ath11k_hw_regs qca6390_regs = { /* Shadow register area */ .hal_shadow_base_addr = 0x000008fc, + + /* REO misc control register, not used in QCA6390 */ + .hal_reo1_misc_ctl = 0x0, }; const struct ath11k_hw_regs qcn9074_regs = { @@ -2147,6 +2153,9 @@ const struct ath11k_hw_regs qcn9074_regs = { /* Shadow register area */ .hal_shadow_base_addr = 0x0, + + /* REO misc control register, not used in QCN9074 */ + .hal_reo1_misc_ctl = 0x0, }; const struct ath11k_hw_regs wcn6855_regs = { @@ -2229,6 +2238,11 @@ const struct ath11k_hw_regs wcn6855_regs = { /* Shadow register area */ .hal_shadow_base_addr = 0x000008fc, + + /* REO misc control register, used for fragment + * destination ring config in WCN6855. + */ + .hal_reo1_misc_ctl = 0x00000630, }; const struct ath11k_hw_regs wcn6750_regs = { @@ -2311,6 +2325,11 @@ const struct ath11k_hw_regs wcn6750_regs = { /* Shadow register area */ .hal_shadow_base_addr = 0x00000504, + + /* REO misc control register, used for fragment + * destination ring config in WCN6750. + */ + .hal_reo1_misc_ctl = 0x000005d8, }; const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = { diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 6d588cd80093..77dc5c851c9b 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -204,6 +204,7 @@ struct ath11k_hw_params { u8 dp_window_idx; u8 ce_window_idx; bool fixed_fw_mem; + bool support_off_channel_tx; }; struct ath11k_hw_ops { @@ -379,6 +380,7 @@ struct ath11k_hw_regs { u32 pcie_pcs_osc_dtct_config_base; u32 hal_shadow_base_addr; + u32 hal_reo1_misc_ctl; }; extern const struct ath11k_hw_regs ipq8074_regs; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 1957e1713548..ee1590b16eff 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1951,7 +1951,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar, /* Calculate peer NSS capability from VHT capabilities if STA * supports VHT. */ - for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) { + for (i = 0, max_nss = 0; i < NL80211_VHT_NSS_MAX; i++) { vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >> (2 * i) & 3; @@ -2272,7 +2272,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, /* Calculate peer NSS capability from HE capabilities if STA * supports HE. */ - for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) { + for (i = 0, max_nss = 0; i < NL80211_HE_NSS_MAX; i++) { he_mcs = he_tx_mcs >> (2 * i) & 3; /* In case of fixed rates, MCS Range in he_tx_mcs might have @@ -5551,8 +5551,8 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work) } arvif = ath11k_vif_to_arvif(skb_cb->vif); - if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) && - arvif->is_started) { + mutex_lock(&ar->conf_mutex); + if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) { ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb); if (ret) { ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n", @@ -5570,6 +5570,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work) arvif->is_started); ath11k_mgmt_over_wmi_tx_drop(ar, skb); } + mutex_unlock(&ar->conf_mutex); } } @@ -6155,6 +6156,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar) ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n", ar->vdev_id_11d_scan); + if (ar->state_11d == ATH11K_11D_PREPARING) { + ar->state_11d = ATH11K_11D_IDLE; + complete(&ar->completed_11d_scan); + } + if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) { vdev_id = ar->vdev_id_11d_scan; @@ -7741,6 +7747,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b bool he_fixed_rate = false, vht_fixed_rate = false; struct ath11k_peer *peer, *tmp; const u16 *vht_mcs_mask, *he_mcs_mask; + struct ieee80211_link_sta *deflink; u8 vht_nss, he_nss; bool ret = true; @@ -7763,13 +7770,16 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b spin_lock_bh(&ar->ab->base_lock); list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { if (peer->sta) { - if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported || - peer->sta->deflink.rx_nss < vht_nss)) { + deflink = &peer->sta->deflink; + + if (vht_fixed_rate && (!deflink->vht_cap.vht_supported || + deflink->rx_nss < vht_nss)) { ret = false; goto out; } - if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he || - peer->sta->deflink.rx_nss < he_nss)) { + + if (he_fixed_rate && (!deflink->he_cap.has_he || + deflink->rx_nss < he_nss)) { ret = false; goto out; } @@ -8345,6 +8355,118 @@ exit: return ret; } +static int ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath11k *ar = hw->priv; + + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + ar->scan.roc_notify = false; + spin_unlock_bh(&ar->data_lock); + + ath11k_scan_abort(ar); + + mutex_unlock(&ar->conf_mutex); + + cancel_delayed_work_sync(&ar->scan.timeout); + + return 0; +} + +static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum ieee80211_roc_type type) +{ + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct scan_req_params arg; + int ret; + u32 scan_time_msec; + + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + switch (ar->scan.state) { + case ATH11K_SCAN_IDLE: + reinit_completion(&ar->scan.started); + reinit_completion(&ar->scan.completed); + reinit_completion(&ar->scan.on_channel); + ar->scan.state = ATH11K_SCAN_STARTING; + ar->scan.is_roc = true; + ar->scan.vdev_id = arvif->vdev_id; + ar->scan.roc_freq = chan->center_freq; + ar->scan.roc_notify = true; + ret = 0; + break; + case ATH11K_SCAN_STARTING: + case ATH11K_SCAN_RUNNING: + case ATH11K_SCAN_ABORTING: + ret = -EBUSY; + break; + } + spin_unlock_bh(&ar->data_lock); + + if (ret) + goto exit; + + scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2; + + memset(&arg, 0, sizeof(arg)); + ath11k_wmi_start_scan_init(ar, &arg); + arg.num_chan = 1; + arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), + GFP_KERNEL); + if (!arg.chan_list) { + ret = -ENOMEM; + goto exit; + } + + arg.vdev_id = arvif->vdev_id; + arg.scan_id = ATH11K_SCAN_ID; + arg.chan_list[0] = chan->center_freq; + arg.dwell_time_active = scan_time_msec; + arg.dwell_time_passive = scan_time_msec; + arg.max_scan_time = scan_time_msec; + arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE; + arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ; + arg.burst_duration = duration; + + ret = ath11k_start_scan(ar, &arg); + if (ret) { + ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret); + + spin_lock_bh(&ar->data_lock); + ar->scan.state = ATH11K_SCAN_IDLE; + spin_unlock_bh(&ar->data_lock); + goto free_chan_list; + } + + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ); + if (ret == 0) { + ath11k_warn(ar->ab, "failed to switch to channel for roc scan\n"); + ret = ath11k_scan_stop(ar); + if (ret) + ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret); + ret = -ETIMEDOUT; + goto free_chan_list; + } + + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, + msecs_to_jiffies(duration)); + + ret = 0; + +free_chan_list: + kfree(arg.chan_list); +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + static const struct ieee80211_ops ath11k_ops = { .tx = ath11k_mac_op_tx, .start = ath11k_mac_op_start, @@ -8397,6 +8519,8 @@ static const struct ieee80211_ops ath11k_ops = { #endif .set_sar_specs = ath11k_mac_op_set_bios_sar_specs, + .remain_on_channel = ath11k_mac_op_remain_on_channel, + .cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel, }; static void ath11k_mac_update_ch_list(struct ath11k *ar, @@ -8986,6 +9110,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) init_completion(&ar->bss_survey_done); init_completion(&ar->scan.started); init_completion(&ar->scan.completed); + init_completion(&ar->scan.on_channel); init_completion(&ar->thermal.wmi_sync); INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work); @@ -9026,3 +9151,34 @@ void ath11k_mac_destroy(struct ath11k_base *ab) pdev->ar = NULL; } } + +int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, + enum wmi_sta_keepalive_method method, + u32 interval) +{ + struct ath11k *ar = arvif->ar; + struct wmi_sta_keepalive_arg arg = {}; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + return 0; + + if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map)) + return 0; + + arg.vdev_id = arvif->vdev_id; + arg.enabled = 1; + arg.method = method; + arg.interval = interval; + + ret = ath11k_wmi_sta_keepalive(ar, &arg); + if (ret) { + ath11k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + + return 0; +} diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 7f93e3a9ca23..57ebfc592b00 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -8,6 +8,7 @@ #include <net/mac80211.h> #include <net/cfg80211.h> +#include "wmi.h" struct ath11k; struct ath11k_base; @@ -173,4 +174,7 @@ void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb); void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id); void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif); int ath11k_mac_wait_tx_complete(struct ath11k *ar); +int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, + enum wmi_sta_keepalive_method method, + u32 interval); #endif diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index d1e945074bc1..61ead37a944a 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -1970,6 +1970,21 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) for (i = 0; i < ab->qmi.mem_seg_count; i++) { chunk = &ab->qmi.target_mem[i]; + + /* Firmware reloads in coldboot/firmware recovery. + * in such case, no need to allocate memory for FW again. + */ + if (chunk->vaddr) { + if (chunk->prev_type == chunk->type || + chunk->prev_size == chunk->size) + continue; + + /* cannot reuse the existing chunk */ + dma_free_coherent(ab->dev, chunk->size, + chunk->vaddr, chunk->paddr); + chunk->vaddr = NULL; + } + chunk->vaddr = dma_alloc_coherent(ab->dev, chunk->size, &chunk->paddr, @@ -1990,6 +2005,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) chunk->type); return -EINVAL; } + chunk->prev_type = chunk->type; + chunk->prev_size = chunk->size; } return 0; @@ -2466,9 +2483,6 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab) char path[100]; int ret; - if (m3_mem->vaddr || m3_mem->size) - return 0; - fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE); if (IS_ERR(fw)) { ret = PTR_ERR(fw); @@ -2478,6 +2492,9 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab) return ret; } + if (m3_mem->vaddr || m3_mem->size) + goto skip_m3_alloc; + m3_mem->vaddr = dma_alloc_coherent(ab->dev, fw->size, &m3_mem->paddr, GFP_KERNEL); @@ -2488,6 +2505,7 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab) return -ENOMEM; } +skip_m3_alloc: memcpy(m3_mem->vaddr, fw->data, fw->size); m3_mem->size = fw->size; release_firmware(fw); diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h index c24e6995cca3..c83cf822be81 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -97,6 +97,8 @@ struct ath11k_qmi_event_msg { struct target_mem_chunk { u32 size; u32 type; + u32 prev_size; + u32 prev_type; dma_addr_t paddr; u32 *vaddr; void __iomem *iaddr; diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 79ac2142317a..7ee3ff69dfc8 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -139,6 +139,9 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) "reg hw scan wait left time %d\n", left); } + if (ar->state == ATH11K_STATE_RESTARTING) + return 0; + bands = hw->wiphy->bands; for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!bands[band]) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 1410114d1d5c..84d1c7054013 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -625,10 +625,25 @@ struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len) return skb; } +static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar, + struct ieee80211_tx_info *info) +{ + struct ath11k_base *ab = ar->ab; + u32 freq = 0; + + if (ab->hw_params.support_off_channel_tx && + ar->scan.is_roc && + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) + freq = ar->scan.roc_freq; + + return freq; +} + int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame) { struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame); struct wmi_mgmt_send_cmd *cmd; struct wmi_tlv *frame_tlv; struct sk_buff *skb; @@ -649,7 +664,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->vdev_id = vdev_id; cmd->desc_id = buf_id; - cmd->chanfreq = 0; + cmd->chanfreq = ath11k_wmi_mgmt_get_freq(ar, info); cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->frame_len = frame->len; @@ -5264,6 +5279,8 @@ static void ath11k_wmi_event_scan_started(struct ath11k *ar) break; case ATH11K_SCAN_STARTING: ar->scan.state = ATH11K_SCAN_RUNNING; + if (ar->scan.is_roc) + ieee80211_ready_on_channel(ar->hw); complete(&ar->scan.started); break; } @@ -5346,6 +5363,8 @@ static void ath11k_wmi_event_scan_foreign_chan(struct ath11k *ar, u32 freq) case ATH11K_SCAN_RUNNING: case ATH11K_SCAN_ABORTING: ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); + if (ar->scan.is_roc && ar->scan.roc_freq == freq) + complete(&ar->scan.on_channel); break; } } @@ -8959,3 +8978,44 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar) return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID); } + +int ath11k_wmi_sta_keepalive(struct ath11k *ar, + const struct wmi_sta_keepalive_arg *arg) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct wmi_sta_keepalive_cmd *cmd; + struct wmi_sta_keepalive_arp_resp *arp; + struct sk_buff *skb; + size_t len; + + len = sizeof(*cmd) + sizeof(*arp); + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_sta_keepalive_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_STA_KEEPALIVE_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + cmd->vdev_id = arg->vdev_id; + cmd->enabled = arg->enabled; + cmd->interval = arg->interval; + cmd->method = arg->method; + + if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE || + arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) { + arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1); + arp->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_STA_KEEPALVE_ARP_RESPONSE) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE); + arp->src_ip4_addr = arg->src_ip4_addr; + arp->dest_ip4_addr = arg->dest_ip4_addr; + ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr); + } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi sta keepalive vdev %d enabled %d method %d interval %d\n", + arg->vdev_id, arg->enabled, arg->method, arg->interval); + + return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID); +} diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 7600e9a52da8..b1fad4707dc6 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5907,6 +5907,50 @@ struct wmi_pdev_set_geo_table_cmd { u32 rsvd_len; } __packed; +struct wmi_sta_keepalive_cmd { + u32 tlv_header; + u32 vdev_id; + u32 enabled; + + /* WMI_STA_KEEPALIVE_METHOD_ */ + u32 method; + + /* in seconds */ + u32 interval; + + /* following this structure is the TLV for struct + * wmi_sta_keepalive_arp_resp + */ +} __packed; + +struct wmi_sta_keepalive_arp_resp { + u32 tlv_header; + u32 src_ip4_addr; + u32 dest_ip4_addr; + struct wmi_mac_addr dest_mac_addr; +} __packed; + +struct wmi_sta_keepalive_arg { + u32 vdev_id; + u32 enabled; + u32 method; + u32 interval; + u32 src_ip4_addr; + u32 dest_ip4_addr; + const u8 dest_mac_addr[ETH_ALEN]; +}; + +enum wmi_sta_keepalive_method { + WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1, + WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE = 2, + WMI_STA_KEEPALIVE_METHOD_ETHERNET_LOOPBACK = 3, + WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4, + WMI_STA_KEEPALIVE_METHOD_MGMT_VENDOR_ACTION = 5, +}; + +#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30 +#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); @@ -6087,5 +6131,7 @@ int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar, struct ath11k_vif *arvif); int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_val); int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar); +int ath11k_wmi_sta_keepalive(struct ath11k *ar, + const struct wmi_sta_keepalive_arg *arg); #endif diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 9d088cebef03..b3e65cd13d83 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -640,6 +640,24 @@ static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable) return 0; } +static int ath11k_wow_set_keepalive(struct ath11k *ar, + enum wmi_sta_keepalive_method method, + u32 interval) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + ret = ath11k_mac_vif_set_keepalive(arvif, method, interval); + if (ret) + return ret; + } + + return 0; +} + int ath11k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { @@ -691,6 +709,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, goto cleanup; } + ret = ath11k_wow_set_keepalive(ar, + WMI_STA_KEEPALIVE_METHOD_NULL_FRAME, + WMI_STA_KEEPALIVE_INTERVAL_DEFAULT); + if (ret) { + ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret); + goto cleanup; + } + ret = ath11k_wow_enable(ar->ab); if (ret) { ath11k_warn(ar->ab, "failed to start wow: %d\n", ret); @@ -786,6 +812,14 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) goto exit; } + ret = ath11k_wow_set_keepalive(ar, + WMI_STA_KEEPALIVE_METHOD_NULL_FRAME, + WMI_STA_KEEPALIVE_INTERVAL_DISABLE); + if (ret) { + ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret); + goto exit; + } + exit: if (ret) { switch (ar->state) { diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 4c944e595978..64d6c98174c8 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1391,19 +1391,6 @@ static int temp_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(temp); -/*---------freq------------*/ -static int freq_show(struct seq_file *s, void *data) -{ - struct wil6210_priv *wil = s->private; - struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; - u32 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0; - - seq_printf(s, "Freq = %d\n", freq); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(freq); - /*---------link------------*/ static int link_show(struct seq_file *s, void *data) { @@ -2380,7 +2367,6 @@ static const struct { {"pmcdata", 0444, &fops_pmcdata}, {"pmcring", 0444, &fops_pmcring}, {"temp", 0444, &temp_fops}, - {"freq", 0444, &freq_fops}, {"link", 0444, &link_fops}, {"info", 0444, &info_fops}, {"recovery", 0644, &fops_recovery}, diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 390648066382..87a88f26233e 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -458,16 +458,14 @@ int wil_if_add(struct wil6210_priv *wil) netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx_edma, NAPI_POLL_WEIGHT); - netif_tx_napi_add(&wil->napi_ndev, - &wil->napi_tx, wil6210_netdev_poll_tx_edma, - NAPI_POLL_WEIGHT); + netif_napi_add_tx(&wil->napi_ndev, + &wil->napi_tx, wil6210_netdev_poll_tx_edma); } else { netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx, NAPI_POLL_WEIGHT); - netif_tx_napi_add(&wil->napi_ndev, - &wil->napi_tx, wil6210_netdev_poll_tx, - NAPI_POLL_WEIGHT); + netif_napi_add_tx(&wil->napi_ndev, + &wil->napi_tx, wil6210_netdev_poll_tx); } wil_update_net_queues_bh(wil, vif, NULL, true); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index e3758bd86acf..fe01da9e620d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -202,13 +202,24 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) char *ptr; s32 err; - /* retreive mac address */ - err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, - sizeof(ifp->mac_addr)); - if (err < 0) { - bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err); - goto done; + if (is_valid_ether_addr(ifp->mac_addr)) { + /* set mac address */ + err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr, + ETH_ALEN); + if (err < 0) { + bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err); + goto done; + } + } else { + /* retrieve mac address */ + err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, + sizeof(ifp->mac_addr)); + if (err < 0) { + bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err); + goto done; + } } + memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index 8b5f49997c8b..15accc88d5c0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -50,6 +50,7 @@ struct brcmf_mp_device { bool ignore_probe_fail; struct brcmfmac_pd_cc *country_codes; const char *board_type; + unsigned char mac[ETH_ALEN]; union { struct brcmfmac_sdio_pd sdio; } bus; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 26fab4bee22c..87aef211b35f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -7,6 +7,7 @@ #include <linux/etherdevice.h> #include <linux/module.h> #include <linux/inetdevice.h> +#include <linux/property.h> #include <net/cfg80211.h> #include <net/rtnetlink.h> #include <net/addrconf.h> @@ -1197,7 +1198,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) brcmf_dbg(TRACE, "\n"); /* add primary networking interface */ - ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL); + ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", + is_valid_ether_addr(drvr->settings->mac) ? drvr->settings->mac : NULL); if (IS_ERR(ifp)) return PTR_ERR(ifp); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index 8623bde5eb70..083ac58f466d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -5,6 +5,7 @@ #include <linux/init.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/of_net.h> #include <defs.h> #include "debug.h" @@ -99,6 +100,8 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, if (err) brcmf_err("failed to get OF country code map (err=%d)\n", err); + of_get_mac_address(np, settings->mac); + if (bus_type != BRCMF_BUSTYPE_SDIO) return; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 33aae639ad37..e6d64152c81a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -937,6 +937,9 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, { int i, j; + if (!fwrt->geo_enabled) + return -ENODATA; + if (!iwl_sar_geo_support(fwrt)) return -EOPNOTSUPP; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index a22788a68168..157d1f31c487 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -389,6 +389,8 @@ enum { #define WFPM_LMAC1_PD_NOTIFICATION 0xa0338c #define WFPM_ARC1_PD_NOTIFICATION 0xa03044 #define HPM_SECONDARY_DEVICE_STATE 0xa03404 +#define WFPM_MAC_OTP_CFG7_ADDR 0xa03338 +#define WFPM_MAC_OTP_CFG7_DATA 0xa0333c /* For UMAG_GEN_HW_STATUS reg check */ diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index b4f45234cfc8..357f14626cf4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -493,6 +493,7 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx) if (cb_tx) { struct iwl_sap_cb_data *cb_hdr = skb_push(skb, sizeof(*cb_hdr)); + memset(cb_hdr, 0, sizeof(*cb_hdr)); cb_hdr->hdr.type = cpu_to_le16(SAP_MSG_CB_DATA_PACKET); cb_hdr->hdr.len = cpu_to_le16(skb->len - sizeof(cb_hdr->hdr)); cb_hdr->hdr.seq_num = cpu_to_le32(atomic_inc_return(&mei->sap_seq_no)); @@ -1019,6 +1020,8 @@ static void iwl_mei_handle_sap_data(struct mei_cl_device *cldev, /* We need enough room for the WiFi header + SNAP + IV */ skb = netdev_alloc_skb(netdev, len + QOS_HDR_IV_SNAP_LEN); + if (!skb) + continue; skb_reserve(skb, QOS_HDR_IV_SNAP_LEN); ethhdr = skb_push(skb, sizeof(*ethhdr)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index bcc4ed20fe5b..61f9136a333d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1956,18 +1956,18 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \ \ if (len < sizeof(*data)) { \ IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \ - return ERR_PTR(-EIO); \ + return NULL; \ } \ \ data_size = ALIGN(le32_to_cpu(data->wake_packet_bufsize), 4); \ if (len != sizeof(*data) + data_size) { \ IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \ - return ERR_PTR(-EIO); \ + return NULL; \ } \ \ status = kzalloc(sizeof(*status) + data_size, GFP_KERNEL); \ if (!status) \ - return ERR_PTR(-ENOMEM); \ + return NULL; \ \ /* copy all the common fields */ \ status->replay_ctr = le64_to_cpu(data->replay_ctr); \ @@ -2097,7 +2097,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data; status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len); - if (IS_ERR(status)) + if (!status) goto out_free_resp; BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) > @@ -2128,7 +2128,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len); - if (IS_ERR(status)) + if (!status) goto out_free_resp; iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc); @@ -2141,7 +2141,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) * difference is only in a few not used (reserved) fields. */ status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len); - if (IS_ERR(status)) + if (!status) goto out_free_resp; iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc); @@ -2153,7 +2153,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data; status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len); - if (IS_ERR(status)) + if (!status) goto out_free_resp; iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc); @@ -2165,7 +2165,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) IWL_ERR(mvm, "Firmware advertises unknown WoWLAN status response %d!\n", notif_ver); - status = ERR_PTR(-EIO); + status = NULL; } out_free_resp: @@ -2203,7 +2203,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_ap_sta; status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id); - if (IS_ERR(status)) + if (!status) goto out_unlock; IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n", @@ -2370,7 +2370,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, int i, n_matches, ret; status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA); - if (!IS_ERR(status)) { + if (status) { reasons = status->wakeup_reasons; kfree(status); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index e842816134f1..f041e77af059 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -287,6 +287,9 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait, static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm) { +#define IWL_FW_PRINT_REG_INFO(reg_name) \ + IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name)) + struct iwl_trans *trans = mvm->trans; enum iwl_device_family device_family = trans->trans_cfg->device_family; @@ -294,15 +297,15 @@ static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm) return; if (device_family <= IWL_DEVICE_FAMILY_9000) - IWL_ERR(mvm, "WFPM_ARC1_PD_NOTIFICATION: 0x%x\n", - iwl_read_umac_prph(trans, WFPM_ARC1_PD_NOTIFICATION)); + IWL_FW_PRINT_REG_INFO(WFPM_ARC1_PD_NOTIFICATION); else - IWL_ERR(mvm, "WFPM_LMAC1_PD_NOTIFICATION: 0x%x\n", - iwl_read_umac_prph(trans, WFPM_LMAC1_PD_NOTIFICATION)); + IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION); - IWL_ERR(mvm, "HPM_SECONDARY_DEVICE_STATE: 0x%x\n", - iwl_read_umac_prph(trans, HPM_SECONDARY_DEVICE_STATE)); + IWL_FW_PRINT_REG_INFO(HPM_SECONDARY_DEVICE_STATE); + /* print OPT info */ + IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_ADDR); + IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_DATA); } static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 5aa4520b70ac..56fa20596f16 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -552,6 +552,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, /* Fill the common data for all mac context types */ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action); + /* + * We always want to hear MCAST frames, if we're not authorized yet, + * we'll drop them. + */ + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP); + if (vif->p2p) { struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr; @@ -567,7 +573,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && !force_assoc_off) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - u8 ap_sta_id = mvmvif->ap_sta_id; u32 dtim_offs; /* @@ -609,29 +614,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO)) ctxt_sta->data_policy |= cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE); - - /* - * allow multicast data frames only as long as the station is - * authorized, i.e., GTK keys are already installed (if needed) - */ - if (ap_sta_id < mvm->fw->ucode_capa.num_stations) { - struct ieee80211_sta *sta; - - rcu_read_lock(); - - sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]); - if (!IS_ERR_OR_NULL(sta)) { - struct iwl_mvm_sta *mvmsta = - iwl_mvm_sta_from_mac80211(sta); - - if (mvmsta->sta_state == - IEEE80211_STA_AUTHORIZED) - cmd.filter_flags |= - cpu_to_le32(MAC_FILTER_ACCEPT_GRP); - } - - rcu_read_unlock(); - } } else { ctxt_sta->is_assoc = cpu_to_le32(0); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 4fda6c3ba9f3..bb9bd2165355 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -976,7 +976,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ieee80211_wake_queues(mvm->hw); - mvm->vif_count = 0; mvm->rx_ba_sessions = 0; mvm->fwrt.dump.conf = FW_DBG_INVALID; mvm->monitor_on = false; @@ -1380,10 +1379,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif); - /* Counting number of interfaces is needed for legacy PM */ - if (vif->type != NL80211_IFTYPE_P2P_DEVICE) - mvm->vif_count++; - /* * The AP binding flow can be done only after the beacon * template is configured (which happens only in the mac80211 @@ -1400,7 +1395,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ret = iwl_mvm_alloc_bcast_sta(mvm, vif); if (ret) { IWL_ERR(mvm, "Failed to allocate bcast sta\n"); - goto out_release; + goto out_unlock; } /* @@ -1411,7 +1406,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, 0, vif->type, IWL_STA_MULTICAST); if (ret) - goto out_release; + goto out_unlock; iwl_mvm_vif_dbgfs_register(mvm, vif); goto out_unlock; @@ -1421,7 +1416,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ret = iwl_mvm_mac_ctxt_add(mvm, vif); if (ret) - goto out_release; + goto out_unlock; ret = iwl_mvm_power_update_mac(mvm); if (ret) @@ -1498,9 +1493,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, out_remove_mac: mvmvif->phy_ctxt = NULL; iwl_mvm_mac_ctxt_remove(mvm, vif); - out_release: - if (vif->type != NL80211_IFTYPE_P2P_DEVICE) - mvm->vif_count--; out_unlock: mutex_unlock(&mvm->mutex); @@ -1582,9 +1574,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvmvif->phy_ctxt = NULL; } - if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) - mvm->vif_count--; - iwl_mvm_power_update_mac(mvm); iwl_mvm_mac_ctxt_remove(mvm, vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index c6bc85d4600a..bf35e130c876 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -934,7 +934,6 @@ struct iwl_mvm { unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; u8 fw_key_deleted[STA_KEY_MAX_NUM]; - u8 vif_count; struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; /* -1 for always, 0 for never, >0 for that many times */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index b2ea2fca5376..b9bd81242b21 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -563,6 +563,9 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac, struct iwl_power_vifs *power_iterator = _data; bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX; + if (!mvmvif->uploaded) + return; + switch (ieee80211_vif_type_p2p(vif)) { case NL80211_IFTYPE_P2P_DEVICE: break; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 78198da7e55b..49ca1e168fc5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -327,17 +327,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status = IEEE80211_SKB_RXCB(skb); /* - * drop the packet if it has failed being decrypted by HW - */ - if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status, - &crypt_len)) { - IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n", - rx_pkt_status); - kfree_skb(skb); - return; - } - - /* * Keep packets with CRC errors (and with overrun) for monitor mode * (otherwise the firmware discards them) but mark them as bad. */ @@ -388,6 +377,37 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, if (sta) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct ieee80211_vif *vif = mvmsta->vif; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + /* + * Don't even try to decrypt a MCAST frame that was received + * before the managed vif is authorized, we'd fail anyway. + */ + if (vif->type == NL80211_IFTYPE_STATION && + !mvmvif->authorized && + is_multicast_ether_addr(hdr->addr1)) { + IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n"); + kfree_skb(skb); + rcu_read_unlock(); + return; + } + } + + /* + * drop the packet if it has failed being decrypted by HW + */ + if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status, + &crypt_len)) { + IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n", + rx_pkt_status); + kfree_skb(skb); + rcu_read_unlock(); + return; + } + + if (sta) { + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_vif *tx_blocked_vif = rcu_dereference(mvm->csa_tx_blocked_vif); struct iwl_fw_dbg_trigger_tlv *trig; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 8be3c3c8c68b..6fc69c42f36e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1085,34 +1085,44 @@ bool iwl_pcie_check_hw_rf_kill(struct iwl_trans *trans) } struct iwl_causes_list { - u32 cause_num; - u32 mask_reg; + u16 mask_reg; + u8 bit; u8 addr; }; +#define CAUSE(reg, mask) \ + { \ + .mask_reg = reg, \ + .bit = ilog2(mask), \ + .addr = ilog2(mask) + \ + ((reg) == CSR_MSIX_FH_INT_MASK_AD ? -16 : \ + (reg) == CSR_MSIX_HW_INT_MASK_AD ? 16 : \ + 0xffff), /* causes overflow warning */ \ + } + static const struct iwl_causes_list causes_list_common[] = { - {MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0}, - {MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1}, - {MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3}, - {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5}, - {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10}, - {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, - {MSIX_HW_INT_CAUSES_REG_RESET_DONE, CSR_MSIX_HW_INT_MASK_AD, 0x12}, - {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16}, - {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17}, - {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18}, - {MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A}, - {MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B}, - {MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D}, - {MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E}, + CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH0_NUM), + CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH1_NUM), + CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_S2D), + CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_FH_ERR), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_ALIVE), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_WAKEUP), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RESET_DONE), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_CT_KILL), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RF_KILL), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_PERIODIC), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SCD), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_FH_TX), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HW_ERR), + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HAP), }; static const struct iwl_causes_list causes_list_pre_bz[] = { - {MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29}, + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR), }; static const struct iwl_causes_list causes_list_bz[] = { - {MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ, CSR_MSIX_HW_INT_MASK_AD, 0x15}, + CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ), }; static void iwl_pcie_map_list(struct iwl_trans *trans, @@ -1124,7 +1134,7 @@ static void iwl_pcie_map_list(struct iwl_trans *trans, for (i = 0; i < arr_size; i++) { iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); iwl_clear_bit(trans, causes[i].mask_reg, - causes[i].cause_num); + BIT(causes[i].bit)); } } diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 72622220051b..10cbd9e560e7 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -162,15 +162,15 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) if (!sta) return; - if (!status->aggr && !(status->flag & RX_FLAG_8023)) { - mt76_rx_aggr_check_ctl(skb, frames); + if (!status->aggr) { + if (!(status->flag & RX_FLAG_8023)) + mt76_rx_aggr_check_ctl(skb, frames); return; } /* not part of a BA session */ ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK; - if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && - ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) + if (ackp == IEEE80211_QOS_CTL_ACK_POLICY_NOACK) return; tid = rcu_dereference(wcid->aggr[tidno]); diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 02daeefb0761..30de8be4aac1 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -7,6 +7,37 @@ #include "mt76.h" #include "dma.h" +#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) + +#define Q_READ(_dev, _q, _field) ({ \ + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ + u32 _val; \ + if ((_q)->flags & MT_QFLAG_WED) \ + _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \ + ((_q)->wed_regs + \ + _offset)); \ + else \ + _val = readl(&(_q)->regs->_field); \ + _val; \ +}) + +#define Q_WRITE(_dev, _q, _field, _val) do { \ + u32 _offset = offsetof(struct mt76_queue_regs, _field); \ + if ((_q)->flags & MT_QFLAG_WED) \ + mtk_wed_device_reg_write(&(_dev)->mmio.wed, \ + ((_q)->wed_regs + _offset), \ + _val); \ + else \ + writel(_val, &(_q)->regs->_field); \ +} while (0) + +#else + +#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field) +#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field) + +#endif + static struct mt76_txwi_cache * mt76_alloc_txwi(struct mt76_dev *dev) { @@ -16,11 +47,11 @@ mt76_alloc_txwi(struct mt76_dev *dev) int size; size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t)); - txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC); + txwi = kzalloc(size, GFP_ATOMIC); if (!txwi) return NULL; - addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size, + addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size, DMA_TO_DEVICE); t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size); t->dma_addr = addr; @@ -73,18 +104,20 @@ mt76_free_pending_txwi(struct mt76_dev *dev) struct mt76_txwi_cache *t; local_bh_disable(); - while ((t = __mt76_get_txwi(dev)) != NULL) - dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size, + while ((t = __mt76_get_txwi(dev)) != NULL) { + dma_unmap_single(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); + kfree(mt76_get_txwi_ptr(dev, t)); + } local_bh_enable(); } static void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) { - writel(q->desc_dma, &q->regs->desc_base); - writel(q->ndesc, &q->regs->ring_size); - q->head = readl(&q->regs->dma_idx); + Q_WRITE(dev, q, desc_base, q->desc_dma); + Q_WRITE(dev, q, ring_size, q->ndesc); + q->head = Q_READ(dev, q, dma_idx); q->tail = q->head; } @@ -100,42 +133,12 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) for (i = 0; i < q->ndesc; i++) q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); - writel(0, &q->regs->cpu_idx); - writel(0, &q->regs->dma_idx); + Q_WRITE(dev, q, cpu_idx, 0); + Q_WRITE(dev, q, dma_idx, 0); mt76_dma_sync_idx(dev, q); } static int -mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, - int idx, int n_desc, int bufsize, - u32 ring_base) -{ - int size; - - spin_lock_init(&q->lock); - spin_lock_init(&q->cleanup_lock); - - q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; - q->ndesc = n_desc; - q->buf_size = bufsize; - q->hw_idx = idx; - - size = q->ndesc * sizeof(struct mt76_desc); - q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL); - if (!q->desc) - return -ENOMEM; - - size = q->ndesc * sizeof(*q->entry); - q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); - if (!q->entry) - return -ENOMEM; - - mt76_dma_queue_reset(dev, q); - - return 0; -} - -static int mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, int nbufs, u32 info, struct sk_buff *skb, void *txwi) @@ -203,11 +206,11 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, struct mt76_queue_entry *e = &q->entry[idx]; if (!e->skip_buf0) - dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0], + dma_unmap_single(dev->dma_dev, e->dma_addr[0], e->dma_len[0], DMA_TO_DEVICE); if (!e->skip_buf1) - dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1], + dma_unmap_single(dev->dma_dev, e->dma_addr[1], e->dma_len[1], DMA_TO_DEVICE); if (e->txwi == DMA_DUMMY_DATA) @@ -224,7 +227,7 @@ static void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) { wmb(); - writel(q->head, &q->regs->cpu_idx); + Q_WRITE(dev, q, cpu_idx, q->head); } static void @@ -240,7 +243,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) if (flush) last = -1; else - last = readl(&q->regs->dma_idx); + last = Q_READ(dev, q, dma_idx); while (q->queued > 0 && q->tail != last) { mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry); @@ -252,8 +255,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush) } if (!flush && q->tail == last) - last = readl(&q->regs->dma_idx); - + last = Q_READ(dev, q, dma_idx); } spin_unlock_bh(&q->cleanup_lock); @@ -288,7 +290,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, if (info) *info = le32_to_cpu(desc->info); - dma_unmap_single(dev->dev, buf_addr, buf_len, DMA_FROM_DEVICE); + dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE); e->buf = NULL; return buf; @@ -325,9 +327,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, if (q->queued + 1 >= q->ndesc - 1) goto error; - addr = dma_map_single(dev->dev, skb->data, skb->len, + addr = dma_map_single(dev->dma_dev, skb->data, skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto error; buf.addr = addr; @@ -374,8 +376,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, mt76_insert_hdr_pad(skb); len = skb_headlen(skb); - addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + addr = dma_map_single(dev->dma_dev, skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto free; tx_info.buf[n].addr = t->dma_addr; @@ -387,9 +389,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, if (n == ARRAY_SIZE(tx_info.buf)) goto unmap; - addr = dma_map_single(dev->dev, iter->data, iter->len, + addr = dma_map_single(dev->dma_dev, iter->data, iter->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) goto unmap; tx_info.buf[n].addr = addr; @@ -402,10 +404,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, goto unmap; } - dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size, + dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info); - dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size, + dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size, DMA_TO_DEVICE); if (ret < 0) goto unmap; @@ -415,7 +417,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, unmap: for (n--; n > 0; n--) - dma_unmap_single(dev->dev, tx_info.buf[n].addr, + dma_unmap_single(dev->dma_dev, tx_info.buf[n].addr, tx_info.buf[n].len, DMA_TO_DEVICE); free: @@ -460,8 +462,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) if (!buf) break; - addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev->dev, addr))) { + addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { skb_free_frag(buf); break; } @@ -481,6 +483,85 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) return frames; } +static int +mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mmio.wed; + int ret, type, ring; + u8 flags = q->flags; + + if (!mtk_wed_device_active(wed)) + q->flags &= ~MT_QFLAG_WED; + + if (!(q->flags & MT_QFLAG_WED)) + return 0; + + type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags); + ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags); + + switch (type) { + case MT76_WED_Q_TX: + ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs); + if (!ret) + q->wed_regs = wed->tx_ring[ring].reg_base; + break; + case MT76_WED_Q_TXFREE: + /* WED txfree queue needs ring to be initialized before setup */ + q->flags = 0; + mt76_dma_queue_reset(dev, q); + mt76_dma_rx_fill(dev, q); + q->flags = flags; + + ret = mtk_wed_device_txfree_ring_setup(wed, q->regs); + if (!ret) + q->wed_regs = wed->txfree_ring.reg_base; + break; + default: + ret = -EINVAL; + } + + return ret; +#else + return 0; +#endif +} + +static int +mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, + int idx, int n_desc, int bufsize, + u32 ring_base) +{ + int ret, size; + + spin_lock_init(&q->lock); + spin_lock_init(&q->cleanup_lock); + + q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE; + q->ndesc = n_desc; + q->buf_size = bufsize; + q->hw_idx = idx; + + size = q->ndesc * sizeof(struct mt76_desc); + q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL); + if (!q->desc) + return -ENOMEM; + + size = q->ndesc * sizeof(*q->entry); + q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL); + if (!q->entry) + return -ENOMEM; + + ret = mt76_dma_wed_setup(dev, q); + if (ret) + return ret; + + if (q->flags != MT_WED_Q_TXFREE) + mt76_dma_queue_reset(dev, q); + + return 0; +} + static void mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) { @@ -562,14 +643,29 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, static int mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) { - int len, data_len, done = 0; + int len, data_len, done = 0, dma_idx; struct sk_buff *skb; unsigned char *data; + bool check_ddone = false; bool more; + if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) && + q->flags == MT_WED_Q_TXFREE) { + dma_idx = Q_READ(dev, q, dma_idx); + check_ddone = true; + } + while (done < budget) { u32 info; + if (check_ddone) { + if (q->tail == dma_idx) + dma_idx = Q_READ(dev, q, dma_idx); + + if (q->tail == dma_idx) + break; + } + data = mt76_dma_dequeue(dev, q, false, &len, &info, &more); if (!data) break; @@ -710,5 +806,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev) } mt76_free_pending_txwi(dev); + + if (mtk_wed_device_active(&dev->mmio.wed)) + mtk_wed_device_detach(&dev->mmio.wed); } EXPORT_SYMBOL_GPL(mt76_dma_cleanup); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 5b53d008eb66..18b5de55334c 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -248,6 +248,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; else vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC; + vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; for (i = 0; i < 8; i++) { if (i < nstream) @@ -323,8 +325,6 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC | IEEE80211_VHT_CAP_RXSTBC_1 | IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | (3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); return 0; @@ -545,6 +545,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, dev->hw = hw; dev->dev = pdev; dev->drv = drv_ops; + dev->dma_dev = pdev; phy = &dev->phy; phy->dev = dev; @@ -579,6 +580,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, INIT_LIST_HEAD(&dev->wcid_list); INIT_LIST_HEAD(&dev->txwi_cache); + dev->token_size = dev->drv->token_size; for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) skb_queue_head_init(&dev->rx_skb[i]); @@ -1303,7 +1305,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, continue; mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; - mtxq->wcid = wcid; + mtxq->wcid = wcid->idx; } ewma_signal_init(&wcid->rssi); @@ -1381,7 +1383,9 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; mutex_lock(&dev->mutex); + spin_lock_bh(&dev->status_lock); rcu_assign_pointer(dev->wcid[wcid->idx], NULL); + spin_unlock_bh(&dev->status_lock); mutex_unlock(&dev->mutex); } EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); @@ -1578,7 +1582,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna); struct mt76_queue * mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, - int ring_base) + int ring_base, u32 flags) { struct mt76_queue *hwq; int err; @@ -1587,6 +1591,8 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc, if (!hwq) return ERR_PTR(-ENOMEM); + hwq->flags = flags; + err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base); if (err < 0) return ERR_PTR(err); diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 3f94c37251df..914ee278e6e2 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -6,14 +6,14 @@ #include "mt76.h" struct sk_buff * -mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, - int data_len) +__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, + int data_len, gfp_t gfp) { const struct mt76_mcu_ops *ops = dev->mcu_ops; int length = ops->headroom + data_len + ops->tailroom; struct sk_buff *skb; - skb = alloc_skb(length, GFP_KERNEL); + skb = alloc_skb(length, gfp); if (!skb) return NULL; @@ -25,7 +25,7 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, return skb; } -EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); +EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires) diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 26353b6bce97..86e3d2ac4d0d 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -73,8 +73,13 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, spin_lock_irqsave(&dev->mmio.irq_lock, flags); dev->mmio.irqmask &= ~clear; dev->mmio.irqmask |= set; - if (addr) - mt76_mmio_wr(dev, addr, dev->mmio.irqmask); + if (addr) { + if (mtk_wed_device_active(&dev->mmio.wed)) + mtk_wed_device_irq_set_mask(&dev->mmio.wed, + dev->mmio.irqmask); + else + mt76_mmio_wr(dev, addr, dev->mmio.irqmask); + } spin_unlock_irqrestore(&dev->mmio.irq_lock, flags); } EXPORT_SYMBOL_GPL(mt76_set_irq_mask); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 882fb5d2517f..4e8997c45c1b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -13,6 +13,7 @@ #include <linux/leds.h> #include <linux/usb.h> #include <linux/average.h> +#include <linux/soc/mediatek/mtk_wed.h> #include <net/mac80211.h> #include "util.h" #include "testmode.h" @@ -26,6 +27,16 @@ #define MT76_TOKEN_FREE_THR 64 +#define MT_QFLAG_WED_RING GENMASK(1, 0) +#define MT_QFLAG_WED_TYPE GENMASK(3, 2) +#define MT_QFLAG_WED BIT(4) + +#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \ + FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \ + FIELD_PREP(MT_QFLAG_WED_RING, _n)) +#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n) +#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0) + struct mt76_dev; struct mt76_phy; struct mt76_wcid; @@ -42,6 +53,11 @@ enum mt76_bus_type { MT76_BUS_SDIO, }; +enum mt76_wed_type { + MT76_WED_Q_TX, + MT76_WED_Q_TXFREE, +}; + struct mt76_bus_ops { u32 (*rr)(struct mt76_dev *dev, u32 offset); void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); @@ -170,6 +186,9 @@ struct mt76_queue { u8 buf_offset; u8 hw_idx; u8 qid; + u8 flags; + + u32 wed_regs; dma_addr_t desc_dma; struct sk_buff *rx_head; @@ -275,7 +294,7 @@ struct mt76_wcid { }; struct mt76_txq { - struct mt76_wcid *wcid; + u16 wcid; u16 agg_ssn; bool send_bar; @@ -537,6 +556,8 @@ struct mt76_mmio { void __iomem *regs; spinlock_t irq_lock; u32 irqmask; + + struct mtk_wed_device wed; }; struct mt76_rx_status { @@ -698,6 +719,7 @@ struct mt76_dev { const struct mt76_driver_ops *drv; const struct mt76_mcu_ops *mcu_ops; struct device *dev; + struct device *dma_dev; struct mt76_mcu mcu; @@ -718,7 +740,9 @@ struct mt76_dev { spinlock_t token_lock; struct idr token; - int token_count; + u16 wed_token_count; + u16 token_count; + u16 token_size; wait_queue_head_t tx_wait; /* spinclock used to protect wcid pktid linked list */ @@ -727,7 +751,7 @@ struct mt76_dev { u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; - u32 vif_mask; + u64 vif_mask; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; @@ -942,14 +966,14 @@ 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); + int ring_base, u32 flags); u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx); static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx, - int n_desc, int ring_base) + int n_desc, int ring_base, u32 flags) { struct mt76_queue *q; - q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base); + q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags); if (IS_ERR(q)) return PTR_ERR(q); @@ -964,7 +988,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx, { struct mt76_queue *q; - q = mt76_init_queue(dev, qid, idx, n_desc, ring_base); + q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0); if (IS_ERR(q)) return PTR_ERR(q); @@ -1321,8 +1345,15 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *data, int len); struct sk_buff * +__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, + int data_len, gfp_t gfp); +static inline struct sk_buff * mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data, - int data_len); + int data_len) +{ + return __mt76_mcu_msg_alloc(dev, data, data_len, GFP_KERNEL); +} + void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); @@ -1380,8 +1411,7 @@ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) int token; spin_lock_bh(&dev->token_lock); - token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size, - GFP_ATOMIC); + token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); spin_unlock_bh(&dev->token_lock); return token; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index 5d4522f440b7..b5e8308e0cc7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -82,12 +82,12 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) __skb_queue_head_init(&data.q); q = dev->mphy.q_tx[MT_TXQ_BEACON]; - spin_lock_bh(&q->lock); + spin_lock(&q->lock); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt7603_update_beacon_iter, dev); mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); + spin_unlock(&q->lock); /* Flush all previous CAB queue packets */ mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); @@ -117,7 +117,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) mt76_skb_set_moredata(data.tail[i], false); } - spin_lock_bh(&q->lock); + spin_lock(&q->lock); while ((skb = __skb_dequeue(&data.q)) != NULL) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; @@ -126,7 +126,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t) mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL); } mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); + spin_unlock(&q->lock); for (i = 0; i < ARRAY_SIZE(data.count); i++) mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i), diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 37b092e3ea51..f9e5857850e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -173,13 +173,13 @@ int mt7603_dma_init(struct mt7603_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], - MT7603_TX_RING_SIZE, MT_TX_RING_BASE); + MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT7603_PSD_RING_SIZE, MT_TX_RING_BASE); + MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -189,12 +189,12 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN, - MT_MCU_RING_SIZE, MT_TX_RING_BASE); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC, - MT_MCU_RING_SIZE, MT_TX_RING_BASE); + MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -223,8 +223,8 @@ int mt7603_dma_init(struct mt7603_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7603_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7603_poll_tx); napi_enable(&dev->mt76.tx_napi); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 83c5eec5b163..91425b454cae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -44,7 +44,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_lock(&dev->mt76.mutex); - mvif->idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->idx = __ffs64(~dev->mt76.vif_mask); if (mvif->idx >= MT7603_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -65,7 +65,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; - dev->mt76.vif_mask |= BIT(mvif->idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->idx); INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; @@ -75,7 +75,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); out: @@ -106,7 +106,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) spin_unlock_bh(&dev->sta_poll_lock); mutex_lock(&dev->mt76.mutex); - dev->mt76.vif_mask &= ~BIT(mvif->idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); mutex_unlock(&dev->mt76.mutex); mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 00aefea1bf61..ce19f57de475 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev) for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], MT7615_TX_RING_SIZE / 2, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; @@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev) return mt7622_init_tx_queues_multi(dev); ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; @@ -284,8 +284,8 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7615_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7615_poll_tx); napi_enable(&dev->mt76.tx_napi); mt76_poll(dev, MT_WPDMA_GLO_CFG, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index d79cbdbd5a05..a9c9b97d173e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -194,7 +194,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, is_zero_ether_addr(vif->addr)) phy->monitor_vif = vif; - mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); if (mvif->mt76.idx >= MT7615_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -212,7 +212,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, if (ext_phy) mvif->mt76.wmm_idx += 2; - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); @@ -234,7 +234,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } ret = mt7615_mcu_add_dev_info(phy, vif, true); @@ -268,7 +268,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index ce45c3bfc443..a208035e197a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -145,7 +145,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t) return; dev->reset_state = mcu_int; - ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + queue_work(dev->mt76.wq, &dev->reset_work); wake_up(&dev->reset_wait); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 51a9b5d60c7a..faa279bbbcb2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -2185,11 +2185,8 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev, return -ENOMEM; skb_put_data(skb, &req_hdr, sizeof(req_hdr)); - for (i = 0; i < len; i++) { - u8 *addr = (u8 *)skb_put(skb, sizeof(__be32)); - - memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); - } + for (i = 0; i < len; i++) + skb_put_data(skb, &info->arp_addr_list[i], sizeof(__be32)); return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index c3c93338d56a..561fb0368708 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -974,7 +974,6 @@ enum { MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, MCU_EXT_CMD_MWDS_SUPPORT = 0x80, MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, - MCU_EXT_CMD_SCS_CTRL = 0x82, MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94, MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 8bcd8afa0d3a..96ec96df6a3c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -191,13 +191,13 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) for (i = 0; i < IEEE80211_NUM_ACS; i++) { ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i), MT76x02_TX_RING_SIZE, - MT_TX_RING_BASE); + MT_TX_RING_BASE, 0); if (ret) return ret; } ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT, - MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE); + MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0); if (ret) return ret; @@ -230,8 +230,8 @@ int mt76x02_dma_init(struct mt76x02_dev *dev) if (ret) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt76x02_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt76x02_poll_tx); napi_enable(&dev->mt76.tx_napi); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index dd30f537676d..5bd0a0bae688 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -292,7 +292,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, mt76_packet_id_init(&mvif->group_wcid); mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->group_wcid; + rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid); + mtxq->wcid = MT_VIF_WCID(idx); } int @@ -327,11 +328,11 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) idx += 8; /* vif is already set or idx is 8 for AP/Mesh/... */ - if (dev->mt76.vif_mask & BIT(idx) || + if (dev->mt76.vif_mask & BIT_ULL(idx) || (vif->type != NL80211_IFTYPE_STATION && idx > 7)) return -EBUSY; - dev->mt76.vif_mask |= BIT(idx); + dev->mt76.vif_mask |= BIT_ULL(idx); mt76x02_vif_init(dev, vif, idx); return 0; @@ -344,7 +345,8 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, struct mt76x02_dev *dev = hw->priv; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; - dev->mt76.vif_mask &= ~BIT(mvif->idx); + 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); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index e9cab1165f38..cab6e02e1f8c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -44,35 +44,113 @@ mt7915_implicit_txbf_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get, mt7915_implicit_txbf_set, "%lld\n"); -/* test knob of system layer 1/2 error recovery */ -static int mt7915_ser_trigger_set(void *data, u64 val) +/* test knob of system error recovery */ +static ssize_t +mt7915_fw_ser_set(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) { - enum { - SER_SET_RECOVER_L1 = 1, - SER_SET_RECOVER_L2, - SER_ENABLE = 2, - SER_RECOVER - }; - struct mt7915_dev *dev = data; + struct mt7915_phy *phy = file->private_data; + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + char buf[16]; int ret = 0; + u16 val; + + if (count >= sizeof(buf)) + return -EINVAL; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + if (count && buf[count - 1] == '\n') + buf[count - 1] = '\0'; + else + buf[count] = '\0'; + + if (kstrtou16(buf, 0, &val)) + return -EINVAL; switch (val) { + case SER_QUERY: + /* grab firmware SER stats */ + ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy); + break; case SER_SET_RECOVER_L1: case SER_SET_RECOVER_L2: - ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0); + case SER_SET_RECOVER_L3_RX_ABORT: + case SER_SET_RECOVER_L3_TX_ABORT: + case SER_SET_RECOVER_L3_TX_DISABLE: + case SER_SET_RECOVER_L3_BF: + ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy); if (ret) return ret; - return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0); + ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy); + break; default: break; } + return ret ? ret : count; +} + +static ssize_t +mt7915_fw_ser_get(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct mt7915_phy *phy = file->private_data; + struct mt7915_dev *dev = phy->dev; + char *buff; + int desc = 0; + ssize_t ret; + static const size_t bufsz = 400; + + buff = kmalloc(bufsz, GFP_KERNEL); + if (!buff) + return -ENOMEM; + + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_STATUS = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_SER_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_PSE_ERR_1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_PSE1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS)); + desc += scnprintf(buff + desc, bufsz - desc, + "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n", + mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS)); + + ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); + kfree(buff); return ret; } -DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL, - mt7915_ser_trigger_set, "%lld\n"); +static const struct file_operations mt7915_fw_ser_ops = { + .write = mt7915_fw_ser_set, + .read = mt7915_fw_ser_get, + .open = simple_open, + .llseek = default_llseek, +}; static int mt7915_radar_trigger(void *data, u64 val) @@ -95,7 +173,7 @@ mt7915_muru_debug_set(void *data, u64 val) struct mt7915_dev *dev = data; dev->muru_debug = val; - mt7915_mcu_muru_debug_set(dev, data); + mt7915_mcu_muru_debug_set(dev, dev->muru_debug); return 0; } @@ -369,20 +447,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val) bool tx, rx, en; int ret; - dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; + dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; - if (dev->fw_debug_bin) + if (dev->fw.debug_bin) val = 16; else - val = dev->fw_debug_wm; + val = dev->fw.debug_wm; - tx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(1)); - rx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(2)); - en = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(0)); + tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1)); + rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2)); + en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0)); ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val); if (ret) - return ret; + goto out; for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) { if (debug == DEBUG_RPT_RX) @@ -392,16 +470,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val) ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val); if (ret) - return ret; + goto out; } /* WM CPU info record control */ mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0)); - mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw_debug_wm); + mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5)); mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5)); - return 0; +out: + if (ret) + dev->fw.debug_wm = 0; + + return ret; } static int @@ -409,7 +491,7 @@ mt7915_fw_debug_wm_get(void *data, u64 *val) { struct mt7915_dev *dev = data; - *val = dev->fw_debug_wm; + *val = dev->fw.debug_wm; return 0; } @@ -423,14 +505,19 @@ mt7915_fw_debug_wa_set(void *data, u64 val) struct mt7915_dev *dev = data; int ret; - dev->fw_debug_wa = val ? MCU_FW_LOG_TO_HOST : 0; + dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0; - ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw_debug_wa); + ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa); if (ret) - return ret; + goto out; - return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_PDMA_RX, - !!dev->fw_debug_wa, 0); + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), + MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0); +out: + if (ret) + dev->fw.debug_wa = 0; + + return ret; } static int @@ -438,7 +525,7 @@ mt7915_fw_debug_wa_get(void *data, u64 *val) { struct mt7915_dev *dev = data; - *val = dev->fw_debug_wa; + *val = dev->fw.debug_wa; return 0; } @@ -485,11 +572,11 @@ mt7915_fw_debug_bin_set(void *data, u64 val) if (!dev->relay_fwlog) return -ENOMEM; - dev->fw_debug_bin = val; + dev->fw.debug_bin = val; relay_reset(dev->relay_fwlog); - return mt7915_fw_debug_wm_set(dev, dev->fw_debug_wm); + return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm); } static int @@ -497,7 +584,7 @@ mt7915_fw_debug_bin_get(void *data, u64 *val) { struct mt7915_dev *dev = data; - *val = dev->fw_debug_bin; + *val = dev->fw.debug_bin; return 0; } @@ -510,7 +597,13 @@ mt7915_fw_util_wm_show(struct seq_file *file, void *data) { struct mt7915_dev *dev = file->private; - if (dev->fw_debug_wm) { + seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC)); + seq_printf(file, "Exception state: 0x%x\n", + is_mt7915(&dev->mt76) ? + (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(15, 8)) : + (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(7, 0))); + + if (dev->fw.debug_wm) { seq_printf(file, "Busy: %u%% Peak busy: %u%%\n", mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT), mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT)); @@ -529,7 +622,9 @@ mt7915_fw_util_wa_show(struct seq_file *file, void *data) { struct mt7915_dev *dev = file->private; - if (dev->fw_debug_wa) + seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC)); + + if (dev->fw.debug_wa) return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY), MCU_WA_PARAM_CPU_UTIL, 0, 0); @@ -867,6 +962,36 @@ mt7915_twt_stats(struct seq_file *s, void *data) return 0; } +/* The index of RF registers use the generic regidx, combined with two parts: + * WF selection [31:28] and offset [27:0]. + */ +static int +mt7915_rf_regval_get(void *data, u64 *val) +{ + struct mt7915_dev *dev = data; + u32 regval; + int ret; + + ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, ®val, false); + if (ret) + return ret; + + *val = le32_to_cpu(regval); + + return 0; +} + +static int +mt7915_rf_regval_set(void *data, u64 val) +{ + struct mt7915_dev *dev = data; + + return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true); +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get, + mt7915_rf_regval_set, "0x%08llx\n"); + int mt7915_init_debugfs(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; @@ -884,6 +1009,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) debugfs_create_file("xmit-queues", 0400, dir, phy, &mt7915_xmit_queues_fops); debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops); + debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_ops); debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm); debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa); debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin); @@ -897,7 +1023,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) &mt7915_rate_txpower_fops); debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, mt7915_twt_stats); - debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger); + debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); + if (!dev->dbdc_support || phy->band_idx) { debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 49b4d8ade16b..f3d608d2d3b2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -5,11 +5,19 @@ #include "../dma.h" #include "mac.h" -int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base) +static int +mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base) { + struct mt7915_dev *dev = phy->dev; int i, err; - err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base); + if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { + ring_base = MT_WED_TX_RING_BASE; + idx -= MT_TXQ_ID(0); + } + + err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base, + MT_WED_Q_TX(idx)); if (err < 0) return err; @@ -318,14 +326,23 @@ static int mt7915_dma_enable(struct mt7915_dev *dev) if (dev->dbdc_support || dev->phy.band_idx) irq_mask |= MT_INT_BAND1_RX_DONE; + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + u32 wed_irq_mask = irq_mask; + + wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; + mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); + mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + } + mt7915_irq_enable(dev, irq_mask); return 0; } -int mt7915_dma_init(struct mt7915_dev *dev) +int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) { struct mt76_dev *mdev = &dev->mt76; + u32 wa_rx_base, wa_rx_idx; u32 hif1_ofs = 0; int ret; @@ -338,6 +355,17 @@ int mt7915_dma_init(struct mt7915_dev *dev) mt7915_dma_disable(dev, true); + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED); + + mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL, + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) | + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) | + FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1)); + } else { + mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED); + } + /* init tx queue */ ret = mt7915_init_tx_queues(&dev->phy, MT_TXQ_ID(dev->phy.band_idx), @@ -346,6 +374,15 @@ int mt7915_dma_init(struct mt7915_dev *dev) if (ret) return ret; + if (phy2) { + ret = mt7915_init_tx_queues(phy2, + MT_TXQ_ID(phy2->band_idx), + MT7915_TX_RING_SIZE, + MT_TXQ_RING_BASE(1)); + if (ret) + return ret; + } + /* command to WM */ ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT_MCUQ_ID(MT_MCUQ_WM), @@ -380,11 +417,17 @@ int mt7915_dma_init(struct mt7915_dev *dev) return ret; /* event from WA */ + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { + wa_rx_base = MT_WED_RX_RING_BASE; + wa_rx_idx = MT7915_RXQ_MCU_WA; + dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE; + } else { + wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA); + wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA); + } ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], - MT_RXQ_ID(MT_RXQ_MCU_WA), - MT7915_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, - MT_RXQ_RING_BASE(MT_RXQ_MCU_WA)); + wa_rx_idx, MT7915_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, wa_rx_base); if (ret) return ret; @@ -434,8 +477,8 @@ int mt7915_dma_init(struct mt7915_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7915_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7915_poll_tx); napi_enable(&dev->mt76.tx_napi); mt7915_dma_enable(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 5b133bcdab17..4b1a9811646f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -152,6 +152,8 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) phy->mt76->cap.has_2ghz = true; return; } + } else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) { + val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; } switch (val) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 6d29366c5139..01169853355e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); if (!mdev->dev->of_node || !of_property_read_bool(mdev->dev->of_node, @@ -450,6 +452,9 @@ static void mt7915_mac_init(struct mt7915_dev *dev) mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len); + if (!is_mt7915(&dev->mt76)) + mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); + /* enable hardware de-agg */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); @@ -484,21 +489,18 @@ static int mt7915_txbf_init(struct mt7915_dev *dev) return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE); } -static int mt7915_register_ext_phy(struct mt7915_dev *dev) +static struct mt7915_phy * +mt7915_alloc_ext_phy(struct mt7915_dev *dev) { - struct mt7915_phy *phy = mt7915_ext_phy(dev); + struct mt7915_phy *phy; struct mt76_phy *mphy; - int ret; if (!dev->dbdc_support) - return 0; - - if (phy) - return 0; + return NULL; mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); if (!mphy) - return -ENOMEM; + return ERR_PTR(-ENOMEM); phy = mphy->priv; phy->dev = dev; @@ -507,6 +509,15 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev) /* Bind main phy to band0 and ext_phy to band1 for dbdc case */ phy->band_idx = 1; + return phy; +} + +static int +mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy) +{ + struct mt76_phy *mphy = phy->mt76; + int ret; + INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); mt7915_eeprom_parse_hw_cap(dev, phy); @@ -526,29 +537,22 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev) /* init wiphy according to mphy and phy */ mt7915_init_wiphy(mphy->hw); - ret = mt7915_init_tx_queues(phy, MT_TXQ_ID(phy->band_idx), - MT7915_TX_RING_SIZE, - MT_TXQ_RING_BASE(1)); - if (ret) - goto error; ret = mt76_register_phy(mphy, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) - goto error; + return ret; ret = mt7915_thermal_init(phy); if (ret) - goto error; + goto unreg; - ret = mt7915_init_debugfs(phy); - if (ret) - goto error; + mt7915_init_debugfs(phy); return 0; -error: - ieee80211_free_hw(mphy->hw); +unreg: + mt76_unregister_phy(mphy); return ret; } @@ -565,7 +569,7 @@ static void mt7915_init_work(struct work_struct *work) mt7915_txbf_init(dev); } -static void mt7915_wfsys_reset(struct mt7915_dev *dev) +void mt7915_wfsys_reset(struct mt7915_dev *dev) { #define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) #define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) @@ -645,36 +649,25 @@ static bool mt7915_band_config(struct mt7915_dev *dev) return ret; } -static int mt7915_init_hardware(struct mt7915_dev *dev) +static int +mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2) { int ret, idx; + mt76_wr(dev, MT_INT_MASK_CSR, 0); mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); INIT_WORK(&dev->init_work, mt7915_init_work); - dev->dbdc_support = mt7915_band_config(dev); - - /* If MCU was already running, it is likely in a bad state */ - if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) > - FW_STATE_FW_DOWNLOAD) - mt7915_wfsys_reset(dev); - - ret = mt7915_dma_init(dev); + ret = mt7915_dma_init(dev, phy2); if (ret) return ret; set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); ret = mt7915_mcu_init(dev); - if (ret) { - /* Reset and try again */ - mt7915_wfsys_reset(dev); - - ret = mt7915_mcu_init(dev); - if (ret) - return ret; - } + if (ret) + return ret; ret = mt7915_eeprom_init(dev); if (ret < 0) @@ -814,7 +807,7 @@ static void mt7915_gen_ppe_thresh(u8 *he_ppet, int nss) { u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; + static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, @@ -1048,9 +1041,22 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) ieee80211_free_hw(mphy->hw); } +static void mt7915_stop_hardware(struct mt7915_dev *dev) +{ + mt7915_mcu_exit(dev); + mt7915_tx_token_put(dev); + mt7915_dma_cleanup(dev); + tasklet_disable(&dev->irq_tasklet); + + if (is_mt7986(&dev->mt76)) + mt7986_wmac_disable(dev); +} + + int mt7915_register_device(struct mt7915_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7915_phy *phy2; int ret; dev->phy.dev = dev; @@ -1066,9 +1072,15 @@ int mt7915_register_device(struct mt7915_dev *dev) init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); - ret = mt7915_init_hardware(dev); + dev->dbdc_support = mt7915_band_config(dev); + + phy2 = mt7915_alloc_ext_phy(dev); + if (IS_ERR(phy2)) + return PTR_ERR(phy2); + + ret = mt7915_init_hardware(dev, phy2); if (ret) - return ret; + goto free_phy2; mt7915_init_wiphy(hw); @@ -1085,19 +1097,34 @@ int mt7915_register_device(struct mt7915_dev *dev) ret = mt76_register_device(&dev->mt76, true, mt76_rates, ARRAY_SIZE(mt76_rates)); if (ret) - return ret; + goto stop_hw; ret = mt7915_thermal_init(&dev->phy); if (ret) - return ret; + goto unreg_dev; ieee80211_queue_work(mt76_hw(dev), &dev->init_work); - ret = mt7915_register_ext_phy(dev); - if (ret) - return ret; + if (phy2) { + ret = mt7915_register_ext_phy(dev, phy2); + if (ret) + goto unreg_thermal; + } + + mt7915_init_debugfs(&dev->phy); + + return 0; - return mt7915_init_debugfs(&dev->phy); +unreg_thermal: + mt7915_unregister_thermal(&dev->phy); +unreg_dev: + mt76_unregister_device(&dev->mt76); +stop_hw: + mt7915_stop_hardware(dev); +free_phy2: + if (phy2) + ieee80211_free_hw(phy2->mt76->hw); + return ret; } void mt7915_unregister_device(struct mt7915_dev *dev) @@ -1105,13 +1132,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev) mt7915_unregister_ext_phy(dev); mt7915_unregister_thermal(&dev->phy); mt76_unregister_device(&dev->mt76); - mt7915_mcu_exit(dev); - mt7915_tx_token_put(dev); - mt7915_dma_cleanup(dev); - tasklet_disable(&dev->irq_tasklet); - - if (is_mt7986(&dev->mt76)) - mt7986_wmac_disable(dev); + mt7915_stop_hardware(dev); mt76_free_device(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index bab70cf981bb..086244d9be76 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -309,7 +309,7 @@ mt7915_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) } static void -mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode) +mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; static const struct ieee80211_radiotap_he known = { @@ -474,10 +474,10 @@ static int mt7915_mac_fill_rx_rate(struct mt7915_dev *dev, struct mt76_rx_status *status, struct ieee80211_supported_band *sband, - __le32 *rxv) + __le32 *rxv, u8 *mode) { u32 v0, v2; - u8 stbc, gi, bw, dcm, mode, nss; + u8 stbc, gi, bw, dcm, nss; int i, idx; bool cck = false; @@ -490,18 +490,18 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev, if (!is_mt7915(&dev->mt76)) { stbc = FIELD_GET(MT_PRXV_HT_STBC, v0); gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v0); - mode = FIELD_GET(MT_PRXV_TX_MODE, v0); + *mode = FIELD_GET(MT_PRXV_TX_MODE, v0); dcm = FIELD_GET(MT_PRXV_DCM, v0); bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0); } else { stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); - mode = FIELD_GET(MT_CRXV_TX_MODE, v2); + *mode = FIELD_GET(MT_CRXV_TX_MODE, v2); dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM); bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2); } - switch (mode) { + switch (*mode) { case MT_PHY_TYPE_CCK: cck = true; fallthrough; @@ -521,7 +521,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev, status->encoding = RX_ENC_VHT; if (gi) status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - if (i > 9) + if (i > 11) return -EINVAL; break; case MT_PHY_TYPE_HE_MU: @@ -546,7 +546,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev, case IEEE80211_STA_RX_BW_20: break; case IEEE80211_STA_RX_BW_40: - if (mode & MT_PHY_TYPE_HE_EXT_SU && + 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 = @@ -566,7 +566,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev, } status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - if (mode < MT_PHY_TYPE_HE_SU && gi) + if (*mode < MT_PHY_TYPE_HE_SU && gi) status->enc_flags |= RX_ENC_FLAG_SHORT_GI; return 0; @@ -581,7 +581,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) struct ieee80211_supported_band *sband; __le32 *rxd = (__le32 *)skb->data; __le32 *rxv = NULL; - u32 mode = 0; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); @@ -590,10 +589,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; bool unicast, insert_ccmp_hdr = false; u8 remove_pad, amsdu_info; + u8 mode = 0, qos_ctl = 0; bool hdr_trans; u16 hdr_gap; u16 seq_ctrl = 0; - u8 qos_ctl = 0; __le16 fc = 0; int idx; @@ -766,7 +765,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) } if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) { - ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv); + ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv, + &mode); if (ret < 0) return ret; } @@ -837,10 +837,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; - /* drop no data frame */ - if (fc & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)) - return -EINVAL; - status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc); status->qos_ctl = qos_ctl; @@ -864,8 +860,11 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) int i; band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX); - if (band_idx && !phy->band_idx) + if (band_idx && !phy->band_idx) { phy = mt7915_ext_phy(dev); + if (!phy) + goto out; + } rcpi = le32_to_cpu(rxv[6]); ib_rssi = le32_to_cpu(rxv[7]); @@ -890,8 +889,8 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) phy->test.last_freq_offset = foe; phy->test.last_snr = snr; +out: #endif - dev_kfree_skb(skb); } @@ -1017,6 +1016,7 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi, u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; u8 fc_type, fc_stype; + u16 ethertype; bool wmm = false; u32 val; @@ -1030,7 +1030,8 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi, val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | FIELD_PREP(MT_TXD1_TID, tid); - if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) + 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); @@ -1176,7 +1177,7 @@ out: void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, bool beacon) + struct ieee80211_key_conf *key, u32 changed) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; @@ -1187,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, bool mcast = false; u16 tx_count = 15; u32 val; + bool beacon = !!(changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)); + bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)); if (vif) { struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; @@ -1199,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, if (ext_phy && dev->mt76.phy2) mphy = dev->mt76.phy2; - if (beacon) { + 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 (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { @@ -1307,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, - false); + mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0); txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { @@ -1347,6 +1354,29 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } +u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) +{ + struct mt7915_txp *txp = ptr + MT_TXD_SIZE; + __le32 *txwi = ptr; + u32 val; + + memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp)); + + val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3); + txwi[1] = cpu_to_le32(val); + + txp->token = cpu_to_le16(token_id); + txp->nbuf = 1; + txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp)); + + return MT_TXD_SIZE + sizeof(*txp); +} + static void mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) { @@ -1380,7 +1410,7 @@ mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t) txp = mt7915_txwi_to_txp(dev, t); for (i = 0; i < txp->nbuf; i++) - dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), + dma_unmap_single(dev->dma_dev, le32_to_cpu(txp->buf[i]), le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); } @@ -1389,6 +1419,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, struct ieee80211_sta *sta, struct list_head *free_list) { struct mt76_dev *mdev = &dev->mt76; + struct mt7915_sta *msta; struct mt76_wcid *wcid; __le32 *txwi; u16 wcid_idx; @@ -1401,13 +1432,24 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, if (sta) { wcid = (struct mt76_wcid *)sta->drv_priv; wcid_idx = wcid->idx; - - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7915_tx_check_aggr(sta, txwi); } else { wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]); + + if (wcid && wcid->sta) { + msta = container_of(wcid, struct mt7915_sta, wcid); + sta = container_of((void *)msta, struct ieee80211_sta, + drv_priv); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->poll_list)) + list_add_tail(&msta->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + } } + if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt7915_tx_check_aggr(sta, txwi); + __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); out: @@ -1416,28 +1458,54 @@ out: } static void +mt7915_mac_tx_free_prepare(struct mt7915_dev *dev) +{ + struct mt76_dev *mdev = &dev->mt76; + struct mt76_phy *mphy_ext = mdev->phy2; + + /* 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 (mphy_ext) { + mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); + mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); + } +} + +static void +mt7915_mac_tx_free_done(struct mt7915_dev *dev, + struct list_head *free_list, bool wake) +{ + struct sk_buff *skb, *tmp; + + mt7915_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); + } +} + +static void mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) { struct mt7915_tx_free *free = (struct mt7915_tx_free *)data; struct mt76_dev *mdev = &dev->mt76; - struct mt76_phy *mphy_ext = mdev->phy2; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; LIST_HEAD(free_list); - struct sk_buff *skb, *tmp; void *end = data + len; bool v3, wake = false; u16 total, count = 0; u32 txd = le32_to_cpu(free->txd); __le32 *cur_info; - /* 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 (mphy_ext) { - mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); - mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); - } + mt7915_mac_tx_free_prepare(dev); total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4); @@ -1491,17 +1559,38 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) } } - mt7915_mac_sta_poll(dev); + mt7915_mac_tx_free_done(dev, &free_list, wake); +} - if (wake) - mt76_set_tx_blocked(&dev->mt76, false); +static void +mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) +{ + struct mt7915_tx_free *free = (struct mt7915_tx_free *)data; + struct mt76_dev *mdev = &dev->mt76; + __le16 *info = (__le16 *)free->info; + void *end = data + len; + LIST_HEAD(free_list); + bool wake = false; + u8 i, count; - mt76_worker_schedule(&dev->mt76.tx_worker); + mt7915_mac_tx_free_prepare(dev); - list_for_each_entry_safe(skb, tmp, &free_list, list) { - skb_list_del_init(skb); - napi_consume_skb(skb, 1); + count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl)); + if (WARN_ON_ONCE((void *)&info[count] > end)) + return; + + for (i = 0; i < count; i++) { + struct mt76_txwi_cache *txwi; + u16 msdu = le16_to_cpu(info[i]); + + txwi = mt76_token_release(mdev, msdu, &wake); + if (!txwi) + continue; + + mt7915_txwi_free(dev, txwi, NULL, &free_list); } + + mt7915_mac_tx_free_done(dev, &free_list, wake); } static bool @@ -1681,6 +1770,9 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len) case PKT_TYPE_TXRX_NOTIFY: mt7915_mac_tx_free(dev, data, len); return false; + case PKT_TYPE_TXRX_NOTIFY_V0: + mt7915_mac_tx_free_v0(dev, data, len); + return false; case PKT_TYPE_TXS: for (rxd += 2; rxd + 8 <= end; rxd += 8) mt7915_mac_add_txs(dev, rxd); @@ -1708,6 +1800,10 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, mt7915_mac_tx_free(dev, skb->data, skb->len); napi_consume_skb(skb, 1); break; + case PKT_TYPE_TXRX_NOTIFY_V0: + mt7915_mac_tx_free_v0(dev, skb->data, skb->len); + napi_consume_skb(skb, 1); + break; case PKT_TYPE_RX_EVENT: mt7915_mcu_rx_event(dev, skb); break; @@ -1918,7 +2014,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: - mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); + mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, + BSS_CHANGED_BEACON_ENABLED); break; default: break; @@ -2304,6 +2401,32 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy) } } +static void mt7915_mac_severe_check(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 trb; + + if (!phy->omac_mask) + return; + + /* In rare cases, TRB pointers might be out of sync leads to RMAC + * stopping Rx, so check status periodically to see if TRB hardware + * requires minimal recovery. + */ + trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->band_idx)); + + if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) != + FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) && + (FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) != + FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) && + trb == phy->trb_ts) + mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT, + ext_phy); + + phy->trb_ts = trb; +} + void mt7915_mac_sta_rc_work(struct work_struct *work) { struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); @@ -2356,6 +2479,7 @@ void mt7915_mac_work(struct work_struct *work) mphy->mac_work_count = 0; mt7915_mac_update_stats(phy); + mt7915_mac_severe_check(phy); } mutex_unlock(&mphy->dev->mutex); @@ -2600,6 +2724,34 @@ static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt) return 0; } +static bool +mt7915_mac_twt_param_equal(struct mt7915_sta *msta, + struct ieee80211_twt_params *twt_agrt) +{ + u16 type = le16_to_cpu(twt_agrt->req_type); + u8 exp; + int i; + + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); + for (i = 0; i < MT7915_MAX_STA_TWT_AGRT; i++) { + struct mt7915_twt_flow *f; + + if (!(msta->twt.flowid_mask & BIT(i))) + continue; + + f = &msta->twt.flow[i]; + if (f->duration == twt_agrt->min_twt_dur && + f->mantissa == twt_agrt->mantissa && + f->exp == exp && + f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && + f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && + f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) + return true; + } + + return false; +} + void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt) @@ -2625,6 +2777,12 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) goto unlock; + if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) { + setup_cmd = TWT_SETUP_CMD_DICTATE; + twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR; + goto unlock; + } + flowid = ffs(~msta->twt.flowid_mask) - 1; le16p_replace_bits(&twt_agrt->req_type, flowid, IEEE80211_TWT_REQTYPE_FLOWID); @@ -2633,6 +2791,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); + if (mt7915_mac_twt_param_equal(msta, twt_agrt)) + goto unlock; + flow = &msta->twt.flow[flowid]; memset(flow, 0, sizeof(*flow)); INIT_LIST_HEAD(&flow->list); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index 5add1dd36dbe..c5fd1a618ae7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -24,6 +24,7 @@ enum rx_pkt_type { PKT_TYPE_TXRX_NOTIFY, PKT_TYPE_RX_EVENT, PKT_TYPE_RX_FW_MONITOR = 0x0c, + PKT_TYPE_TXRX_NOTIFY_V0 = 0x18, }; /* RXD DW1 */ @@ -311,6 +312,7 @@ struct mt7915_tx_free { #define MT_TX_FREE_VER GENMASK(18, 16) #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) +#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) #define MT_TX_FREE_LATENCY GENMASK(12, 0) /* 0: success, others: dropped */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index c3f44d801e7f..710ca757fb52 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -42,10 +42,6 @@ static int mt7915_start(struct ieee80211_hw *hw) if (ret) goto out; - ret = mt7915_mcu_set_scs(dev, 0, true); - if (ret) - goto out; - mt7915_mac_enable_nf(dev, 0); } @@ -58,10 +54,6 @@ static int mt7915_start(struct ieee80211_hw *hw) if (ret) goto out; - ret = mt7915_mcu_set_scs(dev, 1, true); - if (ret) - goto out; - mt7915_mac_enable_nf(dev, 1); } @@ -174,14 +166,14 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; - mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0); - mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0); + mvif->bitrate_mask.control[i].he_gi = 0xff; + mvif->bitrate_mask.control[i].he_ltf = 0xff; mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); - memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0), + memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].ht_mcs)); - memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0), + memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].vht_mcs)); - memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0), + memset(mvif->bitrate_mask.control[i].he_mcs, 0xff, sizeof(mvif->bitrate_mask.control[i].he_mcs)); } } @@ -204,8 +196,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, is_zero_ether_addr(vif->addr)) phy->monitor_vif = vif; - mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1; - if (mvif->mt76.idx >= MT7915_MAX_INTERFACES) { + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); + if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) { ret = -ENOSPC; goto out; } @@ -227,7 +219,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; @@ -246,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } if (vif->type != NL80211_IFTYPE_AP && @@ -290,7 +282,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); mutex_lock(&dev->mt76.mutex); - dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); @@ -630,8 +622,10 @@ 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)) - mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); + BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) + mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); mutex_unlock(&dev->mt76.mutex); } @@ -644,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw, struct mt7915_dev *dev = mt7915_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7915_mcu_add_beacon(hw, vif, true); + mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); mutex_unlock(&dev->mt76.mutex); } @@ -1381,6 +1375,39 @@ out: return ret; } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int +mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct net_device_path_ctx *ctx, + struct net_device_path *path) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + + if (!mtk_wed_device_active(wed)) + return -ENODEV; + + if (msta->wcid.idx > 0xff) + return -EIO; + + path->type = DEV_PATH_MTK_WDMA; + path->dev = ctx->dev; + path->mtk_wdma.wdma_idx = wed->wdma_idx; + path->mtk_wdma.bss = mvif->mt76.idx; + path->mtk_wdma.wcid = msta->wcid.idx; + path->mtk_wdma.queue = phy != &dev->phy; + + ctx->dev = NULL; + + return 0; +} +#endif + const struct ieee80211_ops mt7915_ops = { .tx = mt7915_tx, .start = mt7915_start, @@ -1428,4 +1455,7 @@ const struct ieee80211_ops mt7915_ops = { .sta_add_debugfs = mt7915_sta_add_debugfs, #endif .set_radar_background = mt7915_set_radar_background, +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + .net_fill_forward_path = mt7915_net_fill_forward_path, +#endif }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index df31084e860f..b7e2b365356c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1854,7 +1854,8 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, continue; for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) { - const u8 *data; + const struct ieee80211_bssid_index *idx; + const u8 *idx_ie; if (sub_elem->id || sub_elem->datalen < 4) continue; /* not a valid BSS profile */ @@ -1862,14 +1863,19 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb, /* Find WLAN_EID_MULTI_BSSID_IDX * in the merged nontransmitted profile */ - data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX, - sub_elem->data, - sub_elem->datalen); - if (!data || data[1] < 1 || !data[2]) + 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; - mbss->offset[data[2]] = cpu_to_le16(data - skb->data); - mbss->bitmap |= cpu_to_le32(BIT(data[2])); + 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)); } } } @@ -1886,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, u8 *buf; int len = sizeof(*cont) + MT_TXD_SIZE + skb->len; + len = (len & 0x3) ? ((len | 0x3) + 1) : len; tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT, len, &bcn->sub_ntlv, &bcn->len); @@ -1904,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, buf = (u8 *)tlv + sizeof(*cont); mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, - true); + BSS_CHANGED_BEACON); memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); } @@ -1986,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, } } -int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int en) +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) +{ +#define OFFLOAD_TX_MODE_SU BIT(0) +#define OFFLOAD_TX_MODE_MU BIT(1) + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + 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_inband_discovery *discov; + struct ieee80211_tx_info *info; + struct sk_buff *skb = NULL; + struct tlv *tlv; + bool ext_phy = phy != &dev->phy; + u8 *buf, interval; + int len; + + if (changed & BSS_CHANGED_FILS_DISCOVERY && + vif->bss_conf.fils_discovery.max_interval) { + interval = vif->bss_conf.fils_discovery.max_interval; + skb = ieee80211_get_fils_discovery_tmpl(hw, vif); + } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && + vif->bss_conf.unsol_bcast_probe_resp_interval) { + interval = vif->bss_conf.unsol_bcast_probe_resp_interval; + skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); + } + + if (!skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->control.vif = vif; + info->band = band; + + if (ext_phy) + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + + len = sizeof(*discov) + MT_TXD_SIZE + skb->len; + len = (len & 0x3) ? ((len | 0x3) + 1) : len; + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV, + len, &bcn->sub_ntlv, &bcn->len); + discov = (struct bss_info_inband_discovery *)tlv; + discov->tx_mode = OFFLOAD_TX_MODE_SU; + /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */ + discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); + discov->tx_interval = interval; + discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + discov->enable = true; + + buf = (u8 *)tlv + sizeof(*discov); + + mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, + changed); + memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); + + dev_kfree_skb(skb); +} + +int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int en, u32 changed) { #define MAX_BEACON_SIZE 512 struct mt7915_dev *dev = mt7915_hw_dev(hw); @@ -2038,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, 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); @@ -2465,10 +2540,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev) /* force firmware operation mode into normal state, * which should be set before firmware download stage. */ - if (is_mt7915(&dev->mt76)) - mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - else - mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE); + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); ret = mt7915_driver_own(dev, 0); if (ret) @@ -2493,6 +2565,9 @@ int mt7915_mcu_init(struct mt7915_dev *dev) if (ret) return ret; + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); + ret = mt7915_mcu_set_mwds(dev, 1); if (ret) return ret; @@ -2583,22 +2658,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, &req_mac, sizeof(req_mac), true); } -int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) -{ - struct { - __le32 cmd; - u8 band; - u8 enable; - } __packed req = { - .cmd = cpu_to_le32(SCS_ENABLE), - .band = band, - .enable = enable + 1, - }; - - return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SCS_CTRL), &req, - sizeof(req), false); -} - int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param) { struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param; @@ -3671,3 +3730,32 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev, return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE), &req, sizeof(req), true); } + +int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) +{ + struct { + __le32 idx; + __le32 ofs; + __le32 data; + } __packed req = { + .idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 28))), + .ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(27, 0))), + .data = set ? cpu_to_le32(*val) : 0, + }; + struct sk_buff *skb; + int ret; + + if (set) + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS), + &req, sizeof(req), false); + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + *val = le32_to_cpu(*(__le32 *)(skb->data + 8)); + dev_kfree_skb(skb); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 960072a44222..5abde482a97f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -304,16 +304,6 @@ enum mcu_mmps_mode { MCU_MMPS_DISABLE, }; -enum { - SCS_SEND_DATA, - SCS_SET_MANUAL_PD_TH, - SCS_CONFIG, - SCS_ENABLE, - SCS_SHOW_INFO, - SCS_GET_GLO_ADDR, - SCS_GET_GLO_ADDR_EVENT, -}; - struct bss_info_bmc_rate { __le16 tag; __le16 len; @@ -414,11 +404,23 @@ struct bss_info_bcn_cont { __le16 pkt_len; } __packed __aligned(4); +struct bss_info_inband_discovery { + __le16 tag; + __le16 len; + u8 tx_type; + u8 tx_mode; + u8 tx_interval; + u8 enable; + __le16 rsv; + __le16 prob_rsp_len; +} __packed __aligned(4); + enum { BSS_INFO_BCN_CSA, BSS_INFO_BCN_BCC, BSS_INFO_BCN_MBSSID, BSS_INFO_BCN_CONTENT, + BSS_INFO_BCN_DISCOV, BSS_INFO_BCN_MAX }; @@ -473,6 +475,20 @@ enum { MURU_GET_TXC_TX_STATS = 151, }; +enum { + SER_QUERY, + /* recovery */ + SER_SET_RECOVER_L1, + SER_SET_RECOVER_L2, + SER_SET_RECOVER_L3_RX_ABORT, + SER_SET_RECOVER_L3_TX_ABORT, + SER_SET_RECOVER_L3_TX_DISABLE, + SER_SET_RECOVER_L3_BF, + /* action */ + SER_ENABLE = 2, + SER_RECOVER +}; + #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ sizeof(struct bss_info_omac) + \ sizeof(struct bss_info_basic) +\ @@ -486,6 +502,7 @@ enum { #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_bcn_cont) + \ + sizeof(struct bss_info_inband_discovery)) #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 5062e0d8cae4..46ee8a7db7bc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -22,6 +22,8 @@ static const u32 mt7915_reg[] = { [WFDMA_EXT_CSR_ADDR] = 0xd7000, [CBTOP1_PHY_END] = 0x77ffffff, [INFRA_MCU_ADDR_END] = 0x7c3fffff, + [FW_EXCEPTION_ADDR] = 0x219848, + [SWDEF_BASE_ADDR] = 0x41f200, }; static const u32 mt7916_reg[] = { @@ -36,6 +38,8 @@ static const u32 mt7916_reg[] = { [WFDMA_EXT_CSR_ADDR] = 0xd7000, [CBTOP1_PHY_END] = 0x7fffffff, [INFRA_MCU_ADDR_END] = 0x7c085fff, + [FW_EXCEPTION_ADDR] = 0x022050bc, + [SWDEF_BASE_ADDR] = 0x411400, }; static const u32 mt7986_reg[] = { @@ -50,6 +54,8 @@ static const u32 mt7986_reg[] = { [WFDMA_EXT_CSR_ADDR] = 0x27000, [CBTOP1_PHY_END] = 0x7fffffff, [INFRA_MCU_ADDR_END] = 0x7c085fff, + [FW_EXCEPTION_ADDR] = 0x02204ffc, + [SWDEF_BASE_ADDR] = 0x411400, }; static const u32 mt7915_offs[] = { @@ -547,15 +553,21 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev, static void mt7915_irq_tasklet(struct tasklet_struct *t) { struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; u32 intr, intr1, mask; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); + if (mtk_wed_device_active(wed)) { + mtk_wed_device_irq_set_mask(wed, 0); + intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask); + } else { + mt76_wr(dev, MT_INT_MASK_CSR, 0); + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - intr &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + intr &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + } if (dev->hif2) { intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); @@ -601,7 +613,7 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t) mt76_wr(dev, MT_MCU_CMD, val); if (val & MT_MCU_CMD_ERROR_MASK) { dev->reset_state = val; - ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + queue_work(dev->mt76.wq, &dev->reset_work); wake_up(&dev->reset_wait); } } @@ -610,10 +622,15 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t) irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) { struct mt7915_dev *dev = dev_instance; + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - if (dev->hif2) - mt76_wr(dev, MT_INT1_MASK_CSR, 0); + if (mtk_wed_device_active(wed)) { + mtk_wed_device_irq_set_mask(wed, 0); + } else { + mt76_wr(dev, MT_INT_MASK_CSR, 0); + if (dev->hif2) + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + } if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; @@ -665,8 +682,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet); - mt76_wr(dev, MT_INT_MASK_CSR, 0); - return dev; error: diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 6efa0a2e2345..4dcae6991669 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -66,6 +66,7 @@ #define MT7915_MAX_TWT_AGRT 16 #define MT7915_MAX_STA_TWT_AGRT 8 +#define MT7915_MIN_TWT_DUR 64 #define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2) struct mt7915_vif; @@ -247,6 +248,8 @@ struct mt7915_phy { u8 rdd_state; + u32 trb_ts; + u32 rx_ampdu_ts; u32 ampdu_ref; @@ -309,9 +312,6 @@ struct mt7915_dev { bool flash_mode; bool muru_debug; bool ibf; - u8 fw_debug_wm; - u8 fw_debug_wa; - u8 fw_debug_bin; struct dentry *debugfs_dir; struct rchan *relay_fwlog; @@ -319,7 +319,13 @@ struct mt7915_dev { void *cal; struct { - u8 table_mask; + u8 debug_wm; + u8 debug_wa; + u8 debug_bin; + } fw; + + struct { + u16 table_mask; u8 n_agrt; } twt; @@ -429,8 +435,11 @@ static inline void mt7986_wmac_disable(struct mt7915_dev *dev) #endif struct mt7915_dev *mt7915_mmio_probe(struct device *pdev, void __iomem *mem_base, u32 device_id); +void mt7915_wfsys_reset(struct mt7915_dev *dev); irqreturn_t mt7915_irq_handler(int irq, void *dev_instance); u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif); +u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); + int mt7915_register_device(struct mt7915_dev *dev); void mt7915_unregister_device(struct mt7915_dev *dev); int mt7915_eeprom_init(struct mt7915_dev *dev); @@ -440,7 +449,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx); s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band); -int mt7915_dma_init(struct mt7915_dev *dev); +int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); int mt7915_mcu_init(struct mt7915_dev *dev); @@ -463,7 +472,7 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, 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_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int enable); + int enable, u32 changed); int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, @@ -485,7 +494,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, bool hdr_trans); int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode, u8 en); -int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable); int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable); int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy); @@ -506,6 +514,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef); +int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set); int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level); @@ -550,7 +559,7 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy); void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, int pid, - struct ieee80211_key_conf *key, bool beacon); + struct ieee80211_key_conf *key, u32 changed); void mt7915_mac_set_timing(struct mt7915_phy *phy); int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -572,7 +581,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info); void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); void mt7915_tx_token_put(struct mt7915_dev *dev); -int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index 6f819c41a4c4..d74f609775d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -12,6 +12,9 @@ #include "mac.h" #include "../trace.h" +static bool wed_enable = false; +module_param(wed_enable, bool, 0644); + static LIST_HEAD(hif_list); static DEFINE_SPINLOCK(hif_lock); static u32 hif_idx; @@ -92,12 +95,79 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev) return 0; } +#ifdef CONFIG_NET_MEDIATEK_SOC_WED +static int mt7915_wed_offload_enable(struct mtk_wed_device *wed) +{ + struct mt7915_dev *dev; + int ret; + + dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); + + spin_lock_bh(&dev->mt76.token_lock); + dev->mt76.token_size = wed->wlan.token_start; + spin_unlock_bh(&dev->mt76.token_lock); + + ret = wait_event_timeout(dev->mt76.tx_wait, + !dev->mt76.wed_token_count, HZ); + if (!ret) + return -EAGAIN; + + return 0; +} + +static void mt7915_wed_offload_disable(struct mtk_wed_device *wed) +{ + struct mt7915_dev *dev; + + dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); + + spin_lock_bh(&dev->mt76.token_lock); + dev->mt76.token_size = MT7915_TOKEN_SIZE; + spin_unlock_bh(&dev->mt76.token_lock); +} +#endif + +static int +mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq) +{ +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + int ret; + + if (!wed_enable) + return 0; + + wed->wlan.pci_dev = pdev; + wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) + + MT_WFDMA_EXT_CSR_BASE; + wed->wlan.nbuf = 4096; + wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; + wed->wlan.init_buf = mt7915_wed_init_buf; + wed->wlan.offload_enable = mt7915_wed_offload_enable; + wed->wlan.offload_disable = mt7915_wed_offload_disable; + + if (mtk_wed_device_attach(wed) != 0) + return 0; + + *irq = wed->irq; + dev->mt76.dma_dev = wed->dev; + + ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + return 1; +#else + return 0; +#endif +} + static int mt7915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + struct mt7915_hif *hif2 = NULL; struct mt7915_dev *dev; struct mt76_dev *mdev; - struct mt7915_hif *hif2; int irq; int ret; @@ -126,19 +196,27 @@ static int mt7915_pci_probe(struct pci_dev *pdev, return PTR_ERR(dev); mdev = &dev->mt76; + mt7915_wfsys_reset(dev); hif2 = mt7915_pci_init_hif2(pdev); - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + ret = mt7915_pci_wed_init(dev, pdev, &irq); if (ret < 0) - goto free_device; + goto free_wed_or_irq_vector; + + if (!ret) { + hif2 = mt7915_pci_init_hif2(pdev); + + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + goto free_device; + + irq = pdev->irq; + } - irq = pdev->irq; ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) - goto free_irq_vector; - - mt76_wr(dev, MT_INT_MASK_CSR, 0); + goto free_wed_or_irq_vector; /* master switch of PCIe tnterrupt enable */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); @@ -173,8 +251,11 @@ free_hif2: if (dev->hif2) put_device(dev->hif2->dev); devm_free_irq(mdev->dev, irq, dev); -free_irq_vector: - pci_free_irq_vectors(pdev); +free_wed_or_irq_vector: + if (mtk_wed_device_active(&mdev->mmio.wed)) + mtk_wed_device_detach(&mdev->mmio.wed); + else + pci_free_irq_vectors(pdev); free_device: mt76_free_device(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index e5f93c40591c..4953be208c5e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -30,6 +30,8 @@ enum reg_rev { WFDMA_EXT_CSR_ADDR, CBTOP1_PHY_END, INFRA_MCU_ADDR_END, + FW_EXCEPTION_ADDR, + SWDEF_BASE_ADDR, __MT_REG_MAX, }; @@ -158,6 +160,9 @@ enum offs_rev { #define MT_MDP_DCR1 MT_MDP(0x004) #define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3) +#define MT_MDP_DCR2 MT_MDP(0x0e8) +#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2) + #define MT_MDP_BNRCFR0(_band) MT_MDP(__OFFS(MDP_BNRCFR0) + \ ((_band) << 8)) #define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4) @@ -172,6 +177,14 @@ enum offs_rev { #define MT_MDP_TO_HIF 0 #define MT_MDP_TO_WM 1 +/* TRB: band 0(0x820e1000), band 1(0x820f1000) */ +#define MT_WF_TRB_BASE(_band) ((_band) ? 0x820f1000 : 0x820e1000) +#define MT_WF_TRB(_band, ofs) (MT_WF_TRB_BASE(_band) + (ofs)) + +#define MT_TRB_RXPSR0(_band) MT_WF_TRB(_band, 0x03c) +#define MT_TRB_RXPSR0_RX_WTBL_PTR GENMASK(25, 16) +#define MT_TRB_RXPSR0_RX_RMAC_PTR GENMASK(9, 0) + /* TMAC: band 0(0x820e4000), band 1(0x820f4000) */ #define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) #define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) @@ -565,18 +578,31 @@ enum offs_rev { /* WFDMA CSR */ #define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR) +#define MT_WFDMA_EXT_CSR_PHYS_BASE 0x18027000 #define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) +#define MT_WFDMA_EXT_CSR_PHYS(ofs) (MT_WFDMA_EXT_CSR_PHYS_BASE + (ofs)) -#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30) +#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR_PHYS(0x30) #define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0) +#define MT_WFDMA_HOST_CONFIG_WED BIT(1) -#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) +#define MT_WFDMA_WED_RING_CONTROL MT_WFDMA_EXT_CSR_PHYS(0x34) +#define MT_WFDMA_WED_RING_CONTROL_TX0 GENMASK(4, 0) +#define MT_WFDMA_WED_RING_CONTROL_TX1 GENMASK(12, 8) +#define MT_WFDMA_WED_RING_CONTROL_RX1 GENMASK(20, 16) + +#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR_PHYS(0x44) #define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) #define MT_PCIE_RECOG_ID 0xd7090 #define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0) #define MT_PCIE_RECOG_ID_SEM BIT(31) +#define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204) + +#define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300) +#define MT_WED_RX_RING_BASE MT_WFDMA_EXT_CSR(0x400) + /* WFDMA0 PCIE1 */ #define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR) #define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) @@ -794,6 +820,7 @@ enum offs_rev { /* ADIE */ #define MT_ADIE_CHIP_ID 0x02c +#define MT_ADIE_VERSION_MASK GENMASK(15, 0) #define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16) #define MT_ADIE_IDX0 GENMASK(15, 0) #define MT_ADIE_IDX1 GENMASK(31, 16) @@ -913,12 +940,27 @@ enum offs_rev { #define MT_ADIE_TYPE_MASK BIT(1) /* FW MODE SYNC */ -#define MT_SWDEF_MODE 0x41f23c -#define MT_SWDEF_MODE_MT7916 0x41143c +#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR) + +#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR) + +#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) +#define MT_SWDEF_MODE MT_SWDEF(0x3c) #define MT_SWDEF_NORMAL_MODE 0 #define MT_SWDEF_ICAP_MODE 1 #define MT_SWDEF_SPECTRUM_MODE 2 +#define MT_SWDEF_SER_STATS MT_SWDEF(0x040) +#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044) +#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048) +#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C) +#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050) +#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054) +#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058) +#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C) +#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x060) +#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x064) + #define MT_DIC_CMD_REG_BASE 0x41f000 #define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs)) #define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10) @@ -965,10 +1007,6 @@ enum offs_rev { #define MT_TOP_MISC MT_TOP(0xf0) #define MT_TOP_MISC_FW_STATE GENMASK(2, 0) -#define MT_HW_BOUND 0x70010020 -#define MT_HW_REV 0x70010204 -#define MT_WF_SUBSYS_RST 0x70002600 - #define MT_TOP_WFSYS_WAKEUP MT_TOP(0x1a4) #define MT_TOP_WFSYS_WAKEUP_MASK BIT(0) @@ -1030,6 +1068,10 @@ enum offs_rev { #define MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK BIT(3) #define MT_MCU_BUS_DBG_TIMEOUT_EN_MASK BIT(2) +#define MT_HW_BOUND 0x70010020 +#define MT_HW_REV 0x70010204 +#define MT_WF_SUBSYS_RST 0x70002600 + /* PCIE MAC */ #define MT_PCIE_MAC_BASE 0x74030000 #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) @@ -1038,6 +1080,9 @@ enum offs_rev { #define MT_PCIE1_MAC_INT_ENABLE 0x74020188 #define MT_PCIE1_MAC_INT_ENABLE_MT7916 0x74090188 +#define MT_WM_MCU_PC 0x7c060204 +#define MT_WA_MCU_PC 0x7c06020c + /* PP TOP */ #define MT_WF_PP_TOP_BASE 0x820cc000 #define MT_WF_PP_TOP(ofs) (MT_WF_PP_TOP_BASE + (ofs)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 3028c02cb840..c74afa746251 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -12,6 +12,7 @@ #include <linux/iopoll.h> #include <linux/reset.h> #include <linux/of_net.h> +#include <linux/clk.h> #include "mt7915.h" @@ -210,6 +211,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev) if (IS_ERR_OR_NULL(state)) return -EINVAL; break; + default: + return -EINVAL; } ret = pinctrl_select_state(pinctrl, state); @@ -468,17 +471,32 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie) static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) { + u32 id, version, rg_xo_01, rg_xo_03; int ret; + ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id); + if (ret) + return ret; + + version = FIELD_GET(MT_ADIE_VERSION_MASK, id); + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00); if (ret) return ret; - ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1d59080f); + if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) { + rg_xo_01 = 0x1d59080f; + rg_xo_03 = 0x34c00fe0; + } else { + rg_xo_01 = 0x1959f80f; + rg_xo_03 = 0x34d00fe0; + } + + ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01); if (ret) return ret; - return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0); + return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03); } static int @@ -1115,6 +1133,19 @@ static int mt7986_wmac_init(struct mt7915_dev *dev) { struct device *pdev = dev->mt76.dev; struct platform_device *pfdev = to_platform_device(pdev); + struct clk *mcu_clk, *ap_conn_clk; + + mcu_clk = devm_clk_get(pdev, "mcu"); + if (IS_ERR(mcu_clk)) + dev_err(pdev, "mcu clock not found\n"); + else if (clk_prepare_enable(mcu_clk)) + dev_err(pdev, "mcu clock configuration failed\n"); + + ap_conn_clk = devm_clk_get(pdev, "ap2conn"); + if (IS_ERR(ap_conn_clk)) + dev_err(pdev, "ap2conn clock not found\n"); + else if (clk_prepare_enable(ap_conn_clk)) + dev_err(pdev, "ap2conn clock configuration failed\n"); dev->dcm = devm_platform_ioremap_resource(pfdev, 1); if (IS_ERR(dev->dcm)) @@ -1128,7 +1159,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev) if (IS_ERR(dev->rstc)) return PTR_ERR(dev->rstc); - return mt7986_wmac_enable(dev); + return 0; } static int mt7986_wmac_probe(struct platform_device *pdev) @@ -1161,12 +1192,12 @@ static int mt7986_wmac_probe(struct platform_device *pdev) if (ret) goto free_device; - mt76_wr(dev, MT_INT_MASK_CSR, 0); - ret = mt7986_wmac_init(dev); if (ret) goto free_irq; + mt7915_wfsys_reset(dev); + ret = mt7915_register_device(dev); if (ret) goto free_irq; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index ca7e20fb5fc0..3a6b158b779e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -9,7 +9,7 @@ static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc) { int i, err; - err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE); + err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE, 0); if (err < 0) return err; @@ -296,8 +296,8 @@ int mt7921_dma_init(struct mt7921_dev *dev) if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7921_poll_tx, NAPI_POLL_WEIGHT); + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt7921_poll_tx); napi_enable(&dev->mt76.tx_napi); return mt7921_dma_enable(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 91fc41922d95..4a8675634f80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -11,6 +11,10 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = MT7921_MAX_INTERFACES, .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) } }; @@ -64,7 +68,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->iface_combinations = if_comb; wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | WIPHY_FLAG_4ADDR_STATION); - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_scan_ssids = 4; @@ -80,6 +85,10 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, HAS_RATE_CONTROL); @@ -255,6 +264,10 @@ int mt7921_register_device(struct mt7921_dev *dev) INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work); INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work); INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work); +#if IS_ENABLED(CONFIG_IPV6) + INIT_WORK(&dev->ipv6_ns_work, mt7921_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_LIST_HEAD(&dev->sta_poll_list); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index b67615487910..a630ddbf19e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -696,7 +696,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; status->encoding = RX_ENC_VHT; - if (i > 9) + if (i > 11) return -EINVAL; break; case MT_PHY_TYPE_HE_MU: @@ -814,6 +814,7 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi, { u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; u8 fc_type, fc_stype; + u16 ethertype; bool wmm = false; u32 val; @@ -827,7 +828,8 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi, val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | FIELD_PREP(MT_TXD1_TID, tid); - if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN) + 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); @@ -1361,12 +1363,21 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; struct mt7921_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); mt7921_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); + mt7921_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); + mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); + } } /* system error recovery */ @@ -1715,3 +1726,29 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) return false; } EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data); + +#if IS_ENABLED(CONFIG_IPV6) +void mt7921_set_ipv6_ns_work(struct work_struct *work) +{ + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + ipv6_ns_work); + struct sk_buff *skb; + int ret = 0; + + do { + skb = skb_dequeue(&dev->ipv6_ns_list); + + if (!skb) + break; + + mt7921_mutex_acquire(dev); + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD(OFFLOAD), true); + mt7921_mutex_release(dev); + + } while (!ret); + + if (ret) + skb_queue_purge(&dev->ipv6_ns_list); +} +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index fdaf2451bc1d..80279f342109 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -5,6 +5,7 @@ #include <linux/platform_device.h> #include <linux/pci.h> #include <linux/module.h> +#include <net/ipv6.h> #include "mt7921.h" #include "mcu.h" @@ -12,7 +13,7 @@ static void mt7921_gen_ppe_thresh(u8 *he_ppet, int nss) { u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */ - u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; + static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71}; he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) | FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, @@ -53,6 +54,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, switch (i) { case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: break; default: continue; @@ -86,6 +88,23 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, 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; @@ -294,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, mt7921_mutex_acquire(dev); - mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1; + mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) { ret = -ENOSPC; goto out; @@ -310,7 +329,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); idx = MT7921_WTBL_RESERVED - mvif->mt76.idx; @@ -330,7 +349,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); if (vif->txq) { mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; + mtxq->wcid = idx; } out: @@ -354,7 +373,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw, rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx); + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt7921_mutex_release(dev); @@ -489,8 +508,8 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); mt7921_mcu_set_sniffer(dev, vif, monitor); - pm->enable = !monitor; - pm->ds_enable = !monitor; + pm->enable = pm->enable_user && !monitor; + pm->ds_enable = pm->ds_enable_user && !monitor; mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); @@ -566,7 +585,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | MT_WF_RFCR1_DROP_BF_POLL | MT_WF_RFCR1_DROP_BA | @@ -576,23 +594,23 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - phy->rxfilter &= ~(_hw); \ - phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + dev->mt76.rxfilter &= ~(_hw); \ + dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) mt7921_mutex_acquire(dev); - phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); + dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | @@ -606,7 +624,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter); + mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter); if (*total_flags & FIF_CONTROL) mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags); @@ -635,6 +653,20 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, } } + if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + + mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, + true); + mt7921_mcu_sta_update(dev, NULL, vif, true, + MT76_STA_INFO_STATE_NONE); + } + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7921_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)) mt7921_mcu_set_tx(dev, vif); @@ -1301,7 +1333,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, - mt76_connac_mcu_set_suspend_iter, + mt7921_mcu_set_suspend_iter, &dev->mphy); mt7921_mutex_release(dev); @@ -1376,6 +1408,67 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, MCU_UNI_CMD(STA_REC_UPDATE)); } +#if IS_ENABLED(CONFIG_IPV6) +static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct inet6_dev *idev) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_dev *dev = mvif->phy->dev; + struct inet6_ifaddr *ifa; + struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; + struct sk_buff *skb; + u8 i, idx = 0; + + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arpns; + } req_hdr = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arpns = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), + .mode = 2, /* update */ + .option = 1, /* update only */ + }, + }; + + read_lock_bh(&idev->lock); + list_for_each_entry(ifa, &idev->addr_list, if_list) { + if (ifa->flags & IFA_F_TENTATIVE) + continue; + ns_addrs[idx] = ifa->addr; + if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN) + break; + } + read_unlock_bh(&idev->lock); + + if (!idx) + return; + + skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + + idx * sizeof(struct in6_addr), GFP_ATOMIC); + if (!skb) + return; + + req_hdr.arpns.ips_num = idx; + req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv) + + idx * sizeof(struct in6_addr)); + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + + for (i = 0; i < idx; i++) + skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr)); + + skb_queue_tail(&dev->ipv6_ns_list, skb); + + ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work); +} +#endif + static int mt7921_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { @@ -1395,6 +1488,18 @@ out: return err; } +static void +mt7921_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct mt7921_dev *dev = mt7921_hw_dev(hw); + + mt7921_mutex_acquire(dev); + mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); + mt7921_mutex_release(dev); +} + const struct ieee80211_ops mt7921_ops = { .tx = mt7921_tx, .start = mt7921_start, @@ -1409,10 +1514,14 @@ const struct ieee80211_ops mt7921_ops = { .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7921_set_key, .sta_set_decap_offload = mt7921_sta_set_decap_offload, +#if IS_ENABLED(CONFIG_IPV6) + .ipv6_addr_change = mt7921_ipv6_addr_change, +#endif /* CONFIG_IPV6 */ .ampdu_action = mt7921_ampdu_action, .set_rts_threshold = mt7921_set_rts_threshold, .wake_tx_queue = mt76_wake_tx_queue, .release_buffered_frames = mt76_release_buffered_frames, + .channel_switch_beacon = mt7921_channel_switch_beacon, .get_txpower = mt76_get_txpower, .get_stats = mt7921_get_stats, .get_et_sset_count = mt7921_get_et_sset_count, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index da2be050ed7c..12bab18c4171 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -224,6 +224,49 @@ exit: } EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message); +#ifdef CONFIG_PM + +static int +mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev, + struct ieee80211_vif *vif, bool suspend) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arpns; + } req = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arpns = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND), + .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)), + .mode = suspend, + }, + }; + + return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req), + true); +} + +void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + if (IS_ENABLED(CONFIG_IPV6)) { + struct mt76_phy *phy = priv; + + mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif, + !test_bit(MT76_STATE_RUNNING, + &phy->state)); + } + + mt76_connac_mcu_set_suspend_iter(priv, mac, vif); +} + +#endif /* CONFIG_PM */ + static void mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) { @@ -248,7 +291,8 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac, if (mvif->idx != event->bss_idx) return; - if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER)) + if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) || + vif->type != NL80211_IFTYPE_STATION) return; ieee80211_connection_loss(vif); @@ -1166,3 +1210,79 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true); } + +int +mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + 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, + }, + }; + struct sk_buff *skb; + + if (!enable) + goto out; + + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "beacon size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + mt7921_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb, + wcid, NULL, 0, true); + memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + + if (offs.cntdwn_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4; + req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs); + } + dev_kfree_skb(skb); + +out: + return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE), + &req, sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 7690364bc079..5ca584bb2fc6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -155,7 +155,6 @@ struct mt7921_phy { struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; - u32 rxfilter; u64 omac_mask; u16 noise; @@ -212,6 +211,10 @@ struct mt7921_dev { struct mt76_connac_pm pm; struct mt76_connac_coredump coredump; const struct mt7921_hif_ops *hif_ops; + + struct work_struct ipv6_ns_work; + /* IPv6 addresses for WoWLAN */ + struct sk_buff_head ipv6_ns_list; }; enum { @@ -450,6 +453,10 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); void mt7921_set_runtime_pm(struct mt7921_dev *dev); +void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif); +void mt7921_set_ipv6_ns_work(struct work_struct *work); + int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); @@ -467,7 +474,11 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); int mt7921u_mcu_power_on(struct mt7921_dev *dev); int mt7921u_wfsys_reset(struct mt7921_dev *dev); -int mt7921u_dma_init(struct mt7921_dev *dev); +int mt7921u_dma_init(struct mt7921_dev *dev, bool resume); int mt7921u_init_reset(struct mt7921_dev *dev); int mt7921u_mac_reset(struct mt7921_dev *dev); +int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 1a01d025bbe5..b5fb22b8e086 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -119,7 +119,6 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) mt7921_mcu_exit(dev); tasklet_disable(&dev->irq_tasklet); - mt76_free_device(&dev->mt76); } static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) @@ -302,8 +301,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev, dev->bus_ops = dev->mt76.bus; bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), GFP_KERNEL); - if (!bus_ops) - return -ENOMEM; + if (!bus_ops) { + ret = -ENOMEM; + goto err_free_dev; + } bus_ops->rr = mt7921_rr; bus_ops->wr = mt7921_wr; @@ -312,7 +313,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev, ret = __mt7921e_mcu_drv_pmctrl(dev); if (ret) - return ret; + goto err_free_dev; mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) | (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); @@ -354,6 +355,7 @@ static void mt7921_pci_remove(struct pci_dev *pdev) mt7921e_unregister_device(dev); devm_free_irq(&pdev->dev, pdev->irq, dev); + mt76_free_device(&dev->mt76); pci_free_irq_vectors(pdev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 6712ff60c722..ea643260ceb6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -516,4 +516,9 @@ #define MT_TOP_MISC2_FW_PWR_ON BIT(0) #define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) +#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) +#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) +#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) +#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index b7771e9f1fcd..dc38baef273a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -246,7 +246,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (ret) goto error; - ret = mt7921u_dma_init(dev); + ret = mt7921u_dma_init(dev, false); if (ret) return ret; @@ -288,6 +288,61 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf) mt76_free_device(&dev->mt76); } +#ifdef CONFIG_PM +static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct mt7921_dev *dev = usb_get_intfdata(intf); + int err; + + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + if (err) + return err; + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + set_bit(MT76_STATE_SUSPEND, &dev->mphy.state); + + return 0; +} + +static int mt7921u_resume(struct usb_interface *intf) +{ + struct mt7921_dev *dev = usb_get_intfdata(intf); + 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 || mt7921_dma_need_reinit(dev)) { + err = mt7921u_dma_init(dev, true); + if (err) + return err; + } + + clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state); + + err = mt76u_resume_rx(&dev->mt76); + if (err < 0) + return err; + + return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); +} +#endif /* CONFIG_PM */ + MODULE_DEVICE_TABLE(usb, mt7921u_device_table); MODULE_FIRMWARE(MT7921_FIRMWARE_WM); MODULE_FIRMWARE(MT7921_ROM_PATCH); @@ -297,6 +352,11 @@ static struct usb_driver mt7921u_driver = { .id_table = mt7921u_device_table, .probe = mt7921u_probe, .disconnect = mt7921u_disconnect, +#ifdef CONFIG_PM + .suspend = mt7921u_suspend, + .resume = mt7921u_resume, + .reset_resume = mt7921u_resume, +#endif /* CONFIG_PM */ .soft_unbind = 1, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c index 99bcbd858b65..cd2f09743d2f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c @@ -121,7 +121,7 @@ static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); } -int mt7921u_dma_init(struct mt7921_dev *dev) +int mt7921u_dma_init(struct mt7921_dev *dev, bool resume) { int err; @@ -136,6 +136,9 @@ int mt7921u_dma_init(struct mt7921_dev *dev) MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); + if (resume) + return 0; + err = mt7921u_dma_rx_evt_ep4(dev); if (err) return err; @@ -221,7 +224,7 @@ int mt7921u_mac_reset(struct mt7921_dev *dev) if (err) goto out; - err = mt7921u_dma_init(dev); + err = mt7921u_dma_init(dev, false); if (err) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 6b8c9dc80542..1d08d99e298c 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -66,9 +66,8 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list) wcid = rcu_dereference(dev->wcid[cb->wcid]); if (wcid) { status.sta = wcid_to_sta(wcid); - - if (status.sta) - status.rate = &wcid->rate; + status.rates = NULL; + status.n_rates = 0; } hw = mt76_tx_status_get_hw(dev, skb); @@ -120,7 +119,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, memset(cb, 0, sizeof(*cb)); - if (!wcid) + if (!wcid || !rcu_access_pointer(dev->wcid[wcid->idx])) return MT_PACKET_ID_NO_ACK; if (info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -436,12 +435,11 @@ mt76_txq_stopped(struct mt76_queue *q) static int mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, - struct mt76_txq *mtxq) + struct mt76_txq *mtxq, struct mt76_wcid *wcid) { struct mt76_dev *dev = phy->dev; struct ieee80211_txq *txq = mtxq_to_txq(mtxq); enum mt76_txq_id qid = mt76_txq_get_qid(txq); - struct mt76_wcid *wcid = mtxq->wcid; struct ieee80211_tx_info *info; struct sk_buff *skb; int n_frames = 1; @@ -463,7 +461,9 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); + spin_lock(&q->lock); idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); + spin_unlock(&q->lock); if (idx < 0) return idx; @@ -483,14 +483,18 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q, ieee80211_get_tx_rates(txq->vif, txq->sta, skb, info->control.rates, 1); + spin_lock(&q->lock); idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop); + spin_unlock(&q->lock); if (idx < 0) break; n_frames++; } while (1); + spin_lock(&q->lock); dev->queue_ops->kick(dev, q); + spin_unlock(&q->lock); return n_frames; } @@ -521,12 +525,10 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) break; mtxq = (struct mt76_txq *)txq->drv_priv; - wcid = mtxq->wcid; - if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags)) + wcid = rcu_dereference(dev->wcid[mtxq->wcid]); + if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags)) continue; - spin_lock_bh(&q->lock); - if (mtxq->send_bar && mtxq->aggr) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct ieee80211_sta *sta = txq->sta; @@ -535,15 +537,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) u8 tid = txq->tid; mtxq->send_bar = false; - spin_unlock_bh(&q->lock); ieee80211_send_bar(vif, sta->addr, tid, agg_ssn); - spin_lock_bh(&q->lock); } if (!mt76_txq_stopped(q)) - n_frames = mt76_txq_send_burst(phy, q, mtxq); - - spin_unlock_bh(&q->lock); + n_frames = mt76_txq_send_burst(phy, q, mtxq, wcid); ieee80211_return_txq(phy->hw, txq, false); @@ -563,6 +561,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) if (qid >= 4) return; + local_bh_disable(); rcu_read_lock(); do { @@ -572,6 +571,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) } while (len > 0); rcu_read_unlock(); + local_bh_enable(); } EXPORT_SYMBOL_GPL(mt76_txq_schedule); @@ -721,12 +721,17 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) spin_lock_bh(&dev->token_lock); - token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size, - GFP_ATOMIC); + token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC); if (token >= 0) dev->token_count++; - if (dev->token_count >= dev->drv->token_size - MT76_TOKEN_FREE_THR) +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + if (mtk_wed_device_active(&dev->mmio.wed) && + token >= dev->mmio.wed.wlan.token_start) + dev->wed_token_count++; +#endif + + if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR) __mt76_set_tx_blocked(dev, true); spin_unlock_bh(&dev->token_lock); @@ -743,10 +748,18 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake) spin_lock_bh(&dev->token_lock); txwi = idr_remove(&dev->token, token); - if (txwi) + if (txwi) { dev->token_count--; - if (dev->token_count < dev->drv->token_size - MT76_TOKEN_FREE_THR && +#ifdef CONFIG_NET_MEDIATEK_SOC_WED + if (mtk_wed_device_active(&dev->mmio.wed) && + token >= dev->mmio.wed.wlan.token_start && + --dev->wed_token_count == 0) + wake_up(&dev->tx_wait); +#endif + } + + if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR && dev->phy.q_tx[0]->blocked) *wake = true; diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h index cccd54ed0518..77616fc77575 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.h +++ b/drivers/net/wireless/microchip/wilc1000/hif.h @@ -123,7 +123,7 @@ struct wilc_remain_ch { u32 duration; void (*expired)(void *priv, u64 cookie); void *arg; - u32 cookie; + u64 cookie; }; struct wilc; diff --git a/drivers/net/wireless/microchip/wilc1000/mon.c b/drivers/net/wireless/microchip/wilc1000/mon.c index 6bd63934c2d8..b5a1b65c087c 100644 --- a/drivers/net/wireless/microchip/wilc1000/mon.c +++ b/drivers/net/wireless/microchip/wilc1000/mon.c @@ -233,7 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops; wl->monitor_dev->needs_free_netdev = true; - if (cfg80211_register_netdevice(wl->monitor_dev)) { + if (register_netdevice(wl->monitor_dev)) { netdev_err(real_dev, "register_netdevice failed\n"); free_netdev(wl->monitor_dev); return NULL; @@ -251,7 +251,7 @@ void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked) return; if (rtnl_locked) - cfg80211_unregister_netdevice(wl->monitor_dev); + unregister_netdevice(wl->monitor_dev); else unregister_netdev(wl->monitor_dev); wl->monitor_dev = NULL; diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 643bddaae32a..3c292e3464c2 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -14,6 +14,7 @@ #include "wlan_cfg.h" #define WILC_MULTICAST_TABLE_SIZE 8 +#define WILC_MAX_FW_VERSION_STR_SIZE 50 /* latest API version supported */ #define WILC1000_API_VER 1 @@ -522,7 +523,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; - char firmware_ver[20]; + char firmware_ver[WILC_MAX_FW_VERSION_STR_SIZE]; size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION, firmware_ver, diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index ec595dbd8959..7962c11cfe84 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -598,7 +598,7 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) cmd.read_write = 1; cmd.function = 0; cmd.raw = 1; - cmd.address = SDIO_FBR_BASE(func->num); + cmd.address = SDIO_FBR_BASE(1); cmd.data = SDIO_FBR_ENABLE_CSA; ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index fb5633a05fd5..48441f0389ca 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -875,14 +875,15 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) char *bssid; u8 mgmt_ptk = 0; + if (vmm_table[i] == 0 || vmm_entries_ac[i] >= NQUEUES) + break; + tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]); - ac_pkt_num_to_chip[vmm_entries_ac[i]]++; if (!tqe) break; + ac_pkt_num_to_chip[vmm_entries_ac[i]]++; vif = tqe->vif; - if (vmm_table[i] == 0) - break; le32_to_cpus(&vmm_table[i]); vmm_sz = FIELD_GET(WILC_VMM_BUFFER_SIZE, vmm_table[i]); diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c index 840728ed57b2..8c23a77d1671 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c @@ -1146,8 +1146,8 @@ static int qtnf_pcie_pearl_probe(struct qtnf_bus *bus, unsigned int tx_bd_size, } tasklet_setup(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn); - netif_napi_add(&bus->mux_dev, &bus->mux_napi, - qtnf_pcie_pearl_rx_poll, 10); + netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi, + qtnf_pcie_pearl_rx_poll, 10); ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int; ipc_int.arg = ps; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c index 9534e1b33780..d83362578374 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c @@ -1159,8 +1159,8 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus, } tasklet_setup(&ts->base.reclaim_tq, qtnf_reclaim_tasklet_fn); - netif_napi_add(&bus->mux_dev, &bus->mux_napi, - qtnf_topaz_rx_poll, 10); + netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi, + qtnf_topaz_rx_poll, 10); ipc_int.fn = qtnf_topaz_ipc_gen_ep_int; ipc_int.arg = ts; diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 86a236873254..a8eebafb9a7e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -1014,7 +1014,7 @@ int rtl_usb_probe(struct usb_interface *intf, hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) + sizeof(struct rtl_usb_priv), &rtl_ops); if (!hw) { - WARN_ONCE(true, "rtl_usb: ieee80211 alloc failed\n"); + pr_warn("rtl_usb: ieee80211 alloc failed\n"); return -ENOMEM; } rtlpriv = hw->priv; diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index e344e058f943..090610e48d08 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -1786,7 +1786,7 @@ void rtw_fw_adaptivity(struct rtw_dev *rtwdev) SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY); SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode); - SET_ADAPTIVITY_OPTION(h2c_pkt, 2); + SET_ADAPTIVITY_OPTION(h2c_pkt, 1); SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]); SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini); SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density); diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig index dd02b6a6790e..93e09400aac4 100644 --- a/drivers/net/wireless/realtek/rtw89/Kconfig +++ b/drivers/net/wireless/realtek/rtw89/Kconfig @@ -19,8 +19,11 @@ config RTW89_PCI config RTW89_8852A tristate +config RTW89_8852C + tristate + config RTW89_8852AE - tristate "Realtek 8852AE PCI wireless network adapter" + tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter" depends on PCI select RTW89_CORE select RTW89_PCI @@ -28,7 +31,18 @@ config RTW89_8852AE help Select this option will enable support for 8852AE chipset - 802.11ax PCIe wireless network adapter + 802.11ax PCIe wireless network (Wi-Fi 6) adapter + +config RTW89_8852CE + tristate "Realtek 8852CE PCI wireless network (Wi-Fi 6E) adapter" + depends on PCI + select RTW89_CORE + select RTW89_PCI + select RTW89_8852C + help + Select this option will enable support for 8852CE chipset + + 802.11ax PCIe wireless network (Wi-Fi 6E) adapter config RTW89_DEBUG bool diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile index 012ae60c0b81..3006482d25c7 100644 --- a/drivers/net/wireless/realtek/rtw89/Makefile +++ b/drivers/net/wireless/realtek/rtw89/Makefile @@ -23,6 +23,15 @@ rtw89_8852a-objs := rtw8852a.o \ obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o rtw89_8852ae-objs := rtw8852ae.o +obj-$(CONFIG_RTW89_8852C) += rtw89_8852c.o +rtw89_8852c-objs := rtw8852c.o \ + rtw8852c_table.o \ + rtw8852c_rfk.o \ + rtw8852c_rfk_table.o + +obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o +rtw89_8852ce-objs := rtw8852ce.o + rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index e3317deafa1d..a6a90572e74b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1608,10 +1608,13 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, if (rtwdev->scanning && RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { - rx_status->freq = - ieee80211_channel_to_frequency(hal->current_channel, - hal->current_band_type); - rx_status->band = rtwdev->hal.current_band_type; + u8 chan = hal->current_channel; + u8 band = hal->current_band_type; + enum nl80211_band nl_band; + + nl_band = rtw89_hw_to_nl80211_band(band); + rx_status->freq = ieee80211_channel_to_frequency(chan, nl_band); + rx_status->band = nl_band; } if (desc_info->icv_err || desc_info->crc32_err) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 2921814842ff..e8a77225a90f 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3481,6 +3481,20 @@ static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) } static inline +enum nl80211_band rtw89_hw_to_nl80211_band(enum rtw89_band hw_band) +{ + switch (hw_band) { + default: + case RTW89_BAND_2G: + return NL80211_BAND_2GHZ; + case RTW89_BAND_5G: + return NL80211_BAND_5GHZ; + case RTW89_BAND_6G: + return NL80211_BAND_6GHZ; + } +} + +static inline enum rtw89_bandwidth nl_to_rtw89_bandwidth(enum nl80211_chan_width width) { switch (width) { diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index f93f3fee1505..7820bc3ab3b4 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -635,6 +635,11 @@ static int rtw89_debug_priv_mac_reg_dump_get(struct seq_file *m, void *v) start = 0x000; end = 0x014; break; + case RTW89_DBG_SEL_MAC_30: + seq_puts(m, "Debug selected MAC page 0x30\n"); + start = 0x030; + end = 0x033; + break; case RTW89_DBG_SEL_MAC_40: seq_puts(m, "Debug selected MAC page 0x40\n"); start = 0x040; diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h index 1745815f5e00..de72155ad1fe 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.h +++ b/drivers/net/wireless/realtek/rtw89/debug.h @@ -28,6 +28,7 @@ enum rtw89_debug_mask { enum rtw89_debug_mac_reg_sel { RTW89_DBG_SEL_MAC_00, + RTW89_DBG_SEL_MAC_30, RTW89_DBG_SEL_MAC_40, RTW89_DBG_SEL_MAC_80, RTW89_DBG_SEL_MAC_C0, diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index e4be785709d1..4718aced1428 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2068,7 +2068,7 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) struct rtw89_pktofld_info *info, *tmp; u8 idx; - for (idx = RTW89_BAND_2G; idx < NUM_NL80211_BANDS; idx++) { + for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) { if (!(rtwdev->chip->support_bands & BIT(idx))) continue; diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 05b94842fe66..3cf892912c1d 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -29,6 +29,7 @@ const u32 rtw89_mac_mem_base_addrs[RTW89_MAC_MEM_NUM] = { [RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR, [RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR, [RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR, + [RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR, }; static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset, @@ -1050,6 +1051,7 @@ static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev, void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter) { enum rtw89_rpwm_req_pwr_state state; + unsigned long delay = enter ? 10 : 150; int ret; if (enter) @@ -1059,7 +1061,7 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_send_rpwm(rtwdev, state, false); ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret, - 1000, 15000, false, rtwdev, state); + delay, 15000, false, rtwdev, state); if (ret) rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n", enter ? "entering" : "leaving"); @@ -1889,11 +1891,12 @@ static int cca_ctrl_init(struct rtw89_dev *rtwdev, u8 mac_idx) B_AX_CTN_CHK_BASIC_NAV | B_AX_CTN_CHK_BTCCA | B_AX_CTN_CHK_EDCCA | B_AX_CTN_CHK_CCA_S80 | B_AX_CTN_CHK_CCA_S40 | B_AX_CTN_CHK_CCA_S20 | - B_AX_CTN_CHK_CCA_P20 | B_AX_SIFS_CHK_EDCCA); + B_AX_CTN_CHK_CCA_P20); val &= ~(B_AX_TB_CHK_TX_NAV | B_AX_TB_CHK_CCA_S80 | B_AX_TB_CHK_CCA_S40 | B_AX_TB_CHK_CCA_S20 | B_AX_SIFS_CHK_CCA_S80 | B_AX_SIFS_CHK_CCA_S40 | - B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV); + B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV | + B_AX_SIFS_CHK_EDCCA); rtw89_write32(rtwdev, reg, val); @@ -2004,6 +2007,7 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) #define TRXCFG_RMAC_DATA_TO 15 #define RX_MAX_LEN_UNIT 512 #define PLD_RLS_MAX_PG 127 +#define RX_SPEC_MAX_LEN (11454 + RX_MAX_LEN_UNIT) int ret; u32 reg, rx_max_len, rx_qta; u16 val; @@ -2034,11 +2038,10 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) rx_qta = rtwdev->mac.dle_info.c0_rx_qta; else rx_qta = rtwdev->mac.dle_info.c1_rx_qta; - rx_qta = rx_qta > PLD_RLS_MAX_PG ? PLD_RLS_MAX_PG : rx_qta; - rx_max_len = (rx_qta - 1) * rtwdev->mac.dle_info.ple_pg_size / - RX_MAX_LEN_UNIT; - rx_max_len = rx_max_len > B_AX_RX_MPDU_MAX_LEN_SIZE ? - B_AX_RX_MPDU_MAX_LEN_SIZE : rx_max_len; + rx_qta = min_t(u32, rx_qta, PLD_RLS_MAX_PG); + rx_max_len = rx_qta * rtwdev->mac.dle_info.ple_pg_size; + rx_max_len = min_t(u32, rx_max_len, RX_SPEC_MAX_LEN); + rx_max_len /= RX_MAX_LEN_UNIT; rtw89_write32_mask(rtwdev, reg, B_AX_RX_MPDU_MAX_LEN_MASK, rx_max_len); if (rtwdev->chip->chip_id == RTL8852A && @@ -4239,6 +4242,10 @@ static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx) u32_encode_bits(CSI_INIT_RATE_VHT, B_AX_BFMEE_VHT_CSI_RATE_MASK) | u32_encode_bits(CSI_INIT_RATE_HE, B_AX_BFMEE_HE_CSI_RATE_MASK)); + reg = rtw89_mac_reg_by_idx(R_AX_CSIRPT_OPTION, mac_idx); + rtw89_write32_set(rtwdev, reg, + B_AX_CSIPRT_VHTSU_AID_EN | B_AX_CSIPRT_HESU_AID_EN); + return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 9eb4afe348b3..9f511c8d8a37 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -268,6 +268,7 @@ enum rtw89_mac_mem_sel { RTW89_MAC_MEM_TXDATA_FIFO_0, RTW89_MAC_MEM_TXDATA_FIFO_1, RTW89_MAC_MEM_CPU_LOCAL, + RTW89_MAC_MEM_BSSID_CAM, /* keep last */ RTW89_MAC_MEM_NUM, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 8da3e117ad38..f24e4a208376 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -630,7 +630,7 @@ static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta rtwsta->use_cfg_mask = true; rtwsta->mask = *br_data->mask; - rtw89_phy_ra_updata_sta(br_data->rtwdev, sta); + rtw89_phy_ra_updata_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); } static void rtw89_ra_mask_info_update(struct rtw89_dev *rtwdev, @@ -759,6 +759,15 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&rtwdev->mutex); } +static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u32 changed) +{ + struct rtw89_dev *rtwdev = hw->priv; + + rtw89_phy_ra_updata_sta(rtwdev, sta, changed); +} + const struct ieee80211_ops rtw89_ops = { .tx = rtw89_ops_tx, .wake_tx_queue = rtw89_ops_wake_tx_queue, @@ -788,5 +797,6 @@ const struct ieee80211_ops rtw89_ops = { .hw_scan = rtw89_ops_hw_scan, .cancel_hw_scan = rtw89_ops_cancel_hw_scan, .set_sar_specs = rtw89_ops_set_sar_specs, + .sta_rc_update = rtw89_ops_sta_rc_update, }; EXPORT_SYMBOL(rtw89_ops); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 2bdce7024f25..0ef7821b2e0f 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -682,9 +682,6 @@ EXPORT_SYMBOL(rtw89_pci_enable_intr_v1); void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) { rtw89_write32(rtwdev, R_AX_PCIE_HIMR00_V1, 0); - rtw89_write32(rtwdev, R_AX_HIMR0, 0); - rtw89_write32(rtwdev, R_AX_HAXI_HIMR00, 0); - rtw89_write32(rtwdev, R_AX_HIMR1, 0); } EXPORT_SYMBOL(rtw89_pci_disable_intr_v1); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 33494e8451cf..762cdba9d3cf 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -357,13 +357,19 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->csi_mode = csi_mode; } -void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) +void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed) { struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_ra_info *ra = &rtwsta->ra; rtw89_phy_ra_sta_update(rtwdev, sta, false); - ra->upd_mask = 1; + + if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) + ra->upd_mask = 1; + if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED)) + ra->upd_bw_nss_mask = 1; + rtw89_debug(rtwdev, RTW89_DBG_RA, "ra updat: macid = %d, bw = %d, nss = %d, gi = %d %d", ra->macid, @@ -423,27 +429,28 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, RTW89_HW_RATE_MCS16, RTW89_HW_RATE_MCS24}; u8 band = rtwdev->hal.current_band_type; + enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); u8 tx_nss = rtwdev->hal.tx_nss; u8 i; for (i = 0; i < tx_nss; i++) if (!__check_rate_pattern(&next_pattern, hw_rate_he[i], RA_MASK_HE_RATES, RTW89_RA_MODE_HE, - mask->control[band].he_mcs[i], + mask->control[nl_band].he_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i], RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT, - mask->control[band].vht_mcs[i], + mask->control[nl_band].vht_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i], RA_MASK_HT_RATES, RTW89_RA_MODE_HT, - mask->control[band].ht_mcs[i], + mask->control[nl_band].ht_mcs[i], 0, true)) goto out; @@ -451,18 +458,18 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, * require at least one basic rate for ieee80211_set_bitrate_mask, * so the decision just depends on if all bitrates are set or not. */ - sband = rtwdev->hw->wiphy->bands[band]; + sband = rtwdev->hw->wiphy->bands[nl_band]; if (band == RTW89_BAND_2G) { if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1, RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES, RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM, - mask->control[band].legacy, + mask->control[nl_band].legacy, BIT(sband->n_bitrates) - 1, false)) goto out; } else { if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6, RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM, - mask->control[band].legacy, + mask->control[nl_band].legacy, BIT(sband->n_bitrates) - 1, false)) goto out; } @@ -487,7 +494,7 @@ static void rtw89_phy_ra_updata_sta_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; - rtw89_phy_ra_updata_sta(rtwdev, sta); + rtw89_phy_ra_updata_sta(rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); } void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) @@ -2456,6 +2463,11 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val, struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking; u8 macid = phy_ppdu->mac_id; + if (macid >= CFO_TRACK_MAX_USER) { + rtw89_warn(rtwdev, "mac_id %d is out of range\n", macid); + return; + } + cfo->cfo_tail[macid] += cfo_val; cfo->cfo_cnt[macid]++; cfo->packet_count++; diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 3ca5efa4c097..291660154d58 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -471,7 +471,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch); void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); -void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); +void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed); void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 6f5d1012c90c..ebf28719d935 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -2605,7 +2605,6 @@ B_AX_TMAC_HWSIGB_GEN | \ B_AX_TMAC_RXTB | \ B_AX_TMAC_MIMO_CTRL | \ - B_AX_RMAC_CSI | \ B_AX_RMAC_FTM) #define R_AX_WMAC_TX_TF_INFO_0 0xCCD0 @@ -2842,6 +2841,11 @@ #define R_AX_RX_SR_CTRL_C1 0xEE4A #define B_AX_SR_EN BIT(0) +#define R_AX_CSIRPT_OPTION 0xCE64 +#define R_AX_CSIRPT_OPTION_C1 0xEE64 +#define B_AX_CSIPRT_HESU_AID_EN BIT(25) +#define B_AX_CSIPRT_VHTSU_AID_EN BIT(24) + #define R_AX_RX_STATE_MONITOR 0xCEF0 #define R_AX_RX_STATE_MONITOR_C1 0xEEF0 #define B_AX_RX_STATE_MONITOR_MASK GENMASK(31, 0) @@ -3662,7 +3666,7 @@ #define R_DCFO 0x4264 #define B_DCFO GENMASK(1, 0) #define R_SEG0CSI 0x42AC -#define B_SEG0CSI_IDX GENMASK(10, 0) +#define B_SEG0CSI_IDX GENMASK(11, 0) #define R_SEG0CSI_EN 0x42C4 #define B_SEG0CSI_EN BIT(23) #define R_BSS_CLR_MAP 0x43ac @@ -3818,6 +3822,8 @@ #define B_CHBW_MOD_SBW GENMASK(13, 12) #define B_CHBW_MOD_PRICH GENMASK(11, 8) #define B_ANT_RX_SEG0 GENMASK(3, 0) +#define R_PD_BOOST_EN 0x49E8 +#define B_PD_BOOST_EN BIT(7) #define R_P1_BACKOFF_IBADC_V1 0x49F0 #define B_P1_BACKOFF_IBADC_V1 GENMASK(31, 26) #define R_BK_FC0_INV_V1 0x4A1C @@ -3836,6 +3842,12 @@ #define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0) #define R_PATH0_FRC_FIR_TYPE_V1 0x4C00 #define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0) +#define R_PATH0_NOTCH 0x4C14 +#define B_PATH0_NOTCH_EN BIT(12) +#define B_PATH0_NOTCH_VAL GENMASK(11, 0) +#define R_PATH0_NOTCH2 0x4C20 +#define B_PATH0_NOTCH2_EN BIT(12) +#define B_PATH0_NOTCH2_VAL GENMASK(11, 0) #define R_PATH0_5MDET 0x4C4C #define B_PATH0_5MDET_EN BIT(12) #define B_PATH0_5MDET_SB2 BIT(8) @@ -3843,6 +3855,12 @@ #define B_PATH0_5MDET_TH GENMASK(5, 0) #define R_PATH1_FRC_FIR_TYPE_V1 0x4CC4 #define B_PATH1_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0) +#define R_PATH1_NOTCH 0x4CD8 +#define B_PATH1_NOTCH_EN BIT(12) +#define B_PATH1_NOTCH_VAL GENMASK(11, 0) +#define R_PATH1_NOTCH2 0x4CE4 +#define B_PATH1_NOTCH2_EN BIT(12) +#define B_PATH1_NOTCH2_VAL GENMASK(11, 0) #define R_PATH1_5MDET 0x4D10 #define B_PATH1_5MDET_EN BIT(12) #define B_PATH1_5MDET_SB2 BIT(8) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 4fb3de71d032..64840c8d9efe 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1381,19 +1381,72 @@ static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev, } } +static void rtw8852c_spur_notch(struct rtw89_dev *rtwdev, u32 val, + enum rtw89_phy_idx phy_idx) +{ + u32 notch; + u32 notch2; + + if (phy_idx == RTW89_PHY_0) { + notch = R_PATH0_NOTCH; + notch2 = R_PATH0_NOTCH2; + } else { + notch = R_PATH1_NOTCH; + notch2 = R_PATH1_NOTCH2; + } + + rtw89_phy_write32_mask(rtwdev, notch, + B_PATH0_NOTCH_VAL | B_PATH0_NOTCH_EN, val); + rtw89_phy_write32_set(rtwdev, notch, B_PATH0_NOTCH_EN); + rtw89_phy_write32_mask(rtwdev, notch2, + B_PATH0_NOTCH2_VAL | B_PATH0_NOTCH2_EN, val); + rtw89_phy_write32_set(rtwdev, notch2, B_PATH0_NOTCH2_EN); +} + static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev, struct rtw89_channel_params *param, + u8 pri_ch_idx, enum rtw89_phy_idx phy_idx) { rtw8852c_set_csi_tone_idx(rtwdev, param, phy_idx); if (phy_idx == RTW89_PHY_0) { - rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_A); - if (!rtwdev->dbcc_en) - rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B); + if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && + (pri_ch_idx == RTW89_SC_20_LOWER || + pri_ch_idx == RTW89_SC_20_UP3X)) { + rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_0); + if (!rtwdev->dbcc_en) + rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1); + } else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && + (pri_ch_idx == RTW89_SC_20_UPPER || + pri_ch_idx == RTW89_SC_20_LOW3X)) { + rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_0); + if (!rtwdev->dbcc_en) + rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1); + } else { + rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_A); + if (!rtwdev->dbcc_en) + rtw8852c_set_nbi_tone_idx(rtwdev, param, + RF_PATH_B); + } } else { - rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B); + if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && + (pri_ch_idx == RTW89_SC_20_LOWER || + pri_ch_idx == RTW89_SC_20_UP3X)) { + rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1); + } else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && + (pri_ch_idx == RTW89_SC_20_UPPER || + pri_ch_idx == RTW89_SC_20_LOW3X)) { + rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1); + } else { + rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B); + } } + + if (pri_ch_idx == RTW89_SC_20_UP3X || pri_ch_idx == RTW89_SC_20_LOW3X) + rtw89_phy_write32_idx(rtwdev, R_PD_BOOST_EN, B_PD_BOOST_EN, 0, phy_idx); + else + rtw89_phy_write32_idx(rtwdev, R_PD_BOOST_EN, B_PD_BOOST_EN, 1, phy_idx); } static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev, @@ -1664,7 +1717,7 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev, B_PD_ARBITER_OFF, 0x1, phy_idx); } - rtw8852c_spur_elimination(rtwdev, param, phy_idx); + rtw8852c_spur_elimination(rtwdev, param, pri_ch_idx, phy_idx); rtw8852c_ctrl_btg(rtwdev, param->band_type == RTW89_BAND_2G); rtw8852c_5m_mask(rtwdev, param, phy_idx); @@ -1786,6 +1839,7 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev) { enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); rtw8852c_rx_dck(rtwdev, phy_idx, false); rtw8852c_iqk(rtwdev, phy_idx); rtw8852c_tssi(rtwdev, phy_idx); @@ -2306,19 +2360,19 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, rtw89_write32(rtwdev, reg, 0); } - if (tx_path == RF_PATH_A) { + if (tx_path == RF_A) { path_com[0].data = AX_PATH_COM0_PATHA; path_com[1].data = AX_PATH_COM1_PATHA; path_com[2].data = AX_PATH_COM2_PATHA; path_com[7].data = AX_PATH_COM7_PATHA; path_com[8].data = AX_PATH_COM8_PATHA; - } else if (tx_path == RF_PATH_B) { + } else if (tx_path == RF_B) { path_com[0].data = AX_PATH_COM0_PATHB; path_com[1].data = AX_PATH_COM1_PATHB; path_com[2].data = AX_PATH_COM2_PATHB; path_com[7].data = AX_PATH_COM7_PATHB; path_com[8].data = AX_PATH_COM8_PATHB; - } else if (tx_path == RF_PATH_AB) { + } else if (tx_path == RF_AB) { path_com[0].data = AX_PATH_COM0_PATHAB; path_com[1].data = AX_PATH_COM1_PATHAB; path_com[2].data = AX_PATH_COM2_PATHAB; @@ -2337,9 +2391,73 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, } } +static void rtw8852c_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en) +{ + if (bt_en) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1, + B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x3); + rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1, + B_PATH1_FRC_FIR_TYPE_MSK_V1, 0x3); + rtw89_phy_write32_mask(rtwdev, R_PATH0_RXBB_V1, + B_PATH0_RXBB_MSK_V1, 0xf); + rtw89_phy_write32_mask(rtwdev, R_PATH1_RXBB_V1, + B_PATH1_RXBB_MSK_V1, 0xf); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_LNA6_OP1DB_V1, + B_PATH1_G_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA1_LNA6_OP1DB_V1, + B_PATH0_G_TIA1_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA0_LNA6_OP1DB_V1, + B_PATH1_G_TIA0_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA1_LNA6_OP1DB_V1, + B_PATH1_G_TIA1_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_BACKOFF_V1, + B_PATH0_BT_BACKOFF_V1, 0x780D1E); + rtw89_phy_write32_mask(rtwdev, R_PATH1_BT_BACKOFF_V1, + B_PATH1_BT_BACKOFF_V1, 0x780D1E); + rtw89_phy_write32_mask(rtwdev, R_P0_BACKOFF_IBADC_V1, + B_P0_BACKOFF_IBADC_V1, 0x34); + rtw89_phy_write32_mask(rtwdev, R_P1_BACKOFF_IBADC_V1, + B_P1_BACKOFF_IBADC_V1, 0x34); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1, + B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1, + B_PATH1_FRC_FIR_TYPE_MSK_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_RXBB_V1, + B_PATH0_RXBB_MSK_V1, 0x60); + rtw89_phy_write32_mask(rtwdev, R_PATH1_RXBB_V1, + B_PATH1_RXBB_MSK_V1, 0x60); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_LNA6_OP1DB_V1, + B_PATH1_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA1_LNA6_OP1DB_V1, + B_PATH0_G_TIA1_LNA6_OP1DB_V1, 0x2a); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA0_LNA6_OP1DB_V1, + B_PATH1_G_TIA0_LNA6_OP1DB_V1, 0x2a); + rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA1_LNA6_OP1DB_V1, + B_PATH1_G_TIA1_LNA6_OP1DB_V1, 0x2a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_BACKOFF_V1, + B_PATH0_BT_BACKOFF_V1, 0x79E99E); + rtw89_phy_write32_mask(rtwdev, R_PATH1_BT_BACKOFF_V1, + B_PATH1_BT_BACKOFF_V1, 0x79E99E); + rtw89_phy_write32_mask(rtwdev, R_P0_BACKOFF_IBADC_V1, + B_P0_BACKOFF_IBADC_V1, 0x26); + rtw89_phy_write32_mask(rtwdev, R_P1_BACKOFF_IBADC_V1, + B_P1_BACKOFF_IBADC_V1, 0x26); + } +} + static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; + u8 ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_AB; rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB); @@ -2355,7 +2473,7 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 1); } - rtw8852c_ctrl_tx_path_tmac(rtwdev, RF_PATH_AB, RTW89_MAC_0); + rtw8852c_ctrl_tx_path_tmac(rtwdev, ntx_path, RTW89_MAC_0); } static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) @@ -2552,16 +2670,14 @@ rtw8852c_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val) #define __write_ctrl(_reg, _msk, _val, _en, _cond) \ do { \ - const typeof(_msk) __msk = _msk; \ - const typeof(_en) __en = _en; \ - u32 _wrt = FIELD_PREP(__msk, _val); \ - BUILD_BUG_ON((__msk & __en) != 0); \ + u32 _wrt = FIELD_PREP(_msk, _val); \ + BUILD_BUG_ON((_msk & _en) != 0); \ if (_cond) \ - _wrt |= __en; \ + _wrt |= _en; \ else \ - _wrt &= ~__en; \ + _wrt &= ~_en; \ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \ - __msk | __en, _wrt); \ + _msk | _en, _wrt); \ } while (0) switch (arg.ctrl_all_time) { @@ -2598,6 +2714,48 @@ s8 rtw8852c_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val) return clamp_t(s8, val, -100, 0) + 100; } +static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {6, 1, 0, 7}, + {13, 1, 0, 7}, + {13, 1, 0, 7} +}; + +static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_dl[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {255, 1, 0, 7}, + {255, 1, 0, 7}, + {255, 1, 0, 7} +}; + +static const u8 rtw89_btc_8852c_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {60, 50, 40, 30}; +static const u8 rtw89_btc_8852c_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {40, 36, 31, 28}; + +static const struct rtw89_btc_fbtc_mreg rtw89_btc_8852c_mon_reg[] = { + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda00), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda04), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda38), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda44), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda48), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980), +}; + static void rtw8852c_btc_bt_aci_imp(struct rtw89_dev *rtwdev) { @@ -2731,10 +2889,13 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .disable_bb_rf = rtw8852c_mac_disable_bb_rf, .bb_reset = rtw8852c_bb_reset, .bb_sethw = rtw8852c_bb_sethw, + .read_rf = rtw89_phy_read_rf_v1, + .write_rf = rtw89_phy_write_rf_v1, .set_channel = rtw8852c_set_channel, .set_channel_help = rtw8852c_set_channel_help, .read_efuse = rtw8852c_read_efuse, .read_phycap = rtw8852c_read_phycap, + .fem_setup = NULL, .rfk_init = rtw8852c_rfk_init, .rfk_channel = rtw8852c_rfk_channel, .rfk_band_changed = rtw8852c_rfk_band_changed, @@ -2745,11 +2906,11 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl, .init_txpwr_unit = rtw8852c_init_txpwr_unit, .get_thermal = rtw8852c_get_thermal, + .ctrl_btg = rtw8852c_ctrl_btg, .query_ppdu = rtw8852c_query_ppdu, - .read_rf = rtw89_phy_read_rf_v1, - .write_rf = rtw89_phy_write_rf_v1, - .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, + .bb_ctrl_btc_preagc = rtw8852c_bb_ctrl_btc_preagc, .cfg_txrx_path = rtw8852c_bb_cfg_txrx_path, + .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, .pwr_on_func = rtw8852c_pwr_on_func, .pwr_off_func = rtw8852c_pwr_off_func, .fill_txdesc = rtw89_core_fill_txdesc_v1, @@ -2774,6 +2935,10 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, .ops = &rtw8852c_chip_ops, .fw_name = "rtw89/rtw8852c_fw.bin", + .fifo_size = 458752, + .max_amsdu_limit = 8000, + .dis_2g_40m_ul_ofdma = false, + .rsvd_ple_ofst = 0x6f800, .hfc_param_ini = rtw8852c_hfc_param_ini_pcie, .dle_mem = rtw8852c_dle_mem_pcie, .rf_base_addr = {0xe000, 0xf000}, @@ -2795,7 +2960,17 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .txpwr_factor_mac = 1, .dig_table = NULL, .tssi_dbw_table = &rtw89_8852c_tssi_dbw_table, + .support_bands = BIT(NL80211_BAND_2GHZ) | + BIT(NL80211_BAND_5GHZ) | + BIT(NL80211_BAND_6GHZ), + .support_bw160 = true, .hw_sec_hdr = true, + .rf_path_num = 2, + .tx_nss = 2, + .rx_nss = 2, + .acam_num = 128, + .bcam_num = 20, + .scam_num = 128, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, .logical_efuse_size = 2048, @@ -2804,6 +2979,22 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .dav_log_efuse_size = 16, .phycap_addr = 0x590, .phycap_size = 0x60, + .para_ver = 0x05050764, + .wlcx_desired = 0x05050000, + .btcx_desired = 0x5, + .scbd = 0x1, + .mailbox = 0x1, + .afh_guard_ch = 6, + .wl_rssi_thres = rtw89_btc_8852c_wl_rssi_thres, + .bt_rssi_thres = rtw89_btc_8852c_bt_rssi_thres, + .rssi_tol = 2, + .mon_reg_num = ARRAY_SIZE(rtw89_btc_8852c_mon_reg), + .mon_reg = rtw89_btc_8852c_mon_reg, + .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8852c_rf_ul), + .rf_para_ulink = rtw89_btc_8852c_rf_ul, + .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8852c_rf_dl), + .rf_para_dlink = rtw89_btc_8852c_rf_dl, + .ps_mode_supported = 0, .low_power_hci_modes = BIT(RTW89_PS_MODE_CLK_GATED) | BIT(RTW89_PS_MODE_PWR_GATED), .h2c_cctl_func_id = H2C_FUNC_MAC_CCTLINFO_UD_V1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index ffc71ad24927..dfb9caba9bc4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -3809,6 +3809,24 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev, param->bandwidth); } +void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + struct rtw89_mcc_info *mcc_info = &rtwdev->mcc; + u8 idx = mcc_info->table_idx; + int i; + + for (i = 0; i < RTW89_IQK_CHS_NR; i++) { + if (mcc_info->ch[idx] == 0) + break; + if (++idx >= RTW89_IQK_CHS_NR) + idx = 0; + } + + mcc_info->table_idx = idx; + mcc_info->ch[idx] = rtwdev->hal.current_channel; + mcc_info->band[idx] = rtwdev->hal.current_band_type; +} + void rtw8852c_rck(struct rtw89_dev *rtwdev) { u8 path; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h index e42fb1a4965e..c32756f0c01a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h @@ -7,6 +7,7 @@ #include "core.h" +void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); void rtw8852c_rck(struct rtw89_dev *rtwdev); void rtw8852c_dack(struct rtw89_dev *rtwdev); void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c index 477c46041c94..feaa83b16171 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c @@ -13678,27 +13678,27 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = { { 0, 1, 3, 0, 4, 0x50505050, }, { 0, 0, 4, 1, 4, 0x00000000, }, { 0, 0, 4, 0, 1, 0x00000000, }, - { 1, 0, 1, 0, 4, 0x5054585c, }, - { 1, 0, 1, 4, 4, 0x4044484c, }, - { 1, 0, 2, 0, 4, 0x4c505458, }, + { 1, 0, 1, 0, 4, 0x48484848, }, + { 1, 0, 1, 4, 4, 0x40444848, }, + { 1, 0, 2, 0, 4, 0x48484848, }, { 1, 0, 2, 4, 4, 0x3c404448, }, { 1, 0, 2, 8, 4, 0x2c303438, }, - { 1, 0, 3, 0, 4, 0x3c40484c, }, - { 1, 1, 2, 0, 4, 0x4c505458, }, + { 1, 0, 3, 0, 4, 0x48484848, }, + { 1, 1, 2, 0, 4, 0x48484848, }, { 1, 1, 2, 4, 4, 0x3c404448, }, { 1, 1, 2, 8, 4, 0x2c303438, }, - { 1, 1, 3, 0, 4, 0x3c40484c, }, + { 1, 1, 3, 0, 4, 0x48484848, }, { 1, 0, 4, 0, 4, 0x00000000, }, - { 2, 0, 1, 0, 4, 0x5054585c, }, - { 2, 0, 1, 4, 4, 0x4044484c, }, - { 2, 0, 2, 0, 4, 0x4c505458, }, - { 2, 0, 2, 4, 4, 0x3c404448, }, - { 2, 0, 2, 8, 4, 0x2c303438, }, - { 2, 0, 3, 0, 4, 0x3c40484c, }, - { 2, 1, 2, 0, 4, 0x4c505458, }, - { 2, 1, 2, 4, 4, 0x3c404448, }, - { 2, 1, 2, 8, 4, 0x2c303438, }, - { 2, 1, 3, 0, 4, 0x3c40484c, }, + { 2, 0, 1, 0, 4, 0x40404040, }, + { 2, 0, 1, 4, 4, 0x383c4040, }, + { 2, 0, 2, 0, 4, 0x40404040, }, + { 2, 0, 2, 4, 4, 0x34383c40, }, + { 2, 0, 2, 8, 4, 0x24282c30, }, + { 2, 0, 3, 0, 4, 0x40404040, }, + { 2, 1, 2, 0, 4, 0x40404040, }, + { 2, 1, 2, 4, 4, 0x34383c40, }, + { 2, 1, 2, 8, 4, 0x24282c30, }, + { 2, 1, 3, 0, 4, 0x40404040, }, { 2, 0, 4, 0, 4, 0x00000000, }, }; @@ -13857,8 +13857,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_WW][9] = 60, [0][0][0][0][RTW89_WW][10] = 60, [0][0][0][0][RTW89_WW][11] = 60, - [0][0][0][0][RTW89_WW][12] = 58, - [0][0][0][0][RTW89_WW][13] = 74, + [0][0][0][0][RTW89_WW][12] = 48, + [0][0][0][0][RTW89_WW][13] = 72, [0][1][0][0][RTW89_WW][0] = 48, [0][1][0][0][RTW89_WW][1] = 48, [0][1][0][0][RTW89_WW][2] = 48, @@ -13870,34 +13870,34 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_WW][8] = 48, [0][1][0][0][RTW89_WW][9] = 48, [0][1][0][0][RTW89_WW][10] = 48, - [0][1][0][0][RTW89_WW][11] = 48, - [0][1][0][0][RTW89_WW][12] = 44, - [0][1][0][0][RTW89_WW][13] = 62, + [0][1][0][0][RTW89_WW][11] = 46, + [0][1][0][0][RTW89_WW][12] = 34, + [0][1][0][0][RTW89_WW][13] = 60, [1][0][0][0][RTW89_WW][0] = 0, [1][0][0][0][RTW89_WW][1] = 0, - [1][0][0][0][RTW89_WW][2] = 52, - [1][0][0][0][RTW89_WW][3] = 52, - [1][0][0][0][RTW89_WW][4] = 52, - [1][0][0][0][RTW89_WW][5] = 60, - [1][0][0][0][RTW89_WW][6] = 52, - [1][0][0][0][RTW89_WW][7] = 52, - [1][0][0][0][RTW89_WW][8] = 52, - [1][0][0][0][RTW89_WW][9] = 44, - [1][0][0][0][RTW89_WW][10] = 32, + [1][0][0][0][RTW89_WW][2] = 42, + [1][0][0][0][RTW89_WW][3] = 42, + [1][0][0][0][RTW89_WW][4] = 42, + [1][0][0][0][RTW89_WW][5] = 58, + [1][0][0][0][RTW89_WW][6] = 42, + [1][0][0][0][RTW89_WW][7] = 42, + [1][0][0][0][RTW89_WW][8] = 42, + [1][0][0][0][RTW89_WW][9] = 34, + [1][0][0][0][RTW89_WW][10] = 22, [1][0][0][0][RTW89_WW][11] = 0, [1][0][0][0][RTW89_WW][12] = 0, [1][0][0][0][RTW89_WW][13] = 0, [1][1][0][0][RTW89_WW][0] = 0, [1][1][0][0][RTW89_WW][1] = 0, - [1][1][0][0][RTW89_WW][2] = 48, - [1][1][0][0][RTW89_WW][3] = 48, - [1][1][0][0][RTW89_WW][4] = 48, + [1][1][0][0][RTW89_WW][2] = 38, + [1][1][0][0][RTW89_WW][3] = 38, + [1][1][0][0][RTW89_WW][4] = 38, [1][1][0][0][RTW89_WW][5] = 48, - [1][1][0][0][RTW89_WW][6] = 36, - [1][1][0][0][RTW89_WW][7] = 36, - [1][1][0][0][RTW89_WW][8] = 36, - [1][1][0][0][RTW89_WW][9] = 32, - [1][1][0][0][RTW89_WW][10] = 32, + [1][1][0][0][RTW89_WW][6] = 26, + [1][1][0][0][RTW89_WW][7] = 26, + [1][1][0][0][RTW89_WW][8] = 26, + [1][1][0][0][RTW89_WW][9] = 22, + [1][1][0][0][RTW89_WW][10] = 22, [1][1][0][0][RTW89_WW][11] = 0, [1][1][0][0][RTW89_WW][12] = 0, [1][1][0][0][RTW89_WW][13] = 0, @@ -13912,8 +13912,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][8] = 60, [0][0][1][0][RTW89_WW][9] = 60, [0][0][1][0][RTW89_WW][10] = 60, - [0][0][1][0][RTW89_WW][11] = 56, - [0][0][1][0][RTW89_WW][12] = 52, + [0][0][1][0][RTW89_WW][11] = 46, + [0][0][1][0][RTW89_WW][12] = 42, [0][0][1][0][RTW89_WW][13] = 0, [0][1][1][0][RTW89_WW][0] = 48, [0][1][1][0][RTW89_WW][1] = 48, @@ -13926,8 +13926,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_WW][8] = 48, [0][1][1][0][RTW89_WW][9] = 48, [0][1][1][0][RTW89_WW][10] = 48, - [0][1][1][0][RTW89_WW][11] = 48, - [0][1][1][0][RTW89_WW][12] = 44, + [0][1][1][0][RTW89_WW][11] = 38, + [0][1][1][0][RTW89_WW][12] = 34, [0][1][1][0][RTW89_WW][13] = 0, [0][0][2][0][RTW89_WW][0] = 60, [0][0][2][0][RTW89_WW][1] = 60, @@ -13940,8 +13940,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][8] = 60, [0][0][2][0][RTW89_WW][9] = 60, [0][0][2][0][RTW89_WW][10] = 60, - [0][0][2][0][RTW89_WW][11] = 56, - [0][0][2][0][RTW89_WW][12] = 52, + [0][0][2][0][RTW89_WW][11] = 46, + [0][0][2][0][RTW89_WW][12] = 42, [0][0][2][0][RTW89_WW][13] = 0, [0][1][2][0][RTW89_WW][0] = 48, [0][1][2][0][RTW89_WW][1] = 48, @@ -13954,8 +13954,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][8] = 48, [0][1][2][0][RTW89_WW][9] = 48, [0][1][2][0][RTW89_WW][10] = 48, - [0][1][2][0][RTW89_WW][11] = 48, - [0][1][2][0][RTW89_WW][12] = 44, + [0][1][2][0][RTW89_WW][11] = 38, + [0][1][2][0][RTW89_WW][12] = 34, [0][1][2][0][RTW89_WW][13] = 0, [0][1][2][1][RTW89_WW][0] = 36, [0][1][2][1][RTW89_WW][1] = 36, @@ -13969,7 +13969,7 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_WW][9] = 36, [0][1][2][1][RTW89_WW][10] = 36, [0][1][2][1][RTW89_WW][11] = 36, - [0][1][2][1][RTW89_WW][12] = 36, + [0][1][2][1][RTW89_WW][12] = 34, [0][1][2][1][RTW89_WW][13] = 0, [1][0][2][0][RTW89_WW][0] = 0, [1][0][2][0][RTW89_WW][1] = 0, @@ -13981,21 +13981,21 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_WW][7] = 60, [1][0][2][0][RTW89_WW][8] = 60, [1][0][2][0][RTW89_WW][9] = 60, - [1][0][2][0][RTW89_WW][10] = 60, + [1][0][2][0][RTW89_WW][10] = 58, [1][0][2][0][RTW89_WW][11] = 0, [1][0][2][0][RTW89_WW][12] = 0, [1][0][2][0][RTW89_WW][13] = 0, [1][1][2][0][RTW89_WW][0] = 0, [1][1][2][0][RTW89_WW][1] = 0, - [1][1][2][0][RTW89_WW][2] = 48, - [1][1][2][0][RTW89_WW][3] = 48, + [1][1][2][0][RTW89_WW][2] = 46, + [1][1][2][0][RTW89_WW][3] = 46, [1][1][2][0][RTW89_WW][4] = 48, [1][1][2][0][RTW89_WW][5] = 48, [1][1][2][0][RTW89_WW][6] = 48, - [1][1][2][0][RTW89_WW][7] = 48, - [1][1][2][0][RTW89_WW][8] = 48, - [1][1][2][0][RTW89_WW][9] = 44, - [1][1][2][0][RTW89_WW][10] = 40, + [1][1][2][0][RTW89_WW][7] = 46, + [1][1][2][0][RTW89_WW][8] = 46, + [1][1][2][0][RTW89_WW][9] = 34, + [1][1][2][0][RTW89_WW][10] = 30, [1][1][2][0][RTW89_WW][11] = 0, [1][1][2][0][RTW89_WW][12] = 0, [1][1][2][0][RTW89_WW][13] = 0, @@ -14008,149 +14008,149 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_WW][6] = 36, [1][1][2][1][RTW89_WW][7] = 36, [1][1][2][1][RTW89_WW][8] = 36, - [1][1][2][1][RTW89_WW][9] = 36, - [1][1][2][1][RTW89_WW][10] = 36, + [1][1][2][1][RTW89_WW][9] = 34, + [1][1][2][1][RTW89_WW][10] = 30, [1][1][2][1][RTW89_WW][11] = 0, [1][1][2][1][RTW89_WW][12] = 0, [1][1][2][1][RTW89_WW][13] = 0, - [0][0][0][0][RTW89_FCC][0] = 80, + [0][0][0][0][RTW89_FCC][0] = 70, [0][0][0][0][RTW89_ETSI][0] = 60, - [0][0][0][0][RTW89_MKK][0] = 72, - [0][0][0][0][RTW89_IC][0] = 80, + [0][0][0][0][RTW89_MKK][0] = 68, + [0][0][0][0][RTW89_IC][0] = 74, [0][0][0][0][RTW89_ACMA][0] = 60, - [0][0][0][0][RTW89_FCC][1] = 80, + [0][0][0][0][RTW89_FCC][1] = 70, [0][0][0][0][RTW89_ETSI][1] = 60, - [0][0][0][0][RTW89_MKK][1] = 72, - [0][0][0][0][RTW89_IC][1] = 80, + [0][0][0][0][RTW89_MKK][1] = 68, + [0][0][0][0][RTW89_IC][1] = 74, [0][0][0][0][RTW89_ACMA][1] = 60, - [0][0][0][0][RTW89_FCC][2] = 80, + [0][0][0][0][RTW89_FCC][2] = 70, [0][0][0][0][RTW89_ETSI][2] = 60, - [0][0][0][0][RTW89_MKK][2] = 72, - [0][0][0][0][RTW89_IC][2] = 80, + [0][0][0][0][RTW89_MKK][2] = 68, + [0][0][0][0][RTW89_IC][2] = 74, [0][0][0][0][RTW89_ACMA][2] = 60, - [0][0][0][0][RTW89_FCC][3] = 80, + [0][0][0][0][RTW89_FCC][3] = 70, [0][0][0][0][RTW89_ETSI][3] = 60, - [0][0][0][0][RTW89_MKK][3] = 72, - [0][0][0][0][RTW89_IC][3] = 80, + [0][0][0][0][RTW89_MKK][3] = 68, + [0][0][0][0][RTW89_IC][3] = 74, [0][0][0][0][RTW89_ACMA][3] = 60, - [0][0][0][0][RTW89_FCC][4] = 80, + [0][0][0][0][RTW89_FCC][4] = 70, [0][0][0][0][RTW89_ETSI][4] = 60, - [0][0][0][0][RTW89_MKK][4] = 72, - [0][0][0][0][RTW89_IC][4] = 80, + [0][0][0][0][RTW89_MKK][4] = 68, + [0][0][0][0][RTW89_IC][4] = 74, [0][0][0][0][RTW89_ACMA][4] = 60, - [0][0][0][0][RTW89_FCC][5] = 80, + [0][0][0][0][RTW89_FCC][5] = 70, [0][0][0][0][RTW89_ETSI][5] = 60, - [0][0][0][0][RTW89_MKK][5] = 72, - [0][0][0][0][RTW89_IC][5] = 80, + [0][0][0][0][RTW89_MKK][5] = 68, + [0][0][0][0][RTW89_IC][5] = 74, [0][0][0][0][RTW89_ACMA][5] = 60, - [0][0][0][0][RTW89_FCC][6] = 80, + [0][0][0][0][RTW89_FCC][6] = 70, [0][0][0][0][RTW89_ETSI][6] = 60, - [0][0][0][0][RTW89_MKK][6] = 72, - [0][0][0][0][RTW89_IC][6] = 80, + [0][0][0][0][RTW89_MKK][6] = 68, + [0][0][0][0][RTW89_IC][6] = 74, [0][0][0][0][RTW89_ACMA][6] = 60, - [0][0][0][0][RTW89_FCC][7] = 80, + [0][0][0][0][RTW89_FCC][7] = 70, [0][0][0][0][RTW89_ETSI][7] = 60, - [0][0][0][0][RTW89_MKK][7] = 72, - [0][0][0][0][RTW89_IC][7] = 80, + [0][0][0][0][RTW89_MKK][7] = 68, + [0][0][0][0][RTW89_IC][7] = 74, [0][0][0][0][RTW89_ACMA][7] = 60, - [0][0][0][0][RTW89_FCC][8] = 80, + [0][0][0][0][RTW89_FCC][8] = 70, [0][0][0][0][RTW89_ETSI][8] = 60, - [0][0][0][0][RTW89_MKK][8] = 72, - [0][0][0][0][RTW89_IC][8] = 80, + [0][0][0][0][RTW89_MKK][8] = 68, + [0][0][0][0][RTW89_IC][8] = 74, [0][0][0][0][RTW89_ACMA][8] = 60, - [0][0][0][0][RTW89_FCC][9] = 80, + [0][0][0][0][RTW89_FCC][9] = 70, [0][0][0][0][RTW89_ETSI][9] = 60, - [0][0][0][0][RTW89_MKK][9] = 72, - [0][0][0][0][RTW89_IC][9] = 80, + [0][0][0][0][RTW89_MKK][9] = 68, + [0][0][0][0][RTW89_IC][9] = 74, [0][0][0][0][RTW89_ACMA][9] = 60, - [0][0][0][0][RTW89_FCC][10] = 80, + [0][0][0][0][RTW89_FCC][10] = 70, [0][0][0][0][RTW89_ETSI][10] = 60, - [0][0][0][0][RTW89_MKK][10] = 72, - [0][0][0][0][RTW89_IC][10] = 80, + [0][0][0][0][RTW89_MKK][10] = 68, + [0][0][0][0][RTW89_IC][10] = 74, [0][0][0][0][RTW89_ACMA][10] = 60, - [0][0][0][0][RTW89_FCC][11] = 72, + [0][0][0][0][RTW89_FCC][11] = 62, [0][0][0][0][RTW89_ETSI][11] = 60, - [0][0][0][0][RTW89_MKK][11] = 72, + [0][0][0][0][RTW89_MKK][11] = 68, [0][0][0][0][RTW89_IC][11] = 72, [0][0][0][0][RTW89_ACMA][11] = 60, - [0][0][0][0][RTW89_FCC][12] = 58, + [0][0][0][0][RTW89_FCC][12] = 48, [0][0][0][0][RTW89_ETSI][12] = 60, - [0][0][0][0][RTW89_MKK][12] = 72, + [0][0][0][0][RTW89_MKK][12] = 68, [0][0][0][0][RTW89_IC][12] = 58, [0][0][0][0][RTW89_ACMA][12] = 60, [0][0][0][0][RTW89_FCC][13] = 127, [0][0][0][0][RTW89_ETSI][13] = 127, - [0][0][0][0][RTW89_MKK][13] = 74, + [0][0][0][0][RTW89_MKK][13] = 72, [0][0][0][0][RTW89_IC][13] = 127, [0][0][0][0][RTW89_ACMA][13] = 127, - [0][1][0][0][RTW89_FCC][0] = 76, + [0][1][0][0][RTW89_FCC][0] = 66, [0][1][0][0][RTW89_ETSI][0] = 48, - [0][1][0][0][RTW89_MKK][0] = 60, - [0][1][0][0][RTW89_IC][0] = 76, + [0][1][0][0][RTW89_MKK][0] = 58, + [0][1][0][0][RTW89_IC][0] = 74, [0][1][0][0][RTW89_ACMA][0] = 48, - [0][1][0][0][RTW89_FCC][1] = 76, + [0][1][0][0][RTW89_FCC][1] = 66, [0][1][0][0][RTW89_ETSI][1] = 48, - [0][1][0][0][RTW89_MKK][1] = 60, - [0][1][0][0][RTW89_IC][1] = 76, + [0][1][0][0][RTW89_MKK][1] = 58, + [0][1][0][0][RTW89_IC][1] = 74, [0][1][0][0][RTW89_ACMA][1] = 48, - [0][1][0][0][RTW89_FCC][2] = 76, + [0][1][0][0][RTW89_FCC][2] = 66, [0][1][0][0][RTW89_ETSI][2] = 48, - [0][1][0][0][RTW89_MKK][2] = 60, - [0][1][0][0][RTW89_IC][2] = 76, + [0][1][0][0][RTW89_MKK][2] = 58, + [0][1][0][0][RTW89_IC][2] = 74, [0][1][0][0][RTW89_ACMA][2] = 48, - [0][1][0][0][RTW89_FCC][3] = 76, + [0][1][0][0][RTW89_FCC][3] = 66, [0][1][0][0][RTW89_ETSI][3] = 48, - [0][1][0][0][RTW89_MKK][3] = 60, - [0][1][0][0][RTW89_IC][3] = 76, + [0][1][0][0][RTW89_MKK][3] = 58, + [0][1][0][0][RTW89_IC][3] = 74, [0][1][0][0][RTW89_ACMA][3] = 48, - [0][1][0][0][RTW89_FCC][4] = 76, + [0][1][0][0][RTW89_FCC][4] = 66, [0][1][0][0][RTW89_ETSI][4] = 48, - [0][1][0][0][RTW89_MKK][4] = 60, - [0][1][0][0][RTW89_IC][4] = 76, + [0][1][0][0][RTW89_MKK][4] = 58, + [0][1][0][0][RTW89_IC][4] = 74, [0][1][0][0][RTW89_ACMA][4] = 48, - [0][1][0][0][RTW89_FCC][5] = 76, + [0][1][0][0][RTW89_FCC][5] = 66, [0][1][0][0][RTW89_ETSI][5] = 48, - [0][1][0][0][RTW89_MKK][5] = 60, - [0][1][0][0][RTW89_IC][5] = 76, + [0][1][0][0][RTW89_MKK][5] = 58, + [0][1][0][0][RTW89_IC][5] = 74, [0][1][0][0][RTW89_ACMA][5] = 48, - [0][1][0][0][RTW89_FCC][6] = 76, + [0][1][0][0][RTW89_FCC][6] = 66, [0][1][0][0][RTW89_ETSI][6] = 48, - [0][1][0][0][RTW89_MKK][6] = 60, - [0][1][0][0][RTW89_IC][6] = 76, + [0][1][0][0][RTW89_MKK][6] = 58, + [0][1][0][0][RTW89_IC][6] = 74, [0][1][0][0][RTW89_ACMA][6] = 48, - [0][1][0][0][RTW89_FCC][7] = 76, + [0][1][0][0][RTW89_FCC][7] = 66, [0][1][0][0][RTW89_ETSI][7] = 48, - [0][1][0][0][RTW89_MKK][7] = 60, - [0][1][0][0][RTW89_IC][7] = 76, + [0][1][0][0][RTW89_MKK][7] = 58, + [0][1][0][0][RTW89_IC][7] = 74, [0][1][0][0][RTW89_ACMA][7] = 48, - [0][1][0][0][RTW89_FCC][8] = 76, + [0][1][0][0][RTW89_FCC][8] = 66, [0][1][0][0][RTW89_ETSI][8] = 48, - [0][1][0][0][RTW89_MKK][8] = 60, - [0][1][0][0][RTW89_IC][8] = 76, + [0][1][0][0][RTW89_MKK][8] = 58, + [0][1][0][0][RTW89_IC][8] = 74, [0][1][0][0][RTW89_ACMA][8] = 48, - [0][1][0][0][RTW89_FCC][9] = 76, + [0][1][0][0][RTW89_FCC][9] = 66, [0][1][0][0][RTW89_ETSI][9] = 48, - [0][1][0][0][RTW89_MKK][9] = 60, - [0][1][0][0][RTW89_IC][9] = 76, + [0][1][0][0][RTW89_MKK][9] = 58, + [0][1][0][0][RTW89_IC][9] = 74, [0][1][0][0][RTW89_ACMA][9] = 48, - [0][1][0][0][RTW89_FCC][10] = 76, + [0][1][0][0][RTW89_FCC][10] = 66, [0][1][0][0][RTW89_ETSI][10] = 48, - [0][1][0][0][RTW89_MKK][10] = 60, - [0][1][0][0][RTW89_IC][10] = 76, + [0][1][0][0][RTW89_MKK][10] = 58, + [0][1][0][0][RTW89_IC][10] = 74, [0][1][0][0][RTW89_ACMA][10] = 48, - [0][1][0][0][RTW89_FCC][11] = 56, + [0][1][0][0][RTW89_FCC][11] = 46, [0][1][0][0][RTW89_ETSI][11] = 48, - [0][1][0][0][RTW89_MKK][11] = 60, + [0][1][0][0][RTW89_MKK][11] = 58, [0][1][0][0][RTW89_IC][11] = 56, [0][1][0][0][RTW89_ACMA][11] = 48, - [0][1][0][0][RTW89_FCC][12] = 44, + [0][1][0][0][RTW89_FCC][12] = 34, [0][1][0][0][RTW89_ETSI][12] = 48, - [0][1][0][0][RTW89_MKK][12] = 60, + [0][1][0][0][RTW89_MKK][12] = 58, [0][1][0][0][RTW89_IC][12] = 44, [0][1][0][0][RTW89_ACMA][12] = 48, [0][1][0][0][RTW89_FCC][13] = 127, [0][1][0][0][RTW89_ETSI][13] = 127, - [0][1][0][0][RTW89_MKK][13] = 62, + [0][1][0][0][RTW89_MKK][13] = 60, [0][1][0][0][RTW89_IC][13] = 127, [0][1][0][0][RTW89_ACMA][13] = 127, [1][0][0][0][RTW89_FCC][0] = 127, @@ -14163,49 +14163,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_MKK][1] = 127, [1][0][0][0][RTW89_IC][1] = 127, [1][0][0][0][RTW89_ACMA][1] = 127, - [1][0][0][0][RTW89_FCC][2] = 52, + [1][0][0][0][RTW89_FCC][2] = 42, [1][0][0][0][RTW89_ETSI][2] = 60, - [1][0][0][0][RTW89_MKK][2] = 72, + [1][0][0][0][RTW89_MKK][2] = 66, [1][0][0][0][RTW89_IC][2] = 52, [1][0][0][0][RTW89_ACMA][2] = 60, - [1][0][0][0][RTW89_FCC][3] = 52, + [1][0][0][0][RTW89_FCC][3] = 42, [1][0][0][0][RTW89_ETSI][3] = 60, - [1][0][0][0][RTW89_MKK][3] = 72, + [1][0][0][0][RTW89_MKK][3] = 66, [1][0][0][0][RTW89_IC][3] = 52, [1][0][0][0][RTW89_ACMA][3] = 60, - [1][0][0][0][RTW89_FCC][4] = 52, + [1][0][0][0][RTW89_FCC][4] = 42, [1][0][0][0][RTW89_ETSI][4] = 60, - [1][0][0][0][RTW89_MKK][4] = 72, + [1][0][0][0][RTW89_MKK][4] = 66, [1][0][0][0][RTW89_IC][4] = 52, [1][0][0][0][RTW89_ACMA][4] = 60, - [1][0][0][0][RTW89_FCC][5] = 68, + [1][0][0][0][RTW89_FCC][5] = 58, [1][0][0][0][RTW89_ETSI][5] = 60, - [1][0][0][0][RTW89_MKK][5] = 72, + [1][0][0][0][RTW89_MKK][5] = 66, [1][0][0][0][RTW89_IC][5] = 68, [1][0][0][0][RTW89_ACMA][5] = 60, - [1][0][0][0][RTW89_FCC][6] = 52, + [1][0][0][0][RTW89_FCC][6] = 42, [1][0][0][0][RTW89_ETSI][6] = 60, - [1][0][0][0][RTW89_MKK][6] = 72, + [1][0][0][0][RTW89_MKK][6] = 66, [1][0][0][0][RTW89_IC][6] = 52, [1][0][0][0][RTW89_ACMA][6] = 60, - [1][0][0][0][RTW89_FCC][7] = 52, + [1][0][0][0][RTW89_FCC][7] = 42, [1][0][0][0][RTW89_ETSI][7] = 60, - [1][0][0][0][RTW89_MKK][7] = 72, + [1][0][0][0][RTW89_MKK][7] = 66, [1][0][0][0][RTW89_IC][7] = 52, [1][0][0][0][RTW89_ACMA][7] = 60, - [1][0][0][0][RTW89_FCC][8] = 52, + [1][0][0][0][RTW89_FCC][8] = 42, [1][0][0][0][RTW89_ETSI][8] = 60, - [1][0][0][0][RTW89_MKK][8] = 72, + [1][0][0][0][RTW89_MKK][8] = 66, [1][0][0][0][RTW89_IC][8] = 52, [1][0][0][0][RTW89_ACMA][8] = 60, - [1][0][0][0][RTW89_FCC][9] = 44, + [1][0][0][0][RTW89_FCC][9] = 34, [1][0][0][0][RTW89_ETSI][9] = 60, - [1][0][0][0][RTW89_MKK][9] = 72, + [1][0][0][0][RTW89_MKK][9] = 66, [1][0][0][0][RTW89_IC][9] = 44, [1][0][0][0][RTW89_ACMA][9] = 60, - [1][0][0][0][RTW89_FCC][10] = 32, + [1][0][0][0][RTW89_FCC][10] = 22, [1][0][0][0][RTW89_ETSI][10] = 60, - [1][0][0][0][RTW89_MKK][10] = 70, + [1][0][0][0][RTW89_MKK][10] = 66, [1][0][0][0][RTW89_IC][10] = 32, [1][0][0][0][RTW89_ACMA][10] = 60, [1][0][0][0][RTW89_FCC][11] = 127, @@ -14233,49 +14233,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_MKK][1] = 127, [1][1][0][0][RTW89_IC][1] = 127, [1][1][0][0][RTW89_ACMA][1] = 127, - [1][1][0][0][RTW89_FCC][2] = 48, + [1][1][0][0][RTW89_FCC][2] = 38, [1][1][0][0][RTW89_ETSI][2] = 48, - [1][1][0][0][RTW89_MKK][2] = 60, + [1][1][0][0][RTW89_MKK][2] = 58, [1][1][0][0][RTW89_IC][2] = 48, [1][1][0][0][RTW89_ACMA][2] = 48, - [1][1][0][0][RTW89_FCC][3] = 48, + [1][1][0][0][RTW89_FCC][3] = 38, [1][1][0][0][RTW89_ETSI][3] = 48, - [1][1][0][0][RTW89_MKK][3] = 60, + [1][1][0][0][RTW89_MKK][3] = 58, [1][1][0][0][RTW89_IC][3] = 48, [1][1][0][0][RTW89_ACMA][3] = 48, - [1][1][0][0][RTW89_FCC][4] = 48, + [1][1][0][0][RTW89_FCC][4] = 38, [1][1][0][0][RTW89_ETSI][4] = 48, - [1][1][0][0][RTW89_MKK][4] = 60, + [1][1][0][0][RTW89_MKK][4] = 58, [1][1][0][0][RTW89_IC][4] = 48, [1][1][0][0][RTW89_ACMA][4] = 48, - [1][1][0][0][RTW89_FCC][5] = 64, + [1][1][0][0][RTW89_FCC][5] = 54, [1][1][0][0][RTW89_ETSI][5] = 48, - [1][1][0][0][RTW89_MKK][5] = 60, + [1][1][0][0][RTW89_MKK][5] = 58, [1][1][0][0][RTW89_IC][5] = 64, [1][1][0][0][RTW89_ACMA][5] = 48, - [1][1][0][0][RTW89_FCC][6] = 36, + [1][1][0][0][RTW89_FCC][6] = 26, [1][1][0][0][RTW89_ETSI][6] = 48, - [1][1][0][0][RTW89_MKK][6] = 60, + [1][1][0][0][RTW89_MKK][6] = 58, [1][1][0][0][RTW89_IC][6] = 36, [1][1][0][0][RTW89_ACMA][6] = 48, - [1][1][0][0][RTW89_FCC][7] = 36, + [1][1][0][0][RTW89_FCC][7] = 26, [1][1][0][0][RTW89_ETSI][7] = 48, - [1][1][0][0][RTW89_MKK][7] = 60, + [1][1][0][0][RTW89_MKK][7] = 58, [1][1][0][0][RTW89_IC][7] = 36, [1][1][0][0][RTW89_ACMA][7] = 48, - [1][1][0][0][RTW89_FCC][8] = 36, + [1][1][0][0][RTW89_FCC][8] = 26, [1][1][0][0][RTW89_ETSI][8] = 48, - [1][1][0][0][RTW89_MKK][8] = 60, + [1][1][0][0][RTW89_MKK][8] = 58, [1][1][0][0][RTW89_IC][8] = 36, [1][1][0][0][RTW89_ACMA][8] = 48, - [1][1][0][0][RTW89_FCC][9] = 32, + [1][1][0][0][RTW89_FCC][9] = 22, [1][1][0][0][RTW89_ETSI][9] = 48, - [1][1][0][0][RTW89_MKK][9] = 60, + [1][1][0][0][RTW89_MKK][9] = 58, [1][1][0][0][RTW89_IC][9] = 32, [1][1][0][0][RTW89_ACMA][9] = 48, - [1][1][0][0][RTW89_FCC][10] = 32, + [1][1][0][0][RTW89_FCC][10] = 22, [1][1][0][0][RTW89_ETSI][10] = 48, - [1][1][0][0][RTW89_MKK][10] = 58, + [1][1][0][0][RTW89_MKK][10] = 56, [1][1][0][0][RTW89_IC][10] = 32, [1][1][0][0][RTW89_ACMA][10] = 48, [1][1][0][0][RTW89_FCC][11] = 127, @@ -14293,69 +14293,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_MKK][13] = 127, [1][1][0][0][RTW89_IC][13] = 127, [1][1][0][0][RTW89_ACMA][13] = 127, - [0][0][1][0][RTW89_FCC][0] = 78, + [0][0][1][0][RTW89_FCC][0] = 68, [0][0][1][0][RTW89_ETSI][0] = 60, [0][0][1][0][RTW89_MKK][0] = 76, [0][0][1][0][RTW89_IC][0] = 78, [0][0][1][0][RTW89_ACMA][0] = 60, - [0][0][1][0][RTW89_FCC][1] = 78, + [0][0][1][0][RTW89_FCC][1] = 68, [0][0][1][0][RTW89_ETSI][1] = 60, - [0][0][1][0][RTW89_MKK][1] = 76, + [0][0][1][0][RTW89_MKK][1] = 78, [0][0][1][0][RTW89_IC][1] = 78, [0][0][1][0][RTW89_ACMA][1] = 60, - [0][0][1][0][RTW89_FCC][2] = 80, + [0][0][1][0][RTW89_FCC][2] = 70, [0][0][1][0][RTW89_ETSI][2] = 60, - [0][0][1][0][RTW89_MKK][2] = 76, - [0][0][1][0][RTW89_IC][2] = 80, + [0][0][1][0][RTW89_MKK][2] = 78, + [0][0][1][0][RTW89_IC][2] = 78, [0][0][1][0][RTW89_ACMA][2] = 60, - [0][0][1][0][RTW89_FCC][3] = 80, + [0][0][1][0][RTW89_FCC][3] = 70, [0][0][1][0][RTW89_ETSI][3] = 60, - [0][0][1][0][RTW89_MKK][3] = 76, - [0][0][1][0][RTW89_IC][3] = 80, + [0][0][1][0][RTW89_MKK][3] = 78, + [0][0][1][0][RTW89_IC][3] = 78, [0][0][1][0][RTW89_ACMA][3] = 60, - [0][0][1][0][RTW89_FCC][4] = 80, + [0][0][1][0][RTW89_FCC][4] = 70, [0][0][1][0][RTW89_ETSI][4] = 60, - [0][0][1][0][RTW89_MKK][4] = 76, - [0][0][1][0][RTW89_IC][4] = 80, + [0][0][1][0][RTW89_MKK][4] = 78, + [0][0][1][0][RTW89_IC][4] = 78, [0][0][1][0][RTW89_ACMA][4] = 60, - [0][0][1][0][RTW89_FCC][5] = 80, + [0][0][1][0][RTW89_FCC][5] = 70, [0][0][1][0][RTW89_ETSI][5] = 60, - [0][0][1][0][RTW89_MKK][5] = 76, - [0][0][1][0][RTW89_IC][5] = 80, + [0][0][1][0][RTW89_MKK][5] = 78, + [0][0][1][0][RTW89_IC][5] = 78, [0][0][1][0][RTW89_ACMA][5] = 60, - [0][0][1][0][RTW89_FCC][6] = 80, + [0][0][1][0][RTW89_FCC][6] = 70, [0][0][1][0][RTW89_ETSI][6] = 60, [0][0][1][0][RTW89_MKK][6] = 76, - [0][0][1][0][RTW89_IC][6] = 80, + [0][0][1][0][RTW89_IC][6] = 78, [0][0][1][0][RTW89_ACMA][6] = 60, - [0][0][1][0][RTW89_FCC][7] = 80, + [0][0][1][0][RTW89_FCC][7] = 70, [0][0][1][0][RTW89_ETSI][7] = 60, - [0][0][1][0][RTW89_MKK][7] = 76, - [0][0][1][0][RTW89_IC][7] = 80, + [0][0][1][0][RTW89_MKK][7] = 78, + [0][0][1][0][RTW89_IC][7] = 78, [0][0][1][0][RTW89_ACMA][7] = 60, - [0][0][1][0][RTW89_FCC][8] = 80, + [0][0][1][0][RTW89_FCC][8] = 70, [0][0][1][0][RTW89_ETSI][8] = 60, - [0][0][1][0][RTW89_MKK][8] = 76, - [0][0][1][0][RTW89_IC][8] = 80, + [0][0][1][0][RTW89_MKK][8] = 78, + [0][0][1][0][RTW89_IC][8] = 78, [0][0][1][0][RTW89_ACMA][8] = 60, - [0][0][1][0][RTW89_FCC][9] = 76, + [0][0][1][0][RTW89_FCC][9] = 66, [0][0][1][0][RTW89_ETSI][9] = 60, - [0][0][1][0][RTW89_MKK][9] = 76, + [0][0][1][0][RTW89_MKK][9] = 78, [0][0][1][0][RTW89_IC][9] = 76, [0][0][1][0][RTW89_ACMA][9] = 60, - [0][0][1][0][RTW89_FCC][10] = 76, + [0][0][1][0][RTW89_FCC][10] = 66, [0][0][1][0][RTW89_ETSI][10] = 60, - [0][0][1][0][RTW89_MKK][10] = 76, + [0][0][1][0][RTW89_MKK][10] = 78, [0][0][1][0][RTW89_IC][10] = 76, [0][0][1][0][RTW89_ACMA][10] = 60, - [0][0][1][0][RTW89_FCC][11] = 56, + [0][0][1][0][RTW89_FCC][11] = 46, [0][0][1][0][RTW89_ETSI][11] = 60, - [0][0][1][0][RTW89_MKK][11] = 76, + [0][0][1][0][RTW89_MKK][11] = 78, [0][0][1][0][RTW89_IC][11] = 56, [0][0][1][0][RTW89_ACMA][11] = 60, - [0][0][1][0][RTW89_FCC][12] = 52, + [0][0][1][0][RTW89_FCC][12] = 42, [0][0][1][0][RTW89_ETSI][12] = 60, - [0][0][1][0][RTW89_MKK][12] = 76, + [0][0][1][0][RTW89_MKK][12] = 78, [0][0][1][0][RTW89_IC][12] = 52, [0][0][1][0][RTW89_ACMA][12] = 60, [0][0][1][0][RTW89_FCC][13] = 127, @@ -14363,69 +14363,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_MKK][13] = 127, [0][0][1][0][RTW89_IC][13] = 127, [0][0][1][0][RTW89_ACMA][13] = 127, - [0][1][1][0][RTW89_FCC][0] = 64, + [0][1][1][0][RTW89_FCC][0] = 54, [0][1][1][0][RTW89_ETSI][0] = 48, - [0][1][1][0][RTW89_MKK][0] = 68, + [0][1][1][0][RTW89_MKK][0] = 66, [0][1][1][0][RTW89_IC][0] = 64, [0][1][1][0][RTW89_ACMA][0] = 48, - [0][1][1][0][RTW89_FCC][1] = 64, + [0][1][1][0][RTW89_FCC][1] = 54, [0][1][1][0][RTW89_ETSI][1] = 48, - [0][1][1][0][RTW89_MKK][1] = 68, + [0][1][1][0][RTW89_MKK][1] = 66, [0][1][1][0][RTW89_IC][1] = 64, [0][1][1][0][RTW89_ACMA][1] = 48, - [0][1][1][0][RTW89_FCC][2] = 68, + [0][1][1][0][RTW89_FCC][2] = 58, [0][1][1][0][RTW89_ETSI][2] = 48, - [0][1][1][0][RTW89_MKK][2] = 68, + [0][1][1][0][RTW89_MKK][2] = 66, [0][1][1][0][RTW89_IC][2] = 68, [0][1][1][0][RTW89_ACMA][2] = 48, - [0][1][1][0][RTW89_FCC][3] = 72, + [0][1][1][0][RTW89_FCC][3] = 62, [0][1][1][0][RTW89_ETSI][3] = 48, - [0][1][1][0][RTW89_MKK][3] = 68, + [0][1][1][0][RTW89_MKK][3] = 66, [0][1][1][0][RTW89_IC][3] = 72, [0][1][1][0][RTW89_ACMA][3] = 48, - [0][1][1][0][RTW89_FCC][4] = 80, + [0][1][1][0][RTW89_FCC][4] = 70, [0][1][1][0][RTW89_ETSI][4] = 48, - [0][1][1][0][RTW89_MKK][4] = 68, - [0][1][1][0][RTW89_IC][4] = 80, + [0][1][1][0][RTW89_MKK][4] = 66, + [0][1][1][0][RTW89_IC][4] = 78, [0][1][1][0][RTW89_ACMA][4] = 48, - [0][1][1][0][RTW89_FCC][5] = 80, + [0][1][1][0][RTW89_FCC][5] = 70, [0][1][1][0][RTW89_ETSI][5] = 48, - [0][1][1][0][RTW89_MKK][5] = 68, - [0][1][1][0][RTW89_IC][5] = 80, + [0][1][1][0][RTW89_MKK][5] = 66, + [0][1][1][0][RTW89_IC][5] = 78, [0][1][1][0][RTW89_ACMA][5] = 48, - [0][1][1][0][RTW89_FCC][6] = 80, + [0][1][1][0][RTW89_FCC][6] = 70, [0][1][1][0][RTW89_ETSI][6] = 48, - [0][1][1][0][RTW89_MKK][6] = 68, - [0][1][1][0][RTW89_IC][6] = 80, + [0][1][1][0][RTW89_MKK][6] = 66, + [0][1][1][0][RTW89_IC][6] = 78, [0][1][1][0][RTW89_ACMA][6] = 48, - [0][1][1][0][RTW89_FCC][7] = 72, + [0][1][1][0][RTW89_FCC][7] = 62, [0][1][1][0][RTW89_ETSI][7] = 48, - [0][1][1][0][RTW89_MKK][7] = 68, + [0][1][1][0][RTW89_MKK][7] = 66, [0][1][1][0][RTW89_IC][7] = 72, [0][1][1][0][RTW89_ACMA][7] = 48, - [0][1][1][0][RTW89_FCC][8] = 68, + [0][1][1][0][RTW89_FCC][8] = 58, [0][1][1][0][RTW89_ETSI][8] = 48, - [0][1][1][0][RTW89_MKK][8] = 68, + [0][1][1][0][RTW89_MKK][8] = 66, [0][1][1][0][RTW89_IC][8] = 68, [0][1][1][0][RTW89_ACMA][8] = 48, - [0][1][1][0][RTW89_FCC][9] = 64, + [0][1][1][0][RTW89_FCC][9] = 54, [0][1][1][0][RTW89_ETSI][9] = 48, - [0][1][1][0][RTW89_MKK][9] = 68, + [0][1][1][0][RTW89_MKK][9] = 66, [0][1][1][0][RTW89_IC][9] = 64, [0][1][1][0][RTW89_ACMA][9] = 48, - [0][1][1][0][RTW89_FCC][10] = 64, + [0][1][1][0][RTW89_FCC][10] = 54, [0][1][1][0][RTW89_ETSI][10] = 48, - [0][1][1][0][RTW89_MKK][10] = 68, + [0][1][1][0][RTW89_MKK][10] = 66, [0][1][1][0][RTW89_IC][10] = 64, [0][1][1][0][RTW89_ACMA][10] = 48, - [0][1][1][0][RTW89_FCC][11] = 48, + [0][1][1][0][RTW89_FCC][11] = 38, [0][1][1][0][RTW89_ETSI][11] = 48, - [0][1][1][0][RTW89_MKK][11] = 68, + [0][1][1][0][RTW89_MKK][11] = 66, [0][1][1][0][RTW89_IC][11] = 48, [0][1][1][0][RTW89_ACMA][11] = 48, - [0][1][1][0][RTW89_FCC][12] = 44, + [0][1][1][0][RTW89_FCC][12] = 34, [0][1][1][0][RTW89_ETSI][12] = 48, - [0][1][1][0][RTW89_MKK][12] = 68, + [0][1][1][0][RTW89_MKK][12] = 66, [0][1][1][0][RTW89_IC][12] = 44, [0][1][1][0][RTW89_ACMA][12] = 48, [0][1][1][0][RTW89_FCC][13] = 127, @@ -14433,69 +14433,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_MKK][13] = 127, [0][1][1][0][RTW89_IC][13] = 127, [0][1][1][0][RTW89_ACMA][13] = 127, - [0][0][2][0][RTW89_FCC][0] = 78, + [0][0][2][0][RTW89_FCC][0] = 68, [0][0][2][0][RTW89_ETSI][0] = 60, - [0][0][2][0][RTW89_MKK][0] = 76, + [0][0][2][0][RTW89_MKK][0] = 78, [0][0][2][0][RTW89_IC][0] = 78, [0][0][2][0][RTW89_ACMA][0] = 60, - [0][0][2][0][RTW89_FCC][1] = 78, + [0][0][2][0][RTW89_FCC][1] = 68, [0][0][2][0][RTW89_ETSI][1] = 60, - [0][0][2][0][RTW89_MKK][1] = 76, + [0][0][2][0][RTW89_MKK][1] = 78, [0][0][2][0][RTW89_IC][1] = 78, [0][0][2][0][RTW89_ACMA][1] = 60, - [0][0][2][0][RTW89_FCC][2] = 80, + [0][0][2][0][RTW89_FCC][2] = 70, [0][0][2][0][RTW89_ETSI][2] = 60, - [0][0][2][0][RTW89_MKK][2] = 76, - [0][0][2][0][RTW89_IC][2] = 80, + [0][0][2][0][RTW89_MKK][2] = 78, + [0][0][2][0][RTW89_IC][2] = 78, [0][0][2][0][RTW89_ACMA][2] = 60, - [0][0][2][0][RTW89_FCC][3] = 80, + [0][0][2][0][RTW89_FCC][3] = 70, [0][0][2][0][RTW89_ETSI][3] = 60, - [0][0][2][0][RTW89_MKK][3] = 76, - [0][0][2][0][RTW89_IC][3] = 80, + [0][0][2][0][RTW89_MKK][3] = 78, + [0][0][2][0][RTW89_IC][3] = 78, [0][0][2][0][RTW89_ACMA][3] = 60, - [0][0][2][0][RTW89_FCC][4] = 80, + [0][0][2][0][RTW89_FCC][4] = 70, [0][0][2][0][RTW89_ETSI][4] = 60, - [0][0][2][0][RTW89_MKK][4] = 76, - [0][0][2][0][RTW89_IC][4] = 80, + [0][0][2][0][RTW89_MKK][4] = 78, + [0][0][2][0][RTW89_IC][4] = 78, [0][0][2][0][RTW89_ACMA][4] = 60, - [0][0][2][0][RTW89_FCC][5] = 80, + [0][0][2][0][RTW89_FCC][5] = 70, [0][0][2][0][RTW89_ETSI][5] = 60, - [0][0][2][0][RTW89_MKK][5] = 76, - [0][0][2][0][RTW89_IC][5] = 80, + [0][0][2][0][RTW89_MKK][5] = 78, + [0][0][2][0][RTW89_IC][5] = 78, [0][0][2][0][RTW89_ACMA][5] = 60, - [0][0][2][0][RTW89_FCC][6] = 80, + [0][0][2][0][RTW89_FCC][6] = 70, [0][0][2][0][RTW89_ETSI][6] = 60, - [0][0][2][0][RTW89_MKK][6] = 76, - [0][0][2][0][RTW89_IC][6] = 80, + [0][0][2][0][RTW89_MKK][6] = 78, + [0][0][2][0][RTW89_IC][6] = 78, [0][0][2][0][RTW89_ACMA][6] = 60, - [0][0][2][0][RTW89_FCC][7] = 80, + [0][0][2][0][RTW89_FCC][7] = 70, [0][0][2][0][RTW89_ETSI][7] = 60, - [0][0][2][0][RTW89_MKK][7] = 76, - [0][0][2][0][RTW89_IC][7] = 80, + [0][0][2][0][RTW89_MKK][7] = 78, + [0][0][2][0][RTW89_IC][7] = 78, [0][0][2][0][RTW89_ACMA][7] = 60, - [0][0][2][0][RTW89_FCC][8] = 78, + [0][0][2][0][RTW89_FCC][8] = 68, [0][0][2][0][RTW89_ETSI][8] = 60, - [0][0][2][0][RTW89_MKK][8] = 76, + [0][0][2][0][RTW89_MKK][8] = 78, [0][0][2][0][RTW89_IC][8] = 78, [0][0][2][0][RTW89_ACMA][8] = 60, - [0][0][2][0][RTW89_FCC][9] = 74, + [0][0][2][0][RTW89_FCC][9] = 64, [0][0][2][0][RTW89_ETSI][9] = 60, - [0][0][2][0][RTW89_MKK][9] = 76, + [0][0][2][0][RTW89_MKK][9] = 78, [0][0][2][0][RTW89_IC][9] = 74, [0][0][2][0][RTW89_ACMA][9] = 60, - [0][0][2][0][RTW89_FCC][10] = 74, + [0][0][2][0][RTW89_FCC][10] = 64, [0][0][2][0][RTW89_ETSI][10] = 60, - [0][0][2][0][RTW89_MKK][10] = 76, + [0][0][2][0][RTW89_MKK][10] = 78, [0][0][2][0][RTW89_IC][10] = 74, [0][0][2][0][RTW89_ACMA][10] = 60, - [0][0][2][0][RTW89_FCC][11] = 56, + [0][0][2][0][RTW89_FCC][11] = 46, [0][0][2][0][RTW89_ETSI][11] = 60, - [0][0][2][0][RTW89_MKK][11] = 76, + [0][0][2][0][RTW89_MKK][11] = 78, [0][0][2][0][RTW89_IC][11] = 56, [0][0][2][0][RTW89_ACMA][11] = 60, - [0][0][2][0][RTW89_FCC][12] = 52, + [0][0][2][0][RTW89_FCC][12] = 42, [0][0][2][0][RTW89_ETSI][12] = 60, - [0][0][2][0][RTW89_MKK][12] = 76, + [0][0][2][0][RTW89_MKK][12] = 78, [0][0][2][0][RTW89_IC][12] = 52, [0][0][2][0][RTW89_ACMA][12] = 60, [0][0][2][0][RTW89_FCC][13] = 127, @@ -14503,69 +14503,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_MKK][13] = 127, [0][0][2][0][RTW89_IC][13] = 127, [0][0][2][0][RTW89_ACMA][13] = 127, - [0][1][2][0][RTW89_FCC][0] = 60, + [0][1][2][0][RTW89_FCC][0] = 50, [0][1][2][0][RTW89_ETSI][0] = 48, - [0][1][2][0][RTW89_MKK][0] = 70, + [0][1][2][0][RTW89_MKK][0] = 68, [0][1][2][0][RTW89_IC][0] = 60, [0][1][2][0][RTW89_ACMA][0] = 48, - [0][1][2][0][RTW89_FCC][1] = 60, + [0][1][2][0][RTW89_FCC][1] = 50, [0][1][2][0][RTW89_ETSI][1] = 48, - [0][1][2][0][RTW89_MKK][1] = 70, + [0][1][2][0][RTW89_MKK][1] = 68, [0][1][2][0][RTW89_IC][1] = 60, [0][1][2][0][RTW89_ACMA][1] = 48, - [0][1][2][0][RTW89_FCC][2] = 64, + [0][1][2][0][RTW89_FCC][2] = 54, [0][1][2][0][RTW89_ETSI][2] = 48, - [0][1][2][0][RTW89_MKK][2] = 70, + [0][1][2][0][RTW89_MKK][2] = 68, [0][1][2][0][RTW89_IC][2] = 64, [0][1][2][0][RTW89_ACMA][2] = 48, - [0][1][2][0][RTW89_FCC][3] = 68, + [0][1][2][0][RTW89_FCC][3] = 58, [0][1][2][0][RTW89_ETSI][3] = 48, - [0][1][2][0][RTW89_MKK][3] = 70, + [0][1][2][0][RTW89_MKK][3] = 68, [0][1][2][0][RTW89_IC][3] = 68, [0][1][2][0][RTW89_ACMA][3] = 48, - [0][1][2][0][RTW89_FCC][4] = 74, + [0][1][2][0][RTW89_FCC][4] = 64, [0][1][2][0][RTW89_ETSI][4] = 48, - [0][1][2][0][RTW89_MKK][4] = 70, + [0][1][2][0][RTW89_MKK][4] = 68, [0][1][2][0][RTW89_IC][4] = 74, [0][1][2][0][RTW89_ACMA][4] = 48, - [0][1][2][0][RTW89_FCC][5] = 80, + [0][1][2][0][RTW89_FCC][5] = 70, [0][1][2][0][RTW89_ETSI][5] = 48, - [0][1][2][0][RTW89_MKK][5] = 70, - [0][1][2][0][RTW89_IC][5] = 80, + [0][1][2][0][RTW89_MKK][5] = 68, + [0][1][2][0][RTW89_IC][5] = 78, [0][1][2][0][RTW89_ACMA][5] = 48, - [0][1][2][0][RTW89_FCC][6] = 76, + [0][1][2][0][RTW89_FCC][6] = 66, [0][1][2][0][RTW89_ETSI][6] = 48, - [0][1][2][0][RTW89_MKK][6] = 70, + [0][1][2][0][RTW89_MKK][6] = 68, [0][1][2][0][RTW89_IC][6] = 76, [0][1][2][0][RTW89_ACMA][6] = 48, - [0][1][2][0][RTW89_FCC][7] = 68, + [0][1][2][0][RTW89_FCC][7] = 58, [0][1][2][0][RTW89_ETSI][7] = 48, - [0][1][2][0][RTW89_MKK][7] = 70, + [0][1][2][0][RTW89_MKK][7] = 68, [0][1][2][0][RTW89_IC][7] = 68, [0][1][2][0][RTW89_ACMA][7] = 48, - [0][1][2][0][RTW89_FCC][8] = 64, + [0][1][2][0][RTW89_FCC][8] = 54, [0][1][2][0][RTW89_ETSI][8] = 48, - [0][1][2][0][RTW89_MKK][8] = 70, + [0][1][2][0][RTW89_MKK][8] = 68, [0][1][2][0][RTW89_IC][8] = 64, [0][1][2][0][RTW89_ACMA][8] = 48, - [0][1][2][0][RTW89_FCC][9] = 60, + [0][1][2][0][RTW89_FCC][9] = 50, [0][1][2][0][RTW89_ETSI][9] = 48, - [0][1][2][0][RTW89_MKK][9] = 70, + [0][1][2][0][RTW89_MKK][9] = 68, [0][1][2][0][RTW89_IC][9] = 60, [0][1][2][0][RTW89_ACMA][9] = 48, - [0][1][2][0][RTW89_FCC][10] = 60, + [0][1][2][0][RTW89_FCC][10] = 50, [0][1][2][0][RTW89_ETSI][10] = 48, - [0][1][2][0][RTW89_MKK][10] = 70, + [0][1][2][0][RTW89_MKK][10] = 68, [0][1][2][0][RTW89_IC][10] = 60, [0][1][2][0][RTW89_ACMA][10] = 48, - [0][1][2][0][RTW89_FCC][11] = 48, + [0][1][2][0][RTW89_FCC][11] = 38, [0][1][2][0][RTW89_ETSI][11] = 48, - [0][1][2][0][RTW89_MKK][11] = 70, + [0][1][2][0][RTW89_MKK][11] = 68, [0][1][2][0][RTW89_IC][11] = 48, [0][1][2][0][RTW89_ACMA][11] = 48, - [0][1][2][0][RTW89_FCC][12] = 44, + [0][1][2][0][RTW89_FCC][12] = 34, [0][1][2][0][RTW89_ETSI][12] = 48, - [0][1][2][0][RTW89_MKK][12] = 70, + [0][1][2][0][RTW89_MKK][12] = 68, [0][1][2][0][RTW89_IC][12] = 44, [0][1][2][0][RTW89_ACMA][12] = 48, [0][1][2][0][RTW89_FCC][13] = 127, @@ -14573,69 +14573,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_MKK][13] = 127, [0][1][2][0][RTW89_IC][13] = 127, [0][1][2][0][RTW89_ACMA][13] = 127, - [0][1][2][1][RTW89_FCC][0] = 60, - [0][1][2][1][RTW89_ETSI][0] = 38, - [0][1][2][1][RTW89_MKK][0] = 58, + [0][1][2][1][RTW89_FCC][0] = 50, + [0][1][2][1][RTW89_ETSI][0] = 36, + [0][1][2][1][RTW89_MKK][0] = 68, [0][1][2][1][RTW89_IC][0] = 60, [0][1][2][1][RTW89_ACMA][0] = 36, - [0][1][2][1][RTW89_FCC][1] = 60, - [0][1][2][1][RTW89_ETSI][1] = 38, - [0][1][2][1][RTW89_MKK][1] = 58, + [0][1][2][1][RTW89_FCC][1] = 50, + [0][1][2][1][RTW89_ETSI][1] = 36, + [0][1][2][1][RTW89_MKK][1] = 68, [0][1][2][1][RTW89_IC][1] = 60, [0][1][2][1][RTW89_ACMA][1] = 36, - [0][1][2][1][RTW89_FCC][2] = 64, - [0][1][2][1][RTW89_ETSI][2] = 38, - [0][1][2][1][RTW89_MKK][2] = 58, + [0][1][2][1][RTW89_FCC][2] = 54, + [0][1][2][1][RTW89_ETSI][2] = 36, + [0][1][2][1][RTW89_MKK][2] = 68, [0][1][2][1][RTW89_IC][2] = 64, [0][1][2][1][RTW89_ACMA][2] = 36, - [0][1][2][1][RTW89_FCC][3] = 68, - [0][1][2][1][RTW89_ETSI][3] = 38, - [0][1][2][1][RTW89_MKK][3] = 58, + [0][1][2][1][RTW89_FCC][3] = 58, + [0][1][2][1][RTW89_ETSI][3] = 36, + [0][1][2][1][RTW89_MKK][3] = 68, [0][1][2][1][RTW89_IC][3] = 68, [0][1][2][1][RTW89_ACMA][3] = 36, - [0][1][2][1][RTW89_FCC][4] = 74, - [0][1][2][1][RTW89_ETSI][4] = 38, - [0][1][2][1][RTW89_MKK][4] = 58, + [0][1][2][1][RTW89_FCC][4] = 64, + [0][1][2][1][RTW89_ETSI][4] = 36, + [0][1][2][1][RTW89_MKK][4] = 68, [0][1][2][1][RTW89_IC][4] = 74, [0][1][2][1][RTW89_ACMA][4] = 36, - [0][1][2][1][RTW89_FCC][5] = 80, - [0][1][2][1][RTW89_ETSI][5] = 38, - [0][1][2][1][RTW89_MKK][5] = 58, - [0][1][2][1][RTW89_IC][5] = 80, + [0][1][2][1][RTW89_FCC][5] = 70, + [0][1][2][1][RTW89_ETSI][5] = 36, + [0][1][2][1][RTW89_MKK][5] = 68, + [0][1][2][1][RTW89_IC][5] = 78, [0][1][2][1][RTW89_ACMA][5] = 36, - [0][1][2][1][RTW89_FCC][6] = 76, - [0][1][2][1][RTW89_ETSI][6] = 38, - [0][1][2][1][RTW89_MKK][6] = 58, + [0][1][2][1][RTW89_FCC][6] = 66, + [0][1][2][1][RTW89_ETSI][6] = 36, + [0][1][2][1][RTW89_MKK][6] = 68, [0][1][2][1][RTW89_IC][6] = 76, [0][1][2][1][RTW89_ACMA][6] = 36, - [0][1][2][1][RTW89_FCC][7] = 68, - [0][1][2][1][RTW89_ETSI][7] = 38, - [0][1][2][1][RTW89_MKK][7] = 58, + [0][1][2][1][RTW89_FCC][7] = 58, + [0][1][2][1][RTW89_ETSI][7] = 36, + [0][1][2][1][RTW89_MKK][7] = 68, [0][1][2][1][RTW89_IC][7] = 68, [0][1][2][1][RTW89_ACMA][7] = 36, - [0][1][2][1][RTW89_FCC][8] = 64, - [0][1][2][1][RTW89_ETSI][8] = 38, - [0][1][2][1][RTW89_MKK][8] = 58, + [0][1][2][1][RTW89_FCC][8] = 54, + [0][1][2][1][RTW89_ETSI][8] = 36, + [0][1][2][1][RTW89_MKK][8] = 68, [0][1][2][1][RTW89_IC][8] = 64, [0][1][2][1][RTW89_ACMA][8] = 36, - [0][1][2][1][RTW89_FCC][9] = 60, - [0][1][2][1][RTW89_ETSI][9] = 38, - [0][1][2][1][RTW89_MKK][9] = 58, + [0][1][2][1][RTW89_FCC][9] = 50, + [0][1][2][1][RTW89_ETSI][9] = 36, + [0][1][2][1][RTW89_MKK][9] = 68, [0][1][2][1][RTW89_IC][9] = 60, [0][1][2][1][RTW89_ACMA][9] = 36, - [0][1][2][1][RTW89_FCC][10] = 60, - [0][1][2][1][RTW89_ETSI][10] = 38, - [0][1][2][1][RTW89_MKK][10] = 58, + [0][1][2][1][RTW89_FCC][10] = 50, + [0][1][2][1][RTW89_ETSI][10] = 36, + [0][1][2][1][RTW89_MKK][10] = 68, [0][1][2][1][RTW89_IC][10] = 60, [0][1][2][1][RTW89_ACMA][10] = 36, - [0][1][2][1][RTW89_FCC][11] = 48, - [0][1][2][1][RTW89_ETSI][11] = 38, - [0][1][2][1][RTW89_MKK][11] = 58, + [0][1][2][1][RTW89_FCC][11] = 38, + [0][1][2][1][RTW89_ETSI][11] = 36, + [0][1][2][1][RTW89_MKK][11] = 68, [0][1][2][1][RTW89_IC][11] = 48, [0][1][2][1][RTW89_ACMA][11] = 36, - [0][1][2][1][RTW89_FCC][12] = 44, - [0][1][2][1][RTW89_ETSI][12] = 38, - [0][1][2][1][RTW89_MKK][12] = 58, + [0][1][2][1][RTW89_FCC][12] = 34, + [0][1][2][1][RTW89_ETSI][12] = 36, + [0][1][2][1][RTW89_MKK][12] = 68, [0][1][2][1][RTW89_IC][12] = 44, [0][1][2][1][RTW89_ACMA][12] = 36, [0][1][2][1][RTW89_FCC][13] = 127, @@ -14653,49 +14653,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_MKK][1] = 127, [1][0][2][0][RTW89_IC][1] = 127, [1][0][2][0][RTW89_ACMA][1] = 127, - [1][0][2][0][RTW89_FCC][2] = 72, + [1][0][2][0][RTW89_FCC][2] = 62, [1][0][2][0][RTW89_ETSI][2] = 60, - [1][0][2][0][RTW89_MKK][2] = 72, + [1][0][2][0][RTW89_MKK][2] = 74, [1][0][2][0][RTW89_IC][2] = 72, [1][0][2][0][RTW89_ACMA][2] = 60, - [1][0][2][0][RTW89_FCC][3] = 72, + [1][0][2][0][RTW89_FCC][3] = 62, [1][0][2][0][RTW89_ETSI][3] = 60, - [1][0][2][0][RTW89_MKK][3] = 72, + [1][0][2][0][RTW89_MKK][3] = 74, [1][0][2][0][RTW89_IC][3] = 72, [1][0][2][0][RTW89_ACMA][3] = 60, - [1][0][2][0][RTW89_FCC][4] = 74, + [1][0][2][0][RTW89_FCC][4] = 64, [1][0][2][0][RTW89_ETSI][4] = 60, - [1][0][2][0][RTW89_MKK][4] = 72, + [1][0][2][0][RTW89_MKK][4] = 74, [1][0][2][0][RTW89_IC][4] = 74, [1][0][2][0][RTW89_ACMA][4] = 60, - [1][0][2][0][RTW89_FCC][5] = 74, + [1][0][2][0][RTW89_FCC][5] = 64, [1][0][2][0][RTW89_ETSI][5] = 60, - [1][0][2][0][RTW89_MKK][5] = 72, + [1][0][2][0][RTW89_MKK][5] = 74, [1][0][2][0][RTW89_IC][5] = 74, [1][0][2][0][RTW89_ACMA][5] = 60, - [1][0][2][0][RTW89_FCC][6] = 74, + [1][0][2][0][RTW89_FCC][6] = 64, [1][0][2][0][RTW89_ETSI][6] = 60, - [1][0][2][0][RTW89_MKK][6] = 72, + [1][0][2][0][RTW89_MKK][6] = 74, [1][0][2][0][RTW89_IC][6] = 74, [1][0][2][0][RTW89_ACMA][6] = 60, - [1][0][2][0][RTW89_FCC][7] = 70, + [1][0][2][0][RTW89_FCC][7] = 60, [1][0][2][0][RTW89_ETSI][7] = 60, - [1][0][2][0][RTW89_MKK][7] = 72, + [1][0][2][0][RTW89_MKK][7] = 74, [1][0][2][0][RTW89_IC][7] = 70, [1][0][2][0][RTW89_ACMA][7] = 60, - [1][0][2][0][RTW89_FCC][8] = 70, + [1][0][2][0][RTW89_FCC][8] = 60, [1][0][2][0][RTW89_ETSI][8] = 60, - [1][0][2][0][RTW89_MKK][8] = 72, + [1][0][2][0][RTW89_MKK][8] = 74, [1][0][2][0][RTW89_IC][8] = 70, [1][0][2][0][RTW89_ACMA][8] = 60, - [1][0][2][0][RTW89_FCC][9] = 70, + [1][0][2][0][RTW89_FCC][9] = 60, [1][0][2][0][RTW89_ETSI][9] = 60, - [1][0][2][0][RTW89_MKK][9] = 72, + [1][0][2][0][RTW89_MKK][9] = 74, [1][0][2][0][RTW89_IC][9] = 70, [1][0][2][0][RTW89_ACMA][9] = 60, - [1][0][2][0][RTW89_FCC][10] = 68, + [1][0][2][0][RTW89_FCC][10] = 58, [1][0][2][0][RTW89_ETSI][10] = 60, - [1][0][2][0][RTW89_MKK][10] = 72, + [1][0][2][0][RTW89_MKK][10] = 74, [1][0][2][0][RTW89_IC][10] = 68, [1][0][2][0][RTW89_ACMA][10] = 60, [1][0][2][0][RTW89_FCC][11] = 127, @@ -14723,49 +14723,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_MKK][1] = 127, [1][1][2][0][RTW89_IC][1] = 127, [1][1][2][0][RTW89_ACMA][1] = 127, - [1][1][2][0][RTW89_FCC][2] = 56, + [1][1][2][0][RTW89_FCC][2] = 46, [1][1][2][0][RTW89_ETSI][2] = 48, - [1][1][2][0][RTW89_MKK][2] = 70, + [1][1][2][0][RTW89_MKK][2] = 68, [1][1][2][0][RTW89_IC][2] = 56, [1][1][2][0][RTW89_ACMA][2] = 48, - [1][1][2][0][RTW89_FCC][3] = 56, + [1][1][2][0][RTW89_FCC][3] = 46, [1][1][2][0][RTW89_ETSI][3] = 48, - [1][1][2][0][RTW89_MKK][3] = 70, + [1][1][2][0][RTW89_MKK][3] = 68, [1][1][2][0][RTW89_IC][3] = 56, [1][1][2][0][RTW89_ACMA][3] = 48, - [1][1][2][0][RTW89_FCC][4] = 60, + [1][1][2][0][RTW89_FCC][4] = 50, [1][1][2][0][RTW89_ETSI][4] = 48, - [1][1][2][0][RTW89_MKK][4] = 70, + [1][1][2][0][RTW89_MKK][4] = 68, [1][1][2][0][RTW89_IC][4] = 60, [1][1][2][0][RTW89_ACMA][4] = 48, - [1][1][2][0][RTW89_FCC][5] = 68, + [1][1][2][0][RTW89_FCC][5] = 58, [1][1][2][0][RTW89_ETSI][5] = 48, - [1][1][2][0][RTW89_MKK][5] = 70, + [1][1][2][0][RTW89_MKK][5] = 68, [1][1][2][0][RTW89_IC][5] = 68, [1][1][2][0][RTW89_ACMA][5] = 48, - [1][1][2][0][RTW89_FCC][6] = 60, + [1][1][2][0][RTW89_FCC][6] = 50, [1][1][2][0][RTW89_ETSI][6] = 48, - [1][1][2][0][RTW89_MKK][6] = 70, + [1][1][2][0][RTW89_MKK][6] = 68, [1][1][2][0][RTW89_IC][6] = 60, [1][1][2][0][RTW89_ACMA][6] = 48, - [1][1][2][0][RTW89_FCC][7] = 56, + [1][1][2][0][RTW89_FCC][7] = 46, [1][1][2][0][RTW89_ETSI][7] = 48, - [1][1][2][0][RTW89_MKK][7] = 70, + [1][1][2][0][RTW89_MKK][7] = 68, [1][1][2][0][RTW89_IC][7] = 56, [1][1][2][0][RTW89_ACMA][7] = 48, - [1][1][2][0][RTW89_FCC][8] = 56, + [1][1][2][0][RTW89_FCC][8] = 46, [1][1][2][0][RTW89_ETSI][8] = 48, - [1][1][2][0][RTW89_MKK][8] = 70, + [1][1][2][0][RTW89_MKK][8] = 68, [1][1][2][0][RTW89_IC][8] = 56, [1][1][2][0][RTW89_ACMA][8] = 48, - [1][1][2][0][RTW89_FCC][9] = 44, + [1][1][2][0][RTW89_FCC][9] = 34, [1][1][2][0][RTW89_ETSI][9] = 48, - [1][1][2][0][RTW89_MKK][9] = 70, + [1][1][2][0][RTW89_MKK][9] = 68, [1][1][2][0][RTW89_IC][9] = 44, [1][1][2][0][RTW89_ACMA][9] = 48, - [1][1][2][0][RTW89_FCC][10] = 40, + [1][1][2][0][RTW89_FCC][10] = 30, [1][1][2][0][RTW89_ETSI][10] = 48, - [1][1][2][0][RTW89_MKK][10] = 70, + [1][1][2][0][RTW89_MKK][10] = 68, [1][1][2][0][RTW89_IC][10] = 40, [1][1][2][0][RTW89_ACMA][10] = 48, [1][1][2][0][RTW89_FCC][11] = 127, @@ -14793,49 +14793,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_MKK][1] = 127, [1][1][2][1][RTW89_IC][1] = 127, [1][1][2][1][RTW89_ACMA][1] = 127, - [1][1][2][1][RTW89_FCC][2] = 56, - [1][1][2][1][RTW89_ETSI][2] = 38, - [1][1][2][1][RTW89_MKK][2] = 58, + [1][1][2][1][RTW89_FCC][2] = 46, + [1][1][2][1][RTW89_ETSI][2] = 36, + [1][1][2][1][RTW89_MKK][2] = 68, [1][1][2][1][RTW89_IC][2] = 56, [1][1][2][1][RTW89_ACMA][2] = 36, - [1][1][2][1][RTW89_FCC][3] = 56, - [1][1][2][1][RTW89_ETSI][3] = 38, - [1][1][2][1][RTW89_MKK][3] = 58, + [1][1][2][1][RTW89_FCC][3] = 46, + [1][1][2][1][RTW89_ETSI][3] = 36, + [1][1][2][1][RTW89_MKK][3] = 68, [1][1][2][1][RTW89_IC][3] = 56, [1][1][2][1][RTW89_ACMA][3] = 36, - [1][1][2][1][RTW89_FCC][4] = 60, - [1][1][2][1][RTW89_ETSI][4] = 38, - [1][1][2][1][RTW89_MKK][4] = 58, + [1][1][2][1][RTW89_FCC][4] = 50, + [1][1][2][1][RTW89_ETSI][4] = 36, + [1][1][2][1][RTW89_MKK][4] = 68, [1][1][2][1][RTW89_IC][4] = 60, [1][1][2][1][RTW89_ACMA][4] = 36, - [1][1][2][1][RTW89_FCC][5] = 68, - [1][1][2][1][RTW89_ETSI][5] = 38, - [1][1][2][1][RTW89_MKK][5] = 58, + [1][1][2][1][RTW89_FCC][5] = 58, + [1][1][2][1][RTW89_ETSI][5] = 36, + [1][1][2][1][RTW89_MKK][5] = 68, [1][1][2][1][RTW89_IC][5] = 68, [1][1][2][1][RTW89_ACMA][5] = 36, - [1][1][2][1][RTW89_FCC][6] = 60, - [1][1][2][1][RTW89_ETSI][6] = 38, - [1][1][2][1][RTW89_MKK][6] = 58, + [1][1][2][1][RTW89_FCC][6] = 50, + [1][1][2][1][RTW89_ETSI][6] = 36, + [1][1][2][1][RTW89_MKK][6] = 68, [1][1][2][1][RTW89_IC][6] = 60, [1][1][2][1][RTW89_ACMA][6] = 36, - [1][1][2][1][RTW89_FCC][7] = 56, - [1][1][2][1][RTW89_ETSI][7] = 38, - [1][1][2][1][RTW89_MKK][7] = 58, + [1][1][2][1][RTW89_FCC][7] = 46, + [1][1][2][1][RTW89_ETSI][7] = 36, + [1][1][2][1][RTW89_MKK][7] = 68, [1][1][2][1][RTW89_IC][7] = 56, [1][1][2][1][RTW89_ACMA][7] = 36, - [1][1][2][1][RTW89_FCC][8] = 56, - [1][1][2][1][RTW89_ETSI][8] = 38, - [1][1][2][1][RTW89_MKK][8] = 58, + [1][1][2][1][RTW89_FCC][8] = 46, + [1][1][2][1][RTW89_ETSI][8] = 36, + [1][1][2][1][RTW89_MKK][8] = 68, [1][1][2][1][RTW89_IC][8] = 56, [1][1][2][1][RTW89_ACMA][8] = 36, - [1][1][2][1][RTW89_FCC][9] = 44, - [1][1][2][1][RTW89_ETSI][9] = 38, - [1][1][2][1][RTW89_MKK][9] = 58, + [1][1][2][1][RTW89_FCC][9] = 34, + [1][1][2][1][RTW89_ETSI][9] = 36, + [1][1][2][1][RTW89_MKK][9] = 68, [1][1][2][1][RTW89_IC][9] = 44, [1][1][2][1][RTW89_ACMA][9] = 36, - [1][1][2][1][RTW89_FCC][10] = 40, - [1][1][2][1][RTW89_ETSI][10] = 38, - [1][1][2][1][RTW89_MKK][10] = 58, + [1][1][2][1][RTW89_FCC][10] = 30, + [1][1][2][1][RTW89_ETSI][10] = 36, + [1][1][2][1][RTW89_MKK][10] = 68, [1][1][2][1][RTW89_IC][10] = 40, [1][1][2][1][RTW89_ACMA][10] = 36, [1][1][2][1][RTW89_FCC][11] = 127, @@ -14871,21 +14871,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][19] = 60, [0][0][1][0][RTW89_WW][21] = 60, [0][0][1][0][RTW89_WW][23] = 60, - [0][0][1][0][RTW89_WW][25] = 60, - [0][0][1][0][RTW89_WW][27] = 60, - [0][0][1][0][RTW89_WW][29] = 60, + [0][0][1][0][RTW89_WW][25] = 66, + [0][0][1][0][RTW89_WW][27] = 66, + [0][0][1][0][RTW89_WW][29] = 66, [0][0][1][0][RTW89_WW][31] = 60, [0][0][1][0][RTW89_WW][33] = 60, [0][0][1][0][RTW89_WW][35] = 60, - [0][0][1][0][RTW89_WW][37] = 78, + [0][0][1][0][RTW89_WW][37] = 70, [0][0][1][0][RTW89_WW][38] = 30, [0][0][1][0][RTW89_WW][40] = 30, [0][0][1][0][RTW89_WW][42] = 30, [0][0][1][0][RTW89_WW][44] = 30, [0][0][1][0][RTW89_WW][46] = 30, - [0][0][1][0][RTW89_WW][48] = 80, - [0][0][1][0][RTW89_WW][50] = 80, - [0][0][1][0][RTW89_WW][52] = 80, + [0][0][1][0][RTW89_WW][48] = 70, + [0][0][1][0][RTW89_WW][50] = 70, + [0][0][1][0][RTW89_WW][52] = 70, [0][1][1][0][RTW89_WW][0] = 42, [0][1][1][0][RTW89_WW][2] = 42, [0][1][1][0][RTW89_WW][4] = 42, @@ -14899,26 +14899,26 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_WW][19] = 48, [0][1][1][0][RTW89_WW][21] = 48, [0][1][1][0][RTW89_WW][23] = 48, - [0][1][1][0][RTW89_WW][25] = 48, - [0][1][1][0][RTW89_WW][27] = 48, - [0][1][1][0][RTW89_WW][29] = 48, + [0][1][1][0][RTW89_WW][25] = 54, + [0][1][1][0][RTW89_WW][27] = 54, + [0][1][1][0][RTW89_WW][29] = 54, [0][1][1][0][RTW89_WW][31] = 48, [0][1][1][0][RTW89_WW][33] = 48, [0][1][1][0][RTW89_WW][35] = 48, - [0][1][1][0][RTW89_WW][37] = 70, + [0][1][1][0][RTW89_WW][37] = 60, [0][1][1][0][RTW89_WW][38] = 18, [0][1][1][0][RTW89_WW][40] = 16, [0][1][1][0][RTW89_WW][42] = 18, [0][1][1][0][RTW89_WW][44] = 16, [0][1][1][0][RTW89_WW][46] = 18, - [0][1][1][0][RTW89_WW][48] = 58, - [0][1][1][0][RTW89_WW][50] = 58, - [0][1][1][0][RTW89_WW][52] = 58, + [0][1][1][0][RTW89_WW][48] = 48, + [0][1][1][0][RTW89_WW][50] = 48, + [0][1][1][0][RTW89_WW][52] = 48, [0][0][2][0][RTW89_WW][0] = 62, [0][0][2][0][RTW89_WW][2] = 62, [0][0][2][0][RTW89_WW][4] = 62, - [0][0][2][0][RTW89_WW][6] = 62, - [0][0][2][0][RTW89_WW][8] = 62, + [0][0][2][0][RTW89_WW][6] = 60, + [0][0][2][0][RTW89_WW][8] = 58, [0][0][2][0][RTW89_WW][10] = 62, [0][0][2][0][RTW89_WW][12] = 62, [0][0][2][0][RTW89_WW][14] = 62, @@ -14927,26 +14927,26 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][19] = 62, [0][0][2][0][RTW89_WW][21] = 62, [0][0][2][0][RTW89_WW][23] = 62, - [0][0][2][0][RTW89_WW][25] = 62, - [0][0][2][0][RTW89_WW][27] = 62, - [0][0][2][0][RTW89_WW][29] = 62, + [0][0][2][0][RTW89_WW][25] = 66, + [0][0][2][0][RTW89_WW][27] = 66, + [0][0][2][0][RTW89_WW][29] = 66, [0][0][2][0][RTW89_WW][31] = 62, [0][0][2][0][RTW89_WW][33] = 62, [0][0][2][0][RTW89_WW][35] = 62, - [0][0][2][0][RTW89_WW][37] = 78, + [0][0][2][0][RTW89_WW][37] = 70, [0][0][2][0][RTW89_WW][38] = 30, [0][0][2][0][RTW89_WW][40] = 30, [0][0][2][0][RTW89_WW][42] = 30, [0][0][2][0][RTW89_WW][44] = 30, [0][0][2][0][RTW89_WW][46] = 30, - [0][0][2][0][RTW89_WW][48] = 80, - [0][0][2][0][RTW89_WW][50] = 80, - [0][0][2][0][RTW89_WW][52] = 80, + [0][0][2][0][RTW89_WW][48] = 70, + [0][0][2][0][RTW89_WW][50] = 70, + [0][0][2][0][RTW89_WW][52] = 70, [0][1][2][0][RTW89_WW][0] = 44, [0][1][2][0][RTW89_WW][2] = 44, [0][1][2][0][RTW89_WW][4] = 44, [0][1][2][0][RTW89_WW][6] = 44, - [0][1][2][0][RTW89_WW][8] = 50, + [0][1][2][0][RTW89_WW][8] = 42, [0][1][2][0][RTW89_WW][10] = 50, [0][1][2][0][RTW89_WW][12] = 50, [0][1][2][0][RTW89_WW][14] = 50, @@ -14955,21 +14955,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][19] = 50, [0][1][2][0][RTW89_WW][21] = 50, [0][1][2][0][RTW89_WW][23] = 50, - [0][1][2][0][RTW89_WW][25] = 50, - [0][1][2][0][RTW89_WW][27] = 50, - [0][1][2][0][RTW89_WW][29] = 50, + [0][1][2][0][RTW89_WW][25] = 54, + [0][1][2][0][RTW89_WW][27] = 54, + [0][1][2][0][RTW89_WW][29] = 54, [0][1][2][0][RTW89_WW][31] = 50, [0][1][2][0][RTW89_WW][33] = 50, [0][1][2][0][RTW89_WW][35] = 50, - [0][1][2][0][RTW89_WW][37] = 72, + [0][1][2][0][RTW89_WW][37] = 62, [0][1][2][0][RTW89_WW][38] = 18, [0][1][2][0][RTW89_WW][40] = 18, [0][1][2][0][RTW89_WW][42] = 18, [0][1][2][0][RTW89_WW][44] = 18, [0][1][2][0][RTW89_WW][46] = 18, - [0][1][2][0][RTW89_WW][48] = 60, - [0][1][2][0][RTW89_WW][50] = 60, - [0][1][2][0][RTW89_WW][52] = 60, + [0][1][2][0][RTW89_WW][48] = 50, + [0][1][2][0][RTW89_WW][50] = 50, + [0][1][2][0][RTW89_WW][52] = 50, [0][1][2][1][RTW89_WW][0] = 38, [0][1][2][1][RTW89_WW][2] = 38, [0][1][2][1][RTW89_WW][4] = 38, @@ -14983,1149 +14983,1149 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_WW][19] = 38, [0][1][2][1][RTW89_WW][21] = 38, [0][1][2][1][RTW89_WW][23] = 38, - [0][1][2][1][RTW89_WW][25] = 42, - [0][1][2][1][RTW89_WW][27] = 42, - [0][1][2][1][RTW89_WW][29] = 42, + [0][1][2][1][RTW89_WW][25] = 40, + [0][1][2][1][RTW89_WW][27] = 40, + [0][1][2][1][RTW89_WW][29] = 40, [0][1][2][1][RTW89_WW][31] = 38, [0][1][2][1][RTW89_WW][33] = 38, [0][1][2][1][RTW89_WW][35] = 38, - [0][1][2][1][RTW89_WW][37] = 70, - [0][1][2][1][RTW89_WW][38] = 8, - [0][1][2][1][RTW89_WW][40] = 8, - [0][1][2][1][RTW89_WW][42] = 8, - [0][1][2][1][RTW89_WW][44] = 8, - [0][1][2][1][RTW89_WW][46] = 8, - [0][1][2][1][RTW89_WW][48] = 60, - [0][1][2][1][RTW89_WW][50] = 60, - [0][1][2][1][RTW89_WW][52] = 60, - [1][0][2][0][RTW89_WW][1] = 66, + [0][1][2][1][RTW89_WW][37] = 60, + [0][1][2][1][RTW89_WW][38] = 6, + [0][1][2][1][RTW89_WW][40] = 6, + [0][1][2][1][RTW89_WW][42] = 6, + [0][1][2][1][RTW89_WW][44] = 6, + [0][1][2][1][RTW89_WW][46] = 6, + [0][1][2][1][RTW89_WW][48] = 50, + [0][1][2][1][RTW89_WW][50] = 50, + [0][1][2][1][RTW89_WW][52] = 50, + [1][0][2][0][RTW89_WW][1] = 58, [1][0][2][0][RTW89_WW][5] = 66, [1][0][2][0][RTW89_WW][9] = 66, - [1][0][2][0][RTW89_WW][13] = 66, - [1][0][2][0][RTW89_WW][16] = 66, + [1][0][2][0][RTW89_WW][13] = 58, + [1][0][2][0][RTW89_WW][16] = 56, [1][0][2][0][RTW89_WW][20] = 66, [1][0][2][0][RTW89_WW][24] = 66, [1][0][2][0][RTW89_WW][28] = 66, [1][0][2][0][RTW89_WW][32] = 66, - [1][0][2][0][RTW89_WW][36] = 76, + [1][0][2][0][RTW89_WW][36] = 66, [1][0][2][0][RTW89_WW][39] = 30, [1][0][2][0][RTW89_WW][43] = 30, - [1][0][2][0][RTW89_WW][47] = 80, - [1][0][2][0][RTW89_WW][51] = 72, - [1][1][2][0][RTW89_WW][1] = 54, - [1][1][2][0][RTW89_WW][5] = 54, - [1][1][2][0][RTW89_WW][9] = 54, - [1][1][2][0][RTW89_WW][13] = 54, - [1][1][2][0][RTW89_WW][16] = 54, + [1][0][2][0][RTW89_WW][47] = 68, + [1][0][2][0][RTW89_WW][51] = 68, + [1][1][2][0][RTW89_WW][1] = 48, + [1][1][2][0][RTW89_WW][5] = 52, + [1][1][2][0][RTW89_WW][9] = 52, + [1][1][2][0][RTW89_WW][13] = 52, + [1][1][2][0][RTW89_WW][16] = 48, [1][1][2][0][RTW89_WW][20] = 54, [1][1][2][0][RTW89_WW][24] = 54, [1][1][2][0][RTW89_WW][28] = 54, [1][1][2][0][RTW89_WW][32] = 54, - [1][1][2][0][RTW89_WW][36] = 72, + [1][1][2][0][RTW89_WW][36] = 66, [1][1][2][0][RTW89_WW][39] = 18, [1][1][2][0][RTW89_WW][43] = 18, - [1][1][2][0][RTW89_WW][47] = 70, - [1][1][2][0][RTW89_WW][51] = 68, - [1][1][2][1][RTW89_WW][1] = 42, - [1][1][2][1][RTW89_WW][5] = 42, - [1][1][2][1][RTW89_WW][9] = 42, - [1][1][2][1][RTW89_WW][13] = 42, - [1][1][2][1][RTW89_WW][16] = 42, - [1][1][2][1][RTW89_WW][20] = 42, - [1][1][2][1][RTW89_WW][24] = 42, - [1][1][2][1][RTW89_WW][28] = 42, - [1][1][2][1][RTW89_WW][32] = 42, - [1][1][2][1][RTW89_WW][36] = 70, - [1][1][2][1][RTW89_WW][39] = 8, - [1][1][2][1][RTW89_WW][43] = 8, - [1][1][2][1][RTW89_WW][47] = 70, - [1][1][2][1][RTW89_WW][51] = 68, - [2][0][2][0][RTW89_WW][3] = 64, - [2][0][2][0][RTW89_WW][11] = 66, - [2][0][2][0][RTW89_WW][18] = 64, - [2][0][2][0][RTW89_WW][26] = 66, - [2][0][2][0][RTW89_WW][34] = 72, + [1][1][2][0][RTW89_WW][47] = 60, + [1][1][2][0][RTW89_WW][51] = 58, + [1][1][2][1][RTW89_WW][1] = 40, + [1][1][2][1][RTW89_WW][5] = 40, + [1][1][2][1][RTW89_WW][9] = 40, + [1][1][2][1][RTW89_WW][13] = 40, + [1][1][2][1][RTW89_WW][16] = 40, + [1][1][2][1][RTW89_WW][20] = 40, + [1][1][2][1][RTW89_WW][24] = 40, + [1][1][2][1][RTW89_WW][28] = 40, + [1][1][2][1][RTW89_WW][32] = 40, + [1][1][2][1][RTW89_WW][36] = 60, + [1][1][2][1][RTW89_WW][39] = 6, + [1][1][2][1][RTW89_WW][43] = 6, + [1][1][2][1][RTW89_WW][47] = 60, + [1][1][2][1][RTW89_WW][51] = 58, + [2][0][2][0][RTW89_WW][3] = 56, + [2][0][2][0][RTW89_WW][11] = 58, + [2][0][2][0][RTW89_WW][18] = 54, + [2][0][2][0][RTW89_WW][26] = 60, + [2][0][2][0][RTW89_WW][34] = 60, [2][0][2][0][RTW89_WW][41] = 30, - [2][0][2][0][RTW89_WW][49] = 66, - [2][1][2][0][RTW89_WW][3] = 54, - [2][1][2][0][RTW89_WW][11] = 54, - [2][1][2][0][RTW89_WW][18] = 54, + [2][0][2][0][RTW89_WW][49] = 56, + [2][1][2][0][RTW89_WW][3] = 48, + [2][1][2][0][RTW89_WW][11] = 52, + [2][1][2][0][RTW89_WW][18] = 48, [2][1][2][0][RTW89_WW][26] = 54, - [2][1][2][0][RTW89_WW][34] = 72, + [2][1][2][0][RTW89_WW][34] = 60, [2][1][2][0][RTW89_WW][41] = 18, - [2][1][2][0][RTW89_WW][49] = 60, - [2][1][2][1][RTW89_WW][3] = 42, - [2][1][2][1][RTW89_WW][11] = 42, - [2][1][2][1][RTW89_WW][18] = 42, - [2][1][2][1][RTW89_WW][26] = 44, - [2][1][2][1][RTW89_WW][34] = 70, - [2][1][2][1][RTW89_WW][41] = 8, - [2][1][2][1][RTW89_WW][49] = 60, - [3][0][2][0][RTW89_WW][7] = 56, - [3][0][2][0][RTW89_WW][22] = 56, - [3][0][2][0][RTW89_WW][45] = 56, - [3][1][2][0][RTW89_WW][7] = 44, - [3][1][2][0][RTW89_WW][22] = 44, - [3][1][2][0][RTW89_WW][45] = 44, - [3][1][2][1][RTW89_WW][7] = 32, - [3][1][2][1][RTW89_WW][22] = 32, - [3][1][2][1][RTW89_WW][45] = 32, - [0][0][1][0][RTW89_FCC][0] = 80, - [0][0][1][0][RTW89_ETSI][0] = 60, - [0][0][1][0][RTW89_MKK][0] = 62, + [2][1][2][0][RTW89_WW][49] = 50, + [2][1][2][1][RTW89_WW][3] = 40, + [2][1][2][1][RTW89_WW][11] = 40, + [2][1][2][1][RTW89_WW][18] = 40, + [2][1][2][1][RTW89_WW][26] = 42, + [2][1][2][1][RTW89_WW][34] = 60, + [2][1][2][1][RTW89_WW][41] = 6, + [2][1][2][1][RTW89_WW][49] = 50, + [3][0][2][0][RTW89_WW][7] = 38, + [3][0][2][0][RTW89_WW][22] = 50, + [3][0][2][0][RTW89_WW][45] = 0, + [3][1][2][0][RTW89_WW][7] = 26, + [3][1][2][0][RTW89_WW][22] = 42, + [3][1][2][0][RTW89_WW][45] = 0, + [3][1][2][1][RTW89_WW][7] = 14, + [3][1][2][1][RTW89_WW][22] = 30, + [3][1][2][1][RTW89_WW][45] = 0, + [0][0][1][0][RTW89_FCC][0] = 70, + [0][0][1][0][RTW89_ETSI][0] = 66, + [0][0][1][0][RTW89_MKK][0] = 66, [0][0][1][0][RTW89_IC][0] = 62, [0][0][1][0][RTW89_ACMA][0] = 60, - [0][0][1][0][RTW89_FCC][2] = 80, - [0][0][1][0][RTW89_ETSI][2] = 60, - [0][0][1][0][RTW89_MKK][2] = 62, + [0][0][1][0][RTW89_FCC][2] = 70, + [0][0][1][0][RTW89_ETSI][2] = 66, + [0][0][1][0][RTW89_MKK][2] = 66, [0][0][1][0][RTW89_IC][2] = 62, [0][0][1][0][RTW89_ACMA][2] = 60, - [0][0][1][0][RTW89_FCC][4] = 80, - [0][0][1][0][RTW89_ETSI][4] = 60, - [0][0][1][0][RTW89_MKK][4] = 62, + [0][0][1][0][RTW89_FCC][4] = 70, + [0][0][1][0][RTW89_ETSI][4] = 66, + [0][0][1][0][RTW89_MKK][4] = 66, [0][0][1][0][RTW89_IC][4] = 62, [0][0][1][0][RTW89_ACMA][4] = 60, - [0][0][1][0][RTW89_FCC][6] = 80, - [0][0][1][0][RTW89_ETSI][6] = 60, - [0][0][1][0][RTW89_MKK][6] = 62, + [0][0][1][0][RTW89_FCC][6] = 70, + [0][0][1][0][RTW89_ETSI][6] = 66, + [0][0][1][0][RTW89_MKK][6] = 66, [0][0][1][0][RTW89_IC][6] = 62, [0][0][1][0][RTW89_ACMA][6] = 60, - [0][0][1][0][RTW89_FCC][8] = 80, - [0][0][1][0][RTW89_ETSI][8] = 60, - [0][0][1][0][RTW89_MKK][8] = 64, + [0][0][1][0][RTW89_FCC][8] = 70, + [0][0][1][0][RTW89_ETSI][8] = 66, + [0][0][1][0][RTW89_MKK][8] = 66, [0][0][1][0][RTW89_IC][8] = 66, [0][0][1][0][RTW89_ACMA][8] = 60, - [0][0][1][0][RTW89_FCC][10] = 80, - [0][0][1][0][RTW89_ETSI][10] = 60, - [0][0][1][0][RTW89_MKK][10] = 64, + [0][0][1][0][RTW89_FCC][10] = 70, + [0][0][1][0][RTW89_ETSI][10] = 66, + [0][0][1][0][RTW89_MKK][10] = 66, [0][0][1][0][RTW89_IC][10] = 66, [0][0][1][0][RTW89_ACMA][10] = 60, - [0][0][1][0][RTW89_FCC][12] = 80, - [0][0][1][0][RTW89_ETSI][12] = 60, - [0][0][1][0][RTW89_MKK][12] = 64, + [0][0][1][0][RTW89_FCC][12] = 70, + [0][0][1][0][RTW89_ETSI][12] = 66, + [0][0][1][0][RTW89_MKK][12] = 66, [0][0][1][0][RTW89_IC][12] = 66, [0][0][1][0][RTW89_ACMA][12] = 60, - [0][0][1][0][RTW89_FCC][14] = 80, - [0][0][1][0][RTW89_ETSI][14] = 60, - [0][0][1][0][RTW89_MKK][14] = 62, + [0][0][1][0][RTW89_FCC][14] = 70, + [0][0][1][0][RTW89_ETSI][14] = 66, + [0][0][1][0][RTW89_MKK][14] = 66, [0][0][1][0][RTW89_IC][14] = 66, [0][0][1][0][RTW89_ACMA][14] = 60, - [0][0][1][0][RTW89_FCC][15] = 78, - [0][0][1][0][RTW89_ETSI][15] = 60, - [0][0][1][0][RTW89_MKK][15] = 78, - [0][0][1][0][RTW89_IC][15] = 78, + [0][0][1][0][RTW89_FCC][15] = 68, + [0][0][1][0][RTW89_ETSI][15] = 66, + [0][0][1][0][RTW89_MKK][15] = 70, + [0][0][1][0][RTW89_IC][15] = 70, [0][0][1][0][RTW89_ACMA][15] = 60, - [0][0][1][0][RTW89_FCC][17] = 80, - [0][0][1][0][RTW89_ETSI][17] = 60, - [0][0][1][0][RTW89_MKK][17] = 78, - [0][0][1][0][RTW89_IC][17] = 80, + [0][0][1][0][RTW89_FCC][17] = 70, + [0][0][1][0][RTW89_ETSI][17] = 66, + [0][0][1][0][RTW89_MKK][17] = 70, + [0][0][1][0][RTW89_IC][17] = 70, [0][0][1][0][RTW89_ACMA][17] = 60, - [0][0][1][0][RTW89_FCC][19] = 80, - [0][0][1][0][RTW89_ETSI][19] = 60, - [0][0][1][0][RTW89_MKK][19] = 78, - [0][0][1][0][RTW89_IC][19] = 80, + [0][0][1][0][RTW89_FCC][19] = 70, + [0][0][1][0][RTW89_ETSI][19] = 66, + [0][0][1][0][RTW89_MKK][19] = 70, + [0][0][1][0][RTW89_IC][19] = 70, [0][0][1][0][RTW89_ACMA][19] = 60, - [0][0][1][0][RTW89_FCC][21] = 80, - [0][0][1][0][RTW89_ETSI][21] = 60, - [0][0][1][0][RTW89_MKK][21] = 78, - [0][0][1][0][RTW89_IC][21] = 80, + [0][0][1][0][RTW89_FCC][21] = 70, + [0][0][1][0][RTW89_ETSI][21] = 66, + [0][0][1][0][RTW89_MKK][21] = 70, + [0][0][1][0][RTW89_IC][21] = 70, [0][0][1][0][RTW89_ACMA][21] = 60, - [0][0][1][0][RTW89_FCC][23] = 80, - [0][0][1][0][RTW89_ETSI][23] = 60, - [0][0][1][0][RTW89_MKK][23] = 78, - [0][0][1][0][RTW89_IC][23] = 80, + [0][0][1][0][RTW89_FCC][23] = 70, + [0][0][1][0][RTW89_ETSI][23] = 66, + [0][0][1][0][RTW89_MKK][23] = 70, + [0][0][1][0][RTW89_IC][23] = 70, [0][0][1][0][RTW89_ACMA][23] = 60, - [0][0][1][0][RTW89_FCC][25] = 80, - [0][0][1][0][RTW89_ETSI][25] = 60, - [0][0][1][0][RTW89_MKK][25] = 78, + [0][0][1][0][RTW89_FCC][25] = 70, + [0][0][1][0][RTW89_ETSI][25] = 66, + [0][0][1][0][RTW89_MKK][25] = 70, [0][0][1][0][RTW89_IC][25] = 127, [0][0][1][0][RTW89_ACMA][25] = 127, - [0][0][1][0][RTW89_FCC][27] = 80, - [0][0][1][0][RTW89_ETSI][27] = 60, - [0][0][1][0][RTW89_MKK][27] = 78, + [0][0][1][0][RTW89_FCC][27] = 70, + [0][0][1][0][RTW89_ETSI][27] = 66, + [0][0][1][0][RTW89_MKK][27] = 70, [0][0][1][0][RTW89_IC][27] = 127, [0][0][1][0][RTW89_ACMA][27] = 127, - [0][0][1][0][RTW89_FCC][29] = 80, - [0][0][1][0][RTW89_ETSI][29] = 60, - [0][0][1][0][RTW89_MKK][29] = 78, + [0][0][1][0][RTW89_FCC][29] = 70, + [0][0][1][0][RTW89_ETSI][29] = 66, + [0][0][1][0][RTW89_MKK][29] = 70, [0][0][1][0][RTW89_IC][29] = 127, [0][0][1][0][RTW89_ACMA][29] = 127, - [0][0][1][0][RTW89_FCC][31] = 80, - [0][0][1][0][RTW89_ETSI][31] = 60, - [0][0][1][0][RTW89_MKK][31] = 78, - [0][0][1][0][RTW89_IC][31] = 80, + [0][0][1][0][RTW89_FCC][31] = 70, + [0][0][1][0][RTW89_ETSI][31] = 66, + [0][0][1][0][RTW89_MKK][31] = 70, + [0][0][1][0][RTW89_IC][31] = 70, [0][0][1][0][RTW89_ACMA][31] = 60, - [0][0][1][0][RTW89_FCC][33] = 80, - [0][0][1][0][RTW89_ETSI][33] = 60, - [0][0][1][0][RTW89_MKK][33] = 78, - [0][0][1][0][RTW89_IC][33] = 80, + [0][0][1][0][RTW89_FCC][33] = 70, + [0][0][1][0][RTW89_ETSI][33] = 66, + [0][0][1][0][RTW89_MKK][33] = 70, + [0][0][1][0][RTW89_IC][33] = 70, [0][0][1][0][RTW89_ACMA][33] = 60, - [0][0][1][0][RTW89_FCC][35] = 72, - [0][0][1][0][RTW89_ETSI][35] = 60, - [0][0][1][0][RTW89_MKK][35] = 78, - [0][0][1][0][RTW89_IC][35] = 72, + [0][0][1][0][RTW89_FCC][35] = 62, + [0][0][1][0][RTW89_ETSI][35] = 66, + [0][0][1][0][RTW89_MKK][35] = 70, + [0][0][1][0][RTW89_IC][35] = 70, [0][0][1][0][RTW89_ACMA][35] = 60, - [0][0][1][0][RTW89_FCC][37] = 80, + [0][0][1][0][RTW89_FCC][37] = 70, [0][0][1][0][RTW89_ETSI][37] = 127, - [0][0][1][0][RTW89_MKK][37] = 78, - [0][0][1][0][RTW89_IC][37] = 80, - [0][0][1][0][RTW89_ACMA][37] = 78, - [0][0][1][0][RTW89_FCC][38] = 80, + [0][0][1][0][RTW89_MKK][37] = 70, + [0][0][1][0][RTW89_IC][37] = 70, + [0][0][1][0][RTW89_ACMA][37] = 70, + [0][0][1][0][RTW89_FCC][38] = 70, [0][0][1][0][RTW89_ETSI][38] = 30, [0][0][1][0][RTW89_MKK][38] = 127, - [0][0][1][0][RTW89_IC][38] = 80, - [0][0][1][0][RTW89_ACMA][38] = 78, - [0][0][1][0][RTW89_FCC][40] = 80, + [0][0][1][0][RTW89_IC][38] = 70, + [0][0][1][0][RTW89_ACMA][38] = 70, + [0][0][1][0][RTW89_FCC][40] = 70, [0][0][1][0][RTW89_ETSI][40] = 30, [0][0][1][0][RTW89_MKK][40] = 127, - [0][0][1][0][RTW89_IC][40] = 80, - [0][0][1][0][RTW89_ACMA][40] = 78, - [0][0][1][0][RTW89_FCC][42] = 80, + [0][0][1][0][RTW89_IC][40] = 70, + [0][0][1][0][RTW89_ACMA][40] = 70, + [0][0][1][0][RTW89_FCC][42] = 70, [0][0][1][0][RTW89_ETSI][42] = 30, [0][0][1][0][RTW89_MKK][42] = 127, - [0][0][1][0][RTW89_IC][42] = 80, - [0][0][1][0][RTW89_ACMA][42] = 78, - [0][0][1][0][RTW89_FCC][44] = 80, + [0][0][1][0][RTW89_IC][42] = 70, + [0][0][1][0][RTW89_ACMA][42] = 70, + [0][0][1][0][RTW89_FCC][44] = 70, [0][0][1][0][RTW89_ETSI][44] = 30, [0][0][1][0][RTW89_MKK][44] = 127, - [0][0][1][0][RTW89_IC][44] = 80, - [0][0][1][0][RTW89_ACMA][44] = 78, - [0][0][1][0][RTW89_FCC][46] = 80, + [0][0][1][0][RTW89_IC][44] = 70, + [0][0][1][0][RTW89_ACMA][44] = 70, + [0][0][1][0][RTW89_FCC][46] = 70, [0][0][1][0][RTW89_ETSI][46] = 30, [0][0][1][0][RTW89_MKK][46] = 127, - [0][0][1][0][RTW89_IC][46] = 80, - [0][0][1][0][RTW89_ACMA][46] = 78, - [0][0][1][0][RTW89_FCC][48] = 80, + [0][0][1][0][RTW89_IC][46] = 70, + [0][0][1][0][RTW89_ACMA][46] = 70, + [0][0][1][0][RTW89_FCC][48] = 70, [0][0][1][0][RTW89_ETSI][48] = 127, [0][0][1][0][RTW89_MKK][48] = 127, [0][0][1][0][RTW89_IC][48] = 127, [0][0][1][0][RTW89_ACMA][48] = 127, - [0][0][1][0][RTW89_FCC][50] = 80, + [0][0][1][0][RTW89_FCC][50] = 70, [0][0][1][0][RTW89_ETSI][50] = 127, [0][0][1][0][RTW89_MKK][50] = 127, [0][0][1][0][RTW89_IC][50] = 127, [0][0][1][0][RTW89_ACMA][50] = 127, - [0][0][1][0][RTW89_FCC][52] = 80, + [0][0][1][0][RTW89_FCC][52] = 70, [0][0][1][0][RTW89_ETSI][52] = 127, [0][0][1][0][RTW89_MKK][52] = 127, [0][0][1][0][RTW89_IC][52] = 127, [0][0][1][0][RTW89_ACMA][52] = 127, - [0][1][1][0][RTW89_FCC][0] = 70, - [0][1][1][0][RTW89_ETSI][0] = 48, - [0][1][1][0][RTW89_MKK][0] = 50, + [0][1][1][0][RTW89_FCC][0] = 60, + [0][1][1][0][RTW89_ETSI][0] = 54, + [0][1][1][0][RTW89_MKK][0] = 54, [0][1][1][0][RTW89_IC][0] = 42, [0][1][1][0][RTW89_ACMA][0] = 48, - [0][1][1][0][RTW89_FCC][2] = 70, - [0][1][1][0][RTW89_ETSI][2] = 48, - [0][1][1][0][RTW89_MKK][2] = 50, + [0][1][1][0][RTW89_FCC][2] = 60, + [0][1][1][0][RTW89_ETSI][2] = 54, + [0][1][1][0][RTW89_MKK][2] = 54, [0][1][1][0][RTW89_IC][2] = 42, [0][1][1][0][RTW89_ACMA][2] = 48, - [0][1][1][0][RTW89_FCC][4] = 70, - [0][1][1][0][RTW89_ETSI][4] = 48, - [0][1][1][0][RTW89_MKK][4] = 50, + [0][1][1][0][RTW89_FCC][4] = 60, + [0][1][1][0][RTW89_ETSI][4] = 54, + [0][1][1][0][RTW89_MKK][4] = 54, [0][1][1][0][RTW89_IC][4] = 42, [0][1][1][0][RTW89_ACMA][4] = 48, - [0][1][1][0][RTW89_FCC][6] = 70, - [0][1][1][0][RTW89_ETSI][6] = 48, - [0][1][1][0][RTW89_MKK][6] = 50, + [0][1][1][0][RTW89_FCC][6] = 60, + [0][1][1][0][RTW89_ETSI][6] = 54, + [0][1][1][0][RTW89_MKK][6] = 54, [0][1][1][0][RTW89_IC][6] = 42, [0][1][1][0][RTW89_ACMA][6] = 48, - [0][1][1][0][RTW89_FCC][8] = 70, - [0][1][1][0][RTW89_ETSI][8] = 48, - [0][1][1][0][RTW89_MKK][8] = 50, + [0][1][1][0][RTW89_FCC][8] = 60, + [0][1][1][0][RTW89_ETSI][8] = 54, + [0][1][1][0][RTW89_MKK][8] = 52, [0][1][1][0][RTW89_IC][8] = 54, [0][1][1][0][RTW89_ACMA][8] = 48, - [0][1][1][0][RTW89_FCC][10] = 70, - [0][1][1][0][RTW89_ETSI][10] = 48, - [0][1][1][0][RTW89_MKK][10] = 50, + [0][1][1][0][RTW89_FCC][10] = 60, + [0][1][1][0][RTW89_ETSI][10] = 54, + [0][1][1][0][RTW89_MKK][10] = 54, [0][1][1][0][RTW89_IC][10] = 54, [0][1][1][0][RTW89_ACMA][10] = 48, - [0][1][1][0][RTW89_FCC][12] = 70, - [0][1][1][0][RTW89_ETSI][12] = 48, - [0][1][1][0][RTW89_MKK][12] = 50, + [0][1][1][0][RTW89_FCC][12] = 60, + [0][1][1][0][RTW89_ETSI][12] = 54, + [0][1][1][0][RTW89_MKK][12] = 54, [0][1][1][0][RTW89_IC][12] = 54, [0][1][1][0][RTW89_ACMA][12] = 48, - [0][1][1][0][RTW89_FCC][14] = 70, - [0][1][1][0][RTW89_ETSI][14] = 48, - [0][1][1][0][RTW89_MKK][14] = 50, + [0][1][1][0][RTW89_FCC][14] = 60, + [0][1][1][0][RTW89_ETSI][14] = 54, + [0][1][1][0][RTW89_MKK][14] = 54, [0][1][1][0][RTW89_IC][14] = 54, [0][1][1][0][RTW89_ACMA][14] = 48, - [0][1][1][0][RTW89_FCC][15] = 68, - [0][1][1][0][RTW89_ETSI][15] = 48, + [0][1][1][0][RTW89_FCC][15] = 58, + [0][1][1][0][RTW89_ETSI][15] = 54, [0][1][1][0][RTW89_MKK][15] = 70, [0][1][1][0][RTW89_IC][15] = 68, [0][1][1][0][RTW89_ACMA][15] = 48, - [0][1][1][0][RTW89_FCC][17] = 70, - [0][1][1][0][RTW89_ETSI][17] = 48, - [0][1][1][0][RTW89_MKK][17] = 72, + [0][1][1][0][RTW89_FCC][17] = 60, + [0][1][1][0][RTW89_ETSI][17] = 54, + [0][1][1][0][RTW89_MKK][17] = 70, [0][1][1][0][RTW89_IC][17] = 70, [0][1][1][0][RTW89_ACMA][17] = 48, - [0][1][1][0][RTW89_FCC][19] = 70, - [0][1][1][0][RTW89_ETSI][19] = 48, - [0][1][1][0][RTW89_MKK][19] = 72, + [0][1][1][0][RTW89_FCC][19] = 60, + [0][1][1][0][RTW89_ETSI][19] = 54, + [0][1][1][0][RTW89_MKK][19] = 70, [0][1][1][0][RTW89_IC][19] = 70, [0][1][1][0][RTW89_ACMA][19] = 48, - [0][1][1][0][RTW89_FCC][21] = 70, - [0][1][1][0][RTW89_ETSI][21] = 48, - [0][1][1][0][RTW89_MKK][21] = 72, + [0][1][1][0][RTW89_FCC][21] = 60, + [0][1][1][0][RTW89_ETSI][21] = 54, + [0][1][1][0][RTW89_MKK][21] = 70, [0][1][1][0][RTW89_IC][21] = 70, [0][1][1][0][RTW89_ACMA][21] = 48, - [0][1][1][0][RTW89_FCC][23] = 70, - [0][1][1][0][RTW89_ETSI][23] = 48, - [0][1][1][0][RTW89_MKK][23] = 72, + [0][1][1][0][RTW89_FCC][23] = 60, + [0][1][1][0][RTW89_ETSI][23] = 54, + [0][1][1][0][RTW89_MKK][23] = 70, [0][1][1][0][RTW89_IC][23] = 70, [0][1][1][0][RTW89_ACMA][23] = 48, - [0][1][1][0][RTW89_FCC][25] = 70, - [0][1][1][0][RTW89_ETSI][25] = 48, + [0][1][1][0][RTW89_FCC][25] = 60, + [0][1][1][0][RTW89_ETSI][25] = 54, [0][1][1][0][RTW89_MKK][25] = 70, [0][1][1][0][RTW89_IC][25] = 127, [0][1][1][0][RTW89_ACMA][25] = 127, - [0][1][1][0][RTW89_FCC][27] = 70, - [0][1][1][0][RTW89_ETSI][27] = 48, - [0][1][1][0][RTW89_MKK][27] = 72, + [0][1][1][0][RTW89_FCC][27] = 60, + [0][1][1][0][RTW89_ETSI][27] = 54, + [0][1][1][0][RTW89_MKK][27] = 70, [0][1][1][0][RTW89_IC][27] = 127, [0][1][1][0][RTW89_ACMA][27] = 127, - [0][1][1][0][RTW89_FCC][29] = 70, - [0][1][1][0][RTW89_ETSI][29] = 48, - [0][1][1][0][RTW89_MKK][29] = 72, + [0][1][1][0][RTW89_FCC][29] = 60, + [0][1][1][0][RTW89_ETSI][29] = 54, + [0][1][1][0][RTW89_MKK][29] = 70, [0][1][1][0][RTW89_IC][29] = 127, [0][1][1][0][RTW89_ACMA][29] = 127, - [0][1][1][0][RTW89_FCC][31] = 70, - [0][1][1][0][RTW89_ETSI][31] = 48, - [0][1][1][0][RTW89_MKK][31] = 72, + [0][1][1][0][RTW89_FCC][31] = 60, + [0][1][1][0][RTW89_ETSI][31] = 54, + [0][1][1][0][RTW89_MKK][31] = 70, [0][1][1][0][RTW89_IC][31] = 70, [0][1][1][0][RTW89_ACMA][31] = 48, - [0][1][1][0][RTW89_FCC][33] = 70, - [0][1][1][0][RTW89_ETSI][33] = 48, - [0][1][1][0][RTW89_MKK][33] = 72, + [0][1][1][0][RTW89_FCC][33] = 60, + [0][1][1][0][RTW89_ETSI][33] = 54, + [0][1][1][0][RTW89_MKK][33] = 70, [0][1][1][0][RTW89_IC][33] = 70, [0][1][1][0][RTW89_ACMA][33] = 48, - [0][1][1][0][RTW89_FCC][35] = 68, - [0][1][1][0][RTW89_ETSI][35] = 48, - [0][1][1][0][RTW89_MKK][35] = 72, + [0][1][1][0][RTW89_FCC][35] = 58, + [0][1][1][0][RTW89_ETSI][35] = 54, + [0][1][1][0][RTW89_MKK][35] = 70, [0][1][1][0][RTW89_IC][35] = 68, [0][1][1][0][RTW89_ACMA][35] = 48, - [0][1][1][0][RTW89_FCC][37] = 70, + [0][1][1][0][RTW89_FCC][37] = 60, [0][1][1][0][RTW89_ETSI][37] = 127, - [0][1][1][0][RTW89_MKK][37] = 72, + [0][1][1][0][RTW89_MKK][37] = 70, [0][1][1][0][RTW89_IC][37] = 70, - [0][1][1][0][RTW89_ACMA][37] = 72, - [0][1][1][0][RTW89_FCC][38] = 80, + [0][1][1][0][RTW89_ACMA][37] = 70, + [0][1][1][0][RTW89_FCC][38] = 70, [0][1][1][0][RTW89_ETSI][38] = 18, [0][1][1][0][RTW89_MKK][38] = 127, - [0][1][1][0][RTW89_IC][38] = 80, - [0][1][1][0][RTW89_ACMA][38] = 74, - [0][1][1][0][RTW89_FCC][40] = 80, + [0][1][1][0][RTW89_IC][38] = 70, + [0][1][1][0][RTW89_ACMA][38] = 70, + [0][1][1][0][RTW89_FCC][40] = 70, [0][1][1][0][RTW89_ETSI][40] = 18, [0][1][1][0][RTW89_MKK][40] = 127, - [0][1][1][0][RTW89_IC][40] = 80, + [0][1][1][0][RTW89_IC][40] = 70, [0][1][1][0][RTW89_ACMA][40] = 16, - [0][1][1][0][RTW89_FCC][42] = 80, + [0][1][1][0][RTW89_FCC][42] = 70, [0][1][1][0][RTW89_ETSI][42] = 18, [0][1][1][0][RTW89_MKK][42] = 127, - [0][1][1][0][RTW89_IC][42] = 80, - [0][1][1][0][RTW89_ACMA][42] = 78, - [0][1][1][0][RTW89_FCC][44] = 80, + [0][1][1][0][RTW89_IC][42] = 70, + [0][1][1][0][RTW89_ACMA][42] = 70, + [0][1][1][0][RTW89_FCC][44] = 70, [0][1][1][0][RTW89_ETSI][44] = 18, [0][1][1][0][RTW89_MKK][44] = 127, - [0][1][1][0][RTW89_IC][44] = 80, + [0][1][1][0][RTW89_IC][44] = 70, [0][1][1][0][RTW89_ACMA][44] = 16, - [0][1][1][0][RTW89_FCC][46] = 80, + [0][1][1][0][RTW89_FCC][46] = 70, [0][1][1][0][RTW89_ETSI][46] = 18, [0][1][1][0][RTW89_MKK][46] = 127, - [0][1][1][0][RTW89_IC][46] = 80, - [0][1][1][0][RTW89_ACMA][46] = 78, - [0][1][1][0][RTW89_FCC][48] = 58, + [0][1][1][0][RTW89_IC][46] = 70, + [0][1][1][0][RTW89_ACMA][46] = 70, + [0][1][1][0][RTW89_FCC][48] = 48, [0][1][1][0][RTW89_ETSI][48] = 127, [0][1][1][0][RTW89_MKK][48] = 127, [0][1][1][0][RTW89_IC][48] = 127, [0][1][1][0][RTW89_ACMA][48] = 127, - [0][1][1][0][RTW89_FCC][50] = 58, + [0][1][1][0][RTW89_FCC][50] = 48, [0][1][1][0][RTW89_ETSI][50] = 127, [0][1][1][0][RTW89_MKK][50] = 127, [0][1][1][0][RTW89_IC][50] = 127, [0][1][1][0][RTW89_ACMA][50] = 127, - [0][1][1][0][RTW89_FCC][52] = 58, + [0][1][1][0][RTW89_FCC][52] = 48, [0][1][1][0][RTW89_ETSI][52] = 127, [0][1][1][0][RTW89_MKK][52] = 127, [0][1][1][0][RTW89_IC][52] = 127, [0][1][1][0][RTW89_ACMA][52] = 127, - [0][0][2][0][RTW89_FCC][0] = 80, - [0][0][2][0][RTW89_ETSI][0] = 62, - [0][0][2][0][RTW89_MKK][0] = 64, + [0][0][2][0][RTW89_FCC][0] = 70, + [0][0][2][0][RTW89_ETSI][0] = 66, + [0][0][2][0][RTW89_MKK][0] = 68, [0][0][2][0][RTW89_IC][0] = 66, [0][0][2][0][RTW89_ACMA][0] = 62, - [0][0][2][0][RTW89_FCC][2] = 80, - [0][0][2][0][RTW89_ETSI][2] = 62, - [0][0][2][0][RTW89_MKK][2] = 64, + [0][0][2][0][RTW89_FCC][2] = 70, + [0][0][2][0][RTW89_ETSI][2] = 66, + [0][0][2][0][RTW89_MKK][2] = 68, [0][0][2][0][RTW89_IC][2] = 66, [0][0][2][0][RTW89_ACMA][2] = 62, - [0][0][2][0][RTW89_FCC][4] = 80, - [0][0][2][0][RTW89_ETSI][4] = 62, - [0][0][2][0][RTW89_MKK][4] = 64, + [0][0][2][0][RTW89_FCC][4] = 70, + [0][0][2][0][RTW89_ETSI][4] = 66, + [0][0][2][0][RTW89_MKK][4] = 68, [0][0][2][0][RTW89_IC][4] = 66, [0][0][2][0][RTW89_ACMA][4] = 62, - [0][0][2][0][RTW89_FCC][6] = 80, - [0][0][2][0][RTW89_ETSI][6] = 62, - [0][0][2][0][RTW89_MKK][6] = 64, + [0][0][2][0][RTW89_FCC][6] = 70, + [0][0][2][0][RTW89_ETSI][6] = 66, + [0][0][2][0][RTW89_MKK][6] = 60, [0][0][2][0][RTW89_IC][6] = 66, [0][0][2][0][RTW89_ACMA][6] = 62, - [0][0][2][0][RTW89_FCC][8] = 80, - [0][0][2][0][RTW89_ETSI][8] = 62, - [0][0][2][0][RTW89_MKK][8] = 64, + [0][0][2][0][RTW89_FCC][8] = 70, + [0][0][2][0][RTW89_ETSI][8] = 66, + [0][0][2][0][RTW89_MKK][8] = 58, [0][0][2][0][RTW89_IC][8] = 66, [0][0][2][0][RTW89_ACMA][8] = 62, - [0][0][2][0][RTW89_FCC][10] = 80, - [0][0][2][0][RTW89_ETSI][10] = 62, - [0][0][2][0][RTW89_MKK][10] = 64, + [0][0][2][0][RTW89_FCC][10] = 70, + [0][0][2][0][RTW89_ETSI][10] = 66, + [0][0][2][0][RTW89_MKK][10] = 70, [0][0][2][0][RTW89_IC][10] = 66, [0][0][2][0][RTW89_ACMA][10] = 62, - [0][0][2][0][RTW89_FCC][12] = 80, - [0][0][2][0][RTW89_ETSI][12] = 62, - [0][0][2][0][RTW89_MKK][12] = 64, + [0][0][2][0][RTW89_FCC][12] = 70, + [0][0][2][0][RTW89_ETSI][12] = 66, + [0][0][2][0][RTW89_MKK][12] = 70, [0][0][2][0][RTW89_IC][12] = 66, [0][0][2][0][RTW89_ACMA][12] = 62, - [0][0][2][0][RTW89_FCC][14] = 80, - [0][0][2][0][RTW89_ETSI][14] = 62, - [0][0][2][0][RTW89_MKK][14] = 64, + [0][0][2][0][RTW89_FCC][14] = 70, + [0][0][2][0][RTW89_ETSI][14] = 66, + [0][0][2][0][RTW89_MKK][14] = 70, [0][0][2][0][RTW89_IC][14] = 66, [0][0][2][0][RTW89_ACMA][14] = 62, - [0][0][2][0][RTW89_FCC][15] = 76, - [0][0][2][0][RTW89_ETSI][15] = 62, - [0][0][2][0][RTW89_MKK][15] = 78, - [0][0][2][0][RTW89_IC][15] = 76, + [0][0][2][0][RTW89_FCC][15] = 66, + [0][0][2][0][RTW89_ETSI][15] = 66, + [0][0][2][0][RTW89_MKK][15] = 70, + [0][0][2][0][RTW89_IC][15] = 70, [0][0][2][0][RTW89_ACMA][15] = 62, - [0][0][2][0][RTW89_FCC][17] = 80, - [0][0][2][0][RTW89_ETSI][17] = 62, - [0][0][2][0][RTW89_MKK][17] = 78, - [0][0][2][0][RTW89_IC][17] = 80, + [0][0][2][0][RTW89_FCC][17] = 70, + [0][0][2][0][RTW89_ETSI][17] = 66, + [0][0][2][0][RTW89_MKK][17] = 70, + [0][0][2][0][RTW89_IC][17] = 70, [0][0][2][0][RTW89_ACMA][17] = 62, - [0][0][2][0][RTW89_FCC][19] = 80, - [0][0][2][0][RTW89_ETSI][19] = 62, - [0][0][2][0][RTW89_MKK][19] = 78, - [0][0][2][0][RTW89_IC][19] = 80, + [0][0][2][0][RTW89_FCC][19] = 70, + [0][0][2][0][RTW89_ETSI][19] = 66, + [0][0][2][0][RTW89_MKK][19] = 70, + [0][0][2][0][RTW89_IC][19] = 70, [0][0][2][0][RTW89_ACMA][19] = 62, - [0][0][2][0][RTW89_FCC][21] = 80, - [0][0][2][0][RTW89_ETSI][21] = 62, - [0][0][2][0][RTW89_MKK][21] = 78, - [0][0][2][0][RTW89_IC][21] = 80, + [0][0][2][0][RTW89_FCC][21] = 70, + [0][0][2][0][RTW89_ETSI][21] = 66, + [0][0][2][0][RTW89_MKK][21] = 70, + [0][0][2][0][RTW89_IC][21] = 70, [0][0][2][0][RTW89_ACMA][21] = 62, - [0][0][2][0][RTW89_FCC][23] = 80, - [0][0][2][0][RTW89_ETSI][23] = 62, - [0][0][2][0][RTW89_MKK][23] = 78, - [0][0][2][0][RTW89_IC][23] = 80, + [0][0][2][0][RTW89_FCC][23] = 70, + [0][0][2][0][RTW89_ETSI][23] = 66, + [0][0][2][0][RTW89_MKK][23] = 70, + [0][0][2][0][RTW89_IC][23] = 70, [0][0][2][0][RTW89_ACMA][23] = 62, - [0][0][2][0][RTW89_FCC][25] = 80, - [0][0][2][0][RTW89_ETSI][25] = 62, - [0][0][2][0][RTW89_MKK][25] = 78, + [0][0][2][0][RTW89_FCC][25] = 70, + [0][0][2][0][RTW89_ETSI][25] = 66, + [0][0][2][0][RTW89_MKK][25] = 70, [0][0][2][0][RTW89_IC][25] = 127, [0][0][2][0][RTW89_ACMA][25] = 127, - [0][0][2][0][RTW89_FCC][27] = 80, - [0][0][2][0][RTW89_ETSI][27] = 62, - [0][0][2][0][RTW89_MKK][27] = 78, + [0][0][2][0][RTW89_FCC][27] = 70, + [0][0][2][0][RTW89_ETSI][27] = 66, + [0][0][2][0][RTW89_MKK][27] = 70, [0][0][2][0][RTW89_IC][27] = 127, [0][0][2][0][RTW89_ACMA][27] = 127, - [0][0][2][0][RTW89_FCC][29] = 80, - [0][0][2][0][RTW89_ETSI][29] = 62, - [0][0][2][0][RTW89_MKK][29] = 78, + [0][0][2][0][RTW89_FCC][29] = 70, + [0][0][2][0][RTW89_ETSI][29] = 66, + [0][0][2][0][RTW89_MKK][29] = 70, [0][0][2][0][RTW89_IC][29] = 127, [0][0][2][0][RTW89_ACMA][29] = 127, - [0][0][2][0][RTW89_FCC][31] = 80, - [0][0][2][0][RTW89_ETSI][31] = 62, - [0][0][2][0][RTW89_MKK][31] = 78, - [0][0][2][0][RTW89_IC][31] = 80, + [0][0][2][0][RTW89_FCC][31] = 70, + [0][0][2][0][RTW89_ETSI][31] = 66, + [0][0][2][0][RTW89_MKK][31] = 70, + [0][0][2][0][RTW89_IC][31] = 70, [0][0][2][0][RTW89_ACMA][31] = 62, - [0][0][2][0][RTW89_FCC][33] = 80, - [0][0][2][0][RTW89_ETSI][33] = 62, - [0][0][2][0][RTW89_MKK][33] = 78, - [0][0][2][0][RTW89_IC][33] = 80, + [0][0][2][0][RTW89_FCC][33] = 70, + [0][0][2][0][RTW89_ETSI][33] = 66, + [0][0][2][0][RTW89_MKK][33] = 70, + [0][0][2][0][RTW89_IC][33] = 70, [0][0][2][0][RTW89_ACMA][33] = 62, - [0][0][2][0][RTW89_FCC][35] = 72, - [0][0][2][0][RTW89_ETSI][35] = 62, - [0][0][2][0][RTW89_MKK][35] = 78, - [0][0][2][0][RTW89_IC][35] = 72, + [0][0][2][0][RTW89_FCC][35] = 62, + [0][0][2][0][RTW89_ETSI][35] = 66, + [0][0][2][0][RTW89_MKK][35] = 70, + [0][0][2][0][RTW89_IC][35] = 70, [0][0][2][0][RTW89_ACMA][35] = 62, - [0][0][2][0][RTW89_FCC][37] = 80, + [0][0][2][0][RTW89_FCC][37] = 70, [0][0][2][0][RTW89_ETSI][37] = 127, - [0][0][2][0][RTW89_MKK][37] = 78, - [0][0][2][0][RTW89_IC][37] = 80, - [0][0][2][0][RTW89_ACMA][37] = 78, - [0][0][2][0][RTW89_FCC][38] = 80, + [0][0][2][0][RTW89_MKK][37] = 70, + [0][0][2][0][RTW89_IC][37] = 70, + [0][0][2][0][RTW89_ACMA][37] = 70, + [0][0][2][0][RTW89_FCC][38] = 70, [0][0][2][0][RTW89_ETSI][38] = 30, [0][0][2][0][RTW89_MKK][38] = 127, - [0][0][2][0][RTW89_IC][38] = 80, - [0][0][2][0][RTW89_ACMA][38] = 78, - [0][0][2][0][RTW89_FCC][40] = 80, + [0][0][2][0][RTW89_IC][38] = 70, + [0][0][2][0][RTW89_ACMA][38] = 70, + [0][0][2][0][RTW89_FCC][40] = 70, [0][0][2][0][RTW89_ETSI][40] = 30, [0][0][2][0][RTW89_MKK][40] = 127, - [0][0][2][0][RTW89_IC][40] = 80, - [0][0][2][0][RTW89_ACMA][40] = 78, - [0][0][2][0][RTW89_FCC][42] = 80, + [0][0][2][0][RTW89_IC][40] = 70, + [0][0][2][0][RTW89_ACMA][40] = 70, + [0][0][2][0][RTW89_FCC][42] = 70, [0][0][2][0][RTW89_ETSI][42] = 30, [0][0][2][0][RTW89_MKK][42] = 127, - [0][0][2][0][RTW89_IC][42] = 80, - [0][0][2][0][RTW89_ACMA][42] = 78, - [0][0][2][0][RTW89_FCC][44] = 80, + [0][0][2][0][RTW89_IC][42] = 70, + [0][0][2][0][RTW89_ACMA][42] = 70, + [0][0][2][0][RTW89_FCC][44] = 70, [0][0][2][0][RTW89_ETSI][44] = 30, [0][0][2][0][RTW89_MKK][44] = 127, - [0][0][2][0][RTW89_IC][44] = 80, - [0][0][2][0][RTW89_ACMA][44] = 78, - [0][0][2][0][RTW89_FCC][46] = 80, + [0][0][2][0][RTW89_IC][44] = 70, + [0][0][2][0][RTW89_ACMA][44] = 70, + [0][0][2][0][RTW89_FCC][46] = 70, [0][0][2][0][RTW89_ETSI][46] = 30, [0][0][2][0][RTW89_MKK][46] = 127, - [0][0][2][0][RTW89_IC][46] = 80, - [0][0][2][0][RTW89_ACMA][46] = 78, - [0][0][2][0][RTW89_FCC][48] = 80, + [0][0][2][0][RTW89_IC][46] = 70, + [0][0][2][0][RTW89_ACMA][46] = 70, + [0][0][2][0][RTW89_FCC][48] = 70, [0][0][2][0][RTW89_ETSI][48] = 127, [0][0][2][0][RTW89_MKK][48] = 127, [0][0][2][0][RTW89_IC][48] = 127, [0][0][2][0][RTW89_ACMA][48] = 127, - [0][0][2][0][RTW89_FCC][50] = 80, + [0][0][2][0][RTW89_FCC][50] = 70, [0][0][2][0][RTW89_ETSI][50] = 127, [0][0][2][0][RTW89_MKK][50] = 127, [0][0][2][0][RTW89_IC][50] = 127, [0][0][2][0][RTW89_ACMA][50] = 127, - [0][0][2][0][RTW89_FCC][52] = 80, + [0][0][2][0][RTW89_FCC][52] = 70, [0][0][2][0][RTW89_ETSI][52] = 127, [0][0][2][0][RTW89_MKK][52] = 127, [0][0][2][0][RTW89_IC][52] = 127, [0][0][2][0][RTW89_ACMA][52] = 127, - [0][1][2][0][RTW89_FCC][0] = 72, - [0][1][2][0][RTW89_ETSI][0] = 50, - [0][1][2][0][RTW89_MKK][0] = 52, + [0][1][2][0][RTW89_FCC][0] = 62, + [0][1][2][0][RTW89_ETSI][0] = 54, + [0][1][2][0][RTW89_MKK][0] = 54, [0][1][2][0][RTW89_IC][0] = 44, [0][1][2][0][RTW89_ACMA][0] = 50, - [0][1][2][0][RTW89_FCC][2] = 72, - [0][1][2][0][RTW89_ETSI][2] = 50, - [0][1][2][0][RTW89_MKK][2] = 52, + [0][1][2][0][RTW89_FCC][2] = 62, + [0][1][2][0][RTW89_ETSI][2] = 54, + [0][1][2][0][RTW89_MKK][2] = 54, [0][1][2][0][RTW89_IC][2] = 44, [0][1][2][0][RTW89_ACMA][2] = 50, - [0][1][2][0][RTW89_FCC][4] = 72, - [0][1][2][0][RTW89_ETSI][4] = 50, - [0][1][2][0][RTW89_MKK][4] = 52, + [0][1][2][0][RTW89_FCC][4] = 62, + [0][1][2][0][RTW89_ETSI][4] = 54, + [0][1][2][0][RTW89_MKK][4] = 54, [0][1][2][0][RTW89_IC][4] = 44, [0][1][2][0][RTW89_ACMA][4] = 50, - [0][1][2][0][RTW89_FCC][6] = 72, - [0][1][2][0][RTW89_ETSI][6] = 50, - [0][1][2][0][RTW89_MKK][6] = 52, + [0][1][2][0][RTW89_FCC][6] = 62, + [0][1][2][0][RTW89_ETSI][6] = 54, + [0][1][2][0][RTW89_MKK][6] = 50, [0][1][2][0][RTW89_IC][6] = 44, [0][1][2][0][RTW89_ACMA][6] = 50, - [0][1][2][0][RTW89_FCC][8] = 72, - [0][1][2][0][RTW89_ETSI][8] = 50, - [0][1][2][0][RTW89_MKK][8] = 52, + [0][1][2][0][RTW89_FCC][8] = 62, + [0][1][2][0][RTW89_ETSI][8] = 54, + [0][1][2][0][RTW89_MKK][8] = 42, [0][1][2][0][RTW89_IC][8] = 54, [0][1][2][0][RTW89_ACMA][8] = 50, - [0][1][2][0][RTW89_FCC][10] = 72, - [0][1][2][0][RTW89_ETSI][10] = 50, - [0][1][2][0][RTW89_MKK][10] = 52, + [0][1][2][0][RTW89_FCC][10] = 62, + [0][1][2][0][RTW89_ETSI][10] = 54, + [0][1][2][0][RTW89_MKK][10] = 54, [0][1][2][0][RTW89_IC][10] = 54, [0][1][2][0][RTW89_ACMA][10] = 50, - [0][1][2][0][RTW89_FCC][12] = 72, - [0][1][2][0][RTW89_ETSI][12] = 50, - [0][1][2][0][RTW89_MKK][12] = 52, + [0][1][2][0][RTW89_FCC][12] = 62, + [0][1][2][0][RTW89_ETSI][12] = 54, + [0][1][2][0][RTW89_MKK][12] = 54, [0][1][2][0][RTW89_IC][12] = 54, [0][1][2][0][RTW89_ACMA][12] = 50, - [0][1][2][0][RTW89_FCC][14] = 72, - [0][1][2][0][RTW89_ETSI][14] = 50, - [0][1][2][0][RTW89_MKK][14] = 52, + [0][1][2][0][RTW89_FCC][14] = 62, + [0][1][2][0][RTW89_ETSI][14] = 54, + [0][1][2][0][RTW89_MKK][14] = 54, [0][1][2][0][RTW89_IC][14] = 54, [0][1][2][0][RTW89_ACMA][14] = 50, - [0][1][2][0][RTW89_FCC][15] = 70, - [0][1][2][0][RTW89_ETSI][15] = 50, - [0][1][2][0][RTW89_MKK][15] = 72, + [0][1][2][0][RTW89_FCC][15] = 60, + [0][1][2][0][RTW89_ETSI][15] = 54, + [0][1][2][0][RTW89_MKK][15] = 68, [0][1][2][0][RTW89_IC][15] = 70, [0][1][2][0][RTW89_ACMA][15] = 50, - [0][1][2][0][RTW89_FCC][17] = 72, - [0][1][2][0][RTW89_ETSI][17] = 50, - [0][1][2][0][RTW89_MKK][17] = 72, - [0][1][2][0][RTW89_IC][17] = 72, + [0][1][2][0][RTW89_FCC][17] = 62, + [0][1][2][0][RTW89_ETSI][17] = 54, + [0][1][2][0][RTW89_MKK][17] = 68, + [0][1][2][0][RTW89_IC][17] = 70, [0][1][2][0][RTW89_ACMA][17] = 50, - [0][1][2][0][RTW89_FCC][19] = 72, - [0][1][2][0][RTW89_ETSI][19] = 50, - [0][1][2][0][RTW89_MKK][19] = 72, - [0][1][2][0][RTW89_IC][19] = 72, + [0][1][2][0][RTW89_FCC][19] = 62, + [0][1][2][0][RTW89_ETSI][19] = 54, + [0][1][2][0][RTW89_MKK][19] = 68, + [0][1][2][0][RTW89_IC][19] = 70, [0][1][2][0][RTW89_ACMA][19] = 50, - [0][1][2][0][RTW89_FCC][21] = 72, - [0][1][2][0][RTW89_ETSI][21] = 50, - [0][1][2][0][RTW89_MKK][21] = 72, - [0][1][2][0][RTW89_IC][21] = 72, + [0][1][2][0][RTW89_FCC][21] = 62, + [0][1][2][0][RTW89_ETSI][21] = 54, + [0][1][2][0][RTW89_MKK][21] = 68, + [0][1][2][0][RTW89_IC][21] = 70, [0][1][2][0][RTW89_ACMA][21] = 50, - [0][1][2][0][RTW89_FCC][23] = 72, - [0][1][2][0][RTW89_ETSI][23] = 50, - [0][1][2][0][RTW89_MKK][23] = 72, - [0][1][2][0][RTW89_IC][23] = 72, + [0][1][2][0][RTW89_FCC][23] = 62, + [0][1][2][0][RTW89_ETSI][23] = 54, + [0][1][2][0][RTW89_MKK][23] = 68, + [0][1][2][0][RTW89_IC][23] = 70, [0][1][2][0][RTW89_ACMA][23] = 50, - [0][1][2][0][RTW89_FCC][25] = 72, - [0][1][2][0][RTW89_ETSI][25] = 50, - [0][1][2][0][RTW89_MKK][25] = 72, + [0][1][2][0][RTW89_FCC][25] = 62, + [0][1][2][0][RTW89_ETSI][25] = 54, + [0][1][2][0][RTW89_MKK][25] = 68, [0][1][2][0][RTW89_IC][25] = 127, [0][1][2][0][RTW89_ACMA][25] = 127, - [0][1][2][0][RTW89_FCC][27] = 72, - [0][1][2][0][RTW89_ETSI][27] = 50, - [0][1][2][0][RTW89_MKK][27] = 72, + [0][1][2][0][RTW89_FCC][27] = 62, + [0][1][2][0][RTW89_ETSI][27] = 54, + [0][1][2][0][RTW89_MKK][27] = 68, [0][1][2][0][RTW89_IC][27] = 127, [0][1][2][0][RTW89_ACMA][27] = 127, - [0][1][2][0][RTW89_FCC][29] = 72, - [0][1][2][0][RTW89_ETSI][29] = 50, - [0][1][2][0][RTW89_MKK][29] = 72, + [0][1][2][0][RTW89_FCC][29] = 62, + [0][1][2][0][RTW89_ETSI][29] = 54, + [0][1][2][0][RTW89_MKK][29] = 68, [0][1][2][0][RTW89_IC][29] = 127, [0][1][2][0][RTW89_ACMA][29] = 127, - [0][1][2][0][RTW89_FCC][31] = 72, - [0][1][2][0][RTW89_ETSI][31] = 50, - [0][1][2][0][RTW89_MKK][31] = 72, - [0][1][2][0][RTW89_IC][31] = 72, + [0][1][2][0][RTW89_FCC][31] = 62, + [0][1][2][0][RTW89_ETSI][31] = 54, + [0][1][2][0][RTW89_MKK][31] = 68, + [0][1][2][0][RTW89_IC][31] = 70, [0][1][2][0][RTW89_ACMA][31] = 50, - [0][1][2][0][RTW89_FCC][33] = 72, - [0][1][2][0][RTW89_ETSI][33] = 50, - [0][1][2][0][RTW89_MKK][33] = 72, - [0][1][2][0][RTW89_IC][33] = 72, + [0][1][2][0][RTW89_FCC][33] = 62, + [0][1][2][0][RTW89_ETSI][33] = 54, + [0][1][2][0][RTW89_MKK][33] = 68, + [0][1][2][0][RTW89_IC][33] = 70, [0][1][2][0][RTW89_ACMA][33] = 50, - [0][1][2][0][RTW89_FCC][35] = 68, - [0][1][2][0][RTW89_ETSI][35] = 50, - [0][1][2][0][RTW89_MKK][35] = 72, + [0][1][2][0][RTW89_FCC][35] = 58, + [0][1][2][0][RTW89_ETSI][35] = 54, + [0][1][2][0][RTW89_MKK][35] = 68, [0][1][2][0][RTW89_IC][35] = 68, [0][1][2][0][RTW89_ACMA][35] = 50, - [0][1][2][0][RTW89_FCC][37] = 72, + [0][1][2][0][RTW89_FCC][37] = 62, [0][1][2][0][RTW89_ETSI][37] = 127, - [0][1][2][0][RTW89_MKK][37] = 72, - [0][1][2][0][RTW89_IC][37] = 72, - [0][1][2][0][RTW89_ACMA][37] = 72, - [0][1][2][0][RTW89_FCC][38] = 80, + [0][1][2][0][RTW89_MKK][37] = 68, + [0][1][2][0][RTW89_IC][37] = 70, + [0][1][2][0][RTW89_ACMA][37] = 70, + [0][1][2][0][RTW89_FCC][38] = 70, [0][1][2][0][RTW89_ETSI][38] = 18, [0][1][2][0][RTW89_MKK][38] = 127, - [0][1][2][0][RTW89_IC][38] = 80, - [0][1][2][0][RTW89_ACMA][38] = 76, - [0][1][2][0][RTW89_FCC][40] = 80, + [0][1][2][0][RTW89_IC][38] = 70, + [0][1][2][0][RTW89_ACMA][38] = 70, + [0][1][2][0][RTW89_FCC][40] = 70, [0][1][2][0][RTW89_ETSI][40] = 18, [0][1][2][0][RTW89_MKK][40] = 127, - [0][1][2][0][RTW89_IC][40] = 80, - [0][1][2][0][RTW89_ACMA][40] = 76, - [0][1][2][0][RTW89_FCC][42] = 80, + [0][1][2][0][RTW89_IC][40] = 70, + [0][1][2][0][RTW89_ACMA][40] = 70, + [0][1][2][0][RTW89_FCC][42] = 70, [0][1][2][0][RTW89_ETSI][42] = 18, [0][1][2][0][RTW89_MKK][42] = 127, - [0][1][2][0][RTW89_IC][42] = 80, - [0][1][2][0][RTW89_ACMA][42] = 78, - [0][1][2][0][RTW89_FCC][44] = 80, + [0][1][2][0][RTW89_IC][42] = 70, + [0][1][2][0][RTW89_ACMA][42] = 70, + [0][1][2][0][RTW89_FCC][44] = 70, [0][1][2][0][RTW89_ETSI][44] = 18, [0][1][2][0][RTW89_MKK][44] = 127, - [0][1][2][0][RTW89_IC][44] = 80, - [0][1][2][0][RTW89_ACMA][44] = 78, - [0][1][2][0][RTW89_FCC][46] = 80, + [0][1][2][0][RTW89_IC][44] = 70, + [0][1][2][0][RTW89_ACMA][44] = 70, + [0][1][2][0][RTW89_FCC][46] = 70, [0][1][2][0][RTW89_ETSI][46] = 18, [0][1][2][0][RTW89_MKK][46] = 127, - [0][1][2][0][RTW89_IC][46] = 80, - [0][1][2][0][RTW89_ACMA][46] = 78, - [0][1][2][0][RTW89_FCC][48] = 60, + [0][1][2][0][RTW89_IC][46] = 70, + [0][1][2][0][RTW89_ACMA][46] = 70, + [0][1][2][0][RTW89_FCC][48] = 50, [0][1][2][0][RTW89_ETSI][48] = 127, [0][1][2][0][RTW89_MKK][48] = 127, [0][1][2][0][RTW89_IC][48] = 127, [0][1][2][0][RTW89_ACMA][48] = 127, - [0][1][2][0][RTW89_FCC][50] = 60, + [0][1][2][0][RTW89_FCC][50] = 50, [0][1][2][0][RTW89_ETSI][50] = 127, [0][1][2][0][RTW89_MKK][50] = 127, [0][1][2][0][RTW89_IC][50] = 127, [0][1][2][0][RTW89_ACMA][50] = 127, - [0][1][2][0][RTW89_FCC][52] = 60, + [0][1][2][0][RTW89_FCC][52] = 50, [0][1][2][0][RTW89_ETSI][52] = 127, [0][1][2][0][RTW89_MKK][52] = 127, [0][1][2][0][RTW89_IC][52] = 127, [0][1][2][0][RTW89_ACMA][52] = 127, - [0][1][2][1][RTW89_FCC][0] = 70, - [0][1][2][1][RTW89_ETSI][0] = 42, - [0][1][2][1][RTW89_MKK][0] = 52, + [0][1][2][1][RTW89_FCC][0] = 60, + [0][1][2][1][RTW89_ETSI][0] = 40, + [0][1][2][1][RTW89_MKK][0] = 54, [0][1][2][1][RTW89_IC][0] = 42, [0][1][2][1][RTW89_ACMA][0] = 38, - [0][1][2][1][RTW89_FCC][2] = 70, - [0][1][2][1][RTW89_ETSI][2] = 42, - [0][1][2][1][RTW89_MKK][2] = 52, + [0][1][2][1][RTW89_FCC][2] = 60, + [0][1][2][1][RTW89_ETSI][2] = 40, + [0][1][2][1][RTW89_MKK][2] = 54, [0][1][2][1][RTW89_IC][2] = 42, [0][1][2][1][RTW89_ACMA][2] = 38, - [0][1][2][1][RTW89_FCC][4] = 70, - [0][1][2][1][RTW89_ETSI][4] = 42, - [0][1][2][1][RTW89_MKK][4] = 52, + [0][1][2][1][RTW89_FCC][4] = 60, + [0][1][2][1][RTW89_ETSI][4] = 40, + [0][1][2][1][RTW89_MKK][4] = 54, [0][1][2][1][RTW89_IC][4] = 42, [0][1][2][1][RTW89_ACMA][4] = 38, - [0][1][2][1][RTW89_FCC][6] = 70, - [0][1][2][1][RTW89_ETSI][6] = 42, - [0][1][2][1][RTW89_MKK][6] = 52, + [0][1][2][1][RTW89_FCC][6] = 60, + [0][1][2][1][RTW89_ETSI][6] = 40, + [0][1][2][1][RTW89_MKK][6] = 50, [0][1][2][1][RTW89_IC][6] = 42, [0][1][2][1][RTW89_ACMA][6] = 38, - [0][1][2][1][RTW89_FCC][8] = 70, - [0][1][2][1][RTW89_ETSI][8] = 42, - [0][1][2][1][RTW89_MKK][8] = 52, + [0][1][2][1][RTW89_FCC][8] = 60, + [0][1][2][1][RTW89_ETSI][8] = 40, + [0][1][2][1][RTW89_MKK][8] = 42, [0][1][2][1][RTW89_IC][8] = 42, [0][1][2][1][RTW89_ACMA][8] = 38, - [0][1][2][1][RTW89_FCC][10] = 70, - [0][1][2][1][RTW89_ETSI][10] = 42, - [0][1][2][1][RTW89_MKK][10] = 52, + [0][1][2][1][RTW89_FCC][10] = 60, + [0][1][2][1][RTW89_ETSI][10] = 40, + [0][1][2][1][RTW89_MKK][10] = 66, [0][1][2][1][RTW89_IC][10] = 42, [0][1][2][1][RTW89_ACMA][10] = 38, - [0][1][2][1][RTW89_FCC][12] = 70, - [0][1][2][1][RTW89_ETSI][12] = 42, - [0][1][2][1][RTW89_MKK][12] = 52, + [0][1][2][1][RTW89_FCC][12] = 60, + [0][1][2][1][RTW89_ETSI][12] = 40, + [0][1][2][1][RTW89_MKK][12] = 66, [0][1][2][1][RTW89_IC][12] = 42, [0][1][2][1][RTW89_ACMA][12] = 38, - [0][1][2][1][RTW89_FCC][14] = 70, - [0][1][2][1][RTW89_ETSI][14] = 42, - [0][1][2][1][RTW89_MKK][14] = 52, + [0][1][2][1][RTW89_FCC][14] = 60, + [0][1][2][1][RTW89_ETSI][14] = 40, + [0][1][2][1][RTW89_MKK][14] = 66, [0][1][2][1][RTW89_IC][14] = 42, [0][1][2][1][RTW89_ACMA][14] = 38, - [0][1][2][1][RTW89_FCC][15] = 70, - [0][1][2][1][RTW89_ETSI][15] = 42, - [0][1][2][1][RTW89_MKK][15] = 72, + [0][1][2][1][RTW89_FCC][15] = 60, + [0][1][2][1][RTW89_ETSI][15] = 40, + [0][1][2][1][RTW89_MKK][15] = 68, [0][1][2][1][RTW89_IC][15] = 70, [0][1][2][1][RTW89_ACMA][15] = 38, - [0][1][2][1][RTW89_FCC][17] = 70, - [0][1][2][1][RTW89_ETSI][17] = 42, - [0][1][2][1][RTW89_MKK][17] = 72, + [0][1][2][1][RTW89_FCC][17] = 60, + [0][1][2][1][RTW89_ETSI][17] = 40, + [0][1][2][1][RTW89_MKK][17] = 68, [0][1][2][1][RTW89_IC][17] = 70, [0][1][2][1][RTW89_ACMA][17] = 38, - [0][1][2][1][RTW89_FCC][19] = 70, - [0][1][2][1][RTW89_ETSI][19] = 42, - [0][1][2][1][RTW89_MKK][19] = 72, + [0][1][2][1][RTW89_FCC][19] = 60, + [0][1][2][1][RTW89_ETSI][19] = 40, + [0][1][2][1][RTW89_MKK][19] = 68, [0][1][2][1][RTW89_IC][19] = 70, [0][1][2][1][RTW89_ACMA][19] = 38, - [0][1][2][1][RTW89_FCC][21] = 70, - [0][1][2][1][RTW89_ETSI][21] = 42, - [0][1][2][1][RTW89_MKK][21] = 72, + [0][1][2][1][RTW89_FCC][21] = 60, + [0][1][2][1][RTW89_ETSI][21] = 40, + [0][1][2][1][RTW89_MKK][21] = 68, [0][1][2][1][RTW89_IC][21] = 70, [0][1][2][1][RTW89_ACMA][21] = 38, - [0][1][2][1][RTW89_FCC][23] = 70, - [0][1][2][1][RTW89_ETSI][23] = 42, - [0][1][2][1][RTW89_MKK][23] = 72, + [0][1][2][1][RTW89_FCC][23] = 60, + [0][1][2][1][RTW89_ETSI][23] = 40, + [0][1][2][1][RTW89_MKK][23] = 68, [0][1][2][1][RTW89_IC][23] = 70, [0][1][2][1][RTW89_ACMA][23] = 38, - [0][1][2][1][RTW89_FCC][25] = 68, - [0][1][2][1][RTW89_ETSI][25] = 42, - [0][1][2][1][RTW89_MKK][25] = 72, + [0][1][2][1][RTW89_FCC][25] = 58, + [0][1][2][1][RTW89_ETSI][25] = 40, + [0][1][2][1][RTW89_MKK][25] = 68, [0][1][2][1][RTW89_IC][25] = 127, [0][1][2][1][RTW89_ACMA][25] = 127, - [0][1][2][1][RTW89_FCC][27] = 68, - [0][1][2][1][RTW89_ETSI][27] = 42, - [0][1][2][1][RTW89_MKK][27] = 72, + [0][1][2][1][RTW89_FCC][27] = 58, + [0][1][2][1][RTW89_ETSI][27] = 40, + [0][1][2][1][RTW89_MKK][27] = 68, [0][1][2][1][RTW89_IC][27] = 127, [0][1][2][1][RTW89_ACMA][27] = 127, - [0][1][2][1][RTW89_FCC][29] = 68, - [0][1][2][1][RTW89_ETSI][29] = 42, - [0][1][2][1][RTW89_MKK][29] = 72, + [0][1][2][1][RTW89_FCC][29] = 58, + [0][1][2][1][RTW89_ETSI][29] = 40, + [0][1][2][1][RTW89_MKK][29] = 68, [0][1][2][1][RTW89_IC][29] = 127, [0][1][2][1][RTW89_ACMA][29] = 127, - [0][1][2][1][RTW89_FCC][31] = 68, - [0][1][2][1][RTW89_ETSI][31] = 42, - [0][1][2][1][RTW89_MKK][31] = 72, + [0][1][2][1][RTW89_FCC][31] = 58, + [0][1][2][1][RTW89_ETSI][31] = 40, + [0][1][2][1][RTW89_MKK][31] = 68, [0][1][2][1][RTW89_IC][31] = 68, [0][1][2][1][RTW89_ACMA][31] = 38, - [0][1][2][1][RTW89_FCC][33] = 68, - [0][1][2][1][RTW89_ETSI][33] = 42, - [0][1][2][1][RTW89_MKK][33] = 72, + [0][1][2][1][RTW89_FCC][33] = 58, + [0][1][2][1][RTW89_ETSI][33] = 40, + [0][1][2][1][RTW89_MKK][33] = 68, [0][1][2][1][RTW89_IC][33] = 68, [0][1][2][1][RTW89_ACMA][33] = 38, - [0][1][2][1][RTW89_FCC][35] = 68, - [0][1][2][1][RTW89_ETSI][35] = 42, - [0][1][2][1][RTW89_MKK][35] = 72, + [0][1][2][1][RTW89_FCC][35] = 58, + [0][1][2][1][RTW89_ETSI][35] = 40, + [0][1][2][1][RTW89_MKK][35] = 68, [0][1][2][1][RTW89_IC][35] = 68, [0][1][2][1][RTW89_ACMA][35] = 38, - [0][1][2][1][RTW89_FCC][37] = 70, + [0][1][2][1][RTW89_FCC][37] = 60, [0][1][2][1][RTW89_ETSI][37] = 127, - [0][1][2][1][RTW89_MKK][37] = 72, + [0][1][2][1][RTW89_MKK][37] = 68, [0][1][2][1][RTW89_IC][37] = 70, - [0][1][2][1][RTW89_ACMA][37] = 72, - [0][1][2][1][RTW89_FCC][38] = 80, - [0][1][2][1][RTW89_ETSI][38] = 8, + [0][1][2][1][RTW89_ACMA][37] = 70, + [0][1][2][1][RTW89_FCC][38] = 70, + [0][1][2][1][RTW89_ETSI][38] = 6, [0][1][2][1][RTW89_MKK][38] = 127, - [0][1][2][1][RTW89_IC][38] = 80, - [0][1][2][1][RTW89_ACMA][38] = 76, - [0][1][2][1][RTW89_FCC][40] = 80, - [0][1][2][1][RTW89_ETSI][40] = 8, + [0][1][2][1][RTW89_IC][38] = 70, + [0][1][2][1][RTW89_ACMA][38] = 70, + [0][1][2][1][RTW89_FCC][40] = 70, + [0][1][2][1][RTW89_ETSI][40] = 6, [0][1][2][1][RTW89_MKK][40] = 127, - [0][1][2][1][RTW89_IC][40] = 80, - [0][1][2][1][RTW89_ACMA][40] = 76, - [0][1][2][1][RTW89_FCC][42] = 80, - [0][1][2][1][RTW89_ETSI][42] = 8, + [0][1][2][1][RTW89_IC][40] = 70, + [0][1][2][1][RTW89_ACMA][40] = 70, + [0][1][2][1][RTW89_FCC][42] = 70, + [0][1][2][1][RTW89_ETSI][42] = 6, [0][1][2][1][RTW89_MKK][42] = 127, - [0][1][2][1][RTW89_IC][42] = 80, - [0][1][2][1][RTW89_ACMA][42] = 78, - [0][1][2][1][RTW89_FCC][44] = 80, - [0][1][2][1][RTW89_ETSI][44] = 8, + [0][1][2][1][RTW89_IC][42] = 70, + [0][1][2][1][RTW89_ACMA][42] = 70, + [0][1][2][1][RTW89_FCC][44] = 70, + [0][1][2][1][RTW89_ETSI][44] = 6, [0][1][2][1][RTW89_MKK][44] = 127, - [0][1][2][1][RTW89_IC][44] = 80, - [0][1][2][1][RTW89_ACMA][44] = 78, - [0][1][2][1][RTW89_FCC][46] = 80, - [0][1][2][1][RTW89_ETSI][46] = 8, + [0][1][2][1][RTW89_IC][44] = 70, + [0][1][2][1][RTW89_ACMA][44] = 70, + [0][1][2][1][RTW89_FCC][46] = 70, + [0][1][2][1][RTW89_ETSI][46] = 6, [0][1][2][1][RTW89_MKK][46] = 127, - [0][1][2][1][RTW89_IC][46] = 80, - [0][1][2][1][RTW89_ACMA][46] = 78, - [0][1][2][1][RTW89_FCC][48] = 60, + [0][1][2][1][RTW89_IC][46] = 70, + [0][1][2][1][RTW89_ACMA][46] = 70, + [0][1][2][1][RTW89_FCC][48] = 50, [0][1][2][1][RTW89_ETSI][48] = 127, [0][1][2][1][RTW89_MKK][48] = 127, [0][1][2][1][RTW89_IC][48] = 127, [0][1][2][1][RTW89_ACMA][48] = 127, - [0][1][2][1][RTW89_FCC][50] = 60, + [0][1][2][1][RTW89_FCC][50] = 50, [0][1][2][1][RTW89_ETSI][50] = 127, [0][1][2][1][RTW89_MKK][50] = 127, [0][1][2][1][RTW89_IC][50] = 127, [0][1][2][1][RTW89_ACMA][50] = 127, - [0][1][2][1][RTW89_FCC][52] = 60, + [0][1][2][1][RTW89_FCC][52] = 50, [0][1][2][1][RTW89_ETSI][52] = 127, [0][1][2][1][RTW89_MKK][52] = 127, [0][1][2][1][RTW89_IC][52] = 127, [0][1][2][1][RTW89_ACMA][52] = 127, - [1][0][2][0][RTW89_FCC][1] = 68, + [1][0][2][0][RTW89_FCC][1] = 58, [1][0][2][0][RTW89_ETSI][1] = 66, - [1][0][2][0][RTW89_MKK][1] = 72, - [1][0][2][0][RTW89_IC][1] = 72, - [1][0][2][0][RTW89_ACMA][1] = 72, - [1][0][2][0][RTW89_FCC][5] = 80, + [1][0][2][0][RTW89_MKK][1] = 66, + [1][0][2][0][RTW89_IC][1] = 66, + [1][0][2][0][RTW89_ACMA][1] = 66, + [1][0][2][0][RTW89_FCC][5] = 68, [1][0][2][0][RTW89_ETSI][5] = 66, - [1][0][2][0][RTW89_MKK][5] = 72, - [1][0][2][0][RTW89_IC][5] = 72, - [1][0][2][0][RTW89_ACMA][5] = 72, - [1][0][2][0][RTW89_FCC][9] = 80, + [1][0][2][0][RTW89_MKK][5] = 66, + [1][0][2][0][RTW89_IC][5] = 66, + [1][0][2][0][RTW89_ACMA][5] = 66, + [1][0][2][0][RTW89_FCC][9] = 68, [1][0][2][0][RTW89_ETSI][9] = 66, - [1][0][2][0][RTW89_MKK][9] = 72, - [1][0][2][0][RTW89_IC][9] = 72, - [1][0][2][0][RTW89_ACMA][9] = 72, - [1][0][2][0][RTW89_FCC][13] = 68, + [1][0][2][0][RTW89_MKK][9] = 66, + [1][0][2][0][RTW89_IC][9] = 66, + [1][0][2][0][RTW89_ACMA][9] = 66, + [1][0][2][0][RTW89_FCC][13] = 58, [1][0][2][0][RTW89_ETSI][13] = 66, - [1][0][2][0][RTW89_MKK][13] = 72, - [1][0][2][0][RTW89_IC][13] = 72, - [1][0][2][0][RTW89_ACMA][13] = 72, - [1][0][2][0][RTW89_FCC][16] = 66, + [1][0][2][0][RTW89_MKK][13] = 66, + [1][0][2][0][RTW89_IC][13] = 66, + [1][0][2][0][RTW89_ACMA][13] = 66, + [1][0][2][0][RTW89_FCC][16] = 56, [1][0][2][0][RTW89_ETSI][16] = 66, - [1][0][2][0][RTW89_MKK][16] = 76, - [1][0][2][0][RTW89_IC][16] = 72, - [1][0][2][0][RTW89_ACMA][16] = 72, - [1][0][2][0][RTW89_FCC][20] = 80, + [1][0][2][0][RTW89_MKK][16] = 66, + [1][0][2][0][RTW89_IC][16] = 66, + [1][0][2][0][RTW89_ACMA][16] = 66, + [1][0][2][0][RTW89_FCC][20] = 68, [1][0][2][0][RTW89_ETSI][20] = 66, - [1][0][2][0][RTW89_MKK][20] = 76, - [1][0][2][0][RTW89_IC][20] = 80, - [1][0][2][0][RTW89_ACMA][20] = 72, - [1][0][2][0][RTW89_FCC][24] = 80, + [1][0][2][0][RTW89_MKK][20] = 66, + [1][0][2][0][RTW89_IC][20] = 66, + [1][0][2][0][RTW89_ACMA][20] = 66, + [1][0][2][0][RTW89_FCC][24] = 68, [1][0][2][0][RTW89_ETSI][24] = 66, - [1][0][2][0][RTW89_MKK][24] = 76, + [1][0][2][0][RTW89_MKK][24] = 66, [1][0][2][0][RTW89_IC][24] = 127, [1][0][2][0][RTW89_ACMA][24] = 127, - [1][0][2][0][RTW89_FCC][28] = 80, + [1][0][2][0][RTW89_FCC][28] = 68, [1][0][2][0][RTW89_ETSI][28] = 66, - [1][0][2][0][RTW89_MKK][28] = 76, + [1][0][2][0][RTW89_MKK][28] = 66, [1][0][2][0][RTW89_IC][28] = 127, [1][0][2][0][RTW89_ACMA][28] = 127, - [1][0][2][0][RTW89_FCC][32] = 78, + [1][0][2][0][RTW89_FCC][32] = 68, [1][0][2][0][RTW89_ETSI][32] = 66, - [1][0][2][0][RTW89_MKK][32] = 76, - [1][0][2][0][RTW89_IC][32] = 78, + [1][0][2][0][RTW89_MKK][32] = 66, + [1][0][2][0][RTW89_IC][32] = 66, [1][0][2][0][RTW89_ACMA][32] = 66, - [1][0][2][0][RTW89_FCC][36] = 80, + [1][0][2][0][RTW89_FCC][36] = 68, [1][0][2][0][RTW89_ETSI][36] = 127, - [1][0][2][0][RTW89_MKK][36] = 76, - [1][0][2][0][RTW89_IC][36] = 80, - [1][0][2][0][RTW89_ACMA][36] = 76, - [1][0][2][0][RTW89_FCC][39] = 80, + [1][0][2][0][RTW89_MKK][36] = 66, + [1][0][2][0][RTW89_IC][36] = 66, + [1][0][2][0][RTW89_ACMA][36] = 66, + [1][0][2][0][RTW89_FCC][39] = 68, [1][0][2][0][RTW89_ETSI][39] = 30, [1][0][2][0][RTW89_MKK][39] = 127, - [1][0][2][0][RTW89_IC][39] = 80, - [1][0][2][0][RTW89_ACMA][39] = 76, - [1][0][2][0][RTW89_FCC][43] = 80, + [1][0][2][0][RTW89_IC][39] = 66, + [1][0][2][0][RTW89_ACMA][39] = 66, + [1][0][2][0][RTW89_FCC][43] = 68, [1][0][2][0][RTW89_ETSI][43] = 30, [1][0][2][0][RTW89_MKK][43] = 127, - [1][0][2][0][RTW89_IC][43] = 80, - [1][0][2][0][RTW89_ACMA][43] = 76, - [1][0][2][0][RTW89_FCC][47] = 80, + [1][0][2][0][RTW89_IC][43] = 66, + [1][0][2][0][RTW89_ACMA][43] = 66, + [1][0][2][0][RTW89_FCC][47] = 68, [1][0][2][0][RTW89_ETSI][47] = 127, [1][0][2][0][RTW89_MKK][47] = 127, [1][0][2][0][RTW89_IC][47] = 127, [1][0][2][0][RTW89_ACMA][47] = 127, - [1][0][2][0][RTW89_FCC][51] = 72, + [1][0][2][0][RTW89_FCC][51] = 68, [1][0][2][0][RTW89_ETSI][51] = 127, [1][0][2][0][RTW89_MKK][51] = 127, [1][0][2][0][RTW89_IC][51] = 127, [1][0][2][0][RTW89_ACMA][51] = 127, - [1][1][2][0][RTW89_FCC][1] = 64, + [1][1][2][0][RTW89_FCC][1] = 54, [1][1][2][0][RTW89_ETSI][1] = 54, - [1][1][2][0][RTW89_MKK][1] = 60, + [1][1][2][0][RTW89_MKK][1] = 48, [1][1][2][0][RTW89_IC][1] = 60, [1][1][2][0][RTW89_ACMA][1] = 60, - [1][1][2][0][RTW89_FCC][5] = 78, + [1][1][2][0][RTW89_FCC][5] = 68, [1][1][2][0][RTW89_ETSI][5] = 54, - [1][1][2][0][RTW89_MKK][5] = 60, + [1][1][2][0][RTW89_MKK][5] = 52, [1][1][2][0][RTW89_IC][5] = 60, [1][1][2][0][RTW89_ACMA][5] = 60, - [1][1][2][0][RTW89_FCC][9] = 78, + [1][1][2][0][RTW89_FCC][9] = 68, [1][1][2][0][RTW89_ETSI][9] = 54, - [1][1][2][0][RTW89_MKK][9] = 60, + [1][1][2][0][RTW89_MKK][9] = 52, [1][1][2][0][RTW89_IC][9] = 60, [1][1][2][0][RTW89_ACMA][9] = 60, - [1][1][2][0][RTW89_FCC][13] = 64, + [1][1][2][0][RTW89_FCC][13] = 54, [1][1][2][0][RTW89_ETSI][13] = 54, - [1][1][2][0][RTW89_MKK][13] = 60, + [1][1][2][0][RTW89_MKK][13] = 52, [1][1][2][0][RTW89_IC][13] = 60, [1][1][2][0][RTW89_ACMA][13] = 60, - [1][1][2][0][RTW89_FCC][16] = 58, + [1][1][2][0][RTW89_FCC][16] = 48, [1][1][2][0][RTW89_ETSI][16] = 54, - [1][1][2][0][RTW89_MKK][16] = 72, + [1][1][2][0][RTW89_MKK][16] = 66, [1][1][2][0][RTW89_IC][16] = 58, [1][1][2][0][RTW89_ACMA][16] = 60, - [1][1][2][0][RTW89_FCC][20] = 78, + [1][1][2][0][RTW89_FCC][20] = 68, [1][1][2][0][RTW89_ETSI][20] = 54, - [1][1][2][0][RTW89_MKK][20] = 72, - [1][1][2][0][RTW89_IC][20] = 78, + [1][1][2][0][RTW89_MKK][20] = 66, + [1][1][2][0][RTW89_IC][20] = 66, [1][1][2][0][RTW89_ACMA][20] = 60, - [1][1][2][0][RTW89_FCC][24] = 78, + [1][1][2][0][RTW89_FCC][24] = 68, [1][1][2][0][RTW89_ETSI][24] = 54, - [1][1][2][0][RTW89_MKK][24] = 72, + [1][1][2][0][RTW89_MKK][24] = 66, [1][1][2][0][RTW89_IC][24] = 127, [1][1][2][0][RTW89_ACMA][24] = 127, - [1][1][2][0][RTW89_FCC][28] = 78, + [1][1][2][0][RTW89_FCC][28] = 68, [1][1][2][0][RTW89_ETSI][28] = 54, - [1][1][2][0][RTW89_MKK][28] = 72, + [1][1][2][0][RTW89_MKK][28] = 66, [1][1][2][0][RTW89_IC][28] = 127, [1][1][2][0][RTW89_ACMA][28] = 127, - [1][1][2][0][RTW89_FCC][32] = 70, + [1][1][2][0][RTW89_FCC][32] = 60, [1][1][2][0][RTW89_ETSI][32] = 54, - [1][1][2][0][RTW89_MKK][32] = 72, - [1][1][2][0][RTW89_IC][32] = 70, + [1][1][2][0][RTW89_MKK][32] = 66, + [1][1][2][0][RTW89_IC][32] = 66, [1][1][2][0][RTW89_ACMA][32] = 54, - [1][1][2][0][RTW89_FCC][36] = 78, + [1][1][2][0][RTW89_FCC][36] = 68, [1][1][2][0][RTW89_ETSI][36] = 127, - [1][1][2][0][RTW89_MKK][36] = 72, - [1][1][2][0][RTW89_IC][36] = 78, - [1][1][2][0][RTW89_ACMA][36] = 76, - [1][1][2][0][RTW89_FCC][39] = 80, + [1][1][2][0][RTW89_MKK][36] = 66, + [1][1][2][0][RTW89_IC][36] = 66, + [1][1][2][0][RTW89_ACMA][36] = 66, + [1][1][2][0][RTW89_FCC][39] = 68, [1][1][2][0][RTW89_ETSI][39] = 18, [1][1][2][0][RTW89_MKK][39] = 127, - [1][1][2][0][RTW89_IC][39] = 80, - [1][1][2][0][RTW89_ACMA][39] = 74, - [1][1][2][0][RTW89_FCC][43] = 80, + [1][1][2][0][RTW89_IC][39] = 66, + [1][1][2][0][RTW89_ACMA][39] = 66, + [1][1][2][0][RTW89_FCC][43] = 68, [1][1][2][0][RTW89_ETSI][43] = 18, [1][1][2][0][RTW89_MKK][43] = 127, - [1][1][2][0][RTW89_IC][43] = 80, - [1][1][2][0][RTW89_ACMA][43] = 76, - [1][1][2][0][RTW89_FCC][47] = 70, + [1][1][2][0][RTW89_IC][43] = 66, + [1][1][2][0][RTW89_ACMA][43] = 66, + [1][1][2][0][RTW89_FCC][47] = 60, [1][1][2][0][RTW89_ETSI][47] = 127, [1][1][2][0][RTW89_MKK][47] = 127, [1][1][2][0][RTW89_IC][47] = 127, [1][1][2][0][RTW89_ACMA][47] = 127, - [1][1][2][0][RTW89_FCC][51] = 68, + [1][1][2][0][RTW89_FCC][51] = 58, [1][1][2][0][RTW89_ETSI][51] = 127, [1][1][2][0][RTW89_MKK][51] = 127, [1][1][2][0][RTW89_IC][51] = 127, [1][1][2][0][RTW89_ACMA][51] = 127, - [1][1][2][1][RTW89_FCC][1] = 64, - [1][1][2][1][RTW89_ETSI][1] = 42, - [1][1][2][1][RTW89_MKK][1] = 60, + [1][1][2][1][RTW89_FCC][1] = 54, + [1][1][2][1][RTW89_ETSI][1] = 40, + [1][1][2][1][RTW89_MKK][1] = 48, [1][1][2][1][RTW89_IC][1] = 48, [1][1][2][1][RTW89_ACMA][1] = 48, - [1][1][2][1][RTW89_FCC][5] = 70, - [1][1][2][1][RTW89_ETSI][5] = 42, - [1][1][2][1][RTW89_MKK][5] = 60, + [1][1][2][1][RTW89_FCC][5] = 60, + [1][1][2][1][RTW89_ETSI][5] = 40, + [1][1][2][1][RTW89_MKK][5] = 52, [1][1][2][1][RTW89_IC][5] = 48, [1][1][2][1][RTW89_ACMA][5] = 48, - [1][1][2][1][RTW89_FCC][9] = 70, - [1][1][2][1][RTW89_ETSI][9] = 42, - [1][1][2][1][RTW89_MKK][9] = 60, + [1][1][2][1][RTW89_FCC][9] = 60, + [1][1][2][1][RTW89_ETSI][9] = 40, + [1][1][2][1][RTW89_MKK][9] = 52, [1][1][2][1][RTW89_IC][9] = 48, [1][1][2][1][RTW89_ACMA][9] = 48, - [1][1][2][1][RTW89_FCC][13] = 64, - [1][1][2][1][RTW89_ETSI][13] = 42, - [1][1][2][1][RTW89_MKK][13] = 60, + [1][1][2][1][RTW89_FCC][13] = 54, + [1][1][2][1][RTW89_ETSI][13] = 40, + [1][1][2][1][RTW89_MKK][13] = 52, [1][1][2][1][RTW89_IC][13] = 48, [1][1][2][1][RTW89_ACMA][13] = 48, - [1][1][2][1][RTW89_FCC][16] = 58, - [1][1][2][1][RTW89_ETSI][16] = 42, - [1][1][2][1][RTW89_MKK][16] = 72, + [1][1][2][1][RTW89_FCC][16] = 48, + [1][1][2][1][RTW89_ETSI][16] = 40, + [1][1][2][1][RTW89_MKK][16] = 66, [1][1][2][1][RTW89_IC][16] = 58, [1][1][2][1][RTW89_ACMA][16] = 48, - [1][1][2][1][RTW89_FCC][20] = 70, - [1][1][2][1][RTW89_ETSI][20] = 42, - [1][1][2][1][RTW89_MKK][20] = 72, - [1][1][2][1][RTW89_IC][20] = 70, + [1][1][2][1][RTW89_FCC][20] = 60, + [1][1][2][1][RTW89_ETSI][20] = 40, + [1][1][2][1][RTW89_MKK][20] = 66, + [1][1][2][1][RTW89_IC][20] = 66, [1][1][2][1][RTW89_ACMA][20] = 48, - [1][1][2][1][RTW89_FCC][24] = 70, - [1][1][2][1][RTW89_ETSI][24] = 42, - [1][1][2][1][RTW89_MKK][24] = 72, + [1][1][2][1][RTW89_FCC][24] = 60, + [1][1][2][1][RTW89_ETSI][24] = 40, + [1][1][2][1][RTW89_MKK][24] = 66, [1][1][2][1][RTW89_IC][24] = 127, [1][1][2][1][RTW89_ACMA][24] = 127, - [1][1][2][1][RTW89_FCC][28] = 70, - [1][1][2][1][RTW89_ETSI][28] = 42, - [1][1][2][1][RTW89_MKK][28] = 72, + [1][1][2][1][RTW89_FCC][28] = 60, + [1][1][2][1][RTW89_ETSI][28] = 40, + [1][1][2][1][RTW89_MKK][28] = 66, [1][1][2][1][RTW89_IC][28] = 127, [1][1][2][1][RTW89_ACMA][28] = 127, - [1][1][2][1][RTW89_FCC][32] = 70, - [1][1][2][1][RTW89_ETSI][32] = 42, - [1][1][2][1][RTW89_MKK][32] = 72, - [1][1][2][1][RTW89_IC][32] = 70, + [1][1][2][1][RTW89_FCC][32] = 60, + [1][1][2][1][RTW89_ETSI][32] = 40, + [1][1][2][1][RTW89_MKK][32] = 66, + [1][1][2][1][RTW89_IC][32] = 66, [1][1][2][1][RTW89_ACMA][32] = 42, - [1][1][2][1][RTW89_FCC][36] = 70, + [1][1][2][1][RTW89_FCC][36] = 60, [1][1][2][1][RTW89_ETSI][36] = 127, - [1][1][2][1][RTW89_MKK][36] = 72, - [1][1][2][1][RTW89_IC][36] = 70, - [1][1][2][1][RTW89_ACMA][36] = 72, - [1][1][2][1][RTW89_FCC][39] = 80, - [1][1][2][1][RTW89_ETSI][39] = 8, + [1][1][2][1][RTW89_MKK][36] = 66, + [1][1][2][1][RTW89_IC][36] = 66, + [1][1][2][1][RTW89_ACMA][36] = 66, + [1][1][2][1][RTW89_FCC][39] = 68, + [1][1][2][1][RTW89_ETSI][39] = 6, [1][1][2][1][RTW89_MKK][39] = 127, - [1][1][2][1][RTW89_IC][39] = 80, - [1][1][2][1][RTW89_ACMA][39] = 74, - [1][1][2][1][RTW89_FCC][43] = 80, - [1][1][2][1][RTW89_ETSI][43] = 8, + [1][1][2][1][RTW89_IC][39] = 66, + [1][1][2][1][RTW89_ACMA][39] = 66, + [1][1][2][1][RTW89_FCC][43] = 68, + [1][1][2][1][RTW89_ETSI][43] = 6, [1][1][2][1][RTW89_MKK][43] = 127, - [1][1][2][1][RTW89_IC][43] = 80, - [1][1][2][1][RTW89_ACMA][43] = 76, - [1][1][2][1][RTW89_FCC][47] = 70, + [1][1][2][1][RTW89_IC][43] = 66, + [1][1][2][1][RTW89_ACMA][43] = 66, + [1][1][2][1][RTW89_FCC][47] = 60, [1][1][2][1][RTW89_ETSI][47] = 127, [1][1][2][1][RTW89_MKK][47] = 127, [1][1][2][1][RTW89_IC][47] = 127, [1][1][2][1][RTW89_ACMA][47] = 127, - [1][1][2][1][RTW89_FCC][51] = 68, + [1][1][2][1][RTW89_FCC][51] = 58, [1][1][2][1][RTW89_ETSI][51] = 127, [1][1][2][1][RTW89_MKK][51] = 127, [1][1][2][1][RTW89_IC][51] = 127, [1][1][2][1][RTW89_ACMA][51] = 127, - [2][0][2][0][RTW89_FCC][3] = 66, - [2][0][2][0][RTW89_ETSI][3] = 66, - [2][0][2][0][RTW89_MKK][3] = 66, - [2][0][2][0][RTW89_IC][3] = 64, - [2][0][2][0][RTW89_ACMA][3] = 66, - [2][0][2][0][RTW89_FCC][11] = 68, - [2][0][2][0][RTW89_ETSI][11] = 66, - [2][0][2][0][RTW89_MKK][11] = 66, - [2][0][2][0][RTW89_IC][11] = 66, - [2][0][2][0][RTW89_ACMA][11] = 66, - [2][0][2][0][RTW89_FCC][18] = 64, - [2][0][2][0][RTW89_ETSI][18] = 66, - [2][0][2][0][RTW89_MKK][18] = 72, - [2][0][2][0][RTW89_IC][18] = 64, - [2][0][2][0][RTW89_ACMA][18] = 66, - [2][0][2][0][RTW89_FCC][26] = 76, - [2][0][2][0][RTW89_ETSI][26] = 66, - [2][0][2][0][RTW89_MKK][26] = 72, + [2][0][2][0][RTW89_FCC][3] = 56, + [2][0][2][0][RTW89_ETSI][3] = 60, + [2][0][2][0][RTW89_MKK][3] = 60, + [2][0][2][0][RTW89_IC][3] = 60, + [2][0][2][0][RTW89_ACMA][3] = 60, + [2][0][2][0][RTW89_FCC][11] = 58, + [2][0][2][0][RTW89_ETSI][11] = 60, + [2][0][2][0][RTW89_MKK][11] = 60, + [2][0][2][0][RTW89_IC][11] = 60, + [2][0][2][0][RTW89_ACMA][11] = 60, + [2][0][2][0][RTW89_FCC][18] = 54, + [2][0][2][0][RTW89_ETSI][18] = 60, + [2][0][2][0][RTW89_MKK][18] = 60, + [2][0][2][0][RTW89_IC][18] = 60, + [2][0][2][0][RTW89_ACMA][18] = 60, + [2][0][2][0][RTW89_FCC][26] = 62, + [2][0][2][0][RTW89_ETSI][26] = 60, + [2][0][2][0][RTW89_MKK][26] = 60, [2][0][2][0][RTW89_IC][26] = 127, [2][0][2][0][RTW89_ACMA][26] = 127, - [2][0][2][0][RTW89_FCC][34] = 76, + [2][0][2][0][RTW89_FCC][34] = 62, [2][0][2][0][RTW89_ETSI][34] = 127, - [2][0][2][0][RTW89_MKK][34] = 72, - [2][0][2][0][RTW89_IC][34] = 76, - [2][0][2][0][RTW89_ACMA][34] = 72, - [2][0][2][0][RTW89_FCC][41] = 76, + [2][0][2][0][RTW89_MKK][34] = 60, + [2][0][2][0][RTW89_IC][34] = 60, + [2][0][2][0][RTW89_ACMA][34] = 60, + [2][0][2][0][RTW89_FCC][41] = 62, [2][0][2][0][RTW89_ETSI][41] = 30, [2][0][2][0][RTW89_MKK][41] = 127, - [2][0][2][0][RTW89_IC][41] = 76, - [2][0][2][0][RTW89_ACMA][41] = 72, - [2][0][2][0][RTW89_FCC][49] = 66, + [2][0][2][0][RTW89_IC][41] = 60, + [2][0][2][0][RTW89_ACMA][41] = 60, + [2][0][2][0][RTW89_FCC][49] = 56, [2][0][2][0][RTW89_ETSI][49] = 127, [2][0][2][0][RTW89_MKK][49] = 127, [2][0][2][0][RTW89_IC][49] = 127, [2][0][2][0][RTW89_ACMA][49] = 127, - [2][1][2][0][RTW89_FCC][3] = 58, + [2][1][2][0][RTW89_FCC][3] = 48, [2][1][2][0][RTW89_ETSI][3] = 54, - [2][1][2][0][RTW89_MKK][3] = 54, - [2][1][2][0][RTW89_IC][3] = 54, - [2][1][2][0][RTW89_ACMA][3] = 54, - [2][1][2][0][RTW89_FCC][11] = 64, + [2][1][2][0][RTW89_MKK][3] = 56, + [2][1][2][0][RTW89_IC][3] = 52, + [2][1][2][0][RTW89_ACMA][3] = 52, + [2][1][2][0][RTW89_FCC][11] = 54, [2][1][2][0][RTW89_ETSI][11] = 54, [2][1][2][0][RTW89_MKK][11] = 54, - [2][1][2][0][RTW89_IC][11] = 54, - [2][1][2][0][RTW89_ACMA][11] = 54, - [2][1][2][0][RTW89_FCC][18] = 58, + [2][1][2][0][RTW89_IC][11] = 52, + [2][1][2][0][RTW89_ACMA][11] = 52, + [2][1][2][0][RTW89_FCC][18] = 48, [2][1][2][0][RTW89_ETSI][18] = 54, - [2][1][2][0][RTW89_MKK][18] = 72, + [2][1][2][0][RTW89_MKK][18] = 60, [2][1][2][0][RTW89_IC][18] = 58, - [2][1][2][0][RTW89_ACMA][18] = 54, - [2][1][2][0][RTW89_FCC][26] = 72, + [2][1][2][0][RTW89_ACMA][18] = 52, + [2][1][2][0][RTW89_FCC][26] = 62, [2][1][2][0][RTW89_ETSI][26] = 54, - [2][1][2][0][RTW89_MKK][26] = 72, + [2][1][2][0][RTW89_MKK][26] = 56, [2][1][2][0][RTW89_IC][26] = 127, [2][1][2][0][RTW89_ACMA][26] = 127, - [2][1][2][0][RTW89_FCC][34] = 76, + [2][1][2][0][RTW89_FCC][34] = 62, [2][1][2][0][RTW89_ETSI][34] = 127, - [2][1][2][0][RTW89_MKK][34] = 72, - [2][1][2][0][RTW89_IC][34] = 76, - [2][1][2][0][RTW89_ACMA][34] = 72, - [2][1][2][0][RTW89_FCC][41] = 76, + [2][1][2][0][RTW89_MKK][34] = 60, + [2][1][2][0][RTW89_IC][34] = 60, + [2][1][2][0][RTW89_ACMA][34] = 60, + [2][1][2][0][RTW89_FCC][41] = 62, [2][1][2][0][RTW89_ETSI][41] = 18, [2][1][2][0][RTW89_MKK][41] = 127, - [2][1][2][0][RTW89_IC][41] = 76, - [2][1][2][0][RTW89_ACMA][41] = 72, - [2][1][2][0][RTW89_FCC][49] = 60, + [2][1][2][0][RTW89_IC][41] = 60, + [2][1][2][0][RTW89_ACMA][41] = 60, + [2][1][2][0][RTW89_FCC][49] = 50, [2][1][2][0][RTW89_ETSI][49] = 127, [2][1][2][0][RTW89_MKK][49] = 127, [2][1][2][0][RTW89_IC][49] = 127, [2][1][2][0][RTW89_ACMA][49] = 127, - [2][1][2][1][RTW89_FCC][3] = 58, - [2][1][2][1][RTW89_ETSI][3] = 42, - [2][1][2][1][RTW89_MKK][3] = 54, - [2][1][2][1][RTW89_IC][3] = 42, - [2][1][2][1][RTW89_ACMA][3] = 42, - [2][1][2][1][RTW89_FCC][11] = 64, - [2][1][2][1][RTW89_ETSI][11] = 42, + [2][1][2][1][RTW89_FCC][3] = 48, + [2][1][2][1][RTW89_ETSI][3] = 40, + [2][1][2][1][RTW89_MKK][3] = 56, + [2][1][2][1][RTW89_IC][3] = 40, + [2][1][2][1][RTW89_ACMA][3] = 40, + [2][1][2][1][RTW89_FCC][11] = 54, + [2][1][2][1][RTW89_ETSI][11] = 40, [2][1][2][1][RTW89_MKK][11] = 54, - [2][1][2][1][RTW89_IC][11] = 42, - [2][1][2][1][RTW89_ACMA][11] = 42, - [2][1][2][1][RTW89_FCC][18] = 58, - [2][1][2][1][RTW89_ETSI][18] = 42, - [2][1][2][1][RTW89_MKK][18] = 72, + [2][1][2][1][RTW89_IC][11] = 40, + [2][1][2][1][RTW89_ACMA][11] = 40, + [2][1][2][1][RTW89_FCC][18] = 48, + [2][1][2][1][RTW89_ETSI][18] = 40, + [2][1][2][1][RTW89_MKK][18] = 60, [2][1][2][1][RTW89_IC][18] = 58, - [2][1][2][1][RTW89_ACMA][18] = 42, - [2][1][2][1][RTW89_FCC][26] = 70, - [2][1][2][1][RTW89_ETSI][26] = 44, - [2][1][2][1][RTW89_MKK][26] = 72, + [2][1][2][1][RTW89_ACMA][18] = 40, + [2][1][2][1][RTW89_FCC][26] = 60, + [2][1][2][1][RTW89_ETSI][26] = 42, + [2][1][2][1][RTW89_MKK][26] = 56, [2][1][2][1][RTW89_IC][26] = 127, [2][1][2][1][RTW89_ACMA][26] = 127, - [2][1][2][1][RTW89_FCC][34] = 70, + [2][1][2][1][RTW89_FCC][34] = 60, [2][1][2][1][RTW89_ETSI][34] = 127, - [2][1][2][1][RTW89_MKK][34] = 72, - [2][1][2][1][RTW89_IC][34] = 70, - [2][1][2][1][RTW89_ACMA][34] = 72, - [2][1][2][1][RTW89_FCC][41] = 76, - [2][1][2][1][RTW89_ETSI][41] = 8, + [2][1][2][1][RTW89_MKK][34] = 60, + [2][1][2][1][RTW89_IC][34] = 60, + [2][1][2][1][RTW89_ACMA][34] = 60, + [2][1][2][1][RTW89_FCC][41] = 62, + [2][1][2][1][RTW89_ETSI][41] = 6, [2][1][2][1][RTW89_MKK][41] = 127, - [2][1][2][1][RTW89_IC][41] = 76, - [2][1][2][1][RTW89_ACMA][41] = 72, - [2][1][2][1][RTW89_FCC][49] = 60, + [2][1][2][1][RTW89_IC][41] = 60, + [2][1][2][1][RTW89_ACMA][41] = 60, + [2][1][2][1][RTW89_FCC][49] = 50, [2][1][2][1][RTW89_ETSI][49] = 127, [2][1][2][1][RTW89_MKK][49] = 127, [2][1][2][1][RTW89_IC][49] = 127, [2][1][2][1][RTW89_ACMA][49] = 127, - [3][0][2][0][RTW89_FCC][7] = 56, - [3][0][2][0][RTW89_ETSI][7] = 56, - [3][0][2][0][RTW89_MKK][7] = 56, - [3][0][2][0][RTW89_IC][7] = 56, - [3][0][2][0][RTW89_ACMA][7] = 56, - [3][0][2][0][RTW89_FCC][22] = 56, - [3][0][2][0][RTW89_ETSI][22] = 56, - [3][0][2][0][RTW89_MKK][22] = 56, - [3][0][2][0][RTW89_IC][22] = 56, - [3][0][2][0][RTW89_ACMA][22] = 56, - [3][0][2][0][RTW89_FCC][45] = 56, + [3][0][2][0][RTW89_FCC][7] = 38, + [3][0][2][0][RTW89_ETSI][7] = 50, + [3][0][2][0][RTW89_MKK][7] = 50, + [3][0][2][0][RTW89_IC][7] = 50, + [3][0][2][0][RTW89_ACMA][7] = 50, + [3][0][2][0][RTW89_FCC][22] = 52, + [3][0][2][0][RTW89_ETSI][22] = 50, + [3][0][2][0][RTW89_MKK][22] = 50, + [3][0][2][0][RTW89_IC][22] = 50, + [3][0][2][0][RTW89_ACMA][22] = 50, + [3][0][2][0][RTW89_FCC][45] = 127, [3][0][2][0][RTW89_ETSI][45] = 127, [3][0][2][0][RTW89_MKK][45] = 127, [3][0][2][0][RTW89_IC][45] = 127, [3][0][2][0][RTW89_ACMA][45] = 127, - [3][1][2][0][RTW89_FCC][7] = 44, - [3][1][2][0][RTW89_ETSI][7] = 44, - [3][1][2][0][RTW89_MKK][7] = 44, + [3][1][2][0][RTW89_FCC][7] = 26, + [3][1][2][0][RTW89_ETSI][7] = 50, + [3][1][2][0][RTW89_MKK][7] = 36, [3][1][2][0][RTW89_IC][7] = 44, [3][1][2][0][RTW89_ACMA][7] = 44, - [3][1][2][0][RTW89_FCC][22] = 44, - [3][1][2][0][RTW89_ETSI][22] = 44, - [3][1][2][0][RTW89_MKK][22] = 44, + [3][1][2][0][RTW89_FCC][22] = 42, + [3][1][2][0][RTW89_ETSI][22] = 50, + [3][1][2][0][RTW89_MKK][22] = 48, [3][1][2][0][RTW89_IC][22] = 44, [3][1][2][0][RTW89_ACMA][22] = 44, - [3][1][2][0][RTW89_FCC][45] = 44, + [3][1][2][0][RTW89_FCC][45] = 127, [3][1][2][0][RTW89_ETSI][45] = 127, [3][1][2][0][RTW89_MKK][45] = 127, [3][1][2][0][RTW89_IC][45] = 127, [3][1][2][0][RTW89_ACMA][45] = 127, - [3][1][2][1][RTW89_FCC][7] = 32, - [3][1][2][1][RTW89_ETSI][7] = 32, - [3][1][2][1][RTW89_MKK][7] = 32, + [3][1][2][1][RTW89_FCC][7] = 14, + [3][1][2][1][RTW89_ETSI][7] = 42, + [3][1][2][1][RTW89_MKK][7] = 36, [3][1][2][1][RTW89_IC][7] = 32, [3][1][2][1][RTW89_ACMA][7] = 32, - [3][1][2][1][RTW89_FCC][22] = 32, - [3][1][2][1][RTW89_ETSI][22] = 32, - [3][1][2][1][RTW89_MKK][22] = 32, + [3][1][2][1][RTW89_FCC][22] = 30, + [3][1][2][1][RTW89_ETSI][22] = 42, + [3][1][2][1][RTW89_MKK][22] = 48, [3][1][2][1][RTW89_IC][22] = 32, [3][1][2][1][RTW89_ACMA][22] = 32, - [3][1][2][1][RTW89_FCC][45] = 32, + [3][1][2][1][RTW89_FCC][45] = 127, [3][1][2][1][RTW89_ETSI][45] = 127, [3][1][2][1][RTW89_MKK][45] = 127, [3][1][2][1][RTW89_IC][45] = 127, @@ -17127,7 +17127,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_WW][9] = 32, [0][0][RTW89_WW][10] = 32, [0][0][RTW89_WW][11] = 32, - [0][0][RTW89_WW][12] = 32, + [0][0][RTW89_WW][12] = 24, [0][0][RTW89_WW][13] = 0, [0][1][RTW89_WW][0] = 20, [0][1][RTW89_WW][1] = 22, @@ -17154,8 +17154,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_WW][8] = 44, [1][0][RTW89_WW][9] = 44, [1][0][RTW89_WW][10] = 44, - [1][0][RTW89_WW][11] = 44, - [1][0][RTW89_WW][12] = 38, + [1][0][RTW89_WW][11] = 42, + [1][0][RTW89_WW][12] = 30, [1][0][RTW89_WW][13] = 0, [1][1][RTW89_WW][0] = 32, [1][1][RTW89_WW][1] = 32, @@ -17168,8 +17168,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_WW][8] = 32, [1][1][RTW89_WW][9] = 32, [1][1][RTW89_WW][10] = 32, - [1][1][RTW89_WW][11] = 32, - [1][1][RTW89_WW][12] = 32, + [1][1][RTW89_WW][11] = 30, + [1][1][RTW89_WW][12] = 24, [1][1][RTW89_WW][13] = 0, [2][0][RTW89_WW][0] = 56, [2][0][RTW89_WW][1] = 56, @@ -17182,8 +17182,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_WW][8] = 56, [2][0][RTW89_WW][9] = 56, [2][0][RTW89_WW][10] = 56, - [2][0][RTW89_WW][11] = 56, - [2][0][RTW89_WW][12] = 56, + [2][0][RTW89_WW][11] = 42, + [2][0][RTW89_WW][12] = 38, [2][0][RTW89_WW][13] = 0, [2][1][RTW89_WW][0] = 44, [2][1][RTW89_WW][1] = 44, @@ -17196,72 +17196,72 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_WW][8] = 44, [2][1][RTW89_WW][9] = 44, [2][1][RTW89_WW][10] = 44, - [2][1][RTW89_WW][11] = 44, - [2][1][RTW89_WW][12] = 42, + [2][1][RTW89_WW][11] = 30, + [2][1][RTW89_WW][12] = 26, [2][1][RTW89_WW][13] = 0, - [0][0][RTW89_FCC][0] = 68, - [0][0][RTW89_ETSI][0] = 36, - [0][0][RTW89_MKK][0] = 38, + [0][0][RTW89_FCC][0] = 60, + [0][0][RTW89_ETSI][0] = 34, + [0][0][RTW89_MKK][0] = 36, [0][0][RTW89_IC][0] = 68, [0][0][RTW89_ACMA][0] = 32, - [0][0][RTW89_FCC][1] = 68, - [0][0][RTW89_ETSI][1] = 40, - [0][0][RTW89_MKK][1] = 44, + [0][0][RTW89_FCC][1] = 60, + [0][0][RTW89_ETSI][1] = 38, + [0][0][RTW89_MKK][1] = 40, [0][0][RTW89_IC][1] = 68, [0][0][RTW89_ACMA][1] = 32, - [0][0][RTW89_FCC][2] = 72, - [0][0][RTW89_ETSI][2] = 40, - [0][0][RTW89_MKK][2] = 44, + [0][0][RTW89_FCC][2] = 64, + [0][0][RTW89_ETSI][2] = 38, + [0][0][RTW89_MKK][2] = 40, [0][0][RTW89_IC][2] = 72, [0][0][RTW89_ACMA][2] = 32, - [0][0][RTW89_FCC][3] = 76, - [0][0][RTW89_ETSI][3] = 40, - [0][0][RTW89_MKK][3] = 44, + [0][0][RTW89_FCC][3] = 68, + [0][0][RTW89_ETSI][3] = 38, + [0][0][RTW89_MKK][3] = 40, [0][0][RTW89_IC][3] = 76, [0][0][RTW89_ACMA][3] = 32, - [0][0][RTW89_FCC][4] = 76, - [0][0][RTW89_ETSI][4] = 40, - [0][0][RTW89_MKK][4] = 44, + [0][0][RTW89_FCC][4] = 68, + [0][0][RTW89_ETSI][4] = 38, + [0][0][RTW89_MKK][4] = 40, [0][0][RTW89_IC][4] = 76, [0][0][RTW89_ACMA][4] = 32, - [0][0][RTW89_FCC][5] = 84, - [0][0][RTW89_ETSI][5] = 40, - [0][0][RTW89_MKK][5] = 44, + [0][0][RTW89_FCC][5] = 76, + [0][0][RTW89_ETSI][5] = 38, + [0][0][RTW89_MKK][5] = 40, [0][0][RTW89_IC][5] = 84, [0][0][RTW89_ACMA][5] = 32, - [0][0][RTW89_FCC][6] = 74, - [0][0][RTW89_ETSI][6] = 40, - [0][0][RTW89_MKK][6] = 44, + [0][0][RTW89_FCC][6] = 66, + [0][0][RTW89_ETSI][6] = 38, + [0][0][RTW89_MKK][6] = 40, [0][0][RTW89_IC][6] = 74, [0][0][RTW89_ACMA][6] = 32, - [0][0][RTW89_FCC][7] = 74, - [0][0][RTW89_ETSI][7] = 40, - [0][0][RTW89_MKK][7] = 44, + [0][0][RTW89_FCC][7] = 66, + [0][0][RTW89_ETSI][7] = 38, + [0][0][RTW89_MKK][7] = 40, [0][0][RTW89_IC][7] = 74, [0][0][RTW89_ACMA][7] = 32, - [0][0][RTW89_FCC][8] = 70, - [0][0][RTW89_ETSI][8] = 40, - [0][0][RTW89_MKK][8] = 44, + [0][0][RTW89_FCC][8] = 62, + [0][0][RTW89_ETSI][8] = 38, + [0][0][RTW89_MKK][8] = 40, [0][0][RTW89_IC][8] = 70, [0][0][RTW89_ACMA][8] = 32, - [0][0][RTW89_FCC][9] = 66, - [0][0][RTW89_ETSI][9] = 40, - [0][0][RTW89_MKK][9] = 44, + [0][0][RTW89_FCC][9] = 58, + [0][0][RTW89_ETSI][9] = 38, + [0][0][RTW89_MKK][9] = 40, [0][0][RTW89_IC][9] = 66, [0][0][RTW89_ACMA][9] = 32, - [0][0][RTW89_FCC][10] = 66, - [0][0][RTW89_ETSI][10] = 40, - [0][0][RTW89_MKK][10] = 44, + [0][0][RTW89_FCC][10] = 58, + [0][0][RTW89_ETSI][10] = 38, + [0][0][RTW89_MKK][10] = 40, [0][0][RTW89_IC][10] = 66, [0][0][RTW89_ACMA][10] = 32, - [0][0][RTW89_FCC][11] = 56, - [0][0][RTW89_ETSI][11] = 40, - [0][0][RTW89_MKK][11] = 44, + [0][0][RTW89_FCC][11] = 42, + [0][0][RTW89_ETSI][11] = 38, + [0][0][RTW89_MKK][11] = 40, [0][0][RTW89_IC][11] = 56, [0][0][RTW89_ACMA][11] = 32, - [0][0][RTW89_FCC][12] = 32, - [0][0][RTW89_ETSI][12] = 36, - [0][0][RTW89_MKK][12] = 38, + [0][0][RTW89_FCC][12] = 24, + [0][0][RTW89_ETSI][12] = 34, + [0][0][RTW89_MKK][12] = 36, [0][0][RTW89_IC][12] = 32, [0][0][RTW89_ACMA][12] = 32, [0][0][RTW89_FCC][13] = 127, @@ -17269,69 +17269,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_MKK][13] = 127, [0][0][RTW89_IC][13] = 127, [0][0][RTW89_ACMA][13] = 127, - [0][1][RTW89_FCC][0] = 62, - [0][1][RTW89_ETSI][0] = 24, - [0][1][RTW89_MKK][0] = 26, + [0][1][RTW89_FCC][0] = 46, + [0][1][RTW89_ETSI][0] = 22, + [0][1][RTW89_MKK][0] = 24, [0][1][RTW89_IC][0] = 62, [0][1][RTW89_ACMA][0] = 20, - [0][1][RTW89_FCC][1] = 62, - [0][1][RTW89_ETSI][1] = 26, - [0][1][RTW89_MKK][1] = 32, + [0][1][RTW89_FCC][1] = 46, + [0][1][RTW89_ETSI][1] = 24, + [0][1][RTW89_MKK][1] = 30, [0][1][RTW89_IC][1] = 62, [0][1][RTW89_ACMA][1] = 22, - [0][1][RTW89_FCC][2] = 66, - [0][1][RTW89_ETSI][2] = 26, - [0][1][RTW89_MKK][2] = 32, + [0][1][RTW89_FCC][2] = 50, + [0][1][RTW89_ETSI][2] = 24, + [0][1][RTW89_MKK][2] = 30, [0][1][RTW89_IC][2] = 66, [0][1][RTW89_ACMA][2] = 22, - [0][1][RTW89_FCC][3] = 70, - [0][1][RTW89_ETSI][3] = 26, - [0][1][RTW89_MKK][3] = 32, + [0][1][RTW89_FCC][3] = 54, + [0][1][RTW89_ETSI][3] = 24, + [0][1][RTW89_MKK][3] = 30, [0][1][RTW89_IC][3] = 70, [0][1][RTW89_ACMA][3] = 22, - [0][1][RTW89_FCC][4] = 74, - [0][1][RTW89_ETSI][4] = 26, - [0][1][RTW89_MKK][4] = 32, + [0][1][RTW89_FCC][4] = 58, + [0][1][RTW89_ETSI][4] = 24, + [0][1][RTW89_MKK][4] = 30, [0][1][RTW89_IC][4] = 74, [0][1][RTW89_ACMA][4] = 22, - [0][1][RTW89_FCC][5] = 74, - [0][1][RTW89_ETSI][5] = 26, - [0][1][RTW89_MKK][5] = 32, + [0][1][RTW89_FCC][5] = 66, + [0][1][RTW89_ETSI][5] = 24, + [0][1][RTW89_MKK][5] = 30, [0][1][RTW89_IC][5] = 74, [0][1][RTW89_ACMA][5] = 22, - [0][1][RTW89_FCC][6] = 72, - [0][1][RTW89_ETSI][6] = 26, - [0][1][RTW89_MKK][6] = 32, + [0][1][RTW89_FCC][6] = 58, + [0][1][RTW89_ETSI][6] = 24, + [0][1][RTW89_MKK][6] = 30, [0][1][RTW89_IC][6] = 72, [0][1][RTW89_ACMA][6] = 22, - [0][1][RTW89_FCC][7] = 68, - [0][1][RTW89_ETSI][7] = 26, - [0][1][RTW89_MKK][7] = 32, + [0][1][RTW89_FCC][7] = 54, + [0][1][RTW89_ETSI][7] = 24, + [0][1][RTW89_MKK][7] = 30, [0][1][RTW89_IC][7] = 68, [0][1][RTW89_ACMA][7] = 22, - [0][1][RTW89_FCC][8] = 64, - [0][1][RTW89_ETSI][8] = 26, - [0][1][RTW89_MKK][8] = 32, + [0][1][RTW89_FCC][8] = 50, + [0][1][RTW89_ETSI][8] = 24, + [0][1][RTW89_MKK][8] = 30, [0][1][RTW89_IC][8] = 64, [0][1][RTW89_ACMA][8] = 22, - [0][1][RTW89_FCC][9] = 60, - [0][1][RTW89_ETSI][9] = 26, - [0][1][RTW89_MKK][9] = 32, + [0][1][RTW89_FCC][9] = 46, + [0][1][RTW89_ETSI][9] = 24, + [0][1][RTW89_MKK][9] = 30, [0][1][RTW89_IC][9] = 60, [0][1][RTW89_ACMA][9] = 22, - [0][1][RTW89_FCC][10] = 60, - [0][1][RTW89_ETSI][10] = 26, - [0][1][RTW89_MKK][10] = 32, + [0][1][RTW89_FCC][10] = 46, + [0][1][RTW89_ETSI][10] = 24, + [0][1][RTW89_MKK][10] = 30, [0][1][RTW89_IC][10] = 60, [0][1][RTW89_ACMA][10] = 22, - [0][1][RTW89_FCC][11] = 52, - [0][1][RTW89_ETSI][11] = 26, - [0][1][RTW89_MKK][11] = 32, + [0][1][RTW89_FCC][11] = 30, + [0][1][RTW89_ETSI][11] = 24, + [0][1][RTW89_MKK][11] = 30, [0][1][RTW89_IC][11] = 52, [0][1][RTW89_ACMA][11] = 22, - [0][1][RTW89_FCC][12] = 30, - [0][1][RTW89_ETSI][12] = 22, - [0][1][RTW89_MKK][12] = 26, + [0][1][RTW89_FCC][12] = 22, + [0][1][RTW89_ETSI][12] = 20, + [0][1][RTW89_MKK][12] = 24, [0][1][RTW89_IC][12] = 30, [0][1][RTW89_ACMA][12] = 20, [0][1][RTW89_FCC][13] = 127, @@ -17339,69 +17339,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_MKK][13] = 127, [0][1][RTW89_IC][13] = 127, [0][1][RTW89_ACMA][13] = 127, - [1][0][RTW89_FCC][0] = 78, - [1][0][RTW89_ETSI][0] = 48, + [1][0][RTW89_FCC][0] = 64, + [1][0][RTW89_ETSI][0] = 46, [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 78, [1][0][RTW89_ACMA][0] = 42, - [1][0][RTW89_FCC][1] = 78, - [1][0][RTW89_ETSI][1] = 48, + [1][0][RTW89_FCC][1] = 64, + [1][0][RTW89_ETSI][1] = 46, [1][0][RTW89_MKK][1] = 48, [1][0][RTW89_IC][1] = 78, [1][0][RTW89_ACMA][1] = 44, - [1][0][RTW89_FCC][2] = 82, - [1][0][RTW89_ETSI][2] = 48, + [1][0][RTW89_FCC][2] = 68, + [1][0][RTW89_ETSI][2] = 46, [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 82, [1][0][RTW89_ACMA][2] = 44, - [1][0][RTW89_FCC][3] = 84, - [1][0][RTW89_ETSI][3] = 48, + [1][0][RTW89_FCC][3] = 70, + [1][0][RTW89_ETSI][3] = 46, [1][0][RTW89_MKK][3] = 48, [1][0][RTW89_IC][3] = 84, [1][0][RTW89_ACMA][3] = 44, - [1][0][RTW89_FCC][4] = 84, - [1][0][RTW89_ETSI][4] = 48, + [1][0][RTW89_FCC][4] = 70, + [1][0][RTW89_ETSI][4] = 46, [1][0][RTW89_MKK][4] = 48, [1][0][RTW89_IC][4] = 84, [1][0][RTW89_ACMA][4] = 44, - [1][0][RTW89_FCC][5] = 84, - [1][0][RTW89_ETSI][5] = 48, + [1][0][RTW89_FCC][5] = 76, + [1][0][RTW89_ETSI][5] = 46, [1][0][RTW89_MKK][5] = 48, [1][0][RTW89_IC][5] = 84, [1][0][RTW89_ACMA][5] = 44, - [1][0][RTW89_FCC][6] = 78, - [1][0][RTW89_ETSI][6] = 46, + [1][0][RTW89_FCC][6] = 64, + [1][0][RTW89_ETSI][6] = 44, [1][0][RTW89_MKK][6] = 48, [1][0][RTW89_IC][6] = 78, [1][0][RTW89_ACMA][6] = 44, - [1][0][RTW89_FCC][7] = 78, - [1][0][RTW89_ETSI][7] = 48, + [1][0][RTW89_FCC][7] = 64, + [1][0][RTW89_ETSI][7] = 46, [1][0][RTW89_MKK][7] = 48, [1][0][RTW89_IC][7] = 78, [1][0][RTW89_ACMA][7] = 44, - [1][0][RTW89_FCC][8] = 78, - [1][0][RTW89_ETSI][8] = 48, + [1][0][RTW89_FCC][8] = 64, + [1][0][RTW89_ETSI][8] = 46, [1][0][RTW89_MKK][8] = 48, [1][0][RTW89_IC][8] = 78, [1][0][RTW89_ACMA][8] = 44, - [1][0][RTW89_FCC][9] = 74, - [1][0][RTW89_ETSI][9] = 48, + [1][0][RTW89_FCC][9] = 60, + [1][0][RTW89_ETSI][9] = 46, [1][0][RTW89_MKK][9] = 48, [1][0][RTW89_IC][9] = 74, [1][0][RTW89_ACMA][9] = 44, - [1][0][RTW89_FCC][10] = 74, - [1][0][RTW89_ETSI][10] = 48, + [1][0][RTW89_FCC][10] = 60, + [1][0][RTW89_ETSI][10] = 46, [1][0][RTW89_MKK][10] = 48, [1][0][RTW89_IC][10] = 74, [1][0][RTW89_ACMA][10] = 44, - [1][0][RTW89_FCC][11] = 72, - [1][0][RTW89_ETSI][11] = 48, + [1][0][RTW89_FCC][11] = 42, + [1][0][RTW89_ETSI][11] = 46, [1][0][RTW89_MKK][11] = 48, [1][0][RTW89_IC][11] = 72, [1][0][RTW89_ACMA][11] = 44, - [1][0][RTW89_FCC][12] = 38, - [1][0][RTW89_ETSI][12] = 48, - [1][0][RTW89_MKK][12] = 48, + [1][0][RTW89_FCC][12] = 30, + [1][0][RTW89_ETSI][12] = 46, + [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 38, [1][0][RTW89_ACMA][12] = 42, [1][0][RTW89_FCC][13] = 127, @@ -17409,69 +17409,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_MKK][13] = 127, [1][0][RTW89_IC][13] = 127, [1][0][RTW89_ACMA][13] = 127, - [1][1][RTW89_FCC][0] = 66, - [1][1][RTW89_ETSI][0] = 34, - [1][1][RTW89_MKK][0] = 36, + [1][1][RTW89_FCC][0] = 46, + [1][1][RTW89_ETSI][0] = 32, + [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 66, [1][1][RTW89_ACMA][0] = 32, - [1][1][RTW89_FCC][1] = 66, - [1][1][RTW89_ETSI][1] = 36, - [1][1][RTW89_MKK][1] = 36, + [1][1][RTW89_FCC][1] = 46, + [1][1][RTW89_ETSI][1] = 34, + [1][1][RTW89_MKK][1] = 34, [1][1][RTW89_IC][1] = 66, [1][1][RTW89_ACMA][1] = 32, - [1][1][RTW89_FCC][2] = 70, - [1][1][RTW89_ETSI][2] = 36, - [1][1][RTW89_MKK][2] = 36, + [1][1][RTW89_FCC][2] = 50, + [1][1][RTW89_ETSI][2] = 34, + [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 70, [1][1][RTW89_ACMA][2] = 32, - [1][1][RTW89_FCC][3] = 74, - [1][1][RTW89_ETSI][3] = 36, - [1][1][RTW89_MKK][3] = 36, + [1][1][RTW89_FCC][3] = 54, + [1][1][RTW89_ETSI][3] = 34, + [1][1][RTW89_MKK][3] = 34, [1][1][RTW89_IC][3] = 74, [1][1][RTW89_ACMA][3] = 32, - [1][1][RTW89_FCC][4] = 74, - [1][1][RTW89_ETSI][4] = 36, - [1][1][RTW89_MKK][4] = 36, + [1][1][RTW89_FCC][4] = 58, + [1][1][RTW89_ETSI][4] = 34, + [1][1][RTW89_MKK][4] = 34, [1][1][RTW89_IC][4] = 74, [1][1][RTW89_ACMA][4] = 32, - [1][1][RTW89_FCC][5] = 74, - [1][1][RTW89_ETSI][5] = 36, - [1][1][RTW89_MKK][5] = 36, + [1][1][RTW89_FCC][5] = 66, + [1][1][RTW89_ETSI][5] = 34, + [1][1][RTW89_MKK][5] = 34, [1][1][RTW89_IC][5] = 74, [1][1][RTW89_ACMA][5] = 32, - [1][1][RTW89_FCC][6] = 74, - [1][1][RTW89_ETSI][6] = 36, - [1][1][RTW89_MKK][6] = 36, + [1][1][RTW89_FCC][6] = 58, + [1][1][RTW89_ETSI][6] = 34, + [1][1][RTW89_MKK][6] = 34, [1][1][RTW89_IC][6] = 74, [1][1][RTW89_ACMA][6] = 32, - [1][1][RTW89_FCC][7] = 74, - [1][1][RTW89_ETSI][7] = 36, - [1][1][RTW89_MKK][7] = 36, + [1][1][RTW89_FCC][7] = 54, + [1][1][RTW89_ETSI][7] = 34, + [1][1][RTW89_MKK][7] = 34, [1][1][RTW89_IC][7] = 74, [1][1][RTW89_ACMA][7] = 32, - [1][1][RTW89_FCC][8] = 70, - [1][1][RTW89_ETSI][8] = 36, - [1][1][RTW89_MKK][8] = 36, + [1][1][RTW89_FCC][8] = 50, + [1][1][RTW89_ETSI][8] = 34, + [1][1][RTW89_MKK][8] = 34, [1][1][RTW89_IC][8] = 70, [1][1][RTW89_ACMA][8] = 32, - [1][1][RTW89_FCC][9] = 66, - [1][1][RTW89_ETSI][9] = 36, - [1][1][RTW89_MKK][9] = 36, + [1][1][RTW89_FCC][9] = 46, + [1][1][RTW89_ETSI][9] = 34, + [1][1][RTW89_MKK][9] = 34, [1][1][RTW89_IC][9] = 66, [1][1][RTW89_ACMA][9] = 32, - [1][1][RTW89_FCC][10] = 66, - [1][1][RTW89_ETSI][10] = 36, - [1][1][RTW89_MKK][10] = 36, + [1][1][RTW89_FCC][10] = 46, + [1][1][RTW89_ETSI][10] = 34, + [1][1][RTW89_MKK][10] = 34, [1][1][RTW89_IC][10] = 66, [1][1][RTW89_ACMA][10] = 32, - [1][1][RTW89_FCC][11] = 48, - [1][1][RTW89_ETSI][11] = 36, - [1][1][RTW89_MKK][11] = 36, + [1][1][RTW89_FCC][11] = 30, + [1][1][RTW89_ETSI][11] = 34, + [1][1][RTW89_MKK][11] = 34, [1][1][RTW89_IC][11] = 48, [1][1][RTW89_ACMA][11] = 32, - [1][1][RTW89_FCC][12] = 32, - [1][1][RTW89_ETSI][12] = 36, - [1][1][RTW89_MKK][12] = 36, + [1][1][RTW89_FCC][12] = 24, + [1][1][RTW89_ETSI][12] = 34, + [1][1][RTW89_MKK][12] = 34, [1][1][RTW89_IC][12] = 32, [1][1][RTW89_ACMA][12] = 32, [1][1][RTW89_FCC][13] = 127, @@ -17479,69 +17479,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_MKK][13] = 127, [1][1][RTW89_IC][13] = 127, [1][1][RTW89_ACMA][13] = 127, - [2][0][RTW89_FCC][0] = 78, - [2][0][RTW89_ETSI][0] = 60, - [2][0][RTW89_MKK][0] = 60, + [2][0][RTW89_FCC][0] = 64, + [2][0][RTW89_ETSI][0] = 58, + [2][0][RTW89_MKK][0] = 58, [2][0][RTW89_IC][0] = 78, [2][0][RTW89_ACMA][0] = 56, - [2][0][RTW89_FCC][1] = 78, - [2][0][RTW89_ETSI][1] = 60, - [2][0][RTW89_MKK][1] = 60, + [2][0][RTW89_FCC][1] = 64, + [2][0][RTW89_ETSI][1] = 58, + [2][0][RTW89_MKK][1] = 58, [2][0][RTW89_IC][1] = 78, [2][0][RTW89_ACMA][1] = 56, - [2][0][RTW89_FCC][2] = 80, - [2][0][RTW89_ETSI][2] = 60, - [2][0][RTW89_MKK][2] = 60, + [2][0][RTW89_FCC][2] = 66, + [2][0][RTW89_ETSI][2] = 58, + [2][0][RTW89_MKK][2] = 58, [2][0][RTW89_IC][2] = 80, [2][0][RTW89_ACMA][2] = 56, - [2][0][RTW89_FCC][3] = 80, - [2][0][RTW89_ETSI][3] = 60, - [2][0][RTW89_MKK][3] = 60, + [2][0][RTW89_FCC][3] = 66, + [2][0][RTW89_ETSI][3] = 58, + [2][0][RTW89_MKK][3] = 58, [2][0][RTW89_IC][3] = 80, [2][0][RTW89_ACMA][3] = 56, - [2][0][RTW89_FCC][4] = 80, - [2][0][RTW89_ETSI][4] = 60, - [2][0][RTW89_MKK][4] = 60, + [2][0][RTW89_FCC][4] = 66, + [2][0][RTW89_ETSI][4] = 58, + [2][0][RTW89_MKK][4] = 58, [2][0][RTW89_IC][4] = 80, [2][0][RTW89_ACMA][4] = 56, - [2][0][RTW89_FCC][5] = 84, - [2][0][RTW89_ETSI][5] = 60, - [2][0][RTW89_MKK][5] = 60, + [2][0][RTW89_FCC][5] = 76, + [2][0][RTW89_ETSI][5] = 58, + [2][0][RTW89_MKK][5] = 58, [2][0][RTW89_IC][5] = 84, [2][0][RTW89_ACMA][5] = 56, - [2][0][RTW89_FCC][6] = 76, - [2][0][RTW89_ETSI][6] = 58, - [2][0][RTW89_MKK][6] = 60, + [2][0][RTW89_FCC][6] = 62, + [2][0][RTW89_ETSI][6] = 56, + [2][0][RTW89_MKK][6] = 58, [2][0][RTW89_IC][6] = 76, [2][0][RTW89_ACMA][6] = 56, - [2][0][RTW89_FCC][7] = 76, - [2][0][RTW89_ETSI][7] = 60, - [2][0][RTW89_MKK][7] = 60, + [2][0][RTW89_FCC][7] = 62, + [2][0][RTW89_ETSI][7] = 58, + [2][0][RTW89_MKK][7] = 58, [2][0][RTW89_IC][7] = 76, [2][0][RTW89_ACMA][7] = 56, - [2][0][RTW89_FCC][8] = 76, - [2][0][RTW89_ETSI][8] = 60, - [2][0][RTW89_MKK][8] = 60, + [2][0][RTW89_FCC][8] = 62, + [2][0][RTW89_ETSI][8] = 58, + [2][0][RTW89_MKK][8] = 58, [2][0][RTW89_IC][8] = 76, [2][0][RTW89_ACMA][8] = 56, - [2][0][RTW89_FCC][9] = 74, - [2][0][RTW89_ETSI][9] = 60, - [2][0][RTW89_MKK][9] = 60, + [2][0][RTW89_FCC][9] = 60, + [2][0][RTW89_ETSI][9] = 58, + [2][0][RTW89_MKK][9] = 58, [2][0][RTW89_IC][9] = 74, [2][0][RTW89_ACMA][9] = 56, - [2][0][RTW89_FCC][10] = 74, - [2][0][RTW89_ETSI][10] = 60, - [2][0][RTW89_MKK][10] = 60, + [2][0][RTW89_FCC][10] = 60, + [2][0][RTW89_ETSI][10] = 58, + [2][0][RTW89_MKK][10] = 58, [2][0][RTW89_IC][10] = 74, [2][0][RTW89_ACMA][10] = 56, - [2][0][RTW89_FCC][11] = 66, - [2][0][RTW89_ETSI][11] = 60, - [2][0][RTW89_MKK][11] = 60, + [2][0][RTW89_FCC][11] = 42, + [2][0][RTW89_ETSI][11] = 58, + [2][0][RTW89_MKK][11] = 58, [2][0][RTW89_IC][11] = 66, [2][0][RTW89_ACMA][11] = 56, - [2][0][RTW89_FCC][12] = 56, - [2][0][RTW89_ETSI][12] = 60, - [2][0][RTW89_MKK][12] = 60, + [2][0][RTW89_FCC][12] = 38, + [2][0][RTW89_ETSI][12] = 58, + [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 56, [2][0][RTW89_ACMA][12] = 56, [2][0][RTW89_FCC][13] = 127, @@ -17549,69 +17549,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_MKK][13] = 127, [2][0][RTW89_IC][13] = 127, [2][0][RTW89_ACMA][13] = 127, - [2][1][RTW89_FCC][0] = 70, - [2][1][RTW89_ETSI][0] = 48, - [2][1][RTW89_MKK][0] = 48, + [2][1][RTW89_FCC][0] = 46, + [2][1][RTW89_ETSI][0] = 46, + [2][1][RTW89_MKK][0] = 46, [2][1][RTW89_IC][0] = 70, [2][1][RTW89_ACMA][0] = 44, - [2][1][RTW89_FCC][1] = 70, - [2][1][RTW89_ETSI][1] = 48, - [2][1][RTW89_MKK][1] = 48, + [2][1][RTW89_FCC][1] = 46, + [2][1][RTW89_ETSI][1] = 46, + [2][1][RTW89_MKK][1] = 46, [2][1][RTW89_IC][1] = 70, [2][1][RTW89_ACMA][1] = 44, - [2][1][RTW89_FCC][2] = 74, - [2][1][RTW89_ETSI][2] = 48, - [2][1][RTW89_MKK][2] = 48, + [2][1][RTW89_FCC][2] = 50, + [2][1][RTW89_ETSI][2] = 46, + [2][1][RTW89_MKK][2] = 46, [2][1][RTW89_IC][2] = 74, [2][1][RTW89_ACMA][2] = 44, - [2][1][RTW89_FCC][3] = 78, - [2][1][RTW89_ETSI][3] = 48, - [2][1][RTW89_MKK][3] = 48, + [2][1][RTW89_FCC][3] = 54, + [2][1][RTW89_ETSI][3] = 46, + [2][1][RTW89_MKK][3] = 46, [2][1][RTW89_IC][3] = 78, [2][1][RTW89_ACMA][3] = 44, - [2][1][RTW89_FCC][4] = 80, - [2][1][RTW89_ETSI][4] = 48, - [2][1][RTW89_MKK][4] = 48, + [2][1][RTW89_FCC][4] = 56, + [2][1][RTW89_ETSI][4] = 46, + [2][1][RTW89_MKK][4] = 46, [2][1][RTW89_IC][4] = 80, [2][1][RTW89_ACMA][4] = 44, - [2][1][RTW89_FCC][5] = 80, - [2][1][RTW89_ETSI][5] = 48, - [2][1][RTW89_MKK][5] = 48, + [2][1][RTW89_FCC][5] = 72, + [2][1][RTW89_ETSI][5] = 46, + [2][1][RTW89_MKK][5] = 46, [2][1][RTW89_IC][5] = 80, [2][1][RTW89_ACMA][5] = 44, - [2][1][RTW89_FCC][6] = 78, - [2][1][RTW89_ETSI][6] = 46, - [2][1][RTW89_MKK][6] = 48, + [2][1][RTW89_FCC][6] = 54, + [2][1][RTW89_ETSI][6] = 44, + [2][1][RTW89_MKK][6] = 46, [2][1][RTW89_IC][6] = 78, [2][1][RTW89_ACMA][6] = 44, - [2][1][RTW89_FCC][7] = 78, - [2][1][RTW89_ETSI][7] = 48, - [2][1][RTW89_MKK][7] = 48, + [2][1][RTW89_FCC][7] = 54, + [2][1][RTW89_ETSI][7] = 46, + [2][1][RTW89_MKK][7] = 46, [2][1][RTW89_IC][7] = 78, [2][1][RTW89_ACMA][7] = 44, - [2][1][RTW89_FCC][8] = 74, - [2][1][RTW89_ETSI][8] = 48, - [2][1][RTW89_MKK][8] = 48, + [2][1][RTW89_FCC][8] = 50, + [2][1][RTW89_ETSI][8] = 46, + [2][1][RTW89_MKK][8] = 46, [2][1][RTW89_IC][8] = 74, [2][1][RTW89_ACMA][8] = 44, - [2][1][RTW89_FCC][9] = 70, - [2][1][RTW89_ETSI][9] = 48, - [2][1][RTW89_MKK][9] = 48, + [2][1][RTW89_FCC][9] = 46, + [2][1][RTW89_ETSI][9] = 46, + [2][1][RTW89_MKK][9] = 46, [2][1][RTW89_IC][9] = 70, [2][1][RTW89_ACMA][9] = 44, - [2][1][RTW89_FCC][10] = 70, - [2][1][RTW89_ETSI][10] = 48, - [2][1][RTW89_MKK][10] = 48, + [2][1][RTW89_FCC][10] = 46, + [2][1][RTW89_ETSI][10] = 46, + [2][1][RTW89_MKK][10] = 46, [2][1][RTW89_IC][10] = 70, [2][1][RTW89_ACMA][10] = 44, - [2][1][RTW89_FCC][11] = 60, - [2][1][RTW89_ETSI][11] = 48, - [2][1][RTW89_MKK][11] = 48, + [2][1][RTW89_FCC][11] = 30, + [2][1][RTW89_ETSI][11] = 46, + [2][1][RTW89_MKK][11] = 46, [2][1][RTW89_IC][11] = 60, [2][1][RTW89_ACMA][11] = 44, - [2][1][RTW89_FCC][12] = 44, - [2][1][RTW89_ETSI][12] = 46, - [2][1][RTW89_MKK][12] = 48, + [2][1][RTW89_FCC][12] = 26, + [2][1][RTW89_ETSI][12] = 44, + [2][1][RTW89_MKK][12] = 46, [2][1][RTW89_IC][12] = 44, [2][1][RTW89_ACMA][12] = 42, [2][1][RTW89_FCC][13] = 127, @@ -17625,10 +17625,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = { [0][0][RTW89_WW][0] = 24, [0][0][RTW89_WW][2] = 24, - [0][0][RTW89_WW][4] = 24, - [0][0][RTW89_WW][6] = 24, - [0][0][RTW89_WW][8] = 24, - [0][0][RTW89_WW][10] = 24, + [0][0][RTW89_WW][4] = 22, + [0][0][RTW89_WW][6] = 22, + [0][0][RTW89_WW][8] = 18, + [0][0][RTW89_WW][10] = 18, [0][0][RTW89_WW][12] = 24, [0][0][RTW89_WW][14] = 24, [0][0][RTW89_WW][15] = 24, @@ -17636,21 +17636,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_WW][19] = 24, [0][0][RTW89_WW][21] = 24, [0][0][RTW89_WW][23] = 24, - [0][0][RTW89_WW][25] = 32, - [0][0][RTW89_WW][27] = 32, - [0][0][RTW89_WW][29] = 32, + [0][0][RTW89_WW][25] = 30, + [0][0][RTW89_WW][27] = 30, + [0][0][RTW89_WW][29] = 30, [0][0][RTW89_WW][31] = 24, [0][0][RTW89_WW][33] = 24, [0][0][RTW89_WW][35] = 24, [0][0][RTW89_WW][37] = 44, - [0][0][RTW89_WW][38] = 30, - [0][0][RTW89_WW][40] = 30, - [0][0][RTW89_WW][42] = 30, - [0][0][RTW89_WW][44] = 30, - [0][0][RTW89_WW][46] = 30, - [0][0][RTW89_WW][48] = 32, - [0][0][RTW89_WW][50] = 32, - [0][0][RTW89_WW][52] = 32, + [0][0][RTW89_WW][38] = 28, + [0][0][RTW89_WW][40] = 28, + [0][0][RTW89_WW][42] = 28, + [0][0][RTW89_WW][44] = 28, + [0][0][RTW89_WW][46] = 28, + [0][0][RTW89_WW][48] = 24, + [0][0][RTW89_WW][50] = 24, + [0][0][RTW89_WW][52] = 24, [0][1][RTW89_WW][0] = 0, [0][1][RTW89_WW][2] = 4, [0][1][RTW89_WW][4] = 0, @@ -17664,21 +17664,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_WW][19] = 12, [0][1][RTW89_WW][21] = 12, [0][1][RTW89_WW][23] = 12, - [0][1][RTW89_WW][25] = 20, - [0][1][RTW89_WW][27] = 18, - [0][1][RTW89_WW][29] = 18, + [0][1][RTW89_WW][25] = 18, + [0][1][RTW89_WW][27] = 16, + [0][1][RTW89_WW][29] = 16, [0][1][RTW89_WW][31] = 12, [0][1][RTW89_WW][33] = 12, [0][1][RTW89_WW][35] = 12, - [0][1][RTW89_WW][37] = 34, - [0][1][RTW89_WW][38] = 18, - [0][1][RTW89_WW][40] = 18, - [0][1][RTW89_WW][42] = 18, - [0][1][RTW89_WW][44] = 18, - [0][1][RTW89_WW][46] = 18, - [0][1][RTW89_WW][48] = 20, - [0][1][RTW89_WW][50] = 20, - [0][1][RTW89_WW][52] = 20, + [0][1][RTW89_WW][37] = 30, + [0][1][RTW89_WW][38] = 16, + [0][1][RTW89_WW][40] = 16, + [0][1][RTW89_WW][42] = 16, + [0][1][RTW89_WW][44] = 16, + [0][1][RTW89_WW][46] = 16, + [0][1][RTW89_WW][48] = 12, + [0][1][RTW89_WW][50] = 12, + [0][1][RTW89_WW][52] = 12, [1][0][RTW89_WW][0] = 34, [1][0][RTW89_WW][2] = 34, [1][0][RTW89_WW][4] = 34, @@ -17692,21 +17692,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_WW][19] = 34, [1][0][RTW89_WW][21] = 34, [1][0][RTW89_WW][23] = 34, - [1][0][RTW89_WW][25] = 42, - [1][0][RTW89_WW][27] = 44, - [1][0][RTW89_WW][29] = 44, + [1][0][RTW89_WW][25] = 40, + [1][0][RTW89_WW][27] = 42, + [1][0][RTW89_WW][29] = 42, [1][0][RTW89_WW][31] = 34, [1][0][RTW89_WW][33] = 34, [1][0][RTW89_WW][35] = 34, - [1][0][RTW89_WW][37] = 52, - [1][0][RTW89_WW][38] = 30, - [1][0][RTW89_WW][40] = 30, - [1][0][RTW89_WW][42] = 30, - [1][0][RTW89_WW][44] = 30, - [1][0][RTW89_WW][46] = 30, - [1][0][RTW89_WW][48] = 44, - [1][0][RTW89_WW][50] = 44, - [1][0][RTW89_WW][52] = 44, + [1][0][RTW89_WW][37] = 56, + [1][0][RTW89_WW][38] = 28, + [1][0][RTW89_WW][40] = 28, + [1][0][RTW89_WW][42] = 28, + [1][0][RTW89_WW][44] = 28, + [1][0][RTW89_WW][46] = 28, + [1][0][RTW89_WW][48] = 36, + [1][0][RTW89_WW][50] = 36, + [1][0][RTW89_WW][52] = 36, [1][1][RTW89_WW][0] = 10, [1][1][RTW89_WW][2] = 14, [1][1][RTW89_WW][4] = 10, @@ -17720,55 +17720,55 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_WW][19] = 22, [1][1][RTW89_WW][21] = 22, [1][1][RTW89_WW][23] = 22, - [1][1][RTW89_WW][25] = 30, - [1][1][RTW89_WW][27] = 32, - [1][1][RTW89_WW][29] = 32, + [1][1][RTW89_WW][25] = 28, + [1][1][RTW89_WW][27] = 30, + [1][1][RTW89_WW][29] = 30, [1][1][RTW89_WW][31] = 22, [1][1][RTW89_WW][33] = 22, [1][1][RTW89_WW][35] = 22, - [1][1][RTW89_WW][37] = 42, - [1][1][RTW89_WW][38] = 18, - [1][1][RTW89_WW][40] = 18, - [1][1][RTW89_WW][42] = 18, - [1][1][RTW89_WW][44] = 18, - [1][1][RTW89_WW][46] = 18, - [1][1][RTW89_WW][48] = 32, - [1][1][RTW89_WW][50] = 32, - [1][1][RTW89_WW][52] = 32, + [1][1][RTW89_WW][37] = 40, + [1][1][RTW89_WW][38] = 16, + [1][1][RTW89_WW][40] = 16, + [1][1][RTW89_WW][42] = 16, + [1][1][RTW89_WW][44] = 16, + [1][1][RTW89_WW][46] = 16, + [1][1][RTW89_WW][48] = 24, + [1][1][RTW89_WW][50] = 24, + [1][1][RTW89_WW][52] = 24, [2][0][RTW89_WW][0] = 46, [2][0][RTW89_WW][2] = 46, [2][0][RTW89_WW][4] = 46, [2][0][RTW89_WW][6] = 46, - [2][0][RTW89_WW][8] = 48, - [2][0][RTW89_WW][10] = 48, - [2][0][RTW89_WW][12] = 46, - [2][0][RTW89_WW][14] = 46, + [2][0][RTW89_WW][8] = 44, + [2][0][RTW89_WW][10] = 44, + [2][0][RTW89_WW][12] = 48, + [2][0][RTW89_WW][14] = 48, [2][0][RTW89_WW][15] = 48, [2][0][RTW89_WW][17] = 48, [2][0][RTW89_WW][19] = 48, [2][0][RTW89_WW][21] = 48, [2][0][RTW89_WW][23] = 48, - [2][0][RTW89_WW][25] = 54, - [2][0][RTW89_WW][27] = 54, - [2][0][RTW89_WW][29] = 54, + [2][0][RTW89_WW][25] = 52, + [2][0][RTW89_WW][27] = 52, + [2][0][RTW89_WW][29] = 52, [2][0][RTW89_WW][31] = 48, [2][0][RTW89_WW][33] = 48, [2][0][RTW89_WW][35] = 48, - [2][0][RTW89_WW][37] = 66, - [2][0][RTW89_WW][38] = 30, - [2][0][RTW89_WW][40] = 30, - [2][0][RTW89_WW][42] = 30, - [2][0][RTW89_WW][44] = 30, - [2][0][RTW89_WW][46] = 30, - [2][0][RTW89_WW][48] = 56, - [2][0][RTW89_WW][50] = 56, - [2][0][RTW89_WW][52] = 56, + [2][0][RTW89_WW][37] = 62, + [2][0][RTW89_WW][38] = 28, + [2][0][RTW89_WW][40] = 28, + [2][0][RTW89_WW][42] = 28, + [2][0][RTW89_WW][44] = 28, + [2][0][RTW89_WW][46] = 28, + [2][0][RTW89_WW][48] = 48, + [2][0][RTW89_WW][50] = 48, + [2][0][RTW89_WW][52] = 48, [2][1][RTW89_WW][0] = 20, [2][1][RTW89_WW][2] = 18, [2][1][RTW89_WW][4] = 22, [2][1][RTW89_WW][6] = 22, - [2][1][RTW89_WW][8] = 34, - [2][1][RTW89_WW][10] = 34, + [2][1][RTW89_WW][8] = 32, + [2][1][RTW89_WW][10] = 32, [2][1][RTW89_WW][12] = 36, [2][1][RTW89_WW][14] = 36, [2][1][RTW89_WW][15] = 36, @@ -17776,857 +17776,857 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_WW][19] = 36, [2][1][RTW89_WW][21] = 36, [2][1][RTW89_WW][23] = 36, - [2][1][RTW89_WW][25] = 42, - [2][1][RTW89_WW][27] = 42, - [2][1][RTW89_WW][29] = 42, + [2][1][RTW89_WW][25] = 40, + [2][1][RTW89_WW][27] = 40, + [2][1][RTW89_WW][29] = 40, [2][1][RTW89_WW][31] = 36, [2][1][RTW89_WW][33] = 36, [2][1][RTW89_WW][35] = 36, - [2][1][RTW89_WW][37] = 50, - [2][1][RTW89_WW][38] = 18, - [2][1][RTW89_WW][40] = 18, - [2][1][RTW89_WW][42] = 18, - [2][1][RTW89_WW][44] = 18, - [2][1][RTW89_WW][46] = 18, - [2][1][RTW89_WW][48] = 44, - [2][1][RTW89_WW][50] = 44, - [2][1][RTW89_WW][52] = 44, - [0][0][RTW89_FCC][0] = 52, - [0][0][RTW89_ETSI][0] = 32, - [0][0][RTW89_MKK][0] = 26, + [2][1][RTW89_WW][37] = 42, + [2][1][RTW89_WW][38] = 16, + [2][1][RTW89_WW][40] = 16, + [2][1][RTW89_WW][42] = 16, + [2][1][RTW89_WW][44] = 16, + [2][1][RTW89_WW][46] = 16, + [2][1][RTW89_WW][48] = 36, + [2][1][RTW89_WW][50] = 36, + [2][1][RTW89_WW][52] = 36, + [0][0][RTW89_FCC][0] = 44, + [0][0][RTW89_ETSI][0] = 30, + [0][0][RTW89_MKK][0] = 36, [0][0][RTW89_IC][0] = 24, [0][0][RTW89_ACMA][0] = 24, - [0][0][RTW89_FCC][2] = 52, - [0][0][RTW89_ETSI][2] = 32, - [0][0][RTW89_MKK][2] = 26, + [0][0][RTW89_FCC][2] = 44, + [0][0][RTW89_ETSI][2] = 30, + [0][0][RTW89_MKK][2] = 36, [0][0][RTW89_IC][2] = 24, [0][0][RTW89_ACMA][2] = 24, - [0][0][RTW89_FCC][4] = 52, - [0][0][RTW89_ETSI][4] = 32, - [0][0][RTW89_MKK][4] = 26, + [0][0][RTW89_FCC][4] = 44, + [0][0][RTW89_ETSI][4] = 30, + [0][0][RTW89_MKK][4] = 22, [0][0][RTW89_IC][4] = 24, [0][0][RTW89_ACMA][4] = 24, - [0][0][RTW89_FCC][6] = 52, - [0][0][RTW89_ETSI][6] = 32, - [0][0][RTW89_MKK][6] = 26, + [0][0][RTW89_FCC][6] = 44, + [0][0][RTW89_ETSI][6] = 30, + [0][0][RTW89_MKK][6] = 22, [0][0][RTW89_IC][6] = 24, [0][0][RTW89_ACMA][6] = 24, - [0][0][RTW89_FCC][8] = 52, - [0][0][RTW89_ETSI][8] = 30, - [0][0][RTW89_MKK][8] = 26, + [0][0][RTW89_FCC][8] = 44, + [0][0][RTW89_ETSI][8] = 28, + [0][0][RTW89_MKK][8] = 18, [0][0][RTW89_IC][8] = 52, [0][0][RTW89_ACMA][8] = 24, - [0][0][RTW89_FCC][10] = 52, - [0][0][RTW89_ETSI][10] = 30, - [0][0][RTW89_MKK][10] = 26, + [0][0][RTW89_FCC][10] = 44, + [0][0][RTW89_ETSI][10] = 28, + [0][0][RTW89_MKK][10] = 18, [0][0][RTW89_IC][10] = 52, [0][0][RTW89_ACMA][10] = 24, - [0][0][RTW89_FCC][12] = 52, - [0][0][RTW89_ETSI][12] = 30, - [0][0][RTW89_MKK][12] = 24, + [0][0][RTW89_FCC][12] = 44, + [0][0][RTW89_ETSI][12] = 28, + [0][0][RTW89_MKK][12] = 34, [0][0][RTW89_IC][12] = 52, [0][0][RTW89_ACMA][12] = 24, - [0][0][RTW89_FCC][14] = 52, - [0][0][RTW89_ETSI][14] = 30, - [0][0][RTW89_MKK][14] = 24, + [0][0][RTW89_FCC][14] = 44, + [0][0][RTW89_ETSI][14] = 28, + [0][0][RTW89_MKK][14] = 34, [0][0][RTW89_IC][14] = 52, [0][0][RTW89_ACMA][14] = 24, - [0][0][RTW89_FCC][15] = 52, - [0][0][RTW89_ETSI][15] = 32, - [0][0][RTW89_MKK][15] = 46, + [0][0][RTW89_FCC][15] = 44, + [0][0][RTW89_ETSI][15] = 30, + [0][0][RTW89_MKK][15] = 56, [0][0][RTW89_IC][15] = 52, [0][0][RTW89_ACMA][15] = 24, - [0][0][RTW89_FCC][17] = 52, - [0][0][RTW89_ETSI][17] = 32, - [0][0][RTW89_MKK][17] = 48, + [0][0][RTW89_FCC][17] = 44, + [0][0][RTW89_ETSI][17] = 30, + [0][0][RTW89_MKK][17] = 58, [0][0][RTW89_IC][17] = 52, [0][0][RTW89_ACMA][17] = 24, - [0][0][RTW89_FCC][19] = 52, - [0][0][RTW89_ETSI][19] = 32, - [0][0][RTW89_MKK][19] = 48, + [0][0][RTW89_FCC][19] = 44, + [0][0][RTW89_ETSI][19] = 30, + [0][0][RTW89_MKK][19] = 58, [0][0][RTW89_IC][19] = 52, [0][0][RTW89_ACMA][19] = 24, - [0][0][RTW89_FCC][21] = 52, - [0][0][RTW89_ETSI][21] = 32, - [0][0][RTW89_MKK][21] = 48, + [0][0][RTW89_FCC][21] = 44, + [0][0][RTW89_ETSI][21] = 30, + [0][0][RTW89_MKK][21] = 58, [0][0][RTW89_IC][21] = 52, [0][0][RTW89_ACMA][21] = 24, - [0][0][RTW89_FCC][23] = 52, - [0][0][RTW89_ETSI][23] = 32, - [0][0][RTW89_MKK][23] = 48, + [0][0][RTW89_FCC][23] = 44, + [0][0][RTW89_ETSI][23] = 30, + [0][0][RTW89_MKK][23] = 58, [0][0][RTW89_IC][23] = 52, [0][0][RTW89_ACMA][23] = 24, - [0][0][RTW89_FCC][25] = 52, - [0][0][RTW89_ETSI][25] = 32, - [0][0][RTW89_MKK][25] = 48, + [0][0][RTW89_FCC][25] = 44, + [0][0][RTW89_ETSI][25] = 30, + [0][0][RTW89_MKK][25] = 58, [0][0][RTW89_IC][25] = 127, [0][0][RTW89_ACMA][25] = 127, - [0][0][RTW89_FCC][27] = 52, - [0][0][RTW89_ETSI][27] = 32, - [0][0][RTW89_MKK][27] = 48, + [0][0][RTW89_FCC][27] = 44, + [0][0][RTW89_ETSI][27] = 30, + [0][0][RTW89_MKK][27] = 58, [0][0][RTW89_IC][27] = 127, [0][0][RTW89_ACMA][27] = 127, - [0][0][RTW89_FCC][29] = 52, - [0][0][RTW89_ETSI][29] = 32, - [0][0][RTW89_MKK][29] = 48, + [0][0][RTW89_FCC][29] = 44, + [0][0][RTW89_ETSI][29] = 30, + [0][0][RTW89_MKK][29] = 58, [0][0][RTW89_IC][29] = 127, [0][0][RTW89_ACMA][29] = 127, - [0][0][RTW89_FCC][31] = 52, - [0][0][RTW89_ETSI][31] = 32, - [0][0][RTW89_MKK][31] = 48, + [0][0][RTW89_FCC][31] = 44, + [0][0][RTW89_ETSI][31] = 30, + [0][0][RTW89_MKK][31] = 58, [0][0][RTW89_IC][31] = 52, [0][0][RTW89_ACMA][31] = 24, - [0][0][RTW89_FCC][33] = 52, - [0][0][RTW89_ETSI][33] = 32, - [0][0][RTW89_MKK][33] = 48, + [0][0][RTW89_FCC][33] = 44, + [0][0][RTW89_ETSI][33] = 30, + [0][0][RTW89_MKK][33] = 58, [0][0][RTW89_IC][33] = 52, [0][0][RTW89_ACMA][33] = 24, - [0][0][RTW89_FCC][35] = 52, - [0][0][RTW89_ETSI][35] = 32, - [0][0][RTW89_MKK][35] = 48, + [0][0][RTW89_FCC][35] = 44, + [0][0][RTW89_ETSI][35] = 30, + [0][0][RTW89_MKK][35] = 58, [0][0][RTW89_IC][35] = 52, [0][0][RTW89_ACMA][35] = 24, - [0][0][RTW89_FCC][37] = 52, + [0][0][RTW89_FCC][37] = 44, [0][0][RTW89_ETSI][37] = 127, - [0][0][RTW89_MKK][37] = 44, + [0][0][RTW89_MKK][37] = 58, [0][0][RTW89_IC][37] = 52, [0][0][RTW89_ACMA][37] = 52, - [0][0][RTW89_FCC][38] = 84, - [0][0][RTW89_ETSI][38] = 30, + [0][0][RTW89_FCC][38] = 76, + [0][0][RTW89_ETSI][38] = 28, [0][0][RTW89_MKK][38] = 127, [0][0][RTW89_IC][38] = 84, [0][0][RTW89_ACMA][38] = 84, - [0][0][RTW89_FCC][40] = 84, - [0][0][RTW89_ETSI][40] = 30, + [0][0][RTW89_FCC][40] = 76, + [0][0][RTW89_ETSI][40] = 28, [0][0][RTW89_MKK][40] = 127, [0][0][RTW89_IC][40] = 84, [0][0][RTW89_ACMA][40] = 84, - [0][0][RTW89_FCC][42] = 84, - [0][0][RTW89_ETSI][42] = 30, + [0][0][RTW89_FCC][42] = 76, + [0][0][RTW89_ETSI][42] = 28, [0][0][RTW89_MKK][42] = 127, [0][0][RTW89_IC][42] = 84, [0][0][RTW89_ACMA][42] = 84, - [0][0][RTW89_FCC][44] = 84, - [0][0][RTW89_ETSI][44] = 30, + [0][0][RTW89_FCC][44] = 76, + [0][0][RTW89_ETSI][44] = 28, [0][0][RTW89_MKK][44] = 127, [0][0][RTW89_IC][44] = 84, [0][0][RTW89_ACMA][44] = 84, - [0][0][RTW89_FCC][46] = 84, - [0][0][RTW89_ETSI][46] = 30, + [0][0][RTW89_FCC][46] = 76, + [0][0][RTW89_ETSI][46] = 28, [0][0][RTW89_MKK][46] = 127, [0][0][RTW89_IC][46] = 84, [0][0][RTW89_ACMA][46] = 84, - [0][0][RTW89_FCC][48] = 32, + [0][0][RTW89_FCC][48] = 24, [0][0][RTW89_ETSI][48] = 127, [0][0][RTW89_MKK][48] = 127, [0][0][RTW89_IC][48] = 127, [0][0][RTW89_ACMA][48] = 127, - [0][0][RTW89_FCC][50] = 32, + [0][0][RTW89_FCC][50] = 24, [0][0][RTW89_ETSI][50] = 127, [0][0][RTW89_MKK][50] = 127, [0][0][RTW89_IC][50] = 127, [0][0][RTW89_ACMA][50] = 127, - [0][0][RTW89_FCC][52] = 32, + [0][0][RTW89_FCC][52] = 24, [0][0][RTW89_ETSI][52] = 127, [0][0][RTW89_MKK][52] = 127, [0][0][RTW89_IC][52] = 127, [0][0][RTW89_ACMA][52] = 127, - [0][1][RTW89_FCC][0] = 34, - [0][1][RTW89_ETSI][0] = 20, - [0][1][RTW89_MKK][0] = 12, + [0][1][RTW89_FCC][0] = 26, + [0][1][RTW89_ETSI][0] = 18, + [0][1][RTW89_MKK][0] = 20, [0][1][RTW89_IC][0] = 0, [0][1][RTW89_ACMA][0] = 12, - [0][1][RTW89_FCC][2] = 38, - [0][1][RTW89_ETSI][2] = 20, - [0][1][RTW89_MKK][2] = 12, + [0][1][RTW89_FCC][2] = 30, + [0][1][RTW89_ETSI][2] = 18, + [0][1][RTW89_MKK][2] = 20, [0][1][RTW89_IC][2] = 4, [0][1][RTW89_ACMA][2] = 12, - [0][1][RTW89_FCC][4] = 34, - [0][1][RTW89_ETSI][4] = 20, - [0][1][RTW89_MKK][4] = 14, + [0][1][RTW89_FCC][4] = 26, + [0][1][RTW89_ETSI][4] = 18, + [0][1][RTW89_MKK][4] = 8, [0][1][RTW89_IC][4] = 0, [0][1][RTW89_ACMA][4] = 12, - [0][1][RTW89_FCC][6] = 34, - [0][1][RTW89_ETSI][6] = 20, - [0][1][RTW89_MKK][6] = 14, + [0][1][RTW89_FCC][6] = 26, + [0][1][RTW89_ETSI][6] = 18, + [0][1][RTW89_MKK][6] = 8, [0][1][RTW89_IC][6] = 0, [0][1][RTW89_ACMA][6] = 12, - [0][1][RTW89_FCC][8] = 34, - [0][1][RTW89_ETSI][8] = 18, - [0][1][RTW89_MKK][8] = 14, + [0][1][RTW89_FCC][8] = 26, + [0][1][RTW89_ETSI][8] = 16, + [0][1][RTW89_MKK][8] = 20, [0][1][RTW89_IC][8] = 34, [0][1][RTW89_ACMA][8] = 12, - [0][1][RTW89_FCC][10] = 34, - [0][1][RTW89_ETSI][10] = 18, - [0][1][RTW89_MKK][10] = 14, + [0][1][RTW89_FCC][10] = 26, + [0][1][RTW89_ETSI][10] = 16, + [0][1][RTW89_MKK][10] = 20, [0][1][RTW89_IC][10] = 34, [0][1][RTW89_ACMA][10] = 12, - [0][1][RTW89_FCC][12] = 38, - [0][1][RTW89_ETSI][12] = 18, - [0][1][RTW89_MKK][12] = 12, + [0][1][RTW89_FCC][12] = 30, + [0][1][RTW89_ETSI][12] = 16, + [0][1][RTW89_MKK][12] = 34, [0][1][RTW89_IC][12] = 38, [0][1][RTW89_ACMA][12] = 12, - [0][1][RTW89_FCC][14] = 34, - [0][1][RTW89_ETSI][14] = 18, - [0][1][RTW89_MKK][14] = 12, + [0][1][RTW89_FCC][14] = 26, + [0][1][RTW89_ETSI][14] = 16, + [0][1][RTW89_MKK][14] = 34, [0][1][RTW89_IC][14] = 34, [0][1][RTW89_ACMA][14] = 12, - [0][1][RTW89_FCC][15] = 34, - [0][1][RTW89_ETSI][15] = 20, - [0][1][RTW89_MKK][15] = 32, + [0][1][RTW89_FCC][15] = 26, + [0][1][RTW89_ETSI][15] = 18, + [0][1][RTW89_MKK][15] = 44, [0][1][RTW89_IC][15] = 34, [0][1][RTW89_ACMA][15] = 12, - [0][1][RTW89_FCC][17] = 34, - [0][1][RTW89_ETSI][17] = 20, - [0][1][RTW89_MKK][17] = 34, + [0][1][RTW89_FCC][17] = 26, + [0][1][RTW89_ETSI][17] = 18, + [0][1][RTW89_MKK][17] = 44, [0][1][RTW89_IC][17] = 34, [0][1][RTW89_ACMA][17] = 12, - [0][1][RTW89_FCC][19] = 38, - [0][1][RTW89_ETSI][19] = 20, - [0][1][RTW89_MKK][19] = 34, + [0][1][RTW89_FCC][19] = 30, + [0][1][RTW89_ETSI][19] = 18, + [0][1][RTW89_MKK][19] = 44, [0][1][RTW89_IC][19] = 38, [0][1][RTW89_ACMA][19] = 12, - [0][1][RTW89_FCC][21] = 38, - [0][1][RTW89_ETSI][21] = 20, - [0][1][RTW89_MKK][21] = 34, + [0][1][RTW89_FCC][21] = 30, + [0][1][RTW89_ETSI][21] = 18, + [0][1][RTW89_MKK][21] = 44, [0][1][RTW89_IC][21] = 38, [0][1][RTW89_ACMA][21] = 12, - [0][1][RTW89_FCC][23] = 38, - [0][1][RTW89_ETSI][23] = 20, - [0][1][RTW89_MKK][23] = 34, + [0][1][RTW89_FCC][23] = 30, + [0][1][RTW89_ETSI][23] = 18, + [0][1][RTW89_MKK][23] = 44, [0][1][RTW89_IC][23] = 38, [0][1][RTW89_ACMA][23] = 12, - [0][1][RTW89_FCC][25] = 38, - [0][1][RTW89_ETSI][25] = 20, - [0][1][RTW89_MKK][25] = 34, + [0][1][RTW89_FCC][25] = 30, + [0][1][RTW89_ETSI][25] = 18, + [0][1][RTW89_MKK][25] = 44, [0][1][RTW89_IC][25] = 127, [0][1][RTW89_ACMA][25] = 127, - [0][1][RTW89_FCC][27] = 38, - [0][1][RTW89_ETSI][27] = 18, - [0][1][RTW89_MKK][27] = 34, + [0][1][RTW89_FCC][27] = 30, + [0][1][RTW89_ETSI][27] = 16, + [0][1][RTW89_MKK][27] = 44, [0][1][RTW89_IC][27] = 127, [0][1][RTW89_ACMA][27] = 127, - [0][1][RTW89_FCC][29] = 38, - [0][1][RTW89_ETSI][29] = 18, - [0][1][RTW89_MKK][29] = 34, + [0][1][RTW89_FCC][29] = 30, + [0][1][RTW89_ETSI][29] = 16, + [0][1][RTW89_MKK][29] = 44, [0][1][RTW89_IC][29] = 127, [0][1][RTW89_ACMA][29] = 127, - [0][1][RTW89_FCC][31] = 38, - [0][1][RTW89_ETSI][31] = 18, - [0][1][RTW89_MKK][31] = 34, + [0][1][RTW89_FCC][31] = 30, + [0][1][RTW89_ETSI][31] = 16, + [0][1][RTW89_MKK][31] = 44, [0][1][RTW89_IC][31] = 34, [0][1][RTW89_ACMA][31] = 12, - [0][1][RTW89_FCC][33] = 34, - [0][1][RTW89_ETSI][33] = 18, - [0][1][RTW89_MKK][33] = 34, + [0][1][RTW89_FCC][33] = 26, + [0][1][RTW89_ETSI][33] = 16, + [0][1][RTW89_MKK][33] = 44, [0][1][RTW89_IC][33] = 34, [0][1][RTW89_ACMA][33] = 12, - [0][1][RTW89_FCC][35] = 34, - [0][1][RTW89_ETSI][35] = 18, - [0][1][RTW89_MKK][35] = 34, + [0][1][RTW89_FCC][35] = 26, + [0][1][RTW89_ETSI][35] = 16, + [0][1][RTW89_MKK][35] = 44, [0][1][RTW89_IC][35] = 34, [0][1][RTW89_ACMA][35] = 12, - [0][1][RTW89_FCC][37] = 38, + [0][1][RTW89_FCC][37] = 30, [0][1][RTW89_ETSI][37] = 127, - [0][1][RTW89_MKK][37] = 34, + [0][1][RTW89_MKK][37] = 44, [0][1][RTW89_IC][37] = 38, [0][1][RTW89_ACMA][37] = 38, - [0][1][RTW89_FCC][38] = 82, - [0][1][RTW89_ETSI][38] = 18, + [0][1][RTW89_FCC][38] = 74, + [0][1][RTW89_ETSI][38] = 16, [0][1][RTW89_MKK][38] = 127, [0][1][RTW89_IC][38] = 82, [0][1][RTW89_ACMA][38] = 84, - [0][1][RTW89_FCC][40] = 82, - [0][1][RTW89_ETSI][40] = 18, + [0][1][RTW89_FCC][40] = 74, + [0][1][RTW89_ETSI][40] = 16, [0][1][RTW89_MKK][40] = 127, [0][1][RTW89_IC][40] = 82, [0][1][RTW89_ACMA][40] = 84, - [0][1][RTW89_FCC][42] = 82, - [0][1][RTW89_ETSI][42] = 18, + [0][1][RTW89_FCC][42] = 74, + [0][1][RTW89_ETSI][42] = 16, [0][1][RTW89_MKK][42] = 127, [0][1][RTW89_IC][42] = 82, [0][1][RTW89_ACMA][42] = 84, - [0][1][RTW89_FCC][44] = 82, - [0][1][RTW89_ETSI][44] = 18, + [0][1][RTW89_FCC][44] = 74, + [0][1][RTW89_ETSI][44] = 16, [0][1][RTW89_MKK][44] = 127, [0][1][RTW89_IC][44] = 82, [0][1][RTW89_ACMA][44] = 84, - [0][1][RTW89_FCC][46] = 82, - [0][1][RTW89_ETSI][46] = 18, + [0][1][RTW89_FCC][46] = 74, + [0][1][RTW89_ETSI][46] = 16, [0][1][RTW89_MKK][46] = 127, [0][1][RTW89_IC][46] = 82, [0][1][RTW89_ACMA][46] = 84, - [0][1][RTW89_FCC][48] = 20, + [0][1][RTW89_FCC][48] = 12, [0][1][RTW89_ETSI][48] = 127, [0][1][RTW89_MKK][48] = 127, [0][1][RTW89_IC][48] = 127, [0][1][RTW89_ACMA][48] = 127, - [0][1][RTW89_FCC][50] = 20, + [0][1][RTW89_FCC][50] = 12, [0][1][RTW89_ETSI][50] = 127, [0][1][RTW89_MKK][50] = 127, [0][1][RTW89_IC][50] = 127, [0][1][RTW89_ACMA][50] = 127, - [0][1][RTW89_FCC][52] = 20, + [0][1][RTW89_FCC][52] = 12, [0][1][RTW89_ETSI][52] = 127, [0][1][RTW89_MKK][52] = 127, [0][1][RTW89_IC][52] = 127, [0][1][RTW89_ACMA][52] = 127, - [1][0][RTW89_FCC][0] = 62, - [1][0][RTW89_ETSI][0] = 42, - [1][0][RTW89_MKK][0] = 36, + [1][0][RTW89_FCC][0] = 54, + [1][0][RTW89_ETSI][0] = 40, + [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 36, [1][0][RTW89_ACMA][0] = 34, - [1][0][RTW89_FCC][2] = 62, - [1][0][RTW89_ETSI][2] = 42, - [1][0][RTW89_MKK][2] = 36, + [1][0][RTW89_FCC][2] = 54, + [1][0][RTW89_ETSI][2] = 40, + [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 36, [1][0][RTW89_ACMA][2] = 34, - [1][0][RTW89_FCC][4] = 62, - [1][0][RTW89_ETSI][4] = 42, - [1][0][RTW89_MKK][4] = 34, + [1][0][RTW89_FCC][4] = 54, + [1][0][RTW89_ETSI][4] = 40, + [1][0][RTW89_MKK][4] = 40, [1][0][RTW89_IC][4] = 36, [1][0][RTW89_ACMA][4] = 34, - [1][0][RTW89_FCC][6] = 62, - [1][0][RTW89_ETSI][6] = 42, - [1][0][RTW89_MKK][6] = 34, + [1][0][RTW89_FCC][6] = 54, + [1][0][RTW89_ETSI][6] = 40, + [1][0][RTW89_MKK][6] = 40, [1][0][RTW89_IC][6] = 36, [1][0][RTW89_ACMA][6] = 34, - [1][0][RTW89_FCC][8] = 62, - [1][0][RTW89_ETSI][8] = 42, - [1][0][RTW89_MKK][8] = 36, + [1][0][RTW89_FCC][8] = 54, + [1][0][RTW89_ETSI][8] = 40, + [1][0][RTW89_MKK][8] = 34, [1][0][RTW89_IC][8] = 62, [1][0][RTW89_ACMA][8] = 34, - [1][0][RTW89_FCC][10] = 62, - [1][0][RTW89_ETSI][10] = 42, - [1][0][RTW89_MKK][10] = 36, + [1][0][RTW89_FCC][10] = 54, + [1][0][RTW89_ETSI][10] = 40, + [1][0][RTW89_MKK][10] = 34, [1][0][RTW89_IC][10] = 62, [1][0][RTW89_ACMA][10] = 34, - [1][0][RTW89_FCC][12] = 64, - [1][0][RTW89_ETSI][12] = 42, - [1][0][RTW89_MKK][12] = 36, + [1][0][RTW89_FCC][12] = 56, + [1][0][RTW89_ETSI][12] = 40, + [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 64, [1][0][RTW89_ACMA][12] = 34, - [1][0][RTW89_FCC][14] = 62, - [1][0][RTW89_ETSI][14] = 42, - [1][0][RTW89_MKK][14] = 36, + [1][0][RTW89_FCC][14] = 54, + [1][0][RTW89_ETSI][14] = 40, + [1][0][RTW89_MKK][14] = 46, [1][0][RTW89_IC][14] = 62, [1][0][RTW89_ACMA][14] = 34, - [1][0][RTW89_FCC][15] = 62, - [1][0][RTW89_ETSI][15] = 42, - [1][0][RTW89_MKK][15] = 54, + [1][0][RTW89_FCC][15] = 54, + [1][0][RTW89_ETSI][15] = 40, + [1][0][RTW89_MKK][15] = 62, [1][0][RTW89_IC][15] = 62, [1][0][RTW89_ACMA][15] = 34, - [1][0][RTW89_FCC][17] = 62, - [1][0][RTW89_ETSI][17] = 42, - [1][0][RTW89_MKK][17] = 58, + [1][0][RTW89_FCC][17] = 54, + [1][0][RTW89_ETSI][17] = 40, + [1][0][RTW89_MKK][17] = 68, [1][0][RTW89_IC][17] = 62, [1][0][RTW89_ACMA][17] = 34, - [1][0][RTW89_FCC][19] = 62, - [1][0][RTW89_ETSI][19] = 42, - [1][0][RTW89_MKK][19] = 58, + [1][0][RTW89_FCC][19] = 54, + [1][0][RTW89_ETSI][19] = 40, + [1][0][RTW89_MKK][19] = 68, [1][0][RTW89_IC][19] = 62, [1][0][RTW89_ACMA][19] = 34, - [1][0][RTW89_FCC][21] = 62, - [1][0][RTW89_ETSI][21] = 42, - [1][0][RTW89_MKK][21] = 58, + [1][0][RTW89_FCC][21] = 54, + [1][0][RTW89_ETSI][21] = 40, + [1][0][RTW89_MKK][21] = 68, [1][0][RTW89_IC][21] = 62, [1][0][RTW89_ACMA][21] = 34, - [1][0][RTW89_FCC][23] = 62, - [1][0][RTW89_ETSI][23] = 42, - [1][0][RTW89_MKK][23] = 58, + [1][0][RTW89_FCC][23] = 54, + [1][0][RTW89_ETSI][23] = 40, + [1][0][RTW89_MKK][23] = 68, [1][0][RTW89_IC][23] = 62, [1][0][RTW89_ACMA][23] = 34, - [1][0][RTW89_FCC][25] = 62, - [1][0][RTW89_ETSI][25] = 42, - [1][0][RTW89_MKK][25] = 58, + [1][0][RTW89_FCC][25] = 54, + [1][0][RTW89_ETSI][25] = 40, + [1][0][RTW89_MKK][25] = 68, [1][0][RTW89_IC][25] = 127, [1][0][RTW89_ACMA][25] = 127, - [1][0][RTW89_FCC][27] = 62, - [1][0][RTW89_ETSI][27] = 44, - [1][0][RTW89_MKK][27] = 58, + [1][0][RTW89_FCC][27] = 54, + [1][0][RTW89_ETSI][27] = 42, + [1][0][RTW89_MKK][27] = 68, [1][0][RTW89_IC][27] = 127, [1][0][RTW89_ACMA][27] = 127, - [1][0][RTW89_FCC][29] = 62, - [1][0][RTW89_ETSI][29] = 44, - [1][0][RTW89_MKK][29] = 58, + [1][0][RTW89_FCC][29] = 54, + [1][0][RTW89_ETSI][29] = 42, + [1][0][RTW89_MKK][29] = 68, [1][0][RTW89_IC][29] = 127, [1][0][RTW89_ACMA][29] = 127, - [1][0][RTW89_FCC][31] = 62, - [1][0][RTW89_ETSI][31] = 44, - [1][0][RTW89_MKK][31] = 58, + [1][0][RTW89_FCC][31] = 54, + [1][0][RTW89_ETSI][31] = 42, + [1][0][RTW89_MKK][31] = 68, [1][0][RTW89_IC][31] = 62, [1][0][RTW89_ACMA][31] = 34, - [1][0][RTW89_FCC][33] = 62, - [1][0][RTW89_ETSI][33] = 44, - [1][0][RTW89_MKK][33] = 58, + [1][0][RTW89_FCC][33] = 54, + [1][0][RTW89_ETSI][33] = 42, + [1][0][RTW89_MKK][33] = 68, [1][0][RTW89_IC][33] = 62, [1][0][RTW89_ACMA][33] = 34, - [1][0][RTW89_FCC][35] = 62, - [1][0][RTW89_ETSI][35] = 44, - [1][0][RTW89_MKK][35] = 58, + [1][0][RTW89_FCC][35] = 54, + [1][0][RTW89_ETSI][35] = 42, + [1][0][RTW89_MKK][35] = 68, [1][0][RTW89_IC][35] = 62, [1][0][RTW89_ACMA][35] = 34, - [1][0][RTW89_FCC][37] = 64, + [1][0][RTW89_FCC][37] = 56, [1][0][RTW89_ETSI][37] = 127, - [1][0][RTW89_MKK][37] = 52, + [1][0][RTW89_MKK][37] = 68, [1][0][RTW89_IC][37] = 64, [1][0][RTW89_ACMA][37] = 64, - [1][0][RTW89_FCC][38] = 84, - [1][0][RTW89_ETSI][38] = 30, + [1][0][RTW89_FCC][38] = 76, + [1][0][RTW89_ETSI][38] = 28, [1][0][RTW89_MKK][38] = 127, [1][0][RTW89_IC][38] = 84, [1][0][RTW89_ACMA][38] = 84, - [1][0][RTW89_FCC][40] = 84, - [1][0][RTW89_ETSI][40] = 30, + [1][0][RTW89_FCC][40] = 76, + [1][0][RTW89_ETSI][40] = 28, [1][0][RTW89_MKK][40] = 127, [1][0][RTW89_IC][40] = 84, [1][0][RTW89_ACMA][40] = 84, - [1][0][RTW89_FCC][42] = 84, - [1][0][RTW89_ETSI][42] = 30, + [1][0][RTW89_FCC][42] = 76, + [1][0][RTW89_ETSI][42] = 28, [1][0][RTW89_MKK][42] = 127, [1][0][RTW89_IC][42] = 84, [1][0][RTW89_ACMA][42] = 84, - [1][0][RTW89_FCC][44] = 84, - [1][0][RTW89_ETSI][44] = 30, + [1][0][RTW89_FCC][44] = 76, + [1][0][RTW89_ETSI][44] = 28, [1][0][RTW89_MKK][44] = 127, [1][0][RTW89_IC][44] = 84, [1][0][RTW89_ACMA][44] = 84, - [1][0][RTW89_FCC][46] = 84, - [1][0][RTW89_ETSI][46] = 30, + [1][0][RTW89_FCC][46] = 76, + [1][0][RTW89_ETSI][46] = 28, [1][0][RTW89_MKK][46] = 127, [1][0][RTW89_IC][46] = 84, [1][0][RTW89_ACMA][46] = 84, - [1][0][RTW89_FCC][48] = 44, + [1][0][RTW89_FCC][48] = 36, [1][0][RTW89_ETSI][48] = 127, [1][0][RTW89_MKK][48] = 127, [1][0][RTW89_IC][48] = 127, [1][0][RTW89_ACMA][48] = 127, - [1][0][RTW89_FCC][50] = 44, + [1][0][RTW89_FCC][50] = 36, [1][0][RTW89_ETSI][50] = 127, [1][0][RTW89_MKK][50] = 127, [1][0][RTW89_IC][50] = 127, [1][0][RTW89_ACMA][50] = 127, - [1][0][RTW89_FCC][52] = 44, + [1][0][RTW89_FCC][52] = 36, [1][0][RTW89_ETSI][52] = 127, [1][0][RTW89_MKK][52] = 127, [1][0][RTW89_IC][52] = 127, [1][0][RTW89_ACMA][52] = 127, - [1][1][RTW89_FCC][0] = 42, - [1][1][RTW89_ETSI][0] = 32, - [1][1][RTW89_MKK][0] = 22, + [1][1][RTW89_FCC][0] = 34, + [1][1][RTW89_ETSI][0] = 30, + [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 10, [1][1][RTW89_ACMA][0] = 22, - [1][1][RTW89_FCC][2] = 44, - [1][1][RTW89_ETSI][2] = 32, - [1][1][RTW89_MKK][2] = 22, + [1][1][RTW89_FCC][2] = 36, + [1][1][RTW89_ETSI][2] = 30, + [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 14, [1][1][RTW89_ACMA][2] = 22, - [1][1][RTW89_FCC][4] = 42, - [1][1][RTW89_ETSI][4] = 32, - [1][1][RTW89_MKK][4] = 20, + [1][1][RTW89_FCC][4] = 34, + [1][1][RTW89_ETSI][4] = 30, + [1][1][RTW89_MKK][4] = 26, [1][1][RTW89_IC][4] = 10, [1][1][RTW89_ACMA][4] = 22, - [1][1][RTW89_FCC][6] = 42, - [1][1][RTW89_ETSI][6] = 32, - [1][1][RTW89_MKK][6] = 20, + [1][1][RTW89_FCC][6] = 34, + [1][1][RTW89_ETSI][6] = 30, + [1][1][RTW89_MKK][6] = 26, [1][1][RTW89_IC][6] = 10, [1][1][RTW89_ACMA][6] = 22, - [1][1][RTW89_FCC][8] = 44, - [1][1][RTW89_ETSI][8] = 32, + [1][1][RTW89_FCC][8] = 36, + [1][1][RTW89_ETSI][8] = 30, [1][1][RTW89_MKK][8] = 20, [1][1][RTW89_IC][8] = 44, [1][1][RTW89_ACMA][8] = 22, - [1][1][RTW89_FCC][10] = 44, - [1][1][RTW89_ETSI][10] = 32, + [1][1][RTW89_FCC][10] = 36, + [1][1][RTW89_ETSI][10] = 30, [1][1][RTW89_MKK][10] = 20, [1][1][RTW89_IC][10] = 44, [1][1][RTW89_ACMA][10] = 22, - [1][1][RTW89_FCC][12] = 46, - [1][1][RTW89_ETSI][12] = 32, - [1][1][RTW89_MKK][12] = 22, + [1][1][RTW89_FCC][12] = 38, + [1][1][RTW89_ETSI][12] = 30, + [1][1][RTW89_MKK][12] = 34, [1][1][RTW89_IC][12] = 46, [1][1][RTW89_ACMA][12] = 22, - [1][1][RTW89_FCC][14] = 42, - [1][1][RTW89_ETSI][14] = 32, - [1][1][RTW89_MKK][14] = 22, + [1][1][RTW89_FCC][14] = 34, + [1][1][RTW89_ETSI][14] = 30, + [1][1][RTW89_MKK][14] = 34, [1][1][RTW89_IC][14] = 40, [1][1][RTW89_ACMA][14] = 22, - [1][1][RTW89_FCC][15] = 42, - [1][1][RTW89_ETSI][15] = 30, - [1][1][RTW89_MKK][15] = 42, + [1][1][RTW89_FCC][15] = 34, + [1][1][RTW89_ETSI][15] = 28, + [1][1][RTW89_MKK][15] = 56, [1][1][RTW89_IC][15] = 42, [1][1][RTW89_ACMA][15] = 22, - [1][1][RTW89_FCC][17] = 42, - [1][1][RTW89_ETSI][17] = 30, - [1][1][RTW89_MKK][17] = 44, + [1][1][RTW89_FCC][17] = 34, + [1][1][RTW89_ETSI][17] = 28, + [1][1][RTW89_MKK][17] = 58, [1][1][RTW89_IC][17] = 42, [1][1][RTW89_ACMA][17] = 22, - [1][1][RTW89_FCC][19] = 42, - [1][1][RTW89_ETSI][19] = 30, - [1][1][RTW89_MKK][19] = 44, + [1][1][RTW89_FCC][19] = 34, + [1][1][RTW89_ETSI][19] = 28, + [1][1][RTW89_MKK][19] = 58, [1][1][RTW89_IC][19] = 42, [1][1][RTW89_ACMA][19] = 22, - [1][1][RTW89_FCC][21] = 42, - [1][1][RTW89_ETSI][21] = 30, - [1][1][RTW89_MKK][21] = 44, + [1][1][RTW89_FCC][21] = 34, + [1][1][RTW89_ETSI][21] = 28, + [1][1][RTW89_MKK][21] = 58, [1][1][RTW89_IC][21] = 42, [1][1][RTW89_ACMA][21] = 22, - [1][1][RTW89_FCC][23] = 42, - [1][1][RTW89_ETSI][23] = 30, - [1][1][RTW89_MKK][23] = 44, + [1][1][RTW89_FCC][23] = 34, + [1][1][RTW89_ETSI][23] = 28, + [1][1][RTW89_MKK][23] = 58, [1][1][RTW89_IC][23] = 42, [1][1][RTW89_ACMA][23] = 22, - [1][1][RTW89_FCC][25] = 42, - [1][1][RTW89_ETSI][25] = 30, - [1][1][RTW89_MKK][25] = 44, + [1][1][RTW89_FCC][25] = 34, + [1][1][RTW89_ETSI][25] = 28, + [1][1][RTW89_MKK][25] = 58, [1][1][RTW89_IC][25] = 127, [1][1][RTW89_ACMA][25] = 127, - [1][1][RTW89_FCC][27] = 42, - [1][1][RTW89_ETSI][27] = 32, - [1][1][RTW89_MKK][27] = 44, + [1][1][RTW89_FCC][27] = 34, + [1][1][RTW89_ETSI][27] = 30, + [1][1][RTW89_MKK][27] = 58, [1][1][RTW89_IC][27] = 127, [1][1][RTW89_ACMA][27] = 127, - [1][1][RTW89_FCC][29] = 42, - [1][1][RTW89_ETSI][29] = 32, - [1][1][RTW89_MKK][29] = 44, + [1][1][RTW89_FCC][29] = 34, + [1][1][RTW89_ETSI][29] = 30, + [1][1][RTW89_MKK][29] = 58, [1][1][RTW89_IC][29] = 127, [1][1][RTW89_ACMA][29] = 127, - [1][1][RTW89_FCC][31] = 42, - [1][1][RTW89_ETSI][31] = 32, - [1][1][RTW89_MKK][31] = 44, + [1][1][RTW89_FCC][31] = 34, + [1][1][RTW89_ETSI][31] = 30, + [1][1][RTW89_MKK][31] = 58, [1][1][RTW89_IC][31] = 38, [1][1][RTW89_ACMA][31] = 22, - [1][1][RTW89_FCC][33] = 40, - [1][1][RTW89_ETSI][33] = 32, - [1][1][RTW89_MKK][33] = 44, + [1][1][RTW89_FCC][33] = 32, + [1][1][RTW89_ETSI][33] = 30, + [1][1][RTW89_MKK][33] = 58, [1][1][RTW89_IC][33] = 38, [1][1][RTW89_ACMA][33] = 22, - [1][1][RTW89_FCC][35] = 40, - [1][1][RTW89_ETSI][35] = 32, - [1][1][RTW89_MKK][35] = 44, + [1][1][RTW89_FCC][35] = 32, + [1][1][RTW89_ETSI][35] = 30, + [1][1][RTW89_MKK][35] = 58, [1][1][RTW89_IC][35] = 38, [1][1][RTW89_ACMA][35] = 22, - [1][1][RTW89_FCC][37] = 48, + [1][1][RTW89_FCC][37] = 40, [1][1][RTW89_ETSI][37] = 127, - [1][1][RTW89_MKK][37] = 42, + [1][1][RTW89_MKK][37] = 58, [1][1][RTW89_IC][37] = 48, [1][1][RTW89_ACMA][37] = 48, - [1][1][RTW89_FCC][38] = 84, - [1][1][RTW89_ETSI][38] = 18, + [1][1][RTW89_FCC][38] = 76, + [1][1][RTW89_ETSI][38] = 16, [1][1][RTW89_MKK][38] = 127, [1][1][RTW89_IC][38] = 84, [1][1][RTW89_ACMA][38] = 82, - [1][1][RTW89_FCC][40] = 84, - [1][1][RTW89_ETSI][40] = 18, + [1][1][RTW89_FCC][40] = 76, + [1][1][RTW89_ETSI][40] = 16, [1][1][RTW89_MKK][40] = 127, [1][1][RTW89_IC][40] = 84, [1][1][RTW89_ACMA][40] = 82, - [1][1][RTW89_FCC][42] = 84, - [1][1][RTW89_ETSI][42] = 18, + [1][1][RTW89_FCC][42] = 76, + [1][1][RTW89_ETSI][42] = 16, [1][1][RTW89_MKK][42] = 127, [1][1][RTW89_IC][42] = 84, [1][1][RTW89_ACMA][42] = 84, - [1][1][RTW89_FCC][44] = 84, - [1][1][RTW89_ETSI][44] = 18, + [1][1][RTW89_FCC][44] = 76, + [1][1][RTW89_ETSI][44] = 16, [1][1][RTW89_MKK][44] = 127, [1][1][RTW89_IC][44] = 84, [1][1][RTW89_ACMA][44] = 84, - [1][1][RTW89_FCC][46] = 84, - [1][1][RTW89_ETSI][46] = 18, + [1][1][RTW89_FCC][46] = 76, + [1][1][RTW89_ETSI][46] = 16, [1][1][RTW89_MKK][46] = 127, [1][1][RTW89_IC][46] = 84, [1][1][RTW89_ACMA][46] = 84, - [1][1][RTW89_FCC][48] = 32, + [1][1][RTW89_FCC][48] = 24, [1][1][RTW89_ETSI][48] = 127, [1][1][RTW89_MKK][48] = 127, [1][1][RTW89_IC][48] = 127, [1][1][RTW89_ACMA][48] = 127, - [1][1][RTW89_FCC][50] = 32, + [1][1][RTW89_FCC][50] = 24, [1][1][RTW89_ETSI][50] = 127, [1][1][RTW89_MKK][50] = 127, [1][1][RTW89_IC][50] = 127, [1][1][RTW89_ACMA][50] = 127, - [1][1][RTW89_FCC][52] = 32, + [1][1][RTW89_FCC][52] = 24, [1][1][RTW89_ETSI][52] = 127, [1][1][RTW89_MKK][52] = 127, [1][1][RTW89_IC][52] = 127, [1][1][RTW89_ACMA][52] = 127, - [2][0][RTW89_FCC][0] = 70, - [2][0][RTW89_ETSI][0] = 54, - [2][0][RTW89_MKK][0] = 48, + [2][0][RTW89_FCC][0] = 62, + [2][0][RTW89_ETSI][0] = 52, + [2][0][RTW89_MKK][0] = 60, [2][0][RTW89_IC][0] = 46, [2][0][RTW89_ACMA][0] = 48, - [2][0][RTW89_FCC][2] = 70, - [2][0][RTW89_ETSI][2] = 54, - [2][0][RTW89_MKK][2] = 48, + [2][0][RTW89_FCC][2] = 62, + [2][0][RTW89_ETSI][2] = 52, + [2][0][RTW89_MKK][2] = 60, [2][0][RTW89_IC][2] = 46, [2][0][RTW89_ACMA][2] = 48, - [2][0][RTW89_FCC][4] = 70, - [2][0][RTW89_ETSI][4] = 54, - [2][0][RTW89_MKK][4] = 48, + [2][0][RTW89_FCC][4] = 62, + [2][0][RTW89_ETSI][4] = 52, + [2][0][RTW89_MKK][4] = 50, [2][0][RTW89_IC][4] = 46, [2][0][RTW89_ACMA][4] = 48, - [2][0][RTW89_FCC][6] = 70, - [2][0][RTW89_ETSI][6] = 54, - [2][0][RTW89_MKK][6] = 48, + [2][0][RTW89_FCC][6] = 62, + [2][0][RTW89_ETSI][6] = 52, + [2][0][RTW89_MKK][6] = 50, [2][0][RTW89_IC][6] = 46, [2][0][RTW89_ACMA][6] = 48, - [2][0][RTW89_FCC][8] = 70, - [2][0][RTW89_ETSI][8] = 54, - [2][0][RTW89_MKK][8] = 48, + [2][0][RTW89_FCC][8] = 62, + [2][0][RTW89_ETSI][8] = 52, + [2][0][RTW89_MKK][8] = 44, [2][0][RTW89_IC][8] = 66, [2][0][RTW89_ACMA][8] = 48, - [2][0][RTW89_FCC][10] = 70, - [2][0][RTW89_ETSI][10] = 54, - [2][0][RTW89_MKK][10] = 48, + [2][0][RTW89_FCC][10] = 62, + [2][0][RTW89_ETSI][10] = 52, + [2][0][RTW89_MKK][10] = 44, [2][0][RTW89_IC][10] = 66, [2][0][RTW89_ACMA][10] = 48, - [2][0][RTW89_FCC][12] = 70, - [2][0][RTW89_ETSI][12] = 54, - [2][0][RTW89_MKK][12] = 46, + [2][0][RTW89_FCC][12] = 62, + [2][0][RTW89_ETSI][12] = 52, + [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 66, [2][0][RTW89_ACMA][12] = 48, - [2][0][RTW89_FCC][14] = 70, - [2][0][RTW89_ETSI][14] = 54, - [2][0][RTW89_MKK][14] = 46, + [2][0][RTW89_FCC][14] = 62, + [2][0][RTW89_ETSI][14] = 52, + [2][0][RTW89_MKK][14] = 58, [2][0][RTW89_IC][14] = 66, [2][0][RTW89_ACMA][14] = 48, - [2][0][RTW89_FCC][15] = 70, - [2][0][RTW89_ETSI][15] = 54, + [2][0][RTW89_FCC][15] = 62, + [2][0][RTW89_ETSI][15] = 52, [2][0][RTW89_MKK][15] = 68, [2][0][RTW89_IC][15] = 70, [2][0][RTW89_ACMA][15] = 48, - [2][0][RTW89_FCC][17] = 70, - [2][0][RTW89_ETSI][17] = 54, - [2][0][RTW89_MKK][17] = 70, + [2][0][RTW89_FCC][17] = 62, + [2][0][RTW89_ETSI][17] = 52, + [2][0][RTW89_MKK][17] = 74, [2][0][RTW89_IC][17] = 70, [2][0][RTW89_ACMA][17] = 48, - [2][0][RTW89_FCC][19] = 70, - [2][0][RTW89_ETSI][19] = 54, - [2][0][RTW89_MKK][19] = 70, + [2][0][RTW89_FCC][19] = 62, + [2][0][RTW89_ETSI][19] = 52, + [2][0][RTW89_MKK][19] = 74, [2][0][RTW89_IC][19] = 70, [2][0][RTW89_ACMA][19] = 48, - [2][0][RTW89_FCC][21] = 70, - [2][0][RTW89_ETSI][21] = 54, - [2][0][RTW89_MKK][21] = 70, + [2][0][RTW89_FCC][21] = 62, + [2][0][RTW89_ETSI][21] = 52, + [2][0][RTW89_MKK][21] = 74, [2][0][RTW89_IC][21] = 70, [2][0][RTW89_ACMA][21] = 48, - [2][0][RTW89_FCC][23] = 70, - [2][0][RTW89_ETSI][23] = 54, - [2][0][RTW89_MKK][23] = 70, + [2][0][RTW89_FCC][23] = 62, + [2][0][RTW89_ETSI][23] = 52, + [2][0][RTW89_MKK][23] = 74, [2][0][RTW89_IC][23] = 70, [2][0][RTW89_ACMA][23] = 48, - [2][0][RTW89_FCC][25] = 70, - [2][0][RTW89_ETSI][25] = 54, - [2][0][RTW89_MKK][25] = 70, + [2][0][RTW89_FCC][25] = 62, + [2][0][RTW89_ETSI][25] = 52, + [2][0][RTW89_MKK][25] = 74, [2][0][RTW89_IC][25] = 127, [2][0][RTW89_ACMA][25] = 127, - [2][0][RTW89_FCC][27] = 70, - [2][0][RTW89_ETSI][27] = 54, - [2][0][RTW89_MKK][27] = 70, + [2][0][RTW89_FCC][27] = 62, + [2][0][RTW89_ETSI][27] = 52, + [2][0][RTW89_MKK][27] = 74, [2][0][RTW89_IC][27] = 127, [2][0][RTW89_ACMA][27] = 127, - [2][0][RTW89_FCC][29] = 70, - [2][0][RTW89_ETSI][29] = 54, - [2][0][RTW89_MKK][29] = 70, + [2][0][RTW89_FCC][29] = 62, + [2][0][RTW89_ETSI][29] = 52, + [2][0][RTW89_MKK][29] = 74, [2][0][RTW89_IC][29] = 127, [2][0][RTW89_ACMA][29] = 127, - [2][0][RTW89_FCC][31] = 70, - [2][0][RTW89_ETSI][31] = 54, - [2][0][RTW89_MKK][31] = 70, + [2][0][RTW89_FCC][31] = 62, + [2][0][RTW89_ETSI][31] = 52, + [2][0][RTW89_MKK][31] = 74, [2][0][RTW89_IC][31] = 72, [2][0][RTW89_ACMA][31] = 48, - [2][0][RTW89_FCC][33] = 72, - [2][0][RTW89_ETSI][33] = 54, - [2][0][RTW89_MKK][33] = 70, + [2][0][RTW89_FCC][33] = 64, + [2][0][RTW89_ETSI][33] = 52, + [2][0][RTW89_MKK][33] = 74, [2][0][RTW89_IC][33] = 72, [2][0][RTW89_ACMA][33] = 48, - [2][0][RTW89_FCC][35] = 72, - [2][0][RTW89_ETSI][35] = 54, - [2][0][RTW89_MKK][35] = 70, + [2][0][RTW89_FCC][35] = 64, + [2][0][RTW89_ETSI][35] = 52, + [2][0][RTW89_MKK][35] = 74, [2][0][RTW89_IC][35] = 72, [2][0][RTW89_ACMA][35] = 48, - [2][0][RTW89_FCC][37] = 70, + [2][0][RTW89_FCC][37] = 62, [2][0][RTW89_ETSI][37] = 127, - [2][0][RTW89_MKK][37] = 66, + [2][0][RTW89_MKK][37] = 74, [2][0][RTW89_IC][37] = 70, [2][0][RTW89_ACMA][37] = 76, - [2][0][RTW89_FCC][38] = 84, - [2][0][RTW89_ETSI][38] = 30, + [2][0][RTW89_FCC][38] = 76, + [2][0][RTW89_ETSI][38] = 28, [2][0][RTW89_MKK][38] = 127, [2][0][RTW89_IC][38] = 84, [2][0][RTW89_ACMA][38] = 84, - [2][0][RTW89_FCC][40] = 84, - [2][0][RTW89_ETSI][40] = 30, + [2][0][RTW89_FCC][40] = 76, + [2][0][RTW89_ETSI][40] = 28, [2][0][RTW89_MKK][40] = 127, [2][0][RTW89_IC][40] = 84, [2][0][RTW89_ACMA][40] = 84, - [2][0][RTW89_FCC][42] = 84, - [2][0][RTW89_ETSI][42] = 30, + [2][0][RTW89_FCC][42] = 76, + [2][0][RTW89_ETSI][42] = 28, [2][0][RTW89_MKK][42] = 127, [2][0][RTW89_IC][42] = 84, [2][0][RTW89_ACMA][42] = 84, - [2][0][RTW89_FCC][44] = 84, - [2][0][RTW89_ETSI][44] = 30, + [2][0][RTW89_FCC][44] = 76, + [2][0][RTW89_ETSI][44] = 28, [2][0][RTW89_MKK][44] = 127, [2][0][RTW89_IC][44] = 84, [2][0][RTW89_ACMA][44] = 84, - [2][0][RTW89_FCC][46] = 84, - [2][0][RTW89_ETSI][46] = 30, + [2][0][RTW89_FCC][46] = 76, + [2][0][RTW89_ETSI][46] = 28, [2][0][RTW89_MKK][46] = 127, [2][0][RTW89_IC][46] = 84, [2][0][RTW89_ACMA][46] = 84, - [2][0][RTW89_FCC][48] = 56, + [2][0][RTW89_FCC][48] = 48, [2][0][RTW89_ETSI][48] = 127, [2][0][RTW89_MKK][48] = 127, [2][0][RTW89_IC][48] = 127, [2][0][RTW89_ACMA][48] = 127, - [2][0][RTW89_FCC][50] = 56, + [2][0][RTW89_FCC][50] = 48, [2][0][RTW89_ETSI][50] = 127, [2][0][RTW89_MKK][50] = 127, [2][0][RTW89_IC][50] = 127, [2][0][RTW89_ACMA][50] = 127, - [2][0][RTW89_FCC][52] = 56, + [2][0][RTW89_FCC][52] = 48, [2][0][RTW89_ETSI][52] = 127, [2][0][RTW89_MKK][52] = 127, [2][0][RTW89_IC][52] = 127, [2][0][RTW89_ACMA][52] = 127, - [2][1][RTW89_FCC][0] = 50, - [2][1][RTW89_ETSI][0] = 42, - [2][1][RTW89_MKK][0] = 36, + [2][1][RTW89_FCC][0] = 42, + [2][1][RTW89_ETSI][0] = 40, + [2][1][RTW89_MKK][0] = 44, [2][1][RTW89_IC][0] = 20, [2][1][RTW89_ACMA][0] = 36, - [2][1][RTW89_FCC][2] = 50, - [2][1][RTW89_ETSI][2] = 42, - [2][1][RTW89_MKK][2] = 36, + [2][1][RTW89_FCC][2] = 42, + [2][1][RTW89_ETSI][2] = 40, + [2][1][RTW89_MKK][2] = 44, [2][1][RTW89_IC][2] = 18, [2][1][RTW89_ACMA][2] = 36, - [2][1][RTW89_FCC][4] = 50, - [2][1][RTW89_ETSI][4] = 42, + [2][1][RTW89_FCC][4] = 42, + [2][1][RTW89_ETSI][4] = 40, [2][1][RTW89_MKK][4] = 36, [2][1][RTW89_IC][4] = 22, [2][1][RTW89_ACMA][4] = 36, - [2][1][RTW89_FCC][6] = 50, - [2][1][RTW89_ETSI][6] = 42, + [2][1][RTW89_FCC][6] = 42, + [2][1][RTW89_ETSI][6] = 40, [2][1][RTW89_MKK][6] = 36, [2][1][RTW89_IC][6] = 22, [2][1][RTW89_ACMA][6] = 36, - [2][1][RTW89_FCC][8] = 50, - [2][1][RTW89_ETSI][8] = 42, - [2][1][RTW89_MKK][8] = 34, + [2][1][RTW89_FCC][8] = 42, + [2][1][RTW89_ETSI][8] = 40, + [2][1][RTW89_MKK][8] = 32, [2][1][RTW89_IC][8] = 50, [2][1][RTW89_ACMA][8] = 36, - [2][1][RTW89_FCC][10] = 50, - [2][1][RTW89_ETSI][10] = 42, - [2][1][RTW89_MKK][10] = 34, + [2][1][RTW89_FCC][10] = 42, + [2][1][RTW89_ETSI][10] = 40, + [2][1][RTW89_MKK][10] = 32, [2][1][RTW89_IC][10] = 50, [2][1][RTW89_ACMA][10] = 36, - [2][1][RTW89_FCC][12] = 52, - [2][1][RTW89_ETSI][12] = 42, - [2][1][RTW89_MKK][12] = 36, + [2][1][RTW89_FCC][12] = 44, + [2][1][RTW89_ETSI][12] = 40, + [2][1][RTW89_MKK][12] = 44, [2][1][RTW89_IC][12] = 52, [2][1][RTW89_ACMA][12] = 36, - [2][1][RTW89_FCC][14] = 52, - [2][1][RTW89_ETSI][14] = 42, - [2][1][RTW89_MKK][14] = 36, + [2][1][RTW89_FCC][14] = 44, + [2][1][RTW89_ETSI][14] = 40, + [2][1][RTW89_MKK][14] = 44, [2][1][RTW89_IC][14] = 52, [2][1][RTW89_ACMA][14] = 36, - [2][1][RTW89_FCC][15] = 50, - [2][1][RTW89_ETSI][15] = 42, - [2][1][RTW89_MKK][15] = 54, + [2][1][RTW89_FCC][15] = 42, + [2][1][RTW89_ETSI][15] = 40, + [2][1][RTW89_MKK][15] = 66, [2][1][RTW89_IC][15] = 50, [2][1][RTW89_ACMA][15] = 36, - [2][1][RTW89_FCC][17] = 50, - [2][1][RTW89_ETSI][17] = 42, - [2][1][RTW89_MKK][17] = 56, + [2][1][RTW89_FCC][17] = 42, + [2][1][RTW89_ETSI][17] = 40, + [2][1][RTW89_MKK][17] = 66, [2][1][RTW89_IC][17] = 50, [2][1][RTW89_ACMA][17] = 36, - [2][1][RTW89_FCC][19] = 50, - [2][1][RTW89_ETSI][19] = 42, - [2][1][RTW89_MKK][19] = 56, + [2][1][RTW89_FCC][19] = 42, + [2][1][RTW89_ETSI][19] = 40, + [2][1][RTW89_MKK][19] = 66, [2][1][RTW89_IC][19] = 50, [2][1][RTW89_ACMA][19] = 36, - [2][1][RTW89_FCC][21] = 50, - [2][1][RTW89_ETSI][21] = 42, - [2][1][RTW89_MKK][21] = 56, + [2][1][RTW89_FCC][21] = 42, + [2][1][RTW89_ETSI][21] = 40, + [2][1][RTW89_MKK][21] = 66, [2][1][RTW89_IC][21] = 50, [2][1][RTW89_ACMA][21] = 36, - [2][1][RTW89_FCC][23] = 50, - [2][1][RTW89_ETSI][23] = 42, - [2][1][RTW89_MKK][23] = 56, + [2][1][RTW89_FCC][23] = 42, + [2][1][RTW89_ETSI][23] = 40, + [2][1][RTW89_MKK][23] = 66, [2][1][RTW89_IC][23] = 50, [2][1][RTW89_ACMA][23] = 36, - [2][1][RTW89_FCC][25] = 50, - [2][1][RTW89_ETSI][25] = 42, - [2][1][RTW89_MKK][25] = 56, + [2][1][RTW89_FCC][25] = 42, + [2][1][RTW89_ETSI][25] = 40, + [2][1][RTW89_MKK][25] = 66, [2][1][RTW89_IC][25] = 127, [2][1][RTW89_ACMA][25] = 127, - [2][1][RTW89_FCC][27] = 50, - [2][1][RTW89_ETSI][27] = 42, - [2][1][RTW89_MKK][27] = 56, + [2][1][RTW89_FCC][27] = 42, + [2][1][RTW89_ETSI][27] = 40, + [2][1][RTW89_MKK][27] = 66, [2][1][RTW89_IC][27] = 127, [2][1][RTW89_ACMA][27] = 127, - [2][1][RTW89_FCC][29] = 50, - [2][1][RTW89_ETSI][29] = 42, - [2][1][RTW89_MKK][29] = 56, + [2][1][RTW89_FCC][29] = 42, + [2][1][RTW89_ETSI][29] = 40, + [2][1][RTW89_MKK][29] = 66, [2][1][RTW89_IC][29] = 127, [2][1][RTW89_ACMA][29] = 127, - [2][1][RTW89_FCC][31] = 50, - [2][1][RTW89_ETSI][31] = 42, - [2][1][RTW89_MKK][31] = 56, + [2][1][RTW89_FCC][31] = 42, + [2][1][RTW89_ETSI][31] = 40, + [2][1][RTW89_MKK][31] = 66, [2][1][RTW89_IC][31] = 50, [2][1][RTW89_ACMA][31] = 36, - [2][1][RTW89_FCC][33] = 50, - [2][1][RTW89_ETSI][33] = 42, - [2][1][RTW89_MKK][33] = 56, + [2][1][RTW89_FCC][33] = 42, + [2][1][RTW89_ETSI][33] = 40, + [2][1][RTW89_MKK][33] = 66, [2][1][RTW89_IC][33] = 50, [2][1][RTW89_ACMA][33] = 36, - [2][1][RTW89_FCC][35] = 50, - [2][1][RTW89_ETSI][35] = 42, - [2][1][RTW89_MKK][35] = 56, + [2][1][RTW89_FCC][35] = 42, + [2][1][RTW89_ETSI][35] = 40, + [2][1][RTW89_MKK][35] = 66, [2][1][RTW89_IC][35] = 50, [2][1][RTW89_ACMA][35] = 36, - [2][1][RTW89_FCC][37] = 50, + [2][1][RTW89_FCC][37] = 42, [2][1][RTW89_ETSI][37] = 127, - [2][1][RTW89_MKK][37] = 54, + [2][1][RTW89_MKK][37] = 66, [2][1][RTW89_IC][37] = 50, [2][1][RTW89_ACMA][37] = 60, - [2][1][RTW89_FCC][38] = 84, - [2][1][RTW89_ETSI][38] = 18, + [2][1][RTW89_FCC][38] = 76, + [2][1][RTW89_ETSI][38] = 16, [2][1][RTW89_MKK][38] = 127, [2][1][RTW89_IC][38] = 84, [2][1][RTW89_ACMA][38] = 84, - [2][1][RTW89_FCC][40] = 84, - [2][1][RTW89_ETSI][40] = 18, + [2][1][RTW89_FCC][40] = 76, + [2][1][RTW89_ETSI][40] = 16, [2][1][RTW89_MKK][40] = 127, [2][1][RTW89_IC][40] = 84, [2][1][RTW89_ACMA][40] = 84, - [2][1][RTW89_FCC][42] = 84, - [2][1][RTW89_ETSI][42] = 18, + [2][1][RTW89_FCC][42] = 76, + [2][1][RTW89_ETSI][42] = 16, [2][1][RTW89_MKK][42] = 127, [2][1][RTW89_IC][42] = 84, [2][1][RTW89_ACMA][42] = 84, - [2][1][RTW89_FCC][44] = 84, - [2][1][RTW89_ETSI][44] = 18, + [2][1][RTW89_FCC][44] = 76, + [2][1][RTW89_ETSI][44] = 16, [2][1][RTW89_MKK][44] = 127, [2][1][RTW89_IC][44] = 84, [2][1][RTW89_ACMA][44] = 84, - [2][1][RTW89_FCC][46] = 84, - [2][1][RTW89_ETSI][46] = 18, + [2][1][RTW89_FCC][46] = 76, + [2][1][RTW89_ETSI][46] = 16, [2][1][RTW89_MKK][46] = 127, [2][1][RTW89_IC][46] = 84, [2][1][RTW89_ACMA][46] = 84, - [2][1][RTW89_FCC][48] = 44, + [2][1][RTW89_FCC][48] = 36, [2][1][RTW89_ETSI][48] = 127, [2][1][RTW89_MKK][48] = 127, [2][1][RTW89_IC][48] = 127, [2][1][RTW89_ACMA][48] = 127, - [2][1][RTW89_FCC][50] = 44, + [2][1][RTW89_FCC][50] = 36, [2][1][RTW89_ETSI][50] = 127, [2][1][RTW89_MKK][50] = 127, [2][1][RTW89_IC][50] = 127, [2][1][RTW89_ACMA][50] = 127, - [2][1][RTW89_FCC][52] = 44, + [2][1][RTW89_FCC][52] = 36, [2][1][RTW89_ETSI][52] = 127, [2][1][RTW89_MKK][52] = 127, [2][1][RTW89_IC][52] = 127, diff --git a/drivers/net/wireless/silabs/wfx/bh.c b/drivers/net/wireless/silabs/wfx/bh.c index bcea9d5b119c..21dfdcf9cc27 100644 --- a/drivers/net/wireless/silabs/wfx/bh.c +++ b/drivers/net/wireless/silabs/wfx/bh.c @@ -267,7 +267,7 @@ void wfx_bh_request_rx(struct wfx_dev *wdev) wfx_control_reg_read(wdev, &cur); prev = atomic_xchg(&wdev->hif.ctrl_reg, cur); complete(&wdev->hif.ctrl_ready); - queue_work(system_highpri_wq, &wdev->hif.bh); + queue_work(wdev->bh_wq, &wdev->hif.bh); if (!(cur & CTRL_NEXT_LEN_MASK)) dev_err(wdev->dev, "unexpected control register value: length field is 0: %04x\n", @@ -280,7 +280,7 @@ void wfx_bh_request_rx(struct wfx_dev *wdev) /* Driver want to send data */ void wfx_bh_request_tx(struct wfx_dev *wdev) { - queue_work(system_highpri_wq, &wdev->hif.bh); + queue_work(wdev->bh_wq, &wdev->hif.bh); } /* If IRQ is not available, this function allow to manually poll the control register and simulate @@ -295,7 +295,7 @@ void wfx_bh_poll_irq(struct wfx_dev *wdev) u32 reg; WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ"); - flush_workqueue(system_highpri_wq); + flush_workqueue(wdev->bh_wq); start = ktime_get(); for (;;) { wfx_control_reg_read(wdev, ®); diff --git a/drivers/net/wireless/silabs/wfx/data_rx.c b/drivers/net/wireless/silabs/wfx/data_rx.c index a4b5ffe158e4..e099a9e65bae 100644 --- a/drivers/net/wireless/silabs/wfx/data_rx.c +++ b/drivers/net/wireless/silabs/wfx/data_rx.c @@ -15,6 +15,7 @@ static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); int params, tid; if (wfx_api_older_than(wvif->wdev, 3, 6)) @@ -24,12 +25,12 @@ static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt) case WLAN_ACTION_ADDBA_REQ: params = le16_to_cpu(mgmt->u.action.u.addba_req.capab); tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); + ieee80211_start_rx_ba_session_offl(vif, mgmt->sa, tid); break; case WLAN_ACTION_DELBA: params = le16_to_cpu(mgmt->u.action.u.delba.params); tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; - ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid); + ieee80211_stop_rx_ba_session_offl(vif, mgmt->sa, tid); break; } } diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c index e07381b2ff4d..6a5e52a96d18 100644 --- a/drivers/net/wireless/silabs/wfx/data_tx.c +++ b/drivers/net/wireless/silabs/wfx/data_tx.c @@ -212,11 +212,12 @@ static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr) { struct wfx_sta_priv *sta_priv = sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL; + struct ieee80211_vif *vif = wvif_to_vif(wvif); const u8 *da = ieee80211_get_DA(hdr); if (sta_priv && sta_priv->link_id) return sta_priv->link_id; - if (wvif->vif->type != NL80211_IFTYPE_AP) + if (vif->type != NL80211_IFTYPE_AP) return 0; if (is_multicast_ether_addr(da)) return 0; diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c index ae3cc5919dcd..2b92c227efbc 100644 --- a/drivers/net/wireless/silabs/wfx/hif_tx.c +++ b/drivers/net/wireless/silabs/wfx/hif_tx.c @@ -73,7 +73,7 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request, if (no_reply) { /* Chip won't reply. Ensure the wq has send the buffer before to continue. */ - flush_workqueue(system_highpri_wq); + flush_workqueue(wdev->bh_wq); ret = 0; goto end; } diff --git a/drivers/net/wireless/silabs/wfx/key.c b/drivers/net/wireless/silabs/wfx/key.c index 8f23e8d42bd4..196d64ef68f3 100644 --- a/drivers/net/wireless/silabs/wfx/key.c +++ b/drivers/net/wireless/silabs/wfx/key.c @@ -156,6 +156,7 @@ static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct wfx_dev *wdev = wvif->wdev; int idx = wfx_alloc_key(wvif->wdev); bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE; + struct ieee80211_vif *vif = wvif_to_vif(wvif); WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data"); ieee80211_get_key_rx_seq(key, 0, &seq); @@ -174,7 +175,7 @@ static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta, k.type = fill_tkip_pair(&k.key.tkip_pairwise_key, key, sta->addr); else k.type = fill_tkip_group(&k.key.tkip_group_key, key, &seq, - wvif->vif->type); + vif->type); } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) { if (pairwise) k.type = fill_ccmp_pair(&k.key.aes_pairwise_key, key, sta->addr); @@ -224,4 +225,3 @@ int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_ mutex_unlock(&wvif->wdev->conf_mutex); return ret; } - diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c index b93b16b900c8..bbfd3fa51921 100644 --- a/drivers/net/wireless/silabs/wfx/main.c +++ b/drivers/net/wireless/silabs/wfx/main.c @@ -345,6 +345,10 @@ int wfx_probe(struct wfx_dev *wdev) wdev->pdata.gpio_wakeup = NULL; wdev->poll_irq = true; + wdev->bh_wq = alloc_workqueue("wfx_bh_wq", WQ_HIGHPRI, 0); + if (!wdev->bh_wq) + return -ENOMEM; + wfx_bh_register(wdev); err = wfx_init_device(wdev); @@ -458,6 +462,7 @@ irq_unsubscribe: wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); bh_unregister: wfx_bh_unregister(wdev); + destroy_workqueue(wdev->bh_wq); return err; } @@ -467,6 +472,7 @@ void wfx_release(struct wfx_dev *wdev) wfx_hif_shutdown(wdev); wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); wfx_bh_unregister(wdev); + destroy_workqueue(wdev->bh_wq); } static int __init wfx_core_init(void) diff --git a/drivers/net/wireless/silabs/wfx/queue.c b/drivers/net/wireless/silabs/wfx/queue.c index 729825230db2..37f492e5d3be 100644 --- a/drivers/net/wireless/silabs/wfx/queue.c +++ b/drivers/net/wireless/silabs/wfx/queue.c @@ -205,9 +205,10 @@ unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, struct sk_buff * bool wfx_tx_queues_has_cab(struct wfx_vif *wvif) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); int i; - if (wvif->vif->type != NL80211_IFTYPE_AP) + if (vif->type != NL80211_IFTYPE_AP) return false; for (i = 0; i < IEEE80211_NUM_ACS; ++i) /* Note: since only AP can have mcast frames in queue and only one vif can be AP, diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c index 7f34f0d322f9..16f619ed22e0 100644 --- a/drivers/net/wireless/silabs/wfx/scan.c +++ b/drivers/net/wireless/silabs/wfx/scan.c @@ -23,9 +23,11 @@ static void wfx_ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool ab static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request *req) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); struct sk_buff *skb; - skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, NULL, 0, req->ie_len); + skb = ieee80211_probereq_get(wvif->wdev->hw, vif->addr, NULL, 0, + req->ie_len); if (!skb) return -ENOMEM; @@ -37,8 +39,9 @@ static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request static int send_scan_req(struct wfx_vif *wvif, struct cfg80211_scan_request *req, int start_idx) { - int i, ret; + struct ieee80211_vif *vif = wvif_to_vif(wvif); struct ieee80211_channel *ch_start, *ch_cur; + int i, ret; for (i = start_idx; i < req->n_channels; i++) { ch_start = req->channels[start_idx]; @@ -75,8 +78,8 @@ static int send_scan_req(struct wfx_vif *wvif, struct cfg80211_scan_request *req } else { ret = wvif->scan_nb_chan_done; } - if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower) - wfx_hif_set_output_power(wvif, wvif->vif->bss_conf.txpower); + if (req->channels[start_idx]->max_power != vif->bss_conf.txpower) + wfx_hif_set_output_power(wvif, vif->bss_conf.txpower); wfx_tx_unlock(wvif->wdev); return ret; } diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c index 3297d73c327a..e551fa284a43 100644 --- a/drivers/net/wireless/silabs/wfx/sta.c +++ b/drivers/net/wireless/silabs/wfx/sta.c @@ -98,9 +98,10 @@ static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon) void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, u64 unused) { - struct wfx_vif *wvif = NULL; - struct wfx_dev *wdev = hw->priv; bool filter_bssid, filter_prbreq, filter_beacon; + struct ieee80211_vif *vif = NULL; + struct wfx_dev *wdev = hw->priv; + struct wfx_vif *wvif = NULL; /* Notes: * - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered @@ -131,8 +132,9 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, else filter_bssid = true; + vif = wvif_to_vif(wvif); /* In AP mode, chip can reply to probe request itself */ - if (*total_flags & FIF_PROBE_REQ && wvif->vif->type == NL80211_IFTYPE_AP) { + if (*total_flags & FIF_PROBE_REQ && vif->type == NL80211_IFTYPE_AP) { dev_dbg(wdev->dev, "do not forward probe request in AP mode\n"); *total_flags &= ~FIF_PROBE_REQ; } @@ -152,19 +154,28 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) { struct ieee80211_channel *chan0 = NULL, *chan1 = NULL; struct ieee80211_conf *conf = &wvif->wdev->hw->conf; + struct ieee80211_vif *vif = wvif_to_vif(wvif); - WARN(!wvif->vif->bss_conf.assoc && enable_ps, + WARN(!vif->bss_conf.assoc && enable_ps, "enable_ps is reliable only if associated"); - if (wdev_to_wvif(wvif->wdev, 0)) - chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan; - if (wdev_to_wvif(wvif->wdev, 1)) - chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan; - if (chan0 && chan1 && wvif->vif->type != NL80211_IFTYPE_AP) { + if (wdev_to_wvif(wvif->wdev, 0)) { + struct wfx_vif *wvif_ch0 = wdev_to_wvif(wvif->wdev, 0); + struct ieee80211_vif *vif_ch0 = wvif_to_vif(wvif_ch0); + + chan0 = vif_ch0->bss_conf.chandef.chan; + } + if (wdev_to_wvif(wvif->wdev, 1)) { + struct wfx_vif *wvif_ch1 = wdev_to_wvif(wvif->wdev, 1); + struct ieee80211_vif *vif_ch1 = wvif_to_vif(wvif_ch1); + + chan1 = vif_ch1->bss_conf.chandef.chan; + } + if (chan0 && chan1 && vif->type != NL80211_IFTYPE_AP) { if (chan0->hw_value == chan1->hw_value) { /* It is useless to enable PS if channels are the same. */ if (enable_ps) *enable_ps = false; - if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) + if (vif->bss_conf.assoc && vif->bss_conf.ps) dev_info(wvif->wdev->dev, "ignoring requested PS mode"); return -1; } @@ -177,8 +188,8 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) return 30; } if (enable_ps) - *enable_ps = wvif->vif->bss_conf.ps; - if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps) + *enable_ps = vif->bss_conf.ps; + if (vif->bss_conf.assoc && vif->bss_conf.ps) return conf->dynamic_ps_timeout; else return -1; @@ -186,10 +197,11 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps) int wfx_update_pm(struct wfx_vif *wvif) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); int ps_timeout; bool ps; - if (!wvif->vif->bss_conf.assoc) + if (!vif->bss_conf.assoc) return 0; ps_timeout = wfx_get_ps_timeout(wvif, &ps); if (!ps) @@ -215,7 +227,8 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&wdev->conf_mutex); assign_bit(queue, &wvif->uapsd_mask, params->uapsd); wfx_hif_set_edca_queue_params(wvif, queue, params); - if (wvif->vif->type == NL80211_IFTYPE_STATION && old_uapsd != wvif->uapsd_mask) { + if (vif->type == NL80211_IFTYPE_STATION && + old_uapsd != wvif->uapsd_mask) { wfx_hif_set_uapsd_info(wvif, wvif->uapsd_mask); wfx_update_pm(wvif); } @@ -238,24 +251,26 @@ void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi) /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 * RSSI = RCPI / 2 - 110 */ + struct ieee80211_vif *vif = wvif_to_vif(wvif); int rcpi_rssi; int cqm_evt; rcpi_rssi = raw_rcpi_rssi / 2 - 110; - if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold) + if (rcpi_rssi <= vif->bss_conf.cqm_rssi_thold) cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; else cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; - ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL); + ieee80211_cqm_rssi_notify(vif, cqm_evt, rcpi_rssi, GFP_KERNEL); } static void wfx_beacon_loss_work(struct work_struct *work) { struct wfx_vif *wvif = container_of(to_delayed_work(work), struct wfx_vif, beacon_loss_work); - struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf; + struct ieee80211_vif *vif = wvif_to_vif(wvif); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - ieee80211_beacon_loss(wvif->vif); + ieee80211_beacon_loss(vif); schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(bss_conf->beacon_int)); } @@ -321,15 +336,16 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ie static int wfx_upload_ap_templates(struct wfx_vif *wvif) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); struct sk_buff *skb; - skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); + skb = ieee80211_beacon_get(wvif->wdev->hw, vif); if (!skb) return -ENOMEM; wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, API_RATE_INDEX_B_1MBPS); dev_kfree_skb(skb); - skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif); + skb = ieee80211_proberesp_get(wvif->wdev->hw, vif); if (!skb) return -ENOMEM; wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, API_RATE_INDEX_B_1MBPS); @@ -339,7 +355,8 @@ static int wfx_upload_ap_templates(struct wfx_vif *wvif) static void wfx_set_mfp_ap(struct wfx_vif *wvif) { - struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); + struct ieee80211_vif *vif = wvif_to_vif(wvif); + struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, vif); const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset, skb->len - ieoffset); @@ -388,12 +405,13 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static void wfx_join(struct wfx_vif *wvif) { - int ret; - struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; + struct ieee80211_vif *vif = wvif_to_vif(wvif); + struct ieee80211_bss_conf *conf = &vif->bss_conf; struct cfg80211_bss *bss = NULL; u8 ssid[IEEE80211_MAX_SSID_LEN]; const u8 *ssidie = NULL; int ssidlen = 0; + int ret; wfx_tx_lock_flush(wvif->wdev); @@ -420,7 +438,7 @@ static void wfx_join(struct wfx_vif *wvif) wvif->join_in_progress = true; ret = wfx_hif_join(wvif, conf, wvif->channel, ssid, ssidlen); if (ret) { - ieee80211_connection_loss(wvif->vif); + ieee80211_connection_loss(vif); wfx_reset(wvif); } else { /* Due to beacon filtering it is possible that the AP's beacon is not known for the @@ -434,13 +452,14 @@ static void wfx_join(struct wfx_vif *wvif) static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); struct ieee80211_sta *sta = NULL; int ampdu_density = 0; bool greenfield = false; rcu_read_lock(); /* protect sta */ if (info->bssid && !info->ibss_joined) - sta = ieee80211_find_sta(wvif->vif, info->bssid); + sta = ieee80211_find_sta(vif, info->bssid); if (sta && sta->deflink.ht_cap.ht_supported) ampdu_density = sta->deflink.ht_cap.ampdu_density; if (sta && sta->deflink.ht_cap.ht_supported && @@ -561,11 +580,13 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int wfx_update_tim(struct wfx_vif *wvif) { + struct ieee80211_vif *vif = wvif_to_vif(wvif); struct sk_buff *skb; u16 tim_offset, tim_length; u8 *tim_ptr; - skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif, &tim_offset, &tim_length); + skb = ieee80211_beacon_get_tim(wvif->wdev->hw, vif, &tim_offset, + &tim_length); if (!skb) return -ENOENT; tim_ptr = skb->data + tim_offset; @@ -707,8 +728,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return -EOPNOTSUPP; } - /* FIXME: prefer use of container_of() to get vif */ - wvif->vif = vif; wvif->wdev = wdev; wvif->link_id_map = 1; /* link-id 0 is reserved for multicast */ @@ -767,7 +786,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cancel_delayed_work_sync(&wvif->beacon_loss_work); wdev->vif[wvif->id] = NULL; - wvif->vif = NULL; mutex_unlock(&wdev->conf_mutex); diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h index 6594cc647c2f..13ba84b3b2c3 100644 --- a/drivers/net/wireless/silabs/wfx/wfx.h +++ b/drivers/net/wireless/silabs/wfx/wfx.h @@ -57,11 +57,11 @@ struct wfx_dev { struct mutex rx_stats_lock; struct wfx_hif_tx_power_loop_info tx_power_loop_info; struct mutex tx_power_loop_info_lock; + struct workqueue_struct *bh_wq; }; struct wfx_vif { struct wfx_dev *wdev; - struct ieee80211_vif *vif; struct ieee80211_channel *channel; int id; @@ -91,6 +91,11 @@ struct wfx_vif { struct completion set_pm_mode_complete; }; +static inline struct ieee80211_vif *wvif_to_vif(struct wfx_vif *wvif) +{ + return container_of((void *)wvif, struct ieee80211_vif, drv_priv); +} + static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id) { if (vif_id >= ARRAY_SIZE(wdev->vif)) { diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index e6d426edab56..e945aafd88ee 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c @@ -169,11 +169,9 @@ int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) msleep(1); /* read from both event fields */ - wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, - sizeof(events_vector)); + events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[0]); event = events_vector & mask; - wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, - sizeof(events_vector)); + events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[1]); event |= events_vector & mask; } while (!event); @@ -202,7 +200,7 @@ void wl1251_event_mbox_config(struct wl1251 *wl) int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) { - struct event_mailbox mbox; + struct event_mailbox *mbox; int ret; wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); @@ -210,12 +208,20 @@ int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) if (mbox_num > 1) return -EINVAL; + mbox = kmalloc(sizeof(*mbox), GFP_KERNEL); + if (!mbox) { + wl1251_error("can not allocate mbox buffer"); + return -ENOMEM; + } + /* first we read the mbox descriptor */ - wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, - sizeof(struct event_mailbox)); + wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], mbox, + sizeof(*mbox)); /* process the descriptor */ - ret = wl1251_event_process(wl, &mbox); + ret = wl1251_event_process(wl, mbox); + kfree(mbox); + if (ret < 0) return ret; diff --git a/drivers/net/wireless/ti/wl1251/io.c b/drivers/net/wireless/ti/wl1251/io.c index 5ebe7958ed5c..e8d567af74b4 100644 --- a/drivers/net/wireless/ti/wl1251/io.c +++ b/drivers/net/wireless/ti/wl1251/io.c @@ -121,7 +121,13 @@ void wl1251_set_partition(struct wl1251 *wl, u32 mem_start, u32 mem_size, u32 reg_start, u32 reg_size) { - struct wl1251_partition partition[2]; + struct wl1251_partition_set *partition; + + partition = kmalloc(sizeof(*partition), GFP_KERNEL); + if (!partition) { + wl1251_error("can not allocate partition buffer"); + return; + } wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", mem_start, mem_size); @@ -164,10 +170,10 @@ void wl1251_set_partition(struct wl1251 *wl, reg_start, reg_size); } - partition[0].start = mem_start; - partition[0].size = mem_size; - partition[1].start = reg_start; - partition[1].size = reg_size; + partition->mem.start = mem_start; + partition->mem.size = mem_size; + partition->reg.start = reg_start; + partition->reg.size = reg_size; wl->physical_mem_addr = mem_start; wl->physical_reg_addr = reg_start; @@ -176,5 +182,7 @@ void wl1251_set_partition(struct wl1251 *wl, wl->virtual_reg_addr = mem_size; wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition, - sizeof(partition)); + sizeof(*partition)); + + kfree(partition); } diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c index 98cd39619d57..e9dc3c72bb11 100644 --- a/drivers/net/wireless/ti/wl1251/tx.c +++ b/drivers/net/wireless/ti/wl1251/tx.c @@ -443,19 +443,25 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, void wl1251_tx_complete(struct wl1251 *wl) { int i, result_index, num_complete = 0, queue_len; - struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; + struct tx_result *result, *result_ptr; unsigned long flags; if (unlikely(wl->state != WL1251_STATE_ON)) return; + result = kmalloc_array(FW_TX_CMPLT_BLOCK_SIZE, sizeof(*result), GFP_KERNEL); + if (!result) { + wl1251_error("can not allocate result buffer"); + return; + } + /* First we read the result */ - wl1251_mem_read(wl, wl->data_path->tx_complete_addr, - result, sizeof(result)); + wl1251_mem_read(wl, wl->data_path->tx_complete_addr, result, + FW_TX_CMPLT_BLOCK_SIZE * sizeof(*result)); result_index = wl->next_tx_complete; - for (i = 0; i < ARRAY_SIZE(result); i++) { + for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) { result_ptr = &result[result_index]; if (result_ptr->done_1 == 1 && @@ -538,6 +544,7 @@ void wl1251_tx_complete(struct wl1251 *wl) } + kfree(result); wl->next_tx_complete = result_index; } diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 148bcb99c212..493bebbba521 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -914,7 +914,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, err = 0; goto out_free; } - pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); } } err = sprom_extract(bus, sprom, buf, bus->sprom_size); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 68713388b617..cc8a9880b9d6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1183,6 +1183,9 @@ struct cfg80211_mbssid_elems { * Token (measurement type 11) * @lci_len: LCI data length * @civicloc_len: Civic location data length + * @he_bss_color: BSS Color settings + * @he_bss_color_valid: indicates whether bss color + * attribute is present in beacon data or not. */ struct cfg80211_beacon_data { const u8 *head, *tail; @@ -1202,6 +1205,8 @@ struct cfg80211_beacon_data { size_t probe_resp_len; size_t lci_len; size_t civicloc_len; + struct cfg80211_he_bss_color he_bss_color; + bool he_bss_color_valid; }; struct mac_address { @@ -1292,7 +1297,6 @@ struct cfg80211_unsol_bcast_probe_resp { * @sae_h2e_required: stations must support direct H2E technique in SAE * @flags: flags, as defined in enum cfg80211_ap_settings_flags * @he_obss_pd: OBSS Packet Detection settings - * @he_bss_color: BSS Color settings * @he_oper: HE operation IE (or %NULL if HE isn't enabled) * @fils_discovery: FILS discovery transmission parameters * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters @@ -1326,7 +1330,6 @@ struct cfg80211_ap_settings { bool twt_responder; u32 flags; struct ieee80211_he_obss_pd he_obss_pd; - struct cfg80211_he_bss_color he_bss_color; struct cfg80211_fils_discovery fils_discovery; struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; struct cfg80211_mbssid_config mbssid_config; @@ -2735,6 +2738,7 @@ struct cfg80211_auth_request { * userspace if this flag is set. Only applicable for cfg80211_connect() * request (connect callback). * @ASSOC_REQ_DISABLE_HE: Disable HE + * @ASSOC_REQ_DISABLE_EHT: Disable EHT */ enum cfg80211_assoc_req_flags { ASSOC_REQ_DISABLE_HT = BIT(0), @@ -2742,6 +2746,7 @@ enum cfg80211_assoc_req_flags { ASSOC_REQ_USE_RRM = BIT(2), CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3), ASSOC_REQ_DISABLE_HE = BIT(4), + ASSOC_REQ_DISABLE_EHT = BIT(5), }; /** @@ -5549,8 +5554,6 @@ static inline void wiphy_unlock(struct wiphy *wiphy) * @conn_owner_nlportid: (private) connection owner socket port ID * @disconnect_wk: (private) auto-disconnect work * @disconnect_bssid: (private) the BSSID to use for auto-disconnect - * @ibss_fixed: (private) IBSS is using fixed BSSID - * @ibss_dfs_possible: (private) IBSS may change to a DFS channel * @event_list: (private) list for internal event processing * @event_lock: (private) lock for event list * @owner_nlportid: (private) owner socket port ID @@ -5599,9 +5602,6 @@ struct wireless_dev { struct cfg80211_chan_def preset_chandef; struct cfg80211_chan_def chandef; - bool ibss_fixed; - bool ibss_dfs_possible; - bool ps; int ps_timeout; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 75880fc70700..ebadb2103968 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -514,7 +514,6 @@ struct ieee80211_fils_discovery { * to that BSS) that can change during the lifetime of the BSS. * * @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE - * @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK * @uora_exists: is the UORA element advertised by AP * @ack_enabled: indicates support to receive a multi-TID that solicits either * ACK, BACK or both @@ -1144,20 +1143,41 @@ ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info) return info->tx_time_est << 2; } +/*** + * struct ieee80211_rate_status - mrr stage for status path + * + * This struct is used in struct ieee80211_tx_status to provide drivers a + * dynamic way to report about used rates and power levels per packet. + * + * @rate_idx The actual used rate. + * @try_count How often the rate was tried. + * @tx_power_idx An idx into the ieee80211_hw->tx_power_levels list of the + * corresponding wifi hardware. The idx shall point to the power level + * that was used when sending the packet. + */ +struct ieee80211_rate_status { + struct rate_info rate_idx; + u8 try_count; + u8 tx_power_idx; +}; + /** * struct ieee80211_tx_status - extended tx status info for rate control * * @sta: Station that the packet was transmitted for * @info: Basic tx status information * @skb: Packet skb (can be NULL if not provided by the driver) - * @rate: The TX rate that was used when sending the packet + * @rates: Mrr stages that were used when sending the packet + * @n_rates: Number of mrr stages (count of instances for @rates) * @free_list: list where processed skbs are stored to be free'd by the driver */ struct ieee80211_tx_status { struct ieee80211_sta *sta; struct ieee80211_tx_info *info; struct sk_buff *skb; - struct rate_info *rate; + struct ieee80211_rate_status *rates; + u8 n_rates; + struct list_head *free_list; }; @@ -1701,7 +1721,7 @@ enum ieee80211_offload_flags { * these need to be set (or cleared) when the interface is added * or, if supported by the driver, the interface type is changed * at runtime, mac80211 will never touch this field - * @offloaad_flags: hardware offload capabilities/flags for this interface. + * @offload_flags: hardware offload capabilities/flags for this interface. * These are initialized by mac80211 before calling .add_interface, * .change_interface or .update_vif_offload and updated by the driver * within these ops, based on supported features or runtime change @@ -2658,6 +2678,12 @@ enum ieee80211_hw_flags { * refilling deficit of each TXQ. * * @max_mtu: the max mtu could be set. + * + * @tx_power_levels: a list of power levels supported by the wifi hardware. + * The power levels can be specified either as integer or fractions. + * The power level at idx 0 shall be the maximum positive power level. + * + * @max_txpwr_levels_idx: the maximum valid idx of 'tx_power_levels' list. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -2696,6 +2722,8 @@ struct ieee80211_hw { u8 tx_sk_pacing_shift; u8 weight_multiplier; u32 max_mtu; + const s8 *tx_power_levels; + u8 max_txpwr_levels_idx; }; static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw, diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 0568a79097b8..d9490e3062a7 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3175,6 +3175,8 @@ enum nl80211_attrs { NL80211_ATTR_EHT_CAPABILITY, + NL80211_ATTR_DISABLE_EHT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f1d211e61e49..f7896f257e1b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1174,7 +1174,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); changed |= BSS_CHANGED_HE_OBSS_PD; - if (params->he_bss_color.enabled) + if (params->beacon.he_bss_color.enabled) changed |= BSS_CHANGED_HE_BSS_COLOR; } @@ -1231,7 +1231,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p; sdata->vif.bss_conf.twt_responder = params->twt_responder; sdata->vif.bss_conf.he_obss_pd = params->he_obss_pd; - sdata->vif.bss_conf.he_bss_color = params->he_bss_color; + sdata->vif.bss_conf.he_bss_color = params->beacon.he_bss_color; sdata->vif.bss_conf.s1g = params->chandef.chan->band == NL80211_BAND_S1GHZ; @@ -1316,6 +1316,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *params) { struct ieee80211_sub_if_data *sdata; + struct ieee80211_bss_conf *bss_conf; struct beacon_data *old; int err; @@ -1335,10 +1336,28 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, err = ieee80211_assign_beacon(sdata, params, NULL, NULL); if (err < 0) return err; + + bss_conf = &sdata->vif.bss_conf; + if (params->he_bss_color_valid && + params->he_bss_color.enabled != bss_conf->he_bss_color.enabled) { + bss_conf->he_bss_color.enabled = params->he_bss_color.enabled; + err |= BSS_CHANGED_HE_BSS_COLOR; + } + ieee80211_bss_info_change_notify(sdata, err); return 0; } +static void ieee80211_free_next_beacon(struct ieee80211_sub_if_data *sdata) +{ + if (!sdata->u.ap.next_beacon) + return; + + kfree(sdata->u.ap.next_beacon->mbssid_ies); + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; +} + static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -1373,11 +1392,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) mutex_unlock(&local->mtx); - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } + ieee80211_free_next_beacon(sdata); /* turn off carrier for this interface and dependent VLANs */ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) @@ -2928,7 +2943,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) return 0; - ap = sdata->u.mgd.associated->bssid; + ap = sdata->u.mgd.bssid; rcu_read_lock(); list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { @@ -3312,9 +3327,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, NULL, NULL); - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + ieee80211_free_next_beacon(sdata); if (err < 0) return err; @@ -3470,9 +3483,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || (params->n_counter_offsets_presp > IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + ieee80211_free_next_beacon(sdata); return -EINVAL; } @@ -3484,9 +3495,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); if (err < 0) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + ieee80211_free_next_beacon(sdata); return err; } *changed |= err; @@ -3576,11 +3585,8 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) { sdata->vif.color_change_active = false; - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } + + ieee80211_free_next_beacon(sdata); cfg80211_color_change_aborted_notify(sdata->dev); } @@ -4321,9 +4327,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata, ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, NULL, NULL); - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; + ieee80211_free_next_beacon(sdata); if (ret < 0) return ret; @@ -4366,11 +4370,7 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata, err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, NULL, &color_change); if (err < 0) { - if (sdata->u.ap.next_beacon) { - kfree(sdata->u.ap.next_beacon->mbssid_ies); - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - } + ieee80211_free_next_beacon(sdata); return err; } *changed |= err; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index e490c3da3aca..cf71484658c6 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -337,7 +337,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( dev_kfree_skb(skb); return -ENOTCONN; } - memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN); + memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr->addr3, addr, ETH_ALEN); sdata_unlock(sdata); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d4a7ba4a8202..86ef0a46a68c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -453,9 +453,10 @@ struct ieee80211_if_managed { bool nullfunc_failed; u8 connection_loss:1, driver_disconnect:1, - reconnect:1; + reconnect:1, + associated:1; - struct cfg80211_bss *associated; + struct cfg80211_bss *assoc_bss; struct ieee80211_mgd_auth_data *auth_data; struct ieee80211_mgd_assoc_data *assoc_data; @@ -1148,6 +1149,9 @@ struct tpt_led_trigger { * a scan complete for an aborted scan. * @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being * cancelled. + * @SCAN_BEACON_WAIT: Set whenever we're passive scanning because of radar/no-IR + * and could send a probe request after receiving a beacon. + * @SCAN_BEACON_DONE: Beacon received, we can now send a probe request */ enum { SCAN_SW_SCANNING, @@ -1156,6 +1160,8 @@ enum { SCAN_COMPLETED, SCAN_ABORTED, SCAN_HW_CANCELLED, + SCAN_BEACON_WAIT, + SCAN_BEACON_DONE, }; /** @@ -1854,7 +1860,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 reason, bool tx); + u8 reason, bool tx); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a48a32f87897..5a385d4146b9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -287,8 +287,8 @@ static void ieee80211_restart_work(struct work_struct *work) if (sdata->vif.csa_active) { sdata_lock(sdata); ieee80211_sta_connection_lost(sdata, - sdata->u.mgd.associated->bssid, - WLAN_REASON_UNSPECIFIED, false); + WLAN_REASON_UNSPECIFIED, + false); sdata_unlock(sdata); } } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 07a96f7c5dc3..58d48dcae030 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1376,7 +1376,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct cfg80211_bss *cbss = ifmgd->associated; + struct cfg80211_bss *cbss = ifmgd->assoc_bss; struct ieee80211_chanctx_conf *conf; struct ieee80211_chanctx *chanctx; enum nl80211_band current_band; @@ -1398,7 +1398,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band, bss->vht_cap_info, ifmgd->flags, - ifmgd->associated->bssid, &csa_ie); + ifmgd->bssid, &csa_ie); if (!res) { ch_switch.timestamp = timestamp; @@ -1427,7 +1427,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, csa_ie.chandef.chan->band) { sdata_info(sdata, "AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", - ifmgd->associated->bssid, + ifmgd->bssid, csa_ie.chandef.chan->center_freq, csa_ie.chandef.width, csa_ie.chandef.center_freq1, csa_ie.chandef.center_freq2); @@ -1440,7 +1440,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, "AP %pM switches to unsupported channel " "(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), " "disconnecting\n", - ifmgd->associated->bssid, + ifmgd->bssid, csa_ie.chandef.chan->center_freq, csa_ie.chandef.chan->freq_offset, csa_ie.chandef.width, csa_ie.chandef.center_freq1, @@ -1456,7 +1456,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, return; sdata_info(sdata, "AP %pM tries to chanswitch to same channel, ignore\n", - ifmgd->associated->bssid); + ifmgd->bssid); ifmgd->csa_ignored_same_chan = true; return; } @@ -2266,7 +2266,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( beacon_loss_count * bss_conf->beacon_int)); - sdata->u.mgd.associated = cbss; + sdata->u.mgd.associated = true; + sdata->u.mgd.assoc_bss = cbss; memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); ieee80211_check_rate_mask(sdata); @@ -2361,7 +2362,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_stop_poll(sdata); - ifmgd->associated = NULL; + ifmgd->associated = false; + ifmgd->assoc_bss = NULL; netif_carrier_off(sdata->dev); /* @@ -2608,8 +2610,7 @@ static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata, static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - const struct element *ssid; - u8 *dst = ifmgd->associated->bssid; + u8 *dst = ifmgd->bssid; u8 unicast_limit = max(1, max_probe_tries - 3); struct sta_info *sta; @@ -2642,19 +2643,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) ifmgd->nullfunc_failed = false; ieee80211_send_nullfunc(sdata->local, sdata, false); } else { - int ssid_len; - - rcu_read_lock(); - ssid = ieee80211_bss_get_elem(ifmgd->associated, WLAN_EID_SSID); - if (WARN_ON_ONCE(ssid == NULL)) - ssid_len = 0; - else - ssid_len = ssid->datalen; - ieee80211_mlme_send_probe_req(sdata, sdata->vif.addr, dst, - ssid->data, ssid_len, - ifmgd->associated->channel); - rcu_read_unlock(); + sdata->vif.bss_conf.ssid, + sdata->vif.bss_conf.ssid_len, + ifmgd->assoc_bss->channel); } ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); @@ -2744,7 +2736,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, sdata_assert_lock(sdata); if (ifmgd->associated) - cbss = ifmgd->associated; + cbss = ifmgd->assoc_bss; else if (ifmgd->auth_data) cbss = ifmgd->auth_data->bss; else if (ifmgd->assoc_data) @@ -2809,7 +2801,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) * AP is probably out of range (or not reachable for another * reason) so remove the bss struct for that AP. */ - cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated); + cfg80211_unlink_bss(local->hw.wiphy, ifmgd->assoc_bss); } ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, @@ -3219,8 +3211,8 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, } if (ifmgd->associated && - ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) { - const u8 *bssid = ifmgd->associated->bssid; + ether_addr_equal(mgmt->bssid, ifmgd->bssid)) { + const u8 *bssid = ifmgd->bssid; sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n", bssid, reason_code, @@ -3262,7 +3254,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, return; if (!ifmgd->associated || - !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) + !ether_addr_equal(mgmt->bssid, ifmgd->bssid)) return; reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); @@ -3972,7 +3964,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status); if (ifmgd->associated && - ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) + ether_addr_equal(mgmt->bssid, ifmgd->bssid)) ieee80211_reset_ap_probe(sdata); } @@ -4201,9 +4193,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, } if (!ifmgd->associated || - !ieee80211_rx_our_beacon(bssid, ifmgd->associated)) + !ieee80211_rx_our_beacon(bssid, ifmgd->assoc_bss)) return; - bssid = ifmgd->associated->bssid; + bssid = ifmgd->bssid; if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)) ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf, @@ -4519,7 +4511,7 @@ static void ieee80211_sta_timer(struct timer_list *t) } void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 reason, bool tx) + u8 reason, bool tx) { u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; @@ -4750,11 +4742,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL && ifmgd->associated) { - u8 bssid[ETH_ALEN]; + u8 *bssid = ifmgd->bssid; int max_tries; - memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); - if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) max_tries = max_nullfunc_tries; else @@ -4774,7 +4764,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) mlme_dbg(sdata, "No ack for nullfunc frame to AP %pM, disconnecting.\n", bssid); - ieee80211_sta_connection_lost(sdata, bssid, + ieee80211_sta_connection_lost(sdata, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); } @@ -4784,7 +4774,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) mlme_dbg(sdata, "Failed to send nullfunc to AP %pM after %dms, disconnecting\n", bssid, probe_wait_ms); - ieee80211_sta_connection_lost(sdata, bssid, + ieee80211_sta_connection_lost(sdata, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); } else if (ifmgd->probe_send_count < max_tries) { mlme_dbg(sdata, @@ -4801,7 +4791,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) "No probe response from AP %pM after %dms, disconnecting.\n", bssid, probe_wait_ms); - ieee80211_sta_connection_lost(sdata, bssid, + ieee80211_sta_connection_lost(sdata, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); } } @@ -4934,7 +4924,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) .bssid = bssid, }; - memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); + memcpy(bssid, ifmgd->bssid, ETH_ALEN); ieee80211_mgd_deauth(sdata, &req); } @@ -4956,7 +4946,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; mlme_dbg(sdata, "driver requested disconnect after resume\n"); ieee80211_sta_connection_lost(sdata, - ifmgd->associated->bssid, WLAN_REASON_UNSPECIFIED, true); sdata_unlock(sdata); @@ -4967,7 +4956,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_HW_RESTART; mlme_dbg(sdata, "driver requested disconnect after hardware restart\n"); ieee80211_sta_connection_lost(sdata, - ifmgd->associated->bssid, WLAN_REASON_UNSPECIFIED, true); sdata_unlock(sdata); @@ -5842,7 +5830,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, sdata_info(sdata, "disconnect from AP %pM for new auth to %pM\n", - ifmgd->associated->bssid, req->bss->bssid); + ifmgd->bssid, req->bss->bssid); ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_UNSPECIFIED, false, frame_buf); @@ -5918,7 +5906,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata_info(sdata, "disconnect from AP %pM for new assoc to %pM\n", - ifmgd->associated->bssid, req->bss->bssid); + ifmgd->bssid, req->bss->bssid); ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_UNSPECIFIED, false, frame_buf); @@ -6132,6 +6120,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; } + if (req->flags & ASSOC_REQ_DISABLE_EHT) + ifmgd->flags |= IEEE80211_STA_DISABLE_EHT; + err = ieee80211_prep_connection(sdata, req->bss, true, override); if (err) goto err_clear; @@ -6273,7 +6264,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, } if (ifmgd->associated && - ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { + ether_addr_equal(ifmgd->bssid, req->bssid)) { sdata_info(sdata, "deauthenticating from %pM by local choice (Reason: %u=%s)\n", req->bssid, req->reason_code, @@ -6304,7 +6295,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, * to cfg80211 while that's in a locked section already * trying to tell us that the user wants to disconnect. */ - if (ifmgd->associated != req->bss) + if (ifmgd->assoc_bss != req->bss) return -ENOLINK; sdata_info(sdata, @@ -6382,3 +6373,43 @@ void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp) cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp); } EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify); + +static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, + int rssi_min_thold, + int rssi_max_thold) +{ + trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + /* + * Scale up threshold values before storing it, as the RSSI averaging + * algorithm uses a scaled up value as well. Change this scaling + * factor if the RSSI averaging algorithm changes. + */ + sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; + sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; +} + +void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, + int rssi_min_thold, + int rssi_max_thold) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + WARN_ON(rssi_min_thold == rssi_max_thold || + rssi_min_thold > rssi_max_thold); + + _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, + rssi_max_thold); +} +EXPORT_SYMBOL(ieee80211_enable_rssi_reports); + +void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + _ieee80211_enable_rssi_reports(sdata, 0, 0); +} +EXPORT_SYMBOL(ieee80211_disable_rssi_reports); diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 853c9a369d72..c5d2ab9df1e7 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -819,7 +819,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, if (!sdata->u.mgd.associated || (params->offchan && params->wait && local->ops->remain_on_channel && - memcmp(sdata->u.mgd.associated->bssid, + memcmp(sdata->u.mgd.bssid, mgmt->bssid, ETH_ALEN))) need_offchan = true; sdata_unlock(sdata); diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 7b1f5c045e06..5f27e6746762 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -333,6 +333,17 @@ minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); } +/* + * Look up an MCS group index based on new cfg80211 rate_info. + */ +static int +minstrel_ht_ri_get_group_idx(struct rate_info *rate) +{ + return GROUP_IDX((rate->mcs / 8) + 1, + !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI), + !!(rate->bw & RATE_INFO_BW_40)); +} + static int minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate) { @@ -342,6 +353,18 @@ minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate) 2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)); } +/* + * Look up an MCS group index based on new cfg80211 rate_info. + */ +static int +minstrel_vht_ri_get_group_idx(struct rate_info *rate) +{ + return VHT_GROUP_IDX(rate->nss, + !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI), + !!(rate->bw & RATE_INFO_BW_40) + + 2*!!(rate->bw & RATE_INFO_BW_80)); +} + static struct minstrel_rate_stats * minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, struct ieee80211_tx_rate *rate) @@ -385,6 +408,50 @@ out: return &mi->groups[group].rates[idx]; } +/* + * Get the minstrel rate statistics for specified STA and rate info. + */ +static struct minstrel_rate_stats * +minstrel_ht_ri_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, + struct ieee80211_rate_status *rate_status) +{ + int group, idx; + struct rate_info *rate = &rate_status->rate_idx; + + if (rate->flags & RATE_INFO_FLAGS_MCS) { + group = minstrel_ht_ri_get_group_idx(rate); + idx = rate->mcs % 8; + goto out; + } + + if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) { + group = minstrel_vht_ri_get_group_idx(rate); + idx = rate->mcs; + goto out; + } + + group = MINSTREL_CCK_GROUP; + for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) { + if (rate->legacy != minstrel_cck_bitrates[ mp->cck_rates[idx] ]) + continue; + + /* short preamble */ + if ((mi->supported[group] & BIT(idx + 4)) && + mi->use_short_preamble) + idx += 4; + goto out; + } + + group = MINSTREL_OFDM_GROUP; + for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++) + if (rate->legacy == minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][idx] ]) + goto out; + + idx = 0; +out: + return &mi->groups[group].rates[idx]; +} + static inline struct minstrel_rate_stats * minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index) { @@ -1152,6 +1219,40 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, return false; } +/* + * Check whether rate_status contains valid information. + */ +static bool +minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp, + struct minstrel_ht_sta *mi, + struct ieee80211_rate_status *rate_status) +{ + int i; + + if (!rate_status) + return false; + if (!rate_status->try_count) + return false; + + if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS || + rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS) + return true; + + for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) { + if (rate_status->rate_idx.legacy == + minstrel_cck_bitrates[ mp->cck_rates[i] ]) + return true; + } + + for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates); i++) { + if (rate_status->rate_idx.legacy == + minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][i] ]) + return true; + } + + return false; +} + static void minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary) { @@ -1217,16 +1318,34 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, mi->ampdu_packets++; mi->ampdu_len += info->status.ampdu_len; - last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]); - for (i = 0; !last; i++) { - last = (i == IEEE80211_TX_MAX_RATES - 1) || - !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]); + if (st->rates && st->n_rates) { + last = !minstrel_ht_ri_txstat_valid(mp, mi, &(st->rates[0])); + for (i = 0; !last; i++) { + last = (i == st->n_rates - 1) || + !minstrel_ht_ri_txstat_valid(mp, mi, + &(st->rates[i + 1])); + + rate = minstrel_ht_ri_get_stats(mp, mi, + &(st->rates[i])); - rate = minstrel_ht_get_stats(mp, mi, &ar[i]); - if (last) - rate->success += info->status.ampdu_ack_len; + if (last) + rate->success += info->status.ampdu_ack_len; - rate->attempts += ar[i].count * info->status.ampdu_len; + rate->attempts += st->rates[i].try_count * + info->status.ampdu_len; + } + } else { + last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]); + for (i = 0; !last; i++) { + last = (i == IEEE80211_TX_MAX_RATES - 1) || + !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]); + + rate = minstrel_ht_get_stats(mp, mi, &ar[i]); + if (last) + rate->success += info->status.ampdu_ack_len; + + rate->attempts += ar[i].count * info->status.ampdu_len; + } } if (mp->hw->max_rates > 1) { @@ -1439,17 +1558,17 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) /* Start with max_tp_rate[0] */ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]); - if (mp->hw->max_rates >= 3) { - /* At least 3 tx rates supported, use max_tp_rate[1] next */ - minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[1]); - } + /* Fill up remaining, keep one entry for max_probe_rate */ + for (; i < (mp->hw->max_rates - 1); i++) + minstrel_ht_set_rate(mp, mi, rates, i, mi->max_tp_rate[i]); - if (mp->hw->max_rates >= 2) { + if (i < mp->hw->max_rates) minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate); - } + + if (i < IEEE80211_TX_RATE_TABLE_SIZE) + rates->rate[i].idx = -1; mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi); - rates->rate[i].idx = -1; rate_control_set_rates(mp->hw, mi->sta, rates); } @@ -1583,6 +1702,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, u16 ht_cap = sta->deflink.ht_cap.cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; const struct ieee80211_rate *ctl_rate; + struct sta_info *sta_info; bool ldpc, erp; int use_vht; int n_supported = 0; @@ -1701,6 +1821,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, n_supported++; } + sta_info = container_of(sta, struct sta_info, sta); + mi->use_short_preamble = test_sta_flag(sta_info, WLAN_STA_SHORT_PREAMBLE) && + sta_info->sdata->vif.bss_conf.use_short_preamble; + minstrel_ht_update_cck(mp, mi, sband, sta); minstrel_ht_update_ofdm(mp, mi, sband, sta); diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index 06e7126727ad..1766ff0c78d3 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h @@ -180,7 +180,7 @@ struct minstrel_ht_sta { /* tx flags to add for frames for this sta */ u32 tx_flags; - + bool use_short_preamble; u8 band; u8 sample_seq; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5e6b275afc9e..b698756887eb 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -281,6 +281,16 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) if (likely(!sdata1 && !sdata2)) return; + if (test_and_clear_bit(SCAN_BEACON_WAIT, &local->scanning)) { + /* + * we were passive scanning because of radar/no-IR, but + * the beacon/proberesp rx gives us an opportunity to upgrade + * to active scan + */ + set_bit(SCAN_BEACON_DONE, &local->scanning); + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); + } + if (ieee80211_is_probe_resp(mgmt->frame_control)) { struct cfg80211_scan_request *scan_req; struct cfg80211_sched_scan_request *sched_scan_req; @@ -787,6 +797,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, IEEE80211_CHAN_RADAR)) || !req->n_ssids) { next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; + if (req->n_ssids) + set_bit(SCAN_BEACON_WAIT, &local->scanning); } else { ieee80211_scan_state_send_probe(local, &next_delay); next_delay = IEEE80211_CHANNEL_TIME; @@ -998,6 +1010,8 @@ set_channel: !scan_req->n_ssids) { *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; local->next_scan_state = SCAN_DECISION; + if (scan_req->n_ssids) + set_bit(SCAN_BEACON_WAIT, &local->scanning); return; } @@ -1090,6 +1104,8 @@ void ieee80211_scan_work(struct work_struct *work) goto out; } + clear_bit(SCAN_BEACON_WAIT, &local->scanning); + /* * as long as no delay is required advance immediately * without scheduling a new work @@ -1100,6 +1116,10 @@ void ieee80211_scan_work(struct work_struct *work) goto out_complete; } + if (test_and_clear_bit(SCAN_BEACON_DONE, &local->scanning) && + local->next_scan_state == SCAN_DECISION) + local->next_scan_state = SCAN_SEND_PROBE; + switch (local->next_scan_state) { case SCAN_DECISION: /* if no more bands/channels left, complete scan */ diff --git a/net/mac80211/status.c b/net/mac80211/status.c index c563fa718d84..e69272139437 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -247,15 +247,19 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info, struct ieee80211_tx_status *status) { + struct ieee80211_rate_status *status_rate = NULL; int len = sizeof(struct ieee80211_radiotap_header); + if (status && status->n_rates) + status_rate = &status->rates[status->n_rates - 1]; + /* IEEE80211_RADIOTAP_RATE rate */ - if (status && status->rate && !(status->rate->flags & - (RATE_INFO_FLAGS_MCS | - RATE_INFO_FLAGS_DMG | - RATE_INFO_FLAGS_EDMG | - RATE_INFO_FLAGS_VHT_MCS | - RATE_INFO_FLAGS_HE_MCS))) + if (status_rate && !(status_rate->rate_idx.flags & + (RATE_INFO_FLAGS_MCS | + RATE_INFO_FLAGS_DMG | + RATE_INFO_FLAGS_EDMG | + RATE_INFO_FLAGS_VHT_MCS | + RATE_INFO_FLAGS_HE_MCS))) len += 2; else if (info->status.rates[0].idx >= 0 && !(info->status.rates[0].flags & @@ -270,12 +274,12 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info, /* IEEE80211_RADIOTAP_MCS * IEEE80211_RADIOTAP_VHT */ - if (status && status->rate) { - if (status->rate->flags & RATE_INFO_FLAGS_MCS) + if (status_rate) { + if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS) len += 3; - else if (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS) + else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS) len = ALIGN(len, 2) + 12; - else if (status->rate->flags & RATE_INFO_FLAGS_HE_MCS) + else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_HE_MCS) len = ALIGN(len, 2) + 12; } else if (info->status.rates[0].idx >= 0) { if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) @@ -297,10 +301,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_radiotap_header *rthdr; + struct ieee80211_rate_status *status_rate = NULL; unsigned char *pos; u16 legacy_rate = 0; u16 txflags; + if (status && status->n_rates) + status_rate = &status->rates[status->n_rates - 1]; + rthdr = skb_push(skb, rtap_len); memset(rthdr, 0, rtap_len); @@ -318,13 +326,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_RATE */ - if (status && status->rate) { - if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS | - RATE_INFO_FLAGS_DMG | - RATE_INFO_FLAGS_EDMG | - RATE_INFO_FLAGS_VHT_MCS | - RATE_INFO_FLAGS_HE_MCS))) - legacy_rate = status->rate->legacy; + if (status_rate) { + if (!(status_rate->rate_idx.flags & + (RATE_INFO_FLAGS_MCS | + RATE_INFO_FLAGS_DMG | + RATE_INFO_FLAGS_EDMG | + RATE_INFO_FLAGS_VHT_MCS | + RATE_INFO_FLAGS_HE_MCS))) + legacy_rate = status_rate->rate_idx.legacy; } else if (info->status.rates[0].idx >= 0 && !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) @@ -357,20 +366,21 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, *pos = retry_count; pos++; - if (status && status->rate && - (status->rate->flags & RATE_INFO_FLAGS_MCS)) { + if (status_rate && (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS)) + { rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS)); pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | IEEE80211_RADIOTAP_MCS_HAVE_GI | IEEE80211_RADIOTAP_MCS_HAVE_BW; - if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI) + if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI) pos[1] |= IEEE80211_RADIOTAP_MCS_SGI; - if (status->rate->bw == RATE_INFO_BW_40) + if (status_rate->rate_idx.bw == RATE_INFO_BW_40) pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40; - pos[2] = status->rate->mcs; + pos[2] = status_rate->rate_idx.mcs; pos += 3; - } else if (status && status->rate && - (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)) { + } else if (status_rate && (status_rate->rate_idx.flags & + RATE_INFO_FLAGS_VHT_MCS)) + { u16 known = local->hw.radiotap_vht_details & (IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); @@ -385,12 +395,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, pos += 2; /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */ - if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI) + if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI) *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; pos++; /* u8 bandwidth */ - switch (status->rate->bw) { + switch (status_rate->rate_idx.bw) { case RATE_INFO_BW_160: *pos = 11; break; @@ -407,7 +417,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, pos++; /* u8 mcs_nss[4] */ - *pos = (status->rate->mcs << 4) | status->rate->nss; + *pos = (status_rate->rate_idx.mcs << 4) | + status_rate->rate_idx.nss; pos += 4; /* u8 coding */ @@ -416,8 +427,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, pos++; /* u16 partial_aid */ pos += 2; - } else if (status && status->rate && - (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) { + } else if (status_rate && (status_rate->rate_idx.flags & + RATE_INFO_FLAGS_HE_MCS)) + { struct ieee80211_radiotap_he *he; rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE)); @@ -435,7 +447,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, #define HE_PREP(f, val) le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f) - he->data6 |= HE_PREP(DATA6_NSTS, status->rate->nss); + he->data6 |= HE_PREP(DATA6_NSTS, status_rate->rate_idx.nss); #define CHECK_GI(s) \ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \ @@ -445,12 +457,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, CHECK_GI(1_6); CHECK_GI(3_2); - he->data3 |= HE_PREP(DATA3_DATA_MCS, status->rate->mcs); - he->data3 |= HE_PREP(DATA3_DATA_DCM, status->rate->he_dcm); + he->data3 |= HE_PREP(DATA3_DATA_MCS, status_rate->rate_idx.mcs); + he->data3 |= HE_PREP(DATA3_DATA_DCM, status_rate->rate_idx.he_dcm); - he->data5 |= HE_PREP(DATA5_GI, status->rate->he_gi); + he->data5 |= HE_PREP(DATA5_GI, status_rate->rate_idx.he_gi); - switch (status->rate->bw) { + switch (status_rate->rate_idx.bw) { case RATE_INFO_BW_20: he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ); @@ -481,16 +493,16 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local, CHECK_RU_ALLOC(2x996); he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC, - status->rate->he_ru_alloc + 4); + status_rate->rate_idx.he_ru_alloc + 4); break; default: - WARN_ONCE(1, "Invalid SU BW %d\n", status->rate->bw); + WARN_ONCE(1, "Invalid SU BW %d\n", status_rate->rate_idx.bw); } pos += sizeof(struct ieee80211_radiotap_he); } - if ((status && status->rate) || info->status.rates[0].idx < 0) + if (status_rate || info->status.rates[0].idx < 0) return; /* IEEE80211_RADIOTAP_MCS @@ -1111,8 +1123,9 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, if (pubsta) { sta = container_of(pubsta, struct sta_info, sta); - if (status->rate) - sta->deflink.tx_stats.last_rate_info = *status->rate; + if (status->n_rates) + sta->deflink.tx_stats.last_rate_info = + status->rates[status->n_rates - 1].rate_idx; } if (skb && (tx_time_est = diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 13253eb39d09..0e4efc08c762 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3150,8 +3150,6 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC); /* if the kmemdup fails, continue w/o fast_tx */ - if (!fast_tx) - goto out; out: /* we might have raced against another call to this function */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 682a164f795a..1e26b5235add 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2854,46 +2854,6 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) return pos; } -static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, - int rssi_min_thold, - int rssi_max_thold) -{ - trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); - - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) - return; - - /* - * Scale up threshold values before storing it, as the RSSI averaging - * algorithm uses a scaled up value as well. Change this scaling - * factor if the RSSI averaging algorithm changes. - */ - sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; - sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; -} - -void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, - int rssi_min_thold, - int rssi_max_thold) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - - WARN_ON(rssi_min_thold == rssi_max_thold || - rssi_min_thold > rssi_max_thold); - - _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, - rssi_max_thold); -} -EXPORT_SYMBOL(ieee80211_enable_rssi_reports); - -void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - - _ieee80211_enable_rssi_reports(sdata, 0, 0); -} -EXPORT_SYMBOL(ieee80211_disable_rssi_reports); - u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, u16 cap) { diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7ed0d268aff2..5fd8a3e8b5b4 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -311,19 +311,21 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) return RX_CONTINUE; } - -static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) +/* + * Calculate AAD for CCMP/GCMP, returning qos_tid since we + * need that in CCMP also for b_0. + */ +static u8 ccmp_gcmp_aad(struct sk_buff *skb, u8 *aad) { + struct ieee80211_hdr *hdr = (void *)skb->data; __le16 mask_fc; int a4_included, mgmt; u8 qos_tid; - u16 len_a; - unsigned int hdrlen; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + u16 len_a = 22; /* * Mask FC: zero subtype b4 b5 b6 (if not mgmt) - * Retry, PwrMgt, MoreData; set Protected + * Retry, PwrMgt, MoreData, Order (if Qos Data); set Protected */ mgmt = ieee80211_is_mgmt(hdr->frame_control); mask_fc = hdr->frame_control; @@ -333,30 +335,17 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) mask_fc &= ~cpu_to_le16(0x0070); mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - hdrlen = ieee80211_hdrlen(hdr->frame_control); - len_a = hdrlen - 2; a4_included = ieee80211_has_a4(hdr->frame_control); + if (a4_included) + len_a += 6; - if (ieee80211_is_data_qos(hdr->frame_control)) + if (ieee80211_is_data_qos(hdr->frame_control)) { qos_tid = ieee80211_get_tid(hdr); - else + mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_ORDER); + len_a += 2; + } else { qos_tid = 0; - - /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC - * mode authentication are not allowed to collide, yet both are derived - * from this vector b_0. We only set L := 1 here to indicate that the - * data size can be represented in (L+1) bytes. The CCM layer will take - * care of storing the data length in the top (L+1) bytes and setting - * and clearing the other bits as is required to derive the two IVs. - */ - b_0[0] = 0x1; - - /* Nonce: Nonce Flags | A2 | PN - * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) - */ - b_0[1] = qos_tid | (mgmt << 4); - memcpy(&b_0[2], hdr->addr2, ETH_ALEN); - memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); + } /* AAD (extra authenticate-only data) / masked 802.11 header * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ @@ -376,8 +365,31 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); aad[24] = qos_tid; } + + return qos_tid; } +static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + u8 qos_tid = ccmp_gcmp_aad(skb, aad); + + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from this vector b_0. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. + */ + b_0[0] = 0x1; + + /* Nonce: Nonce Flags | A2 | PN + * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) + */ + b_0[1] = qos_tid | (ieee80211_is_mgmt(hdr->frame_control) << 4); + memcpy(&b_0[2], hdr->addr2, ETH_ALEN); + memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); +} static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id) { @@ -571,9 +583,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad) { - __le16 mask_fc; - u8 qos_tid; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (void *)skb->data; memcpy(j_0, hdr->addr2, ETH_ALEN); memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN); @@ -581,40 +591,7 @@ static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad) j_0[14] = 0; j_0[AES_BLOCK_SIZE - 1] = 0x01; - /* AAD (extra authenticate-only data) / masked 802.11 header - * FC | A1 | A2 | A3 | SC | [A4] | [QC] - */ - put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]); - /* Mask FC: zero subtype b4 b5 b6 (if not mgmt) - * Retry, PwrMgt, MoreData; set Protected - */ - mask_fc = hdr->frame_control; - mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | - IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); - if (!ieee80211_is_mgmt(hdr->frame_control)) - mask_fc &= ~cpu_to_le16(0x0070); - mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - put_unaligned(mask_fc, (__le16 *)&aad[2]); - memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); - - /* Mask Seq#, leave Frag# */ - aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f; - aad[23] = 0; - - if (ieee80211_is_data_qos(hdr->frame_control)) - qos_tid = ieee80211_get_tid(hdr); - else - qos_tid = 0; - - if (ieee80211_has_a4(hdr->frame_control)) { - memcpy(&aad[24], hdr->addr4, ETH_ALEN); - aad[30] = qos_tid; - aad[31] = 0; - } else { - memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); - aad[24] = qos_tid; - } + ccmp_gcmp_aad(skb, aad); } static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 8b7fb4a9e07b..f74f176e0d9d 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -6,7 +6,7 @@ * * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright 2018-2021 Intel Corporation + * Copyright 2018-2022 Intel Corporation */ #include <linux/export.h> @@ -1344,97 +1344,6 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, return rdev_set_monitor_channel(rdev, chandef); } -void -cfg80211_get_chan_state(struct wireless_dev *wdev, - struct ieee80211_channel **chan, - enum cfg80211_chan_mode *chanmode, - u8 *radar_detect) -{ - int ret; - - *chan = NULL; - *chanmode = CHAN_MODE_UNDEFINED; - - ASSERT_WDEV_LOCK(wdev); - - if (wdev->netdev && !netif_running(wdev->netdev)) - return; - - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: - if (wdev->current_bss) { - *chan = wdev->current_bss->pub.channel; - *chanmode = (wdev->ibss_fixed && - !wdev->ibss_dfs_possible) - ? CHAN_MODE_SHARED - : CHAN_MODE_EXCLUSIVE; - - /* consider worst-case - IBSS can try to return to the - * original user-specified channel as creator */ - if (wdev->ibss_dfs_possible) - *radar_detect |= BIT(wdev->chandef.width); - return; - } - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - if (wdev->current_bss) { - *chan = wdev->current_bss->pub.channel; - *chanmode = CHAN_MODE_SHARED; - return; - } - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - if (wdev->cac_started) { - *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; - *radar_detect |= BIT(wdev->chandef.width); - } else if (wdev->beacon_interval) { - *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; - - ret = cfg80211_chandef_dfs_required(wdev->wiphy, - &wdev->chandef, - wdev->iftype); - WARN_ON(ret < 0); - if (ret > 0) - *radar_detect |= BIT(wdev->chandef.width); - } - return; - case NL80211_IFTYPE_MESH_POINT: - if (wdev->mesh_id_len) { - *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; - - ret = cfg80211_chandef_dfs_required(wdev->wiphy, - &wdev->chandef, - wdev->iftype); - WARN_ON(ret < 0); - if (ret > 0) - *radar_detect |= BIT(wdev->chandef.width); - } - return; - case NL80211_IFTYPE_OCB: - if (wdev->chandef.chan) { - *chan = wdev->chandef.chan; - *chanmode = CHAN_MODE_SHARED; - return; - } - break; - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_P2P_DEVICE: - case NL80211_IFTYPE_NAN: - /* these interface types don't really have a channel */ - return; - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_WDS: - case NUM_NL80211_IFTYPES: - WARN_ON(1); - } -} - bool cfg80211_any_usable_channels(struct wiphy *wiphy, unsigned long sband_mask, u32 prohibited_flags) diff --git a/net/wireless/core.h b/net/wireless/core.h index 3a7dbd63d8c6..5436ada91b1a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -3,7 +3,7 @@ * Wireless configuration interface internals. * * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #ifndef __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H @@ -281,12 +281,6 @@ struct cfg80211_cached_keys { int def; }; -enum cfg80211_chan_mode { - CHAN_MODE_UNDEFINED, - CHAN_MODE_SHARED, - CHAN_MODE_EXCLUSIVE, -}; - struct cfg80211_beacon_registration { struct list_head list; u32 nlportid; @@ -525,12 +519,6 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start) return jiffies_to_msecs(end + (ULONG_MAX - start) + 1); } -void -cfg80211_get_chan_state(struct wireless_dev *wdev, - struct ieee80211_channel **chan, - enum cfg80211_chan_mode *chanmode, - u8 *radar_detect); - int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, struct cfg80211_chan_def *chandef); diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 8f98e546becf..5d89eec2869a 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -3,7 +3,7 @@ * Some IBSS support code for cfg80211. * * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation */ #include <linux/etherdevice.h> @@ -131,8 +131,6 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, kfree_sensitive(wdev->connect_keys); wdev->connect_keys = connkeys; - wdev->ibss_fixed = params->channel_fixed; - wdev->ibss_dfs_possible = params->userspace_handles_dfs; wdev->chandef = params->chandef; if (connkeys) { params->wep_keys = connkeys->params; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 02a29052e41d..740b29481bc6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -791,6 +791,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { NLA_POLICY_RANGE(NLA_BINARY, NL80211_EHT_MIN_CAPABILITY_LEN, NL80211_EHT_MAX_CAPABILITY_LEN), + [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG }, }; /* policy for the key attributes */ @@ -5181,6 +5182,30 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) return elems; } +static int nl80211_parse_he_bss_color(struct nlattr *attrs, + struct cfg80211_he_bss_color *he_bss_color) +{ + struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1]; + int err; + + err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs, + he_bss_color_policy, NULL); + if (err) + return err; + + if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]) + return -EINVAL; + + he_bss_color->color = + nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]); + he_bss_color->enabled = + !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]); + he_bss_color->partial = + nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]); + + return 0; +} + static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, struct nlattr *attrs[], struct cfg80211_beacon_data *bcn) @@ -5261,6 +5286,14 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, bcn->ftm_responder = -1; } + if (attrs[NL80211_ATTR_HE_BSS_COLOR]) { + err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR], + &bcn->he_bss_color); + if (err) + return err; + bcn->he_bss_color_valid = true; + } + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { struct cfg80211_mbssid_elems *mbssid = nl80211_parse_mbssid_elems(&rdev->wiphy, @@ -5319,30 +5352,6 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs, return 0; } -static int nl80211_parse_he_bss_color(struct nlattr *attrs, - struct cfg80211_he_bss_color *he_bss_color) -{ - struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1]; - int err; - - err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs, - he_bss_color_policy, NULL); - if (err) - return err; - - if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]) - return -EINVAL; - - he_bss_color->color = - nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]); - he_bss_color->enabled = - !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]); - he_bss_color->partial = - nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]); - - return 0; -} - static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev, struct nlattr *attrs, struct cfg80211_ap_settings *params) @@ -5734,14 +5743,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) goto out; } - if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) { - err = nl80211_parse_he_bss_color( - info->attrs[NL80211_ATTR_HE_BSS_COLOR], - ¶ms->he_bss_color); - if (err) - goto out; - } - if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) { err = nl80211_parse_fils_discovery(rdev, info->attrs[NL80211_ATTR_FILS_DISCOVERY], @@ -10387,6 +10388,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE])) req.flags |= ASSOC_REQ_DISABLE_HE; + if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT])) + req.flags |= ASSOC_REQ_DISABLE_EHT; + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) memcpy(&req.vht_capa_mask, nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), @@ -11175,6 +11179,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE])) connect.flags |= ASSOC_REQ_DISABLE_HE; + if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT])) + connect.flags |= ASSOC_REQ_DISABLE_EHT; + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) memcpy(&connect.vht_capa_mask, nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), @@ -15301,23 +15308,79 @@ static int nl80211_set_fils_aad(struct sk_buff *skb, #define NL80211_FLAG_CLEAR_SKB 0x20 #define NL80211_FLAG_NO_WIPHY_MTX 0x40 +#define INTERNAL_FLAG_SELECTORS(__sel) \ + SELECTOR(__sel, NONE, 0) /* must be first */ \ + SELECTOR(__sel, WIPHY, \ + NL80211_FLAG_NEED_WIPHY) \ + SELECTOR(__sel, WDEV, \ + NL80211_FLAG_NEED_WDEV) \ + SELECTOR(__sel, NETDEV, \ + NL80211_FLAG_NEED_NETDEV) \ + SELECTOR(__sel, WIPHY_RTNL, \ + NL80211_FLAG_NEED_WIPHY | \ + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, WIPHY_RTNL_NOMTX, \ + NL80211_FLAG_NEED_WIPHY | \ + NL80211_FLAG_NEED_RTNL | \ + NL80211_FLAG_NO_WIPHY_MTX) \ + SELECTOR(__sel, WDEV_RTNL, \ + NL80211_FLAG_NEED_WDEV | \ + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, NETDEV_RTNL, \ + NL80211_FLAG_NEED_NETDEV | \ + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, NETDEV_UP, \ + NL80211_FLAG_NEED_NETDEV_UP) \ + SELECTOR(__sel, NETDEV_UP_NOTMX, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_NO_WIPHY_MTX) \ + SELECTOR(__sel, NETDEV_UP_CLEAR, \ + NL80211_FLAG_NEED_NETDEV_UP | \ + NL80211_FLAG_CLEAR_SKB) \ + SELECTOR(__sel, WDEV_UP, \ + NL80211_FLAG_NEED_WDEV_UP) \ + SELECTOR(__sel, WDEV_UP_RTNL, \ + NL80211_FLAG_NEED_WDEV_UP | \ + NL80211_FLAG_NEED_RTNL) \ + SELECTOR(__sel, WIPHY_CLEAR, \ + NL80211_FLAG_NEED_WIPHY | \ + NL80211_FLAG_CLEAR_SKB) + +enum nl80211_internal_flags_selector { +#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name, + INTERNAL_FLAG_SELECTORS(_) +#undef SELECTOR +}; + +static u32 nl80211_internal_flags[] = { +#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value, + INTERNAL_FLAG_SELECTORS(_) +#undef SELECTOR +}; + static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = NULL; struct wireless_dev *wdev; struct net_device *dev; + u32 internal_flags; + + if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags))) + return -EINVAL; + + internal_flags = nl80211_internal_flags[ops->internal_flags]; rtnl_lock(); - if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { + if (internal_flags & NL80211_FLAG_NEED_WIPHY) { rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); if (IS_ERR(rdev)) { rtnl_unlock(); return PTR_ERR(rdev); } info->user_ptr[0] = rdev; - } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || - ops->internal_flags & NL80211_FLAG_NEED_WDEV) { + } else if (internal_flags & NL80211_FLAG_NEED_NETDEV || + internal_flags & NL80211_FLAG_NEED_WDEV) { wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info), info->attrs); if (IS_ERR(wdev)) { @@ -15328,7 +15391,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, dev = wdev->netdev; rdev = wiphy_to_rdev(wdev->wiphy); - if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { + if (internal_flags & NL80211_FLAG_NEED_NETDEV) { if (!dev) { rtnl_unlock(); return -EINVAL; @@ -15339,7 +15402,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, info->user_ptr[1] = wdev; } - if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && + if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && !wdev_running(wdev)) { rtnl_unlock(); return -ENETDOWN; @@ -15349,12 +15412,12 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, info->user_ptr[0] = rdev; } - if (rdev && !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) { + if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) { wiphy_lock(&rdev->wiphy); /* we keep the mutex locked until post_doit */ __release(&rdev->wiphy.mtx); } - if (!(ops->internal_flags & NL80211_FLAG_NEED_RTNL)) + if (!(internal_flags & NL80211_FLAG_NEED_RTNL)) rtnl_unlock(); return 0; @@ -15363,8 +15426,10 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { + u32 internal_flags = nl80211_internal_flags[ops->internal_flags]; + if (info->user_ptr[1]) { - if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { + if (internal_flags & NL80211_FLAG_NEED_WDEV) { struct wireless_dev *wdev = info->user_ptr[1]; dev_put(wdev->netdev); @@ -15374,7 +15439,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, } if (info->user_ptr[0] && - !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) { + !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; /* we kept the mutex locked since pre_doit */ @@ -15382,7 +15447,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, wiphy_unlock(&rdev->wiphy); } - if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) + if (internal_flags & NL80211_FLAG_NEED_RTNL) rtnl_unlock(); /* If needed, clear the netlink message payload from the SKB @@ -15390,7 +15455,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, * the heap after the SKB is freed. The netlink message header * is still needed for further processing, so leave it intact. */ - if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) { + if (internal_flags & NL80211_FLAG_CLEAR_SKB) { struct nlmsghdr *nlh = nlmsg_hdr(skb); memset(nlmsg_data(nlh), 0, nlmsg_len(nlh)); @@ -15500,6 +15565,11 @@ error: return err; } +#define SELECTOR(__sel, name, value) \ + ((__sel) == (value)) ? NL80211_IFL_SEL_##name : +int __missing_selector(void); +#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector() + static const struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -15508,7 +15578,7 @@ static const struct genl_ops nl80211_ops[] = { .dumpit = nl80211_dump_wiphy, .done = nl80211_dump_wiphy_done, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, }; @@ -15525,112 +15595,113 @@ static const struct genl_small_ops nl80211_small_ops[] = { .doit = nl80211_get_interface, .dumpit = nl80211_dump_interface, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_WDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV), }, { .cmd = NL80211_CMD_SET_INTERFACE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_interface, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_NEW_INTERFACE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_new_interface, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY | - NL80211_FLAG_NEED_RTNL | - /* we take the wiphy mutex later ourselves */ - NL80211_FLAG_NO_WIPHY_MTX, + .internal_flags = + IFLAGS(NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL | + /* we take the wiphy mutex later ourselves */ + NL80211_FLAG_NO_WIPHY_MTX), }, { .cmd = NL80211_CMD_DEL_INTERFACE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_interface, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_GET_KEY, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_key, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_KEY, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_key, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_NEW_KEY, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_new_key, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_DEL_KEY, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_key, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_BEACON, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .flags = GENL_UNS_ADMIN_PERM, .doit = nl80211_set_beacon, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_START_AP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .flags = GENL_UNS_ADMIN_PERM, .doit = nl80211_start_ap, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_STOP_AP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .flags = GENL_UNS_ADMIN_PERM, .doit = nl80211_stop_ap, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_GET_STATION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_station, .dumpit = nl80211_dump_station, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_STATION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_station, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_NEW_STATION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_new_station, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_DEL_STATION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_station, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_GET_MPATH, @@ -15638,7 +15709,7 @@ static const struct genl_small_ops nl80211_small_ops[] = { .doit = nl80211_get_mpath, .dumpit = nl80211_dump_mpath, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_GET_MPP, @@ -15646,42 +15717,41 @@ static const struct genl_small_ops nl80211_small_ops[] = { .doit = nl80211_get_mpp, .dumpit = nl80211_dump_mpp, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_MPATH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_mpath, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_NEW_MPATH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_new_mpath, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_DEL_MPATH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_mpath, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_BSS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_bss, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_GET_REG, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_reg_do, .dumpit = nl80211_get_reg_dump, - .internal_flags = 0, /* can be retrieved by unprivileged users */ }, #ifdef CONFIG_CFG80211_CRDA_SUPPORT @@ -15690,7 +15760,6 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_reg, .flags = GENL_ADMIN_PERM, - .internal_flags = 0, }, #endif { @@ -15710,28 +15779,28 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_mesh_config, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_MESH_CONFIG, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_update_mesh_config, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_TRIGGER_SCAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_trigger_scan, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_ABORT_SCAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_abort_scan, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_GET_SCAN, @@ -15743,60 +15812,58 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_start_sched_scan, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_STOP_SCHED_SCAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_stop_sched_scan, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_AUTHENTICATE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_authenticate, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_ASSOCIATE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_associate, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_DEAUTHENTICATE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_deauthenticate, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_DISASSOCIATE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_disassociate, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_JOIN_IBSS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_join_ibss, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_LEAVE_IBSS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_leave_ibss, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, #ifdef CONFIG_NL80211_TESTMODE { @@ -15805,7 +15872,7 @@ static const struct genl_small_ops nl80211_small_ops[] = { .doit = nl80211_testmode_do, .dumpit = nl80211_testmode_dump, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, #endif { @@ -15813,34 +15880,32 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_connect, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_update_connect_params, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_DISCONNECT, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_disconnect, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_WIPHY_NETNS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_wiphy_netns, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY | - NL80211_FLAG_NEED_RTNL | - NL80211_FLAG_NO_WIPHY_MTX, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL | + NL80211_FLAG_NO_WIPHY_MTX), }, { .cmd = NL80211_CMD_GET_SURVEY, @@ -15852,121 +15917,120 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_setdel_pmksa, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_DEL_PMKSA, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_setdel_pmksa, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_FLUSH_PMKSA, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_flush_pmksa, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_remain_on_channel, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_cancel_remain_on_channel, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_tx_bitrate_mask, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_REGISTER_FRAME, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_register_mgmt, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV), }, { .cmd = NL80211_CMD_FRAME, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tx_mgmt, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_FRAME_WAIT_CANCEL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tx_mgmt_cancel_wait, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_SET_POWER_SAVE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_power_save, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_GET_POWER_SAVE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_power_save, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_CQM, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_cqm, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_CHANNEL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_channel, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_JOIN_MESH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_join_mesh, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_LEAVE_MESH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_leave_mesh, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_JOIN_OCB, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_join_ocb, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_LEAVE_OCB, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_leave_ocb, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, #ifdef CONFIG_PM { @@ -15974,14 +16038,14 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_wowlan, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, { .cmd = NL80211_CMD_SET_WOWLAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_wowlan, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, #endif { @@ -15989,126 +16053,125 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_rekey_data, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_TDLS_MGMT, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tdls_mgmt, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_TDLS_OPER, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tdls_oper, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_UNEXPECTED_FRAME, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_register_unexpected_frame, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_PROBE_CLIENT, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_probe_client, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_REGISTER_BEACONS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_register_beacons, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, { .cmd = NL80211_CMD_SET_NOACK_MAP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_noack_map, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_START_P2P_DEVICE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_start_p2p_device, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_STOP_P2P_DEVICE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_stop_p2p_device, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_START_NAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_start_nan, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_STOP_NAN, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_stop_nan, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_ADD_NAN_FUNCTION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_nan_add_func, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_DEL_NAN_FUNCTION, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_nan_del_func, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_CHANGE_NAN_CONFIG, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_nan_change_config, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_SET_MCAST_RATE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_mcast_rate, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_MAC_ACL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_mac_acl, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_RADAR_DETECT, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_start_radar_detection, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NO_WIPHY_MTX, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NO_WIPHY_MTX), }, { .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, @@ -16120,41 +16183,41 @@ static const struct genl_small_ops nl80211_small_ops[] = { .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_update_ft_ies, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_CRIT_PROTOCOL_START, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_crit_protocol_start, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_crit_protocol_stop, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_GET_COALESCE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_coalesce, - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, { .cmd = NL80211_CMD_SET_COALESCE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_coalesce, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), }, { .cmd = NL80211_CMD_CHANNEL_SWITCH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_channel_switch, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_VENDOR, @@ -16162,140 +16225,137 @@ static const struct genl_small_ops nl80211_small_ops[] = { .doit = nl80211_vendor_cmd, .dumpit = nl80211_vendor_cmd_dump, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_SET_QOS_MAP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_qos_map, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_ADD_TX_TS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_add_tx_ts, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_DEL_TX_TS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_tx_ts, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tdls_channel_switch, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tdls_cancel_channel_switch, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_multicast_to_unicast, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_PMK, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_pmk, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - 0 | - NL80211_FLAG_CLEAR_SKB, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_CLEAR_SKB), }, { .cmd = NL80211_CMD_DEL_PMK, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_del_pmk, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_EXTERNAL_AUTH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_external_auth, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_CONTROL_PORT_FRAME, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_tx_control_port, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_get_ftm_responder_stats, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_PEER_MEASUREMENT_START, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_pmsr_start, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP), }, { .cmd = NL80211_CMD_NOTIFY_RADAR, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_notify_radar_detection, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_UPDATE_OWE_INFO, .doit = nl80211_update_owe_info, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_PROBE_MESH_LINK, .doit = nl80211_probe_mesh_link, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_TID_CONFIG, .doit = nl80211_set_tid_config, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV), }, { .cmd = NL80211_CMD_SET_SAR_SPECS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_sar_specs, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_WIPHY | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL), }, { .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_color_change, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, { .cmd = NL80211_CMD_SET_FILS_AAD, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .doit = nl80211_set_fils_aad, .flags = GENL_UNS_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, + .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP), }, }; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c76cd973f06e..58e83ce642ad 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -807,6 +807,8 @@ static int __init load_builtin_regdb_keys(void) return 0; } +MODULE_FIRMWARE("regulatory.db.p7s"); + static bool regdb_has_valid_signature(const u8 *data, unsigned int size) { const struct firmware *sig; @@ -1078,6 +1080,8 @@ static void regdb_fw_cb(const struct firmware *fw, void *context) release_firmware(fw); } +MODULE_FIRMWARE("regulatory.db"); + static int query_regdb_file(const char *alpha2) { ASSERT_RTNL(); |