diff options
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(); |