summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2023-04-21 17:35:51 +0300
committerJakub Kicinski <kuba@kernel.org>2023-04-21 17:35:51 +0300
commitca288965801572fe41386560d4e6c5cc0e5cc56d (patch)
tree9bed659bc9fefffc9f280eba3fd21aafec949813
parentdfc39d4026fb2432363c0f77543c4cf3adca4c7b (diff)
parent3288ee5844b74cebb94ed15bc9b5b9d3223ae038 (diff)
downloadlinux-ca288965801572fe41386560d4e6c5cc0e5cc56d.tar.xz
Merge tag 'wireless-next-2023-04-21' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says: ==================== wireless-next patches for v6.4 Most likely the last -next pull request for v6.4. We have changes all over. rtw88 now supports SDIO bus and iwlwifi continues to work on Wi-Fi 7 support. Not much stack changes this time. Major changes: cfg80211/mac80211 - fix some Fine Time Measurement (FTM) frames not being bufferable - flush frames before key removal to avoid potential unencrypted transmission depending on the hardware design iwlwifi - preparation for Wi-Fi 7 EHT and multi-link support rtw88 - SDIO bus support - RTL8822BS, RTL8822CS and RTL8821CS SDIO chipset support rtw89 - framework firmware backwards compatibility brcmfmac - Cypress 43439 SDIO support mt76 - mt7921 P2P support - mt7996 mesh A-MSDU support - mt7996 EHT support - mt7996 coredump support wcn36xx - support for pronto v3 hardware ath11k - PCIe DeviceTree bindings - WCN6750: enable SAR support ath10k - convert DeviceTree bindings to YAML * tag 'wireless-next-2023-04-21' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (261 commits) wifi: rtw88: Update spelling in main.h wifi: airo: remove ISA_DMA_API dependency wifi: rtl8xxxu: Simplify setting the initial gain wifi: rtl8xxxu: Add rtl8xxxu_write{8,16,32}_{set,clear} wifi: rtl8xxxu: Don't print the vendor/product/serial wifi: rtw88: Fix memory leak in rtw88_usb wifi: rtw88: call rtw8821c_switch_rf_set() according to chip variant wifi: rtw88: set pkg_type correctly for specific rtw8821c variants wifi: rtw88: rtw8821c: Fix rfe_option field width wifi: rtw88: usb: fix priority queue to endpoint mapping wifi: rtw88: 8822c: add iface combination wifi: rtw88: handle station mode concurrent scan with AP mode wifi: rtw88: prevent scan abort with other VIFs wifi: rtw88: refine reserved page flow for AP mode wifi: rtw88: disallow PS during AP mode wifi: rtw88: 8822c: extend reserved page number wifi: rtw88: add port switch for AP mode wifi: rtw88: add bitmap for dynamic port settings wifi: rtw89: mac: use regular int as return type of DLE buffer request wifi: mac80211: remove return value check of debugfs_create_dir() ... ==================== Link: https://lore.kernel.org/r/20230421104726.800BCC433D2@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml5
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt215
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml358
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml58
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/bcma/main.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/dbring.c12
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h73
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h6
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c140
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c33
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.c14
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.h20
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c28
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h3
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c50
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c14
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c48
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h5
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c15
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_tx.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c117
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c8
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c30
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h4
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c23
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.h4
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c1
-rw-r--r--drivers/net/wireless/ath/wcn36xx/wcn36xx.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c9
-rw-r--r--drivers/net/wireless/cisco/Kconfig2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c104
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/sta.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dump.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-csr.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-debug.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/main.c40
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c36
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c236
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c69
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c76
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c114
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c139
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h76
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c81
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h21
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c71
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c107
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sf.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c35
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c422
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c73
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h19
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mac.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/dma.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/init.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mac.c18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mac.h12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.c11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.h11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mmio.c11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/pci.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/sdio.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/usb.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac.h21
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h22
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c78
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c21
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h19
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c36
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/dma.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c35
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.h33
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c115
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mmio.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/soc.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/dma.c50
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/init.c43
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.c18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.h53
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c42
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c31
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.h11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c64
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/sdio.c23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb.c27
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/Kconfig1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/Makefile2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/coredump.c268
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/coredump.h97
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c149
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/dma.c64
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/init.c72
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c501
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.h62
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c78
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c222
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.h30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mmio.c23
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h76
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/regs.h51
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c6
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h19
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c5
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c8
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c5
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c54
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c9
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c4
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c6
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c113
-rw-r--r--drivers/net/wireless/realtek/rtw88/Kconfig36
-rw-r--r--drivers/net/wireless/realtek/rtw88/Makefile12
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c20
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.c55
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c40
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c157
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h23
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h12
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c26
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821cs.c36
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822bs.c36
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822cs.c36
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c1394
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.h178
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c71
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.c35
-rw-r--r--drivers/net/wireless/realtek/rtw89/chan.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c362
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h155
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c13
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c456
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h311
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c144
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c92
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c38
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h4
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c92
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c12
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.h19
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c534
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h38
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.c14824
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.h21
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c22
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_table.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_table.h11
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c55
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.h11
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c40
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.c21
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.h16
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c2
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c3
-rw-r--r--include/linux/ieee80211.h63
-rw-r--r--include/linux/mmc/sdio_ids.h14
-rw-r--r--include/net/mac80211.h26
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/debugfs.c4
-rw-r--r--net/mac80211/driver-ops.h15
-rw-r--r--net/mac80211/sta_info.c12
-rw-r--r--net/mac80211/status.c24
-rw-r--r--net/mac80211/trace.h7
-rw-r--r--net/mac80211/tx.c4
239 files changed, 23373 insertions, 2871 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index 7d526ff53fb7..67b63f119f64 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -111,6 +111,11 @@ properties:
$ref: /schemas/leds/common.yaml#
additionalProperties: false
properties:
+ led-active-low:
+ description:
+ LED is enabled with ground signal.
+ type: boolean
+
led-sources:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
deleted file mode 100644
index b61c2d5a0ff7..000000000000
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
+++ /dev/null
@@ -1,215 +0,0 @@
-* Qualcomm Atheros ath10k wireless devices
-
-Required properties:
-- compatible: Should be one of the following:
- * "qcom,ath10k"
- * "qcom,ipq4019-wifi"
- * "qcom,wcn3990-wifi"
-
-PCI based devices uses compatible string "qcom,ath10k" and takes calibration
-data along with board specific data via "qcom,ath10k-calibration-data".
-Rest of the properties are not applicable for PCI based devices.
-
-AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
-and also uses most of the properties defined in this doc (except
-"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data"
-to carry pre calibration data.
-
-In general, entry "qcom,ath10k-pre-calibration-data" and
-"qcom,ath10k-calibration-data" conflict with each other and only one
-can be provided per device.
-
-SNOC based devices (i.e. wcn3990) uses compatible string "qcom,wcn3990-wifi".
-
-- reg: Address and length of the register set for the device.
-- reg-names: Must include the list of following reg names,
- "membase"
-- interrupts: reference to the list of 17 interrupt numbers for "qcom,ipq4019-wifi"
- compatible target.
- reference to the list of 12 interrupt numbers for "qcom,wcn3990-wifi"
- compatible target.
- Must contain interrupt-names property per entry for
- "qcom,ath10k", "qcom,ipq4019-wifi" compatible targets.
-
-- interrupt-names: Must include the entries for MSI interrupt
- names ("msi0" to "msi15") and legacy interrupt
- name ("legacy") for "qcom,ath10k", "qcom,ipq4019-wifi"
- compatible targets.
-
-Optional properties:
-- resets: Must contain an entry for each entry in reset-names.
- See ../reset/reseti.txt for details.
-- reset-names: Must include the list of following reset names,
- "wifi_cpu_init"
- "wifi_radio_srif"
- "wifi_radio_warm"
- "wifi_radio_cold"
- "wifi_core_warm"
- "wifi_core_cold"
-- clocks: List of clock specifiers, must contain an entry for each required
- entry in clock-names.
-- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref",
- "wifi_wcss_rtc" for "qcom,ipq4019-wifi" compatible target and
- "cxo_ref_clk_pin" and optionally "qdss" for "qcom,wcn3990-wifi"
- compatible target.
-- qcom,msi_addr: MSI interrupt address.
-- qcom,msi_base: Base value to add before writing MSI data into
- MSI address register.
-- qcom,ath10k-calibration-variant: string to search for in the board-2.bin
- variant list with the same bus and device
- specific ids
-- qcom,ath10k-calibration-data : calibration data + board specific data
- as an array, the length can vary between
- hw versions.
-- qcom,ath10k-pre-calibration-data : pre calibration data as an array,
- the length can vary between hw versions.
-- <supply-name>-supply: handle to the regulator device tree node
- optional "supply-name" are "vdd-0.8-cx-mx",
- "vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0",
- and "vdd-3.3-ch1".
-- memory-region:
- Usage: optional
- Value type: <phandle>
- Definition: reference to the reserved-memory for the msa region
- used by the wifi firmware running in Q6.
-- iommus:
- Usage: optional
- Value type: <prop-encoded-array>
- Definition: A list of phandle and IOMMU specifier pairs.
-- ext-fem-name:
- Usage: Optional
- Value type: string
- Definition: Name of external front end module used. Some valid FEM names
- for example: "microsemi-lx5586", "sky85703-11"
- and "sky85803" etc.
-- qcom,snoc-host-cap-8bit-quirk:
- Usage: Optional
- Value type: <empty>
- Definition: Quirk specifying that the firmware expects the 8bit version
- of the host capability QMI request
-- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
-
-- qcom,msa-fixed-perm: Boolean context flag to disable SCM call for statically
- mapped msa region.
-
-- qcom,coexist-support : should contain eithr "0" or "1" to indicate coex
- support by the hardware.
-- qcom,coexist-gpio-pin : gpio pin number information to support coex
- which will be used by wifi firmware.
-
-* Subnodes
-The ath10k wifi node can contain one optional firmware subnode.
-Firmware subnode is needed when the platform does not have TustZone.
-The firmware subnode must have:
-
-- iommus:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: A list of phandle and IOMMU specifier pairs.
-
-
-Example (to supply PCI based wifi block details):
-
-In this example, the node is defined as child node of the PCI controller.
-
-pci {
- pcie@0 {
- reg = <0 0 0 0 0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
-
- wifi@0,0 {
- reg = <0 0 0 0 0>;
- qcom,ath10k-calibration-data = [ 01 02 03 ... ];
- ext-fem-name = "microsemi-lx5586";
- };
- };
-};
-
-Example (to supply ipq4019 SoC wifi block details):
-
-wifi0: wifi@a000000 {
- compatible = "qcom,ipq4019-wifi";
- reg = <0xa000000 0x200000>;
- resets = <&gcc WIFI0_CPU_INIT_RESET>,
- <&gcc WIFI0_RADIO_SRIF_RESET>,
- <&gcc WIFI0_RADIO_WARM_RESET>,
- <&gcc WIFI0_RADIO_COLD_RESET>,
- <&gcc WIFI0_CORE_WARM_RESET>,
- <&gcc WIFI0_CORE_COLD_RESET>;
- reset-names = "wifi_cpu_init",
- "wifi_radio_srif",
- "wifi_radio_warm",
- "wifi_radio_cold",
- "wifi_core_warm",
- "wifi_core_cold";
- clocks = <&gcc GCC_WCSS2G_CLK>,
- <&gcc GCC_WCSS2G_REF_CLK>,
- <&gcc GCC_WCSS2G_RTC_CLK>;
- clock-names = "wifi_wcss_cmd",
- "wifi_wcss_ref",
- "wifi_wcss_rtc";
- interrupts = <0 0x20 0x1>,
- <0 0x21 0x1>,
- <0 0x22 0x1>,
- <0 0x23 0x1>,
- <0 0x24 0x1>,
- <0 0x25 0x1>,
- <0 0x26 0x1>,
- <0 0x27 0x1>,
- <0 0x28 0x1>,
- <0 0x29 0x1>,
- <0 0x2a 0x1>,
- <0 0x2b 0x1>,
- <0 0x2c 0x1>,
- <0 0x2d 0x1>,
- <0 0x2e 0x1>,
- <0 0x2f 0x1>,
- <0 0xa8 0x0>;
- interrupt-names = "msi0", "msi1", "msi2", "msi3",
- "msi4", "msi5", "msi6", "msi7",
- "msi8", "msi9", "msi10", "msi11",
- "msi12", "msi13", "msi14", "msi15",
- "legacy";
- qcom,msi_addr = <0x0b006040>;
- qcom,msi_base = <0x40>;
- qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ];
- qcom,coexist-support = <1>;
- qcom,coexist-gpio-pin = <0x33>;
-};
-
-Example (to supply wcn3990 SoC wifi block details):
-
-wifi@18000000 {
- compatible = "qcom,wcn3990-wifi";
- reg = <0x18800000 0x800000>;
- reg-names = "membase";
- clocks = <&clock_gcc clk_rf_clk2_pin>;
- clock-names = "cxo_ref_clk_pin";
- interrupts =
- <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
- vdd-0.8-cx-mx-supply = <&pm8998_l5>;
- vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
- vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
- vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
- vdd-3.3-ch1-supply = <&vreg_l26a_3p3>;
- memory-region = <&wifi_msa_mem>;
- iommus = <&apps_smmu 0x0040 0x1>;
- qcom,msa-fixed-perm;
- wifi-firmware {
- iommus = <&apps_iommu 0xc22 0x1>;
- };
-};
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
new file mode 100644
index 000000000000..c85ed330426d
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -0,0 +1,358 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/wireless/qcom,ath10k.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies ath10k wireless devices
+
+maintainers:
+ - Kalle Valo <kvalo@kernel.org>
+
+description:
+ Qualcomm Technologies, Inc. IEEE 802.11ac devices.
+
+properties:
+ compatible:
+ enum:
+ - qcom,ath10k # SDIO-based devices
+ - qcom,ipq4019-wifi
+ - qcom,wcn3990-wifi # SNoC-based devices
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: membase
+
+ interrupts:
+ minItems: 12
+ maxItems: 17
+
+ interrupt-names:
+ minItems: 12
+ maxItems: 17
+
+ memory-region:
+ maxItems: 1
+ description:
+ Reference to the MSA memory region used by the Wi-Fi firmware
+ running on the Q6 core.
+
+ iommus:
+ minItems: 1
+ maxItems: 2
+
+ clocks:
+ minItems: 1
+ maxItems: 3
+
+ clock-names:
+ minItems: 1
+ maxItems: 3
+
+ resets:
+ maxItems: 6
+
+ reset-names:
+ items:
+ - const: wifi_cpu_init
+ - const: wifi_radio_srif
+ - const: wifi_radio_warm
+ - const: wifi_radio_cold
+ - const: wifi_core_warm
+ - const: wifi_core_cold
+
+ ext-fem-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Name of external front end module used.
+ enum:
+ - microsemi-lx5586
+ - sky85703-11
+ - sky85803
+
+ wifi-firmware:
+ type: object
+ additionalProperties: false
+ description: |
+ The ath10k Wi-Fi node can contain one optional firmware subnode.
+ Firmware subnode is needed when the platform does not have Trustzone.
+ properties:
+ iommus:
+ maxItems: 1
+ required:
+ - iommus
+
+ qcom,ath10k-calibration-data:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ Calibration data + board-specific data as a byte array. The length
+ can vary between hardware versions.
+
+ qcom,ath10k-calibration-variant:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ Unique variant identifier of the calibration data in board-2.bin
+ for designs with colliding bus and device specific ids
+
+ qcom,ath10k-pre-calibration-data:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ Pre-calibration data as a byte array. The length can vary between
+ hardware versions.
+
+ qcom,coexist-support:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ enum: [0, 1]
+ description:
+ Indicate coex support by the hardware.
+
+ qcom,coexist-gpio-pin:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ COEX GPIO number provided to the Wi-Fi firmware.
+
+ qcom,msa-fixed-perm:
+ type: boolean
+ description:
+ Whether to skip executing an SCM call that reassigns the memory
+ region ownership.
+
+ qcom,smem-states:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: State bits used by the AP to signal the WLAN Q6.
+ items:
+ - description: Signal bits used to enable/disable low power mode
+ on WCN in the case of WoW (Wake on Wireless).
+
+ qcom,smem-state-names:
+ description: The names of the state bits used for SMP2P output.
+ items:
+ - const: wlan-smp2p-out
+
+ qcom,snoc-host-cap-8bit-quirk:
+ type: boolean
+ description:
+ Quirk specifying that the firmware expects the 8bit version
+ of the host capability QMI request
+
+ qcom,xo-cal-data:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ XO cal offset to be configured in XO trim register.
+
+ vdd-0.8-cx-mx-supply:
+ description: Main logic power rail
+
+ vdd-1.8-xo-supply:
+ description: Crystal oscillator supply
+
+ vdd-1.3-rfa-supply:
+ description: RFA supply
+
+ vdd-3.3-ch0-supply:
+ description: Primary Wi-Fi antenna supply
+
+ vdd-3.3-ch1-supply:
+ description: Secondary Wi-Fi antenna supply
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,ipq4019-wifi
+ then:
+ properties:
+ interrupts:
+ minItems: 17
+ maxItems: 17
+
+ interrupt-names:
+ items:
+ - const: msi0
+ - const: msi1
+ - const: msi2
+ - const: msi3
+ - const: msi4
+ - const: msi5
+ - const: msi6
+ - const: msi7
+ - const: msi8
+ - const: msi9
+ - const: msi10
+ - const: msi11
+ - const: msi12
+ - const: msi13
+ - const: msi14
+ - const: msi15
+ - const: legacy
+
+ clocks:
+ items:
+ - description: Wi-Fi command clock
+ - description: Wi-Fi reference clock
+ - description: Wi-Fi RTC clock
+
+ clock-names:
+ items:
+ - const: wifi_wcss_cmd
+ - const: wifi_wcss_ref
+ - const: wifi_wcss_rtc
+
+ required:
+ - clocks
+ - clock-names
+ - interrupts
+ - interrupt-names
+ - resets
+ - reset-names
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,wcn3990-wifi
+
+ then:
+ properties:
+ clocks:
+ minItems: 1
+ items:
+ - description: XO reference clock
+ - description: Qualcomm Debug Subsystem clock
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: cxo_ref_clk_pin
+ - const: qdss
+
+ interrupts:
+ items:
+ - description: CE0
+ - description: CE1
+ - description: CE2
+ - description: CE3
+ - description: CE4
+ - description: CE5
+ - description: CE6
+ - description: CE7
+ - description: CE8
+ - description: CE9
+ - description: CE10
+ - description: CE11
+
+ interrupt-names: false
+
+ required:
+ - interrupts
+
+examples:
+ # SNoC
+ - |
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ wifi@18800000 {
+ compatible = "qcom,wcn3990-wifi";
+ reg = <0x18800000 0x800000>;
+ reg-names = "membase";
+ memory-region = <&wlan_msa_mem>;
+ clocks = <&rpmcc RPM_SMD_RF_CLK2_PIN>;
+ clock-names = "cxo_ref_clk_pin";
+ interrupts = <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&anoc2_smmu 0x1900>,
+ <&anoc2_smmu 0x1901>;
+ qcom,snoc-host-cap-8bit-quirk;
+ vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
+ vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+ vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
+
+ wifi-firmware {
+ iommus = <&apps_smmu 0x1c02 0x1>;
+ };
+ };
+
+ # AHB
+ - |
+ #include <dt-bindings/clock/qcom,gcc-ipq4019.h>
+
+ wifi@a000000 {
+ compatible = "qcom,ipq4019-wifi";
+ reg = <0xa000000 0x200000>;
+ resets = <&gcc WIFI0_CPU_INIT_RESET>,
+ <&gcc WIFI0_RADIO_SRIF_RESET>,
+ <&gcc WIFI0_RADIO_WARM_RESET>,
+ <&gcc WIFI0_RADIO_COLD_RESET>,
+ <&gcc WIFI0_CORE_WARM_RESET>,
+ <&gcc WIFI0_CORE_COLD_RESET>;
+ reset-names = "wifi_cpu_init",
+ "wifi_radio_srif",
+ "wifi_radio_warm",
+ "wifi_radio_cold",
+ "wifi_core_warm",
+ "wifi_core_cold";
+ clocks = <&gcc GCC_WCSS2G_CLK>,
+ <&gcc GCC_WCSS2G_REF_CLK>,
+ <&gcc GCC_WCSS2G_RTC_CLK>;
+ clock-names = "wifi_wcss_cmd",
+ "wifi_wcss_ref",
+ "wifi_wcss_rtc";
+ interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 38 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 41 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 42 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 43 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 44 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 45 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 46 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 47 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0",
+ "msi1",
+ "msi2",
+ "msi3",
+ "msi4",
+ "msi5",
+ "msi6",
+ "msi7",
+ "msi8",
+ "msi9",
+ "msi10",
+ "msi11",
+ "msi12",
+ "msi13",
+ "msi14",
+ "msi15",
+ "legacy";
+ };
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml
new file mode 100644
index 000000000000..817f02a8b481
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k-pci.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (c) 2023 Linaro Limited
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k-pci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies ath11k wireless devices (PCIe)
+
+maintainers:
+ - Kalle Valo <kvalo@kernel.org>
+
+description: |
+ Qualcomm Technologies IEEE 802.11ax PCIe devices
+
+properties:
+ compatible:
+ enum:
+ - pci17cb,1103 # WCN6855
+
+ reg:
+ maxItems: 1
+
+ qcom,ath11k-calibration-variant:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: |
+ string to uniquely identify variant of the calibration data for designs
+ with colliding bus and device ids
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pcie {
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ bus-range = <0x01 0xff>;
+
+ wifi@0 {
+ compatible = "pci17cb,1103";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ qcom,ath11k-calibration-variant = "LE_X13S";
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 9420a1599a58..6ac562e0381e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17241,7 +17241,7 @@ S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
F: drivers/net/wireless/ath/ath10k/
-F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
+F: Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
M: Kalle Valo <kvalo@kernel.org>
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 5e438f74ee4c..7061d3ee836a 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/of_device.h>
#include <linux/of_platform.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index b656cfc03648..c27b8204718a 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -84,13 +84,6 @@ ath10k_set_ring_byte(unsigned int offset,
return ((offset << addr_map->lsb) & addr_map->mask);
}
-static inline unsigned int
-ath10k_get_ring_byte(unsigned int offset,
- struct ath10k_hw_ce_regs_addr_map *addr_map)
-{
- return ((offset & addr_map->mask) >> (addr_map->lsb));
-}
-
static inline u32 ath10k_ce_read32(struct ath10k *ar, u32 offset)
{
struct ath10k_ce *ce = ath10k_ce_priv(ar);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 728d607289c3..a7f44f6335fb 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3406,15 +3406,12 @@ static int ath10k_pci_claim(struct ath10k *ar)
if (!ar_pci->mem) {
ath10k_err(ar, "failed to iomap BAR%d\n", BAR_NUM);
ret = -EIO;
- goto err_master;
+ goto err_region;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%pK\n", ar_pci->mem);
return 0;
-err_master:
- pci_clear_master(pdev);
-
err_region:
pci_release_region(pdev, BAR_NUM);
@@ -3431,7 +3428,6 @@ static void ath10k_pci_release(struct ath10k *ar)
pci_iounmap(pdev, ar_pci->mem);
pci_release_region(pdev, BAR_NUM);
- pci_clear_master(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index b549576d0b51..5cbba9a8b6ba 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1078,6 +1078,12 @@ static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
struct iommu_domain *iommu;
size_t unmapped_size;
+ /* Chipsets not requiring MSA would have not initialized
+ * MSA resources, return success in such cases.
+ */
+ if (!ab->hw_params.fixed_fw_mem)
+ return 0;
+
if (ab_ahb->fw.use_tz)
return 0;
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 75fdbe4ef83a..b1b90bd34d67 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -116,7 +116,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tcl_ring_retry = true,
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
- .ftm_responder = true,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -199,7 +198,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
- .ftm_responder = true,
},
{
.name = "qca6390 hw2.0",
@@ -284,7 +282,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
- .ftm_responder = false,
},
{
.name = "qcn9074 hw1.0",
@@ -366,7 +363,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
- .ftm_responder = true,
},
{
.name = "wcn6855 hw2.0",
@@ -451,7 +447,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
- .ftm_responder = false,
},
{
.name = "wcn6855 hw2.1",
@@ -534,7 +529,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
- .ftm_responder = false,
},
{
.name = "wcn6750 hw1.0",
@@ -599,7 +593,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.current_cc_support = true,
.dbr_debug_support = false,
.global_reset = false,
- .bios_sar_capa = NULL,
+ .bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
.m3_fw_support = false,
.fixed_bdf_addr = false,
.fixed_mem_region = false,
@@ -615,7 +609,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
.smp2p_wow_exit = true,
.support_fw_mac_sequence = true,
- .ftm_responder = false,
},
{
.hw_rev = ATH11K_HW_IPQ5018_HW10,
@@ -695,7 +688,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
- .ftm_responder = true,
},
};
diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireless/ath/ath11k/dbring.c
index 2107ec05d14f..5536e8642331 100644
--- a/drivers/net/wireless/ath/ath11k/dbring.c
+++ b/drivers/net/wireless/ath/ath11k/dbring.c
@@ -26,13 +26,13 @@ int ath11k_dbring_validate_buffer(struct ath11k *ar, void *buffer, u32 size)
static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
void *buffer, u32 size)
{
- u32 *temp;
- int idx;
-
- size = size >> 2;
+ /* memset32 function fills buffer payload with the ATH11K_DB_MAGIC_VALUE
+ * and the variable size is expected to be the number of u32 values
+ * to be stored, not the number of bytes.
+ */
+ size = size / sizeof(u32);
- for (idx = 0, temp = buffer; idx < size; idx++, temp++)
- *temp++ = ATH11K_DB_MAGIC_VALUE;
+ memset32(buffer, ATH11K_DB_MAGIC_VALUE, size);
}
static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
index 2b97cbbd28cb..0bbd58a380de 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
@@ -143,7 +143,8 @@ enum htt_tx_pdev_underrun_enum {
/* Bytes stored in little endian order */
/* Length should be multiple of DWORD */
struct htt_stats_string_tlv {
- u32 data[0]; /* Can be variable length */
+ /* Can be variable length */
+ DECLARE_FLEX_ARRAY(u32, data);
} __packed;
#define HTT_STATS_MAC_ID GENMASK(7, 0)
@@ -205,27 +206,32 @@ struct htt_tx_pdev_stats_cmn_tlv {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_pdev_stats_urrn_tlv_v {
- u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */
+ /* HTT_TX_PDEV_MAX_URRN_STATS */
+ DECLARE_FLEX_ARRAY(u32, urrn_stats);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_pdev_stats_flush_tlv_v {
- u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */
+ /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */
+ DECLARE_FLEX_ARRAY(u32, flush_errs);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_pdev_stats_sifs_tlv_v {
- u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */
+ /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */
+ DECLARE_FLEX_ARRAY(u32, sifs_status);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_pdev_stats_phy_err_tlv_v {
- u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */
+ /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */
+ DECLARE_FLEX_ARRAY(u32, phy_errs);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_pdev_stats_sifs_hist_tlv_v {
- u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */
+ /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */
+ DECLARE_FLEX_ARRAY(u32, sifs_hist_status);
};
struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v {
@@ -590,20 +596,20 @@ struct htt_tx_hwq_difs_latency_stats_tlv_v {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_hwq_cmd_result_stats_tlv_v {
- /* Histogram of sched cmd result */
- u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */
+ /* Histogram of sched cmd result, HTT_TX_HWQ_MAX_CMD_RESULT_STATS */
+ DECLARE_FLEX_ARRAY(u32, cmd_result);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_hwq_cmd_stall_stats_tlv_v {
- /* Histogram of various pause conitions */
- u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */
+ /* Histogram of various pause conitions, HTT_TX_HWQ_MAX_CMD_STALL_STATS */
+ DECLARE_FLEX_ARRAY(u32, cmd_stall_status);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_hwq_fes_result_stats_tlv_v {
- /* Histogram of number of user fes result */
- u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */
+ /* Histogram of number of user fes result, HTT_TX_HWQ_MAX_FES_RESULT_STATS */
+ DECLARE_FLEX_ARRAY(u32, fes_result);
};
/* NOTE: Variable length TLV, use length spec to infer array size
@@ -635,8 +641,8 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v {
* #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms )
*/
struct htt_tx_hwq_txop_used_cnt_hist_tlv_v {
- /* Histogram of txop used cnt */
- u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */
+ /* Histogram of txop used cnt, HTT_TX_HWQ_TXOP_USED_CNT_HIST */
+ DECLARE_FLEX_ARRAY(u32, txop_used_cnt_hist);
};
/* == TX SELFGEN STATS == */
@@ -804,17 +810,20 @@ struct htt_tx_pdev_mpdu_stats_tlv {
/* == TX SCHED STATS == */
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_sched_txq_cmd_posted_tlv_v {
- u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
+ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
+ DECLARE_FLEX_ARRAY(u32, sched_cmd_posted);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_sched_txq_cmd_reaped_tlv_v {
- u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
+ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */
+ DECLARE_FLEX_ARRAY(u32, sched_cmd_reaped);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_sched_txq_sched_order_su_tlv_v {
- u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */
+ /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */
+ DECLARE_FLEX_ARRAY(u32, sched_order_su);
};
enum htt_sched_txq_sched_ineligibility_tlv_enum {
@@ -842,7 +851,7 @@ enum htt_sched_txq_sched_ineligibility_tlv_enum {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_sched_txq_sched_ineligibility_tlv_v {
/* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */
- u32 sched_ineligibility[0];
+ DECLARE_FLEX_ARRAY(u32, sched_ineligibility);
};
#define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0)
@@ -888,18 +897,20 @@ struct htt_stats_tx_sched_cmn_tlv {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_tqm_gen_mpdu_stats_tlv_v {
- u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */
+ /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */
+ DECLARE_FLEX_ARRAY(u32, gen_mpdu_end_reason);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_tqm_list_mpdu_stats_tlv_v {
- u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */
+ /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */
+ DECLARE_FLEX_ARRAY(u32, list_mpdu_end_reason);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_tx_tqm_list_mpdu_cnt_tlv_v {
- u32 list_mpdu_cnt_hist[0];
- /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */
+ /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */
+ DECLARE_FLEX_ARRAY(u32, list_mpdu_cnt_hist);
};
struct htt_tx_tqm_pdev_stats_tlv_v {
@@ -1098,7 +1109,7 @@ struct htt_tx_de_compl_stats_tlv {
* ENTRIES_PER_BIN_COUNT)
*/
struct htt_tx_de_fw2wbm_ring_full_hist_tlv {
- u32 fw2wbm_ring_full_hist[0];
+ DECLARE_FLEX_ARRAY(u32, fw2wbm_ring_full_hist);
};
struct htt_tx_de_cmn_stats_tlv {
@@ -1151,7 +1162,7 @@ struct htt_ring_if_cmn_tlv {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_sfm_client_user_tlv_v {
/* Number of DWORDS used per user and per client */
- u32 dwords_used_by_user_n[0];
+ DECLARE_FLEX_ARRAY(u32, dwords_used_by_user_n);
};
struct htt_sfm_client_tlv {
@@ -1436,12 +1447,14 @@ struct htt_rx_soc_fw_stats_tlv {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_soc_fw_refill_ring_empty_tlv_v {
- u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */
+ /* HTT_RX_STATS_REFILL_MAX_RING */
+ DECLARE_FLEX_ARRAY(u32, refill_ring_empty_cnt);
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v {
- u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */
+ /* HTT_RX_STATS_REFILL_MAX_RING */
+ DECLARE_FLEX_ARRAY(u32, refill_ring_num_refill);
};
/* RXDMA error code from WBM released packets */
@@ -1473,7 +1486,7 @@ enum htt_rx_rxdma_error_code_enum {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v {
- u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */
+ DECLARE_FLEX_ARRAY(u32, rxdma_err); /* HTT_RX_RXDMA_MAX_ERR_CODE */
};
/* REO error code from WBM released packets */
@@ -1505,7 +1518,7 @@ enum htt_rx_reo_error_code_enum {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v {
- u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */
+ DECLARE_FLEX_ARRAY(u32, reo_err); /* HTT_RX_REO_MAX_ERR_CODE */
};
/* == RX PDEV STATS == */
@@ -1622,13 +1635,13 @@ struct htt_rx_pdev_fw_stats_phy_err_tlv {
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v {
/* Num error MPDU for each RxDMA error type */
- u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */
+ DECLARE_FLEX_ARRAY(u32, fw_ring_mpdu_err); /* HTT_RX_STATS_RXDMA_MAX_ERR */
};
/* NOTE: Variable length TLV, use length spec to infer array size */
struct htt_rx_pdev_fw_mpdu_drop_tlv_v {
/* Num MPDU dropped */
- u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */
+ DECLARE_FLEX_ARRAY(u32, fw_mpdu_drop); /* HTT_RX_STATS_FW_DROP_REASON_MAX */
};
#define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1)
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index f5156a7fbdd7..d070bcb3fe24 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
}
ath11k_peer_rx_tid_cleanup(ar, peer);
+ peer->dp_setup_done = false;
crypto_free_shash(peer->tfm_mmic);
spin_unlock_bh(&ab->base_lock);
}
@@ -72,7 +73,8 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);
if (ret) {
ath11k_warn(ab, "failed to setup rx defrag context\n");
- return ret;
+ tid--;
+ goto peer_clean;
}
/* TODO: Setup other peer specific resource used in data path */
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index be9eafc872b3..d04f78ab6b37 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -214,7 +214,7 @@ struct ath11k_pdev_dp {
#define DP_REO_REINJECT_RING_SIZE 32
#define DP_RX_RELEASE_RING_SIZE 1024
#define DP_REO_EXCEPTION_RING_SIZE 128
-#define DP_REO_CMD_RING_SIZE 128
+#define DP_REO_CMD_RING_SIZE 256
#define DP_REO_STATUS_RING_SIZE 2048
#define DP_RXDMA_BUF_RING_SIZE 4096
#define DP_RXDMA_REFILL_RING_SIZE 2048
@@ -303,12 +303,16 @@ struct ath11k_dp {
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
+#define HTT_INVALID_PEER_ID 0xffff
+
/* HTT tx completion is overlaid in wbm_release_ring */
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9)
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
#define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24)
+#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0)
+#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21)
struct htt_tx_wbm_completion {
u32 info0;
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index b65a84a88264..f67ce62b2b48 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -389,10 +389,10 @@ int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
goto fail_free_skb;
spin_lock_bh(&rx_ring->idr_lock);
- buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0,
- rx_ring->bufs_max * 3, GFP_ATOMIC);
+ buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 1,
+ (rx_ring->bufs_max * 3) + 1, GFP_ATOMIC);
spin_unlock_bh(&rx_ring->idr_lock);
- if (buf_id < 0)
+ if (buf_id <= 0)
goto fail_dma_unmap;
desc = ath11k_hal_srng_src_get_next_entry(ab, srng);
@@ -435,7 +435,6 @@ fail_free_skb:
static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
struct dp_rxdma_ring *rx_ring)
{
- struct ath11k_pdev_dp *dp = &ar->dp;
struct sk_buff *skb;
int buf_id;
@@ -453,28 +452,6 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
idr_destroy(&rx_ring->bufs_idr);
spin_unlock_bh(&rx_ring->idr_lock);
- /* if rxdma1_enable is false, mon_status_refill_ring
- * isn't setup, so don't clean.
- */
- if (!ar->ab->hw_params.rxdma1_enable)
- return 0;
-
- rx_ring = &dp->rx_mon_status_refill_ring[0];
-
- spin_lock_bh(&rx_ring->idr_lock);
- idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
- idr_remove(&rx_ring->bufs_idr, buf_id);
- /* XXX: Understand where internal driver does this dma_unmap
- * of rxdma_buffer.
- */
- dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
- skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL);
- dev_kfree_skb_any(skb);
- }
-
- idr_destroy(&rx_ring->bufs_idr);
- spin_unlock_bh(&rx_ring->idr_lock);
-
return 0;
}
@@ -691,13 +668,18 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
struct ath11k_dp *dp = &ab->dp;
struct dp_reo_cmd *cmd, *tmp;
struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache;
+ struct dp_rx_tid *rx_tid;
spin_lock_bh(&dp->reo_cmd_lock);
list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
list_del(&cmd->list);
- dma_unmap_single(ab->dev, cmd->data.paddr,
- cmd->data.size, DMA_BIDIRECTIONAL);
- kfree(cmd->data.vaddr);
+ rx_tid = &cmd->data;
+ if (rx_tid->vaddr) {
+ dma_unmap_single(ab->dev, rx_tid->paddr,
+ rx_tid->size, DMA_BIDIRECTIONAL);
+ kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
+ }
kfree(cmd);
}
@@ -705,9 +687,13 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
&dp->reo_cmd_cache_flush_list, list) {
list_del(&cmd_cache->list);
dp->reo_cmd_cache_flush_count--;
- dma_unmap_single(ab->dev, cmd_cache->data.paddr,
- cmd_cache->data.size, DMA_BIDIRECTIONAL);
- kfree(cmd_cache->data.vaddr);
+ rx_tid = &cmd_cache->data;
+ if (rx_tid->vaddr) {
+ dma_unmap_single(ab->dev, rx_tid->paddr,
+ rx_tid->size, DMA_BIDIRECTIONAL);
+ kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
+ }
kfree(cmd_cache);
}
spin_unlock_bh(&dp->reo_cmd_lock);
@@ -721,10 +707,12 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx,
if (status != HAL_REO_CMD_SUCCESS)
ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
rx_tid->tid, status);
-
- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
- DMA_BIDIRECTIONAL);
- kfree(rx_tid->vaddr);
+ if (rx_tid->vaddr) {
+ dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
+ DMA_BIDIRECTIONAL);
+ kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
+ }
}
static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
@@ -763,6 +751,7 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
DMA_BIDIRECTIONAL);
kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
}
}
@@ -815,6 +804,7 @@ free_desc:
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
DMA_BIDIRECTIONAL);
kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
}
void ath11k_peer_rx_tid_delete(struct ath11k *ar,
@@ -827,6 +817,8 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
if (!rx_tid->active)
return;
+ rx_tid->active = false;
+
cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
cmd.addr_lo = lower_32_bits(rx_tid->paddr);
cmd.addr_hi = upper_32_bits(rx_tid->paddr);
@@ -841,9 +833,11 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
DMA_BIDIRECTIONAL);
kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
}
- rx_tid->active = false;
+ rx_tid->paddr = 0;
+ rx_tid->size = 0;
}
static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab,
@@ -990,6 +984,7 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab,
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
DMA_BIDIRECTIONAL);
kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
rx_tid->active = false;
@@ -1014,7 +1009,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
peer = ath11k_peer_find(ab, vdev_id, peer_mac);
if (!peer) {
- ath11k_warn(ab, "failed to find the peer to set up rx tid\n");
+ ath11k_warn(ab, "failed to find the peer %pM to set up rx tid\n",
+ peer_mac);
spin_unlock_bh(&ab->base_lock);
return -ENOENT;
}
@@ -1027,7 +1023,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
ba_win_sz, ssn, true);
spin_unlock_bh(&ab->base_lock);
if (ret) {
- ath11k_warn(ab, "failed to update reo for rx tid %d\n", tid);
+ ath11k_warn(ab, "failed to update reo for peer %pM rx tid %d\n: %d",
+ peer_mac, tid, ret);
return ret;
}
@@ -1035,8 +1032,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
peer_mac, paddr,
tid, 1, ba_win_sz);
if (ret)
- ath11k_warn(ab, "failed to send wmi command to update rx reorder queue, tid :%d (%d)\n",
- tid, ret);
+ ath11k_warn(ab, "failed to send wmi rx reorder queue for peer %pM tid %d: %d\n",
+ peer_mac, tid, ret);
return ret;
}
@@ -1069,6 +1066,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
ret = dma_mapping_error(ab->dev, paddr);
if (ret) {
spin_unlock_bh(&ab->base_lock);
+ ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n",
+ peer_mac, tid, ret);
goto err_mem_free;
}
@@ -1082,15 +1081,16 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
paddr, tid, 1, ba_win_sz);
if (ret) {
- ath11k_warn(ar->ab, "failed to setup rx reorder queue, tid :%d (%d)\n",
- tid, ret);
+ ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n",
+ peer_mac, tid, ret);
ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid);
}
return ret;
err_mem_free:
- kfree(vaddr);
+ kfree(rx_tid->vaddr);
+ rx_tid->vaddr = NULL;
return ret;
}
@@ -2665,6 +2665,9 @@ try_again:
cookie);
mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie);
+ if (unlikely(buf_id == 0))
+ continue;
+
ar = ab->pdevs[mac_id].ar;
rx_ring = &ar->dp.rx_refill_buf_ring;
spin_lock_bh(&rx_ring->idr_lock);
@@ -3029,39 +3032,51 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
spin_lock_bh(&rx_ring->idr_lock);
skb = idr_find(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
+
if (!skb) {
ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n",
buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
pmon->buf_state = DP_MON_STATUS_REPLINISH;
goto move_next;
}
- idr_remove(&rx_ring->bufs_idr, buf_id);
- spin_unlock_bh(&rx_ring->idr_lock);
-
rxcb = ATH11K_SKB_RXCB(skb);
- dma_unmap_single(ab->dev, rxcb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
tlv = (struct hal_tlv_hdr *)skb->data;
if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) !=
HAL_RX_STATUS_BUFFER_DONE) {
- ath11k_warn(ab, "mon status DONE not set %lx\n",
+ ath11k_warn(ab, "mon status DONE not set %lx, buf_id %d\n",
FIELD_GET(HAL_TLV_HDR_TAG,
- tlv->tl));
- dev_kfree_skb_any(skb);
+ tlv->tl), buf_id);
+ /* If done status is missing, hold onto status
+ * ring until status is done for this status
+ * ring buffer.
+ * Keep HP in mon_status_ring unchanged,
+ * and break from here.
+ * Check status for same buffer for next time
+ */
pmon->buf_state = DP_MON_STATUS_NO_DMA;
- goto move_next;
+ break;
}
+ spin_lock_bh(&rx_ring->idr_lock);
+ idr_remove(&rx_ring->bufs_idr, buf_id);
+ spin_unlock_bh(&rx_ring->idr_lock);
if (ab->hw_params.full_monitor_mode) {
ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv);
if (paddr == pmon->mon_status_paddr)
pmon->buf_state = DP_MON_STATUS_MATCH;
}
+
+ dma_unmap_single(ab->dev, rxcb->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+
__skb_queue_tail(skb_list, skb);
} else {
pmon->buf_state = DP_MON_STATUS_REPLINISH;
@@ -3117,8 +3132,11 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
int i;
tfm = crypto_alloc_shash("michael_mic", 0, 0);
- if (IS_ERR(tfm))
+ if (IS_ERR(tfm)) {
+ ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n",
+ PTR_ERR(tfm));
return PTR_ERR(tfm);
+ }
spin_lock_bh(&ab->base_lock);
@@ -3138,6 +3156,7 @@ int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id
}
peer->tfm_mmic = tfm;
+ peer->dp_setup_done = true;
spin_unlock_bh(&ab->base_lock);
return 0;
@@ -3583,6 +3602,13 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
ret = -ENOENT;
goto out_unlock;
}
+ if (!peer->dp_setup_done) {
+ ath11k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n",
+ peer->addr, peer_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
rx_tid = &peer->rx_tid[tid];
if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) ||
@@ -3598,7 +3624,7 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
goto out_unlock;
}
- if (frag_no > __fls(rx_tid->rx_frag_bitmap))
+ if (!rx_tid->rx_frag_bitmap || (frag_no > __fls(rx_tid->rx_frag_bitmap)))
__skb_queue_tail(&rx_tid->rx_frags, msdu);
else
ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu);
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 8afbba236935..08a28464eb7a 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
struct dp_tx_ring *tx_ring,
struct ath11k_dp_htt_wbm_tx_status *ts)
{
+ struct ieee80211_tx_status status = { 0 };
struct sk_buff *msdu;
struct ieee80211_tx_info *info;
struct ath11k_skb_cb *skb_cb;
struct ath11k *ar;
+ struct ath11k_peer *peer;
spin_lock(&tx_ring->tx_idr_lock);
msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id);
@@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+ if (!skb_cb->vif) {
+ dev_kfree_skb_any(msdu);
+ return;
+ }
+
memset(&info->status, 0, sizeof(info->status));
if (ts->acked) {
@@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
}
}
- ieee80211_tx_status(ar->hw, msdu);
+ spin_lock_bh(&ab->base_lock);
+ peer = ath11k_peer_find_by_id(ab, ts->peer_id);
+ if (!peer || !peer->sta) {
+ ath11k_dbg(ab, ATH11K_DBG_DATA,
+ "dp_tx: failed to find the peer with peer_id %d\n",
+ ts->peer_id);
+ spin_unlock_bh(&ab->base_lock);
+ dev_kfree_skb_any(msdu);
+ return;
+ }
+ spin_unlock_bh(&ab->base_lock);
+
+ status.sta = peer->sta;
+ status.info = info;
+ status.skb = msdu;
+
+ ieee80211_tx_status_ext(ar->hw, &status);
}
static void
@@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(struct ath11k_base *ab,
ts.msdu_id = msdu_id;
ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI,
status_desc->info1);
+
+ if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2))
+ ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID,
+ status_desc->info2);
+ else
+ ts.peer_id = HTT_INVALID_PEER_ID;
+
ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts);
+
break;
case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h
index e87d65bfbf06..68a21ea9b934 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
@@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status {
u32 msdu_id;
bool acked;
int ack_rssi;
+ u16 peer_id;
};
void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c
index 7f39c6fb7408..bb1d40034aa8 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -865,6 +865,12 @@ ath11k_hal_rx_populate_mu_user_info(void *rx_tlv, struct hal_rx_mon_ppdu_info *p
ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status);
}
+static u16 ath11k_hal_rx_mpduinfo_get_peerid(struct ath11k_base *ab,
+ struct hal_rx_mpdu_info *mpdu_info)
+{
+ return ab->hw_params.hw_ops->mpdu_info_get_peerid(mpdu_info);
+}
+
static enum hal_rx_mon_status
ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info,
@@ -1023,7 +1029,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
info1 = __le32_to_cpu(vht_sig->info1);
ppdu_info->ldpc = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING,
- info0);
+ info1);
ppdu_info->mcs = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_MCS,
info1);
gi_setting = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING,
@@ -1446,7 +1452,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
* PHYRX_OTHER_RECEIVE_INFO TLV.
*/
ppdu_info->rssi_comb =
- FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB,
+ FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB,
__le32_to_cpu(rssi->info0));
if (db2dbm) {
@@ -1459,9 +1465,11 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
break;
}
case HAL_RX_MPDU_START: {
+ struct hal_rx_mpdu_info *mpdu_info =
+ (struct hal_rx_mpdu_info *)tlv_data;
u16 peer_id;
- peer_id = ab->hw_params.hw_ops->mpdu_info_get_peerid(tlv_data);
+ peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
if (peer_id)
ppdu_info->peer_id = peer_id;
break;
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.h b/drivers/net/wireless/ath/ath11k/hal_rx.h
index f6bae07abfd3..61bd8416c4fd 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
@@ -385,7 +385,7 @@ struct hal_rx_he_sig_b2_ofdma_info {
__le32 info0;
} __packed;
-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8)
#define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0)
@@ -405,7 +405,7 @@ struct hal_rx_phyrx_rssi_legacy_info {
#define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0)
#define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0)
-struct hal_rx_mpdu_info {
+struct hal_rx_mpdu_info_ipq8074 {
__le32 rsvd0;
__le32 info0;
__le32 rsvd1[11];
@@ -413,12 +413,28 @@ struct hal_rx_mpdu_info {
__le32 rsvd2[9];
} __packed;
+struct hal_rx_mpdu_info_qcn9074 {
+ __le32 rsvd0[10];
+ __le32 info0;
+ __le32 rsvd1[2];
+ __le32 info1;
+ __le32 rsvd2[9];
+} __packed;
+
struct hal_rx_mpdu_info_wcn6855 {
__le32 rsvd0[8];
__le32 info0;
__le32 rsvd1[14];
} __packed;
+struct hal_rx_mpdu_info {
+ union {
+ struct hal_rx_mpdu_info_ipq8074 ipq8074;
+ struct hal_rx_mpdu_info_qcn9074 qcn9074;
+ struct hal_rx_mpdu_info_wcn6855 wcn6855;
+ } u;
+} __packed;
+
#define HAL_RX_PPDU_END_DURATION GENMASK(23, 0)
struct hal_rx_ppdu_end_duration {
__le32 rsvd0[9];
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index 60ac215e0678..eb995f9cf0fa 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -835,26 +835,35 @@ static void ath11k_hw_ipq5018_reo_setup(struct ath11k_base *ab)
ring_hash_map);
}
-static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data)
+static u16
+ath11k_hw_ipq8074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
{
u16 peer_id = 0;
- struct hal_rx_mpdu_info *mpdu_info =
- (struct hal_rx_mpdu_info *)tlv_data;
peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID,
- __le32_to_cpu(mpdu_info->info0));
+ __le32_to_cpu(mpdu_info->u.ipq8074.info0));
return peer_id;
}
-static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data)
+static u16
+ath11k_hw_qcn9074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
+{
+ u16 peer_id = 0;
+
+ peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID,
+ __le32_to_cpu(mpdu_info->u.qcn9074.info0));
+
+ return peer_id;
+}
+
+static u16
+ath11k_hw_wcn6855_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info)
{
u16 peer_id = 0;
- struct hal_rx_mpdu_info_wcn6855 *mpdu_info =
- (struct hal_rx_mpdu_info_wcn6855 *)tlv_data;
peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855,
- __le32_to_cpu(mpdu_info->info0));
+ __le32_to_cpu(mpdu_info->u.wcn6855.info0));
return peer_id;
}
@@ -1042,7 +1051,7 @@ const struct ath11k_hw_ops qcn9074_ops = {
.rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention,
.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup,
- .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
+ .mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
@@ -1224,6 +1233,7 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074 = {
ATH11K_RX_WBM_REL_RING_MASK_0,
},
.reo_status = {
+ 0, 0, 0,
ATH11K_REO_STATUS_RING_MASK_0,
},
.rxdma2host = {
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 0be4e1232384..6a5dd2dbdb3a 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -224,7 +224,6 @@ struct ath11k_hw_params {
u32 tx_ring_size;
bool smp2p_wow_exit;
bool support_fw_mac_sequence;
- bool ftm_responder;
};
struct ath11k_hw_ops {
@@ -264,7 +263,7 @@ struct ath11k_hw_ops {
struct rx_attention *(*rx_desc_get_attention)(struct hal_rx_desc *desc);
u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
void (*reo_setup)(struct ath11k_base *ab);
- u16 (*mpdu_info_get_peerid)(u8 *tlv_data);
+ u16 (*mpdu_info_get_peerid)(struct hal_rx_mpdu_info *mpdu_info);
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
u32 (*get_ring_selector)(struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index cad832e0e6b8..1c93f1afccc5 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3538,7 +3538,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_FTM_RESPONDER &&
arvif->ftm_responder != info->ftm_responder &&
- ar->ab->hw_params.ftm_responder &&
+ test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT)) {
arvif->ftm_responder = info->ftm_responder;
@@ -3755,6 +3755,18 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
int i;
u32 scan_timeout;
+ /* Firmwares advertising the support of triggering 11D algorithm
+ * on the scan results of a regular scan expects driver to send
+ * WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID.
+ * With this feature, separate 11D scan can be avoided since
+ * regdomain can be determined with the scan results of the
+ * regular scan.
+ */
+ if (ar->state_11d == ATH11K_11D_PREPARING &&
+ test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN,
+ ar->ab->wmi_ab.svc_map))
+ ath11k_mac_11d_scan_start(ar, arvif->vdev_id);
+
mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
@@ -3819,8 +3831,29 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
goto exit;
}
- for (i = 0; i < arg->num_chan; i++)
- arg->chan_list[i] = req->channels[i]->center_freq;
+ for (i = 0; i < arg->num_chan; i++) {
+ if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,
+ ar->ab->wmi_ab.svc_map)) {
+ arg->chan_list[i] =
+ u32_encode_bits(req->channels[i]->center_freq,
+ WMI_SCAN_CONFIG_PER_CHANNEL_MASK);
+
+ /* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan
+ * flags, then scan all PSC channels in 6 GHz band and
+ * those non-PSC channels where RNR IE is found during
+ * the legacy 2.4/5 GHz scan.
+ * If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set,
+ * then all channels in 6 GHz will be scanned.
+ */
+ if (req->channels[i]->band == NL80211_BAND_6GHZ &&
+ req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ &&
+ !cfg80211_channel_is_psc(req->channels[i]))
+ arg->chan_list[i] |=
+ WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND;
+ } else {
+ arg->chan_list[i] = req->channels[i]->center_freq;
+ }
+ }
}
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
@@ -5552,10 +5585,6 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar,
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
- he_cap_elem->phy_cap_info[0] &=
- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
- he_cap_elem->phy_cap_info[0] &=
- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
@@ -6652,6 +6681,11 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
arvif->vdev_id);
+ ret = ath11k_spectral_vif_stop(arvif);
+ if (ret)
+ ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
ath11k_mac_11d_scan_stop(ar);
@@ -9213,7 +9247,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
- if (ab->hw_params.ftm_responder)
+ if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map))
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 0aeef2948ff5..7b33731a50ee 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -540,7 +540,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
if (!ab->mem) {
ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
ret = -EIO;
- goto clear_master;
+ goto release_region;
}
ab->mem_ce = ab->mem;
@@ -548,8 +548,6 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
return 0;
-clear_master:
- pci_clear_master(pdev);
release_region:
pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
disable_device:
@@ -565,7 +563,6 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
pci_iounmap(pci_dev, ab->mem);
ab->mem = NULL;
- pci_clear_master(pci_dev);
pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
if (pci_is_enabled(pci_dev))
pci_disable_device(pci_dev);
@@ -1039,7 +1036,8 @@ module_exit(ath11k_pci_exit);
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
MODULE_LICENSE("Dual BSD/GPL");
-/* QCA639x 2.0 firmware files */
-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);
+/* firmware files */
+MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*");
+MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*");
+MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*");
+MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*");
diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h
index 6dd17bafe3a0..9bd385d0a38c 100644
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -35,6 +35,7 @@ struct ath11k_peer {
u16 sec_type;
u16 sec_type_grp;
bool is_authorized;
+ bool dp_setup_done;
};
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 27f3fceb33c5..d0b59bc2905a 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -82,6 +82,12 @@ struct wmi_tlv_fw_stats_parse {
bool chain_rssi_done;
};
+struct wmi_tlv_mgmt_rx_parse {
+ const struct wmi_mgmt_rx_hdr *fixed;
+ const u8 *frame_buf;
+ bool frame_buf_done;
+};
+
static const struct wmi_tlv_policy wmi_tlv_policies[] = {
[WMI_TAG_ARRAY_BYTE]
= { .min_len = 0 },
@@ -865,7 +871,8 @@ static void ath11k_wmi_put_wmi_channel(struct wmi_channel *chan,
chan->band_center_freq2 = arg->channel.band_center_freq1;
- } else if (arg->channel.mode == MODE_11AC_VHT80_80) {
+ } else if ((arg->channel.mode == MODE_11AC_VHT80_80) ||
+ (arg->channel.mode == MODE_11AX_HE80_80)) {
chan->band_center_freq2 = arg->channel.band_center_freq2;
} else {
chan->band_center_freq2 = 0;
@@ -5633,28 +5640,49 @@ static int ath11k_pull_vdev_stopped_param_tlv(struct ath11k_base *ab, struct sk_
return 0;
}
+static int ath11k_wmi_tlv_mgmt_rx_parse(struct ath11k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ struct wmi_tlv_mgmt_rx_parse *parse = data;
+
+ switch (tag) {
+ case WMI_TAG_MGMT_RX_HDR:
+ parse->fixed = ptr;
+ break;
+ case WMI_TAG_ARRAY_BYTE:
+ if (!parse->frame_buf_done) {
+ parse->frame_buf = ptr;
+ parse->frame_buf_done = true;
+ }
+ break;
+ }
+ return 0;
+}
+
static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
struct sk_buff *skb,
struct mgmt_rx_event_params *hdr)
{
- const void **tb;
+ struct wmi_tlv_mgmt_rx_parse parse = { };
const struct wmi_mgmt_rx_hdr *ev;
const u8 *frame;
int ret;
- tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
- if (IS_ERR(tb)) {
- ret = PTR_ERR(tb);
- ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath11k_wmi_tlv_mgmt_rx_parse,
+ &parse);
+ if (ret) {
+ ath11k_warn(ab, "failed to parse mgmt rx tlv %d\n",
+ ret);
return ret;
}
- ev = tb[WMI_TAG_MGMT_RX_HDR];
- frame = tb[WMI_TAG_ARRAY_BYTE];
+ ev = parse.fixed;
+ frame = parse.frame_buf;
if (!ev || !frame) {
ath11k_warn(ab, "failed to fetch mgmt rx hdr");
- kfree(tb);
return -EPROTO;
}
@@ -5673,7 +5701,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
if (skb->len < (frame - skb->data) + hdr->buf_len) {
ath11k_warn(ab, "invalid length in mgmt rx hdr ev");
- kfree(tb);
return -EPROTO;
}
@@ -5685,7 +5712,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
ath11k_ce_byte_swap(skb->data, hdr->buf_len);
- kfree(tb);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index b23b7a22bc9a..92fddb77669c 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -2100,8 +2100,10 @@ enum wmi_tlv_service {
/* The second 128 bits */
WMI_MAX_EXT_SERVICE = 256,
+ WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265,
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
+ WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357,
/* The third 128 bits */
WMI_MAX_EXT2_SERVICE = 384
@@ -3249,6 +3251,9 @@ struct wmi_start_scan_cmd {
#define WMI_SCAN_DWELL_MODE_SHIFT 21
#define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800
+#define WMI_SCAN_CONFIG_PER_CHANNEL_MASK GENMASK(19, 0)
+#define WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND BIT(20)
+
enum {
WMI_SCAN_DWELL_MODE_DEFAULT = 0,
WMI_SCAN_DWELL_MODE_CONSERVATIVE = 1,
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index dffa687ee40e..9439052a652e 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -395,6 +395,7 @@ struct ath12k_sta {
u8 rssi_comb;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
+ u32 bw_prev;
};
#define ATH12K_MIN_5G_FREQ 4150
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 0adcbcfa0db5..e78478a5b978 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -196,7 +196,8 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab,
struct hal_rx_desc *desc)
{
- return ab->hw_params->hal_ops->rx_desc_is_mcbc(desc);
+ return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
+ ab->hw_params->hal_ops->rx_desc_is_mcbc(desc));
}
static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
@@ -3047,10 +3048,14 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
reo_ent_ring->rx_mpdu_info.peer_meta_data =
reo_dest_ring->rx_mpdu_info.peer_meta_data;
- reo_ent_ring->queue_addr_lo = cpu_to_le32(lower_32_bits(rx_tid->paddr));
- reo_ent_ring->info0 = le32_encode_bits(upper_32_bits(rx_tid->paddr),
- HAL_REO_ENTR_RING_INFO0_QUEUE_ADDR_HI) |
- le32_encode_bits(dst_ind, HAL_REO_ENTR_RING_INFO0_DEST_IND);
+ /* Firmware expects physical address to be filled in queue_addr_lo in
+ * the MLO scenario and in case of non MLO peer meta data needs to be
+ * filled.
+ * TODO: Need to handle for MLO scenario.
+ */
+ reo_ent_ring->queue_addr_lo = reo_dest_ring->rx_mpdu_info.peer_meta_data;
+ reo_ent_ring->info0 = le32_encode_bits(dst_ind,
+ HAL_REO_ENTR_RING_INFO0_DEST_IND);
reo_ent_ring->info1 = le32_encode_bits(rx_tid->cur_sn,
HAL_REO_ENTR_RING_INFO1_MPDU_SEQ_NUM);
diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c
index fd8d850f9818..d3c7c76d6b75 100644
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
@@ -13,6 +13,10 @@ static enum hal_tcl_encap_type
ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ath12k_base *ab = arvif->ar->ab;
+
+ if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags))
+ return HAL_TCL_ENCAP_TYPE_RAW;
if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
return HAL_TCL_ENCAP_TYPE_ETHERNET;
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index 91d576fd4b0f..1ffac7e3deaa 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -944,7 +944,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.interface_modes = BIT(NL80211_IFTYPE_STATION),
.supports_monitor = false,
- .idle_ps = false,
+ .idle_ps = true,
.download_calib = false,
.supports_suspend = false,
.tcl_ring_retry = false,
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index bf7e5b6977b2..ee792822b411 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3220,10 +3220,11 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
enum nl80211_band band;
const u8 *ht_mcs_mask;
const u16 *vht_mcs_mask;
- u32 changed, bw, nss, smps;
+ u32 changed, bw, nss, smps, bw_prev;
int err, num_vht_rates;
const struct cfg80211_bitrate_mask *mask;
struct ath12k_wmi_peer_assoc_arg peer_arg;
+ enum wmi_phy_mode peer_phymode;
arsta = container_of(wk, struct ath12k_sta, update_wk);
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
@@ -3243,6 +3244,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
arsta->changed = 0;
bw = arsta->bw;
+ bw_prev = arsta->bw_prev;
nss = arsta->nss;
smps = arsta->smps;
@@ -3255,11 +3257,53 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
ath12k_mac_max_vht_nss(vht_mcs_mask)));
if (changed & IEEE80211_RC_BW_CHANGED) {
- err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
- WMI_PEER_CHWIDTH, bw);
- if (err)
- ath12k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
- sta->addr, bw, err);
+ ath12k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
+ peer_phymode = peer_arg.peer_phymode;
+
+ if (bw > bw_prev) {
+ /* Phymode shows maximum supported channel width, if we
+ * upgrade bandwidth then due to sanity check of firmware,
+ * we have to send WMI_PEER_PHYMODE followed by
+ * WMI_PEER_CHWIDTH
+ */
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",
+ sta->addr, bw, bw_prev);
+ err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id, WMI_PEER_PHYMODE,
+ peer_phymode);
+ if (err) {
+ ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
+ sta->addr, peer_phymode, err);
+ goto err_rc_bw_changed;
+ }
+ err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id, WMI_PEER_CHWIDTH,
+ bw);
+ if (err)
+ ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",
+ sta->addr, bw, err);
+ } else {
+ /* When we downgrade bandwidth this will conflict with phymode
+ * and cause to trigger firmware crash. In this case we send
+ * WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE
+ */
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",
+ sta->addr, bw, bw_prev);
+ err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id, WMI_PEER_CHWIDTH,
+ bw);
+ if (err) {
+ ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
+ sta->addr, bw, err);
+ goto err_rc_bw_changed;
+ }
+ err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id, WMI_PEER_PHYMODE,
+ peer_phymode);
+ if (err)
+ ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
+ sta->addr, peer_phymode, err);
+ }
}
if (changed & IEEE80211_RC_NSS_CHANGED) {
@@ -3321,7 +3365,7 @@ static void ath12k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, arvif->vdev_id);
}
}
-
+err_rc_bw_changed:
mutex_unlock(&ar->conf_mutex);
}
@@ -3433,6 +3477,34 @@ exit:
return ret;
}
+static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
+ struct ieee80211_sta *sta)
+{
+ u32 bw = WMI_PEER_CHWIDTH_20MHZ;
+
+ switch (sta->deflink.bandwidth) {
+ case IEEE80211_STA_RX_BW_20:
+ bw = WMI_PEER_CHWIDTH_20MHZ;
+ break;
+ case IEEE80211_STA_RX_BW_40:
+ bw = WMI_PEER_CHWIDTH_40MHZ;
+ break;
+ case IEEE80211_STA_RX_BW_80:
+ bw = WMI_PEER_CHWIDTH_80MHZ;
+ break;
+ case IEEE80211_STA_RX_BW_160:
+ bw = WMI_PEER_CHWIDTH_160MHZ;
+ break;
+ default:
+ ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
+ sta->deflink.bandwidth, sta->addr);
+ bw = WMI_PEER_CHWIDTH_20MHZ;
+ break;
+ }
+
+ return bw;
+}
+
static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -3498,6 +3570,13 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
sta->addr);
+
+ spin_lock_bh(&ar->data_lock);
+
+ arsta->bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
+ arsta->bw_prev = sta->deflink.bandwidth;
+
+ spin_unlock_bh(&ar->data_lock);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
spin_lock_bh(&ar->ab->base_lock);
@@ -3607,28 +3686,8 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
spin_lock_bh(&ar->data_lock);
if (changed & IEEE80211_RC_BW_CHANGED) {
- bw = WMI_PEER_CHWIDTH_20MHZ;
-
- switch (sta->deflink.bandwidth) {
- case IEEE80211_STA_RX_BW_20:
- bw = WMI_PEER_CHWIDTH_20MHZ;
- break;
- case IEEE80211_STA_RX_BW_40:
- bw = WMI_PEER_CHWIDTH_40MHZ;
- break;
- case IEEE80211_STA_RX_BW_80:
- bw = WMI_PEER_CHWIDTH_80MHZ;
- break;
- case IEEE80211_STA_RX_BW_160:
- bw = WMI_PEER_CHWIDTH_160MHZ;
- break;
- default:
- ath12k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
- sta->deflink.bandwidth, sta->addr);
- bw = WMI_PEER_CHWIDTH_20MHZ;
- break;
- }
-
+ bw = ath12k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
+ arsta->bw_prev = arsta->bw;
arsta->bw = bw;
}
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index d32637b0113d..9f174daf324c 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -755,14 +755,12 @@ static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev)
if (!ab->mem) {
ath12k_err(ab, "failed to map pci bar %d\n", ATH12K_PCI_BAR_NUM);
ret = -EIO;
- goto clear_master;
+ goto release_region;
}
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
return 0;
-clear_master:
- pci_clear_master(pdev);
release_region:
pci_release_region(pdev, ATH12K_PCI_BAR_NUM);
disable_device:
@@ -778,7 +776,6 @@ static void ath12k_pci_free_region(struct ath12k_pci *ab_pci)
pci_iounmap(pci_dev, ab->mem);
ab->mem = NULL;
- pci_clear_master(pci_dev);
pci_release_region(pci_dev, ATH12K_PCI_BAR_NUM);
if (pci_is_enabled(pci_dev))
pci_disable_device(pci_dev);
@@ -1223,7 +1220,8 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
dev_err(&pdev->dev,
"Unknown hardware version found for QCN9274: 0x%x\n",
soc_hw_version_major);
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
+ goto err_pci_free_region;
}
break;
case WCN7850_DEVICE_ID:
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 979a63f2e2ab..03ba245fbee9 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2991,7 +2991,7 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
spin_unlock(&qmi->event_lock);
if (test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))
- return;
+ goto skip;
switch (event->type) {
case ATH12K_QMI_EVENT_SERVER_ARRIVE:
@@ -3032,6 +3032,8 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
ath12k_warn(ab, "invalid event type: %d", event->type);
break;
}
+
+skip:
kfree(event);
spin_lock(&qmi->event_lock);
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 3e6991120e53..7ae0bb78b2b5 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -2438,6 +2438,9 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,
if (channel_arg->psc_channel)
chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_PSC);
+ if (channel_arg->dfs_set)
+ chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_DFS);
+
chan_info->info |= le32_encode_bits(channel_arg->phy_mode,
WMI_CHAN_INFO_MODE);
*reg1 |= le32_encode_bits(channel_arg->minpower,
@@ -4934,6 +4937,9 @@ static int freq_to_idx(struct ath12k *ar, int freq)
int band, ch, idx = 0;
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
+ if (!ar->mac.sbands[band].channels)
+ continue;
+
sband = ar->hw->wiphy->bands[band];
if (!sband)
continue;
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index e0130beb304d..27ff1ca2631f 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -42,8 +42,6 @@ static const struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x7015),
.driver_info = AR9287_USB }, /* Atheros */
- { USB_DEVICE(0x1668, 0x1200),
- .driver_info = AR9287_USB }, /* Verizon */
{ USB_DEVICE(0x0cf3, 0x7010),
.driver_info = AR9280_USB }, /* Atheros */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index ef9a8e0b75e6..f6f2ab7a63ff 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -34,6 +34,12 @@
#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
+/* Shifts in ar5008_phy.c and ar9003_phy.c are equal for all revisions */
+#define ATH9K_PWRTBL_11NA_OFDM_SHIFT 0
+#define ATH9K_PWRTBL_11NG_OFDM_SHIFT 4
+#define ATH9K_PWRTBL_11NA_HT_SHIFT 8
+#define ATH9K_PWRTBL_11NG_HT_SHIFT 12
+
static u16 bits_per_symbol[][2] = {
/* 20MHz 40MHz */
@@ -1169,13 +1175,14 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
}
static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
- u8 rateidx, bool is_40, bool is_cck)
+ u8 rateidx, bool is_40, bool is_cck, bool is_mcs)
{
u8 max_power;
struct sk_buff *skb;
struct ath_frame_info *fi;
struct ieee80211_tx_info *info;
struct ath_hw *ah = sc->sc_ah;
+ bool is_2ghz, is_5ghz, use_stbc;
if (sc->tx99_state || !ah->tpc_enabled)
return MAX_RATE_POWER;
@@ -1184,6 +1191,19 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
fi = get_frame_info(skb);
info = IEEE80211_SKB_CB(skb);
+ is_2ghz = info->band == NL80211_BAND_2GHZ;
+ is_5ghz = info->band == NL80211_BAND_5GHZ;
+ use_stbc = is_mcs && rateidx < 8 && (info->flags &
+ IEEE80211_TX_CTL_STBC);
+
+ if (is_mcs)
+ rateidx += is_5ghz ? ATH9K_PWRTBL_11NA_HT_SHIFT
+ : ATH9K_PWRTBL_11NG_HT_SHIFT;
+ else if (is_2ghz && !is_cck)
+ rateidx += ATH9K_PWRTBL_11NG_OFDM_SHIFT;
+ else
+ rateidx += ATH9K_PWRTBL_11NA_OFDM_SHIFT;
+
if (!AR_SREV_9300_20_OR_LATER(ah)) {
int txpower = fi->tx_power;
@@ -1193,10 +1213,8 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
u16 eeprom_rev = ah->eep_ops->get_eeprom_rev(ah);
if (eeprom_rev >= AR5416_EEP_MINOR_VER_2) {
- bool is_2ghz;
struct modal_eep_header *pmodal;
- is_2ghz = info->band == NL80211_BAND_2GHZ;
pmodal = &eep->modalHeader[is_2ghz];
power_ht40delta = pmodal->ht40PowerIncForPdadc;
} else {
@@ -1229,7 +1247,7 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
max_power = 1;
} else if (!bf->bf_state.bfs_paprd) {
- if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
+ if (use_stbc)
max_power = min_t(u8, ah->tx_power_stbc[rateidx],
fi->tx_power);
else
@@ -1319,7 +1337,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
}
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
- is_40, false);
+ is_40, false, true);
continue;
}
@@ -1350,7 +1368,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
is_cck = IS_CCK_RATE(info->rates[i].Rate);
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false,
- is_cck);
+ is_cck, false);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index f2b4f537e4c1..b8ed193c0195 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -120,7 +120,7 @@ struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
{
struct carl9170_cmd *tmp;
- tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC);
+ tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
if (tmp) {
tmp->hdr.cmd = cmd;
tmp->hdr.len = len;
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index ff4b3b50250c..e5bcc364f088 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -320,9 +320,9 @@ struct carl9170_rsp {
struct carl9170_u32_list rreg_res;
struct carl9170_u32_list echo;
#ifdef __CARL9170FW__
- struct carl9170_tx_status tx_status[0];
+ DECLARE_FLEX_ARRAY(struct carl9170_tx_status, tx_status);
#endif /* __CARL9170FW__ */
- struct _carl9170_tx_status _tx_status[0];
+ DECLARE_FLEX_ARRAY(struct _carl9170_tx_status, _tx_status);
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 4e9e13941c8f..9013f056eecb 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -112,8 +112,8 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L;
wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H;
- wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L;
- wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H;
+ wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L(wcn);
+ wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H(wcn);
wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD;
wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD;
@@ -165,8 +165,9 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
}
-static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
+static int wcn36xx_dxe_init_descs(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *wcn_ch)
{
+ struct device *dev = wcn->dev;
struct wcn36xx_dxe_desc *cur_dxe = NULL;
struct wcn36xx_dxe_desc *prev_dxe = NULL;
struct wcn36xx_dxe_ctl *cur_ctl = NULL;
@@ -190,11 +191,11 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
switch (wcn_ch->ch_type) {
case WCN36XX_DXE_CH_TX_L:
cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L;
- cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L;
+ cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L(wcn);
break;
case WCN36XX_DXE_CH_TX_H:
cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H;
- cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H;
+ cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H(wcn);
break;
case WCN36XX_DXE_CH_RX_L:
cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
@@ -914,7 +915,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for TX LOW channel */
/***************************************/
- ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
+ ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_l_ch);
if (ret) {
dev_err(wcn->dev, "Error allocating descriptor\n");
return ret;
@@ -928,14 +929,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/* Program DMA destination addr for TX LOW */
wcn36xx_dxe_write_register(wcn,
WCN36XX_DXE_CH_DEST_ADDR_TX_L,
- WCN36XX_DXE_WQ_TX_L);
+ WCN36XX_DXE_WQ_TX_L(wcn));
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
/***************************************/
/* Init descriptors for TX HIGH channel */
/***************************************/
- ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
+ ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_tx_h_ch);
if (ret) {
dev_err(wcn->dev, "Error allocating descriptor\n");
goto out_err_txh_ch;
@@ -950,14 +951,14 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/* Program DMA destination addr for TX HIGH */
wcn36xx_dxe_write_register(wcn,
WCN36XX_DXE_CH_DEST_ADDR_TX_H,
- WCN36XX_DXE_WQ_TX_H);
+ WCN36XX_DXE_WQ_TX_H(wcn));
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
/***************************************/
/* Init descriptors for RX LOW channel */
/***************************************/
- ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
+ ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_l_ch);
if (ret) {
dev_err(wcn->dev, "Error allocating descriptor\n");
goto out_err_rxl_ch;
@@ -988,7 +989,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
/***************************************/
/* Init descriptors for RX HIGH channel */
/***************************************/
- ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
+ ret = wcn36xx_dxe_init_descs(wcn, &wcn->dxe_rx_h_ch);
if (ret) {
dev_err(wcn->dev, "Error allocating descriptor\n");
goto out_err_rxh_ch;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h
index 26a31edf52e9..dd8c684a3ba7 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -135,8 +135,8 @@ H2H_TEST_RX_TX = DMA2
WCN36xx_DXE_CTRL_ENDIANNESS)
/* TODO This must calculated properly but not hardcoded */
-#define WCN36XX_DXE_WQ_TX_L 0x17
-#define WCN36XX_DXE_WQ_TX_H 0x17
+#define WCN36XX_DXE_WQ_TX_L(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17)
+#define WCN36XX_DXE_WQ_TX_H(wcn) ((wcn)->is_pronto_v3 ? 0x6 : 0x17)
#define WCN36XX_DXE_WQ_RX_L 0xB
#define WCN36XX_DXE_WQ_RX_H 0x4
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 3b79cc1c7c5b..8dbd115a393c 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1508,6 +1508,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
}
wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
+ wcn->is_pronto_v3 = !!of_device_is_compatible(mmio_node, "qcom,pronto-v3-pil");
/* Map the CCU memory */
index = of_property_match_string(mmio_node, "reg-names", "ccu");
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 9aa08b636d08..ff4a8e5d7209 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -217,6 +217,7 @@ struct wcn36xx {
u8 fw_major;
u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
bool is_pronto;
+ bool is_pronto_v3;
/* extra byte for the NULL termination */
u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 65d4799a5658..ff710b0b5071 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -965,6 +965,12 @@ out:
.driver_data = BRCMF_FWVENDOR_ ## fw_vend \
}
+#define CYW_SDIO_DEVICE(dev_id, fw_vend) \
+ { \
+ SDIO_DEVICE(SDIO_VENDOR_ID_CYPRESS, dev_id), \
+ .driver_data = BRCMF_FWVENDOR_ ## fw_vend \
+ }
+
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43143, WCC),
@@ -979,6 +985,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430, WCC),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43439, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354, WCC),
@@ -986,9 +993,9 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
+ CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
diff --git a/drivers/net/wireless/cisco/Kconfig b/drivers/net/wireless/cisco/Kconfig
index 681bfc2d740a..b40ee25aca99 100644
--- a/drivers/net/wireless/cisco/Kconfig
+++ b/drivers/net/wireless/cisco/Kconfig
@@ -14,7 +14,7 @@ if WLAN_VENDOR_CISCO
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
- depends on CFG80211 && ISA_DMA_API && (PCI || BROKEN)
+ depends on CFG80211 && (PCI || BROKEN)
select WIRELESS_EXT
select CRYPTO
select CRYPTO_SKCIPHER
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 0b10b34a77a8..b6f82510e980 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 75
+#define IWL_22000_UCODE_API_MAX 78
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
@@ -50,7 +50,13 @@
#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-"
#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-"
#define IWL_MA_A_FM_A_FW_PRE "iwlwifi-ma-a0-fm-a0-"
+#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0-"
+#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0-"
+#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0-"
+#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0-"
+#define IWL_MA_B_FM_A_FW_PRE "iwlwifi-ma-b0-fm-a0-"
#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-"
+#define IWL_BZ_A_HR_A_FW_PRE "iwlwifi-bz-a0-hr-b0-"
#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-"
#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-"
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
@@ -69,7 +75,9 @@
#define IWL_BNJ_B_GF_A_FW_PRE "iwlwifi-BzBnj-b0-gf-a0-"
#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-"
#define IWL_BNJ_B_GF4_A_FW_PRE "iwlwifi-BzBnj-b0-gf4-a0-"
+#define IWL_BNJ_A_HR_A_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
+#define IWL_BNJ_B_HR_A_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
#define IWL_BNJ_B_HR_B_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
#define IWL_BNJ_B_FM_B_FW_PRE "iwlwifi-BzBnj-b0-fm-b0-"
@@ -116,8 +124,20 @@
IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(api) \
IWL_MA_A_FM_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_HR_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF4_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_MR_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \
IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_BZ_A_HR_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_HR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
@@ -127,17 +147,17 @@
#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \
IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
+ IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_FM4_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
+ IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode"
+ IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode"
#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode"
+ IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode"
#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
+ IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
- IWL_GL_B_FM_B_FW_PRE __stringify(api) ".ucode"
+ IWL_GL_B_FM_B_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_A_FM_A_MODULE_FIRMWARE(api) \
IWL_BNJ_A_FM_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(api) \
@@ -152,8 +172,12 @@
IWL_BNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(api) \
IWL_BNJ_B_GF4_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_BNJ_A_HR_A_MODULE_FIRMWARE(api) \
+ IWL_BNJ_A_HR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_BNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
+#define IWL_BNJ_B_HR_A_MODULE_FIRMWARE(api) \
+ IWL_BNJ_B_HR_A_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_B_HR_B_MODULE_FIRMWARE(api) \
IWL_BNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_BNJ_B_FM_B_MODULE_FIRMWARE(api) \
@@ -882,6 +906,41 @@ const struct iwl_cfg iwl_cfg_ma_a0_ms_a0 = {
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
+const struct iwl_cfg iwl_cfg_ma_b0_fm_a0 = {
+ .fw_name_pre = IWL_MA_B_FM_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma_b0_hr_b0 = {
+ .fw_name_pre = IWL_MA_B_HR_B_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma_b0_gf_a0 = {
+ .fw_name_pre = IWL_MA_B_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0 = {
+ .fw_name_pre = IWL_MA_B_GF4_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma_b0_mr_a0 = {
+ .fw_name_pre = IWL_MA_B_MR_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
.fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
.uhb_supported = false,
@@ -928,6 +987,14 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
+const struct iwl_cfg iwl_cfg_bz_a0_hr_a0 = {
+ .fw_name_pre = IWL_BZ_A_HR_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
.fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
.uhb_supported = true,
@@ -1072,6 +1139,14 @@ const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0 = {
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
+const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0 = {
+ .fw_name_pre = IWL_BNJ_A_HR_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
.fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE,
.uhb_supported = true,
@@ -1080,6 +1155,14 @@ const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
+const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0 = {
+ .fw_name_pre = IWL_BNJ_B_HR_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0 = {
.fw_name_pre = IWL_BNJ_B_HR_B_FW_PRE,
.uhb_supported = true,
@@ -1116,7 +1199,13 @@ MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
@@ -1132,6 +1221,7 @@ MODULE_FIRMWARE(IWL_BNJ_B_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BNJ_B_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
index cef43cf80620..8b01ab986cb1 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
@@ -1081,6 +1081,7 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
{
__le16 key_flags;
struct iwl_addsta_cmd sta_cmd;
+ size_t to_copy;
int i;
spin_lock_bh(&priv->sta_lock);
@@ -1100,7 +1101,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
for (i = 0; i < 5; i++)
sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
- memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+ /* keyconf may contain MIC rx/tx keys which iwl does not use */
+ to_copy = min_t(size_t, sizeof(sta_cmd.key.key), keyconf->keylen);
+ memcpy(sta_cmd.key.key, keyconf->key, to_copy);
break;
case WLAN_CIPHER_SUITE_WEP104:
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index a02e5a67b706..5f4a51310add 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -1006,8 +1006,10 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
union acpi_object *wifi_pkg, *data, *flags;
int i, j, ret, tbl_rev, num_sub_bands = 0;
int idx = 2;
+ u8 cmd_ver;
fwrt->ppag_flags = 0;
+ fwrt->ppag_table_valid = false;
data = iwl_acpi_get_object(fwrt->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
@@ -1054,8 +1056,15 @@ read_table:
}
fwrt->ppag_flags = flags->integer.value & ACPI_PPAG_MASK;
-
- if (!fwrt->ppag_flags) {
+ cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ if (cmd_ver == IWL_FW_CMD_VER_UNKNOWN) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ if (!fwrt->ppag_flags && cmd_ver <= 3) {
ret = 0;
goto out_free;
}
@@ -1076,21 +1085,22 @@ read_table:
}
fwrt->ppag_chains[i].subbands[j] = ent->integer.value;
-
+ /* from ver 4 the fw deals with out of range values */
+ if (cmd_ver >= 4)
+ continue;
if ((j == 0 &&
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_LB ||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_LB)) ||
(j != 0 &&
(fwrt->ppag_chains[i].subbands[j] > ACPI_PPAG_MAX_HB ||
fwrt->ppag_chains[i].subbands[j] < ACPI_PPAG_MIN_HB))) {
- fwrt->ppag_flags = 0;
ret = -EINVAL;
goto out_free;
}
}
}
-
+ fwrt->ppag_table_valid = true;
ret = 0;
out_free:
@@ -1115,19 +1125,22 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
IWL_DEBUG_RADIO(fwrt,
"PPAG capability not supported by FW, command not sent.\n");
return -EINVAL;
- }
- if (!fwrt->ppag_flags) {
- IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
- return -EINVAL;
- }
+ }
+
+ cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ if (!fwrt->ppag_table_valid || (cmd_ver <= 3 && !fwrt->ppag_flags)) {
+ IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n");
+ return -EINVAL;
+ }
/* The 'flags' field is the same in v1 and in v2 so we can just
* use v1 to access it.
*/
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
- cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
- WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD),
- IWL_FW_CMD_VER_UNKNOWN);
+
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
@@ -1138,7 +1151,7 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
fwrt->ppag_ver);
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
- } else if (cmd_ver == 2 || cmd_ver == 3) {
+ } else if (cmd_ver >= 2 && cmd_ver <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v2.gain[0];
*cmd_size = sizeof(cmd->v2);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index df0833890e55..8a613e150a02 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -767,7 +767,7 @@ struct iwl_wowlan_status_v12 {
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */
/**
- * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification
* @gtk: GTK data
* @igtk: IGTK data
* @replay_ctr: GTK rekey replay counter
@@ -785,7 +785,7 @@ struct iwl_wowlan_status_v12 {
* @station_id: station id
* @reserved2: reserved
*/
-struct iwl_wowlan_info_notif {
+struct iwl_wowlan_info_notif_v1 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
@@ -804,6 +804,39 @@ struct iwl_wowlan_info_notif {
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */
/**
+ * struct iwl_wowlan_info_notif - WoWLAN information notification
+ * @gtk: GTK data
+ * @igtk: IGTK data
+ * @replay_ctr: GTK rekey replay counter
+ * @pattern_number: number of the matched patterns
+ * @reserved1: reserved
+ * @qos_seq_ctr: QoS sequence counters to use next
+ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
+ * @num_of_gtk_rekeys: number of GTK rekeys
+ * @transmitted_ndps: number of transmitted neighbor discovery packets
+ * @received_beacons: number of received beacons
+ * @tid_tear_down: bit mask of tids whose BA sessions were closed
+ * in suspend state
+ * @station_id: station id
+ * @reserved2: reserved
+ */
+struct iwl_wowlan_info_notif {
+ struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
+ struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
+ __le64 replay_ctr;
+ __le16 pattern_number;
+ __le16 reserved1;
+ __le16 qos_seq_ctr[8];
+ __le32 wakeup_reasons;
+ __le32 num_of_gtk_rekeys;
+ __le32 transmitted_ndps;
+ __le32 received_beacons;
+ u8 tid_tear_down;
+ u8 station_id;
+ u8 reserved2[2];
+} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
+
+/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
* @wake_packet_length: wakeup packet length
* @station_id: station id
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index e236d1b0aae2..74f2efbad34e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -224,15 +224,6 @@ struct iwl_mac_client_data {
} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */
/**
- * struct iwl_mac_go_ibss_data - configuration data for GO and IBSS MAC context
- *
- * @beacon_template: beacon template ID
- */
-struct iwl_mac_go_ibss_data {
- __le32 beacon_template;
-} __packed; /* MAC_CONTEXT_CONFIG_GO_IBSS_DATA_API_S_VER_1 */
-
-/**
* struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context
*
* @is_disc_extended: if set to true, P2P Device discoverability is enabled on
@@ -278,6 +269,7 @@ enum iwl_mac_config_filter_flags {
* @reserved_for_local_mld_addr: reserved
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
* @he_support: does this MAC support HE
+ * @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
* @eht_support: does this MAC support EHT. Requires he_support
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
@@ -296,13 +288,13 @@ struct iwl_mac_config_cmd {
u8 local_mld_addr[6];
__le16 reserved_for_local_mld_addr;
__le32 filter_flags;
- __le32 he_support;
+ __le16 he_support;
+ __le16 he_ap_support;
__le32 eht_support;
__le32 nic_not_ack_enabled;
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */
union {
struct iwl_mac_client_data client;
- struct iwl_mac_go_ibss_data go_ibss;
struct iwl_mac_p2p_dev_data p2p_dev;
};
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index 7ba0e3409199..ec96ba053a5c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -709,10 +709,13 @@ enum iwl_umac_scan_general_flags_v2 {
* should be aware of a P2P GO operation on the 2GHz band.
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB: scan event scheduling
* should be aware of a P2P GO operation on the 5GHz or 6GHz band.
+ * @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT: don't toggle between
+ * valid antennas, and use the same antenna as in previous scan
*/
enum iwl_umac_scan_general_params_flags2 {
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB = BIT(0),
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB = BIT(1),
+ IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT = BIT(2),
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index ca97f2fcb693..d9faaae01abd 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1038,7 +1038,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
range->range_data_size = reg->dev_addr.size;
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
prph_val = iwl_read_prph(fwrt->trans, addr + i);
- if (prph_val == 0x5a5a5a5a)
+ if ((prph_val & ~0xf) == 0xa5a5a5a0)
return -EBUSY;
*val++ = cpu_to_le32(prph_val);
}
@@ -1388,13 +1388,13 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt,
if (!data)
return;
+ memset(data, 0, sizeof(*data));
+
/* make sure only one bit is set in only one fid */
if (WARN_ONCE(hweight_long(fid1) + hweight_long(fid2) != 1,
"fid1=%x, fid2=%x\n", fid1, fid2))
return;
- memset(data, 0, sizeof(*data));
-
if (fid1) {
fifo_idx = ffs(fid1) - 1;
if (WARN_ONCE(fifo_idx >= MAX_NUM_LMAC, "fifo_idx=%d\n",
@@ -1562,7 +1562,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ?
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
- if (prph_data == 0x5a5a5a5a) {
+ if ((prph_data & ~0xf) == 0xa5a5a5a0) {
iwl_trans_release_nic_access(fwrt->trans);
return -EBUSY;
}
@@ -2345,6 +2345,8 @@ static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt,
/* add the dump file name extension tlv to the list */
list_add_tail(&entry->list, list);
+ fwrt->trans->dbg.dump_file_name_ext_valid = false;
+
return entry->size;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index 43e997283db0..607e07ed2477 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -317,8 +317,10 @@ static void *iwl_dbgfs_fw_info_seq_next(struct seq_file *seq,
const struct iwl_fw *fw = priv->fwrt->fw;
*pos = ++state->pos;
- if (*pos >= fw->ucode_capa.n_cmd_versions)
+ if (*pos >= fw->ucode_capa.n_cmd_versions) {
+ kfree(state);
return NULL;
+ }
return state;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index 59ed321bcc27..f86f7b4baa18 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -484,6 +484,9 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
{
+ struct iwl_pc_data *pc_data;
+ u8 count;
+
if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
IWL_ERR(fwrt,
"DEVICE_ENABLED bit is not set. Aborting dump.\n");
@@ -502,6 +505,14 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_fwrt_dump_rcm_error_log(fwrt, 1);
iwl_fwrt_dump_iml_error_log(fwrt);
iwl_fwrt_dump_fseq_regs(fwrt);
+ if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ pc_data = fwrt->trans->dbg.pc_data;
+ for (count = 0; count < fwrt->trans->dbg.num_pc;
+ count++, pc_data++)
+ IWL_ERR(fwrt, "%s: 0x%x\n",
+ pc_data->pc_name,
+ pc_data->pc_address);
+ }
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index f2eefca6e260..cddf09d6be1c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -101,8 +101,10 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
+ IWL_UCODE_TLV_CURRENT_PC = 68,
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
+ IWL_UCODE_TLV_FW_NUM_BEACONS = IWL_UCODE_TLV_CONST_BASE + 2,
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,
@@ -458,6 +460,8 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_SYNCED_TIME = (__force iwl_ucode_tlv_capa_t)106,
IWL_UCODE_TLV_CAPA_TIME_SYNC_BOTH_FTM_TM = (__force iwl_ucode_tlv_capa_t)108,
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109,
+ IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT = (__force iwl_ucode_tlv_capa_t)110,
+ IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111,
#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index f5c4d93d1033..8d0d58d61892 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -51,6 +51,7 @@ struct iwl_ucode_capabilities {
u32 error_log_addr;
u32 error_log_size;
u32 num_stations;
+ u32 num_beacons;
unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)];
unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)];
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index a59cf4d9567c..df689a9b7e2c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -165,6 +165,7 @@ struct iwl_fw_runtime {
struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
u32 ppag_flags;
u32 ppag_ver;
+ bool ppag_table_valid;
struct iwl_sar_offset_mapping_cmd sgom_table;
bool sgom_enabled;
u8 reduced_power_flags;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 0b6f694cf30d..01afea33c38c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -222,7 +222,7 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
return ERR_PTR(-ENOMEM);
status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
+ NULL, &package_size, package);
if (status != EFI_SUCCESS) {
IWL_DEBUG_FW(trans,
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 9b7b6fca2b1b..411b7d4fcc9a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -469,6 +469,7 @@ struct iwl_dev_info {
u16 mac_type;
u16 rf_type;
u8 mac_step;
+ u8 rf_step;
u8 rf_id;
u8 no_160;
u8 cores;
@@ -639,11 +640,17 @@ extern const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_ms_a0;
extern const struct iwl_cfg iwl_cfg_ma_a0_fm_a0;
+extern const struct iwl_cfg iwl_cfg_ma_b0_hr_b0;
+extern const struct iwl_cfg iwl_cfg_ma_b0_gf_a0;
+extern const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0;
+extern const struct iwl_cfg iwl_cfg_ma_b0_mr_a0;
+extern const struct iwl_cfg iwl_cfg_ma_b0_fm_a0;
extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0;
extern const struct iwl_cfg iwl_cfg_snj_a0_ms_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_ms_a0;
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
+extern const struct iwl_cfg iwl_cfg_bz_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
@@ -661,7 +668,9 @@ extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0;
extern const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0;
extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0;
extern const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0;
+extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0;
+extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0;
extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0;
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0;
extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
index bece76b1a514..587368a0ad4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -102,6 +102,8 @@
#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL 0x000003ff
#define CSR_LTR_LONG_VAL_AD_SCALE_USEC 2
+#define CSR_LTR_LAST_MSG (CSR_BASE + 0x0DC)
+
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
@@ -309,6 +311,8 @@ enum {
SILICON_A_STEP = 0,
SILICON_B_STEP,
SILICON_C_STEP,
+ SILICON_D_STEP,
+ SILICON_E_STEP,
SILICON_Z_STEP = 0xf,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index 87366b70b17f..898d5dcf1012 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -138,6 +138,12 @@ static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans,
alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
goto err;
+ if (buf_location == IWL_FW_INI_LOCATION_DRAM_PATH &&
+ alloc->req_size == 0) {
+ IWL_ERR(trans, "WRT: Invalid DRAM buffer allocation requested size (0)\n");
+ return -EINVAL;
+ }
+
trans->dbg.fw_mon_cfg[alloc_id] = *alloc;
return 0;
@@ -797,7 +803,7 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
if (!ret)
dram_alloc = true;
else
- IWL_WARN(fwrt,
+ IWL_INFO(fwrt,
"WRT: Failed to set DRAM buffer for alloc id %d, ret=%d\n",
i, ret);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
index ae4c2a3d63d5..3a3c13a41fc6 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2011, 2021 Intel Corporation
+ * Copyright (C) 2005-2011, 2021-2022 Intel Corporation
*/
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -57,6 +57,7 @@ void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...)
default:
break;
}
+ vaf.va = &args;
trace_iwlwifi_err(&vaf);
va_end(args);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 4c977ba9cd85..34feb4d29adc 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -127,6 +127,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
kfree(drv->fw.iml);
kfree(drv->fw.ucode_capa.cmd_versions);
kfree(drv->fw.phy_integration_ver);
+ kfree(drv->trans->dbg.pc_data);
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
@@ -894,7 +895,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
drv->fw.img[IWL_UCODE_WOWLAN].is_dual_cpus =
true;
} else if ((num_of_cpus > 2) || (num_of_cpus < 1)) {
- IWL_ERR(drv, "Driver support upto 2 CPUs\n");
+ IWL_ERR(drv, "Driver support up to 2 CPUs\n");
return -EINVAL;
}
break;
@@ -1154,6 +1155,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
capa->num_stations =
le32_to_cpup((const __le32 *)tlv_data);
break;
+ case IWL_UCODE_TLV_FW_NUM_BEACONS:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->num_beacons =
+ le32_to_cpup((const __le32 *)tlv_data);
+ break;
case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
const struct iwl_umac_debug_addrs *dbg_ptrs =
(const void *)tlv_data;
@@ -1232,6 +1239,14 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
iwl_drv_set_dump_exclude(drv, tlv_type,
tlv_data, tlv_len);
break;
+ case IWL_UCODE_TLV_CURRENT_PC:
+ if (tlv_len < sizeof(struct iwl_pc_data))
+ goto invalid_tlv_len;
+ drv->trans->dbg.num_pc =
+ tlv_len / sizeof(struct iwl_pc_data);
+ drv->trans->dbg.pc_data =
+ kmemdup(tlv_data, tlv_len, GFP_KERNEL);
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
@@ -1406,6 +1421,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
fw->ucode_capa.num_stations = IWL_MVM_STATION_COUNT_MAX;
+ fw->ucode_capa.num_beacons = 1;
/* dump all fw memory areas by default */
fw->dbg.dump_mask = 0xffffffff;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
index baa643386018..0e8ca761d24b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.h
@@ -47,13 +47,12 @@ struct iwl_nvm_data {
struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
/*
- * iftype data for low (2.4 GHz) and high (5 and 6 GHz) bands,
- * we can use the same for 5 and 6 GHz bands because they have
- * the same data
+ * iftype data for low (2.4 GHz) high (5 GHz) and uhb (6 GHz) bands
*/
struct {
struct ieee80211_sband_iftype_data low[2];
struct ieee80211_sband_iftype_data high[2];
+ struct ieee80211_sband_iftype_data uhb[2];
} iftd;
struct ieee80211_channel channels[];
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 923bbfc151dd..7dcb1c3ab728 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -860,7 +860,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
/* Advertise an A-MPDU exponent extension based on
* operating band
*/
- if (sband->band != NL80211_BAND_2GHZ)
+ if (sband->band == NL80211_BAND_6GHZ && iftype_data->eht_cap.has_eht)
+ iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
+ IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2;
+ else if (sband->band != NL80211_BAND_2GHZ)
iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1;
else
@@ -876,16 +879,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
break;
case NL80211_BAND_6GHZ:
- if (!is_ap || iwlwifi_mod_params.nvm_file)
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
- IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
fallthrough;
case NL80211_BAND_5GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
- if (!is_ap || iwlwifi_mod_params.nvm_file)
- iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
break;
default:
WARN_ON(1);
@@ -938,6 +938,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
}
}
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap)
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |=
+ IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
+
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
case IWL_CFG_RF_TYPE_GF:
case IWL_CFG_RF_TYPE_MR:
@@ -999,15 +1003,18 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
BUILD_BUG_ON(sizeof(data->iftd.low) != sizeof(iwl_he_eht_capa));
BUILD_BUG_ON(sizeof(data->iftd.high) != sizeof(iwl_he_eht_capa));
+ BUILD_BUG_ON(sizeof(data->iftd.uhb) != sizeof(iwl_he_eht_capa));
switch (sband->band) {
case NL80211_BAND_2GHZ:
iftype_data = data->iftd.low;
break;
case NL80211_BAND_5GHZ:
- case NL80211_BAND_6GHZ:
iftype_data = data->iftd.high;
break;
+ case NL80211_BAND_6GHZ:
+ iftype_data = data->iftd.uhb;
+ break;
default:
WARN_ON(1);
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 62ce116d3783..0dfe00eae05d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -350,6 +350,11 @@
#define WFPM_OTP_CFG1_ADDR 0x00a03098
#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
+#define WFPM_OTP_BZ_BNJ_JACKET_BIT 5
+#define WFPM_OTP_BZ_BNJ_CDB_BIT 4
+#define WFPM_OTP_CFG1_IS_JACKET(_val) (((_val) & 0x00000020) >> WFPM_OTP_BZ_BNJ_JACKET_BIT)
+#define WFPM_OTP_CFG1_IS_CDB(_val) (((_val) & 0x00000010) >> WFPM_OTP_BZ_BNJ_CDB_BIT)
+
#define WFPM_GP2 0xA030B4
@@ -445,6 +450,8 @@ enum {
#define REG_CRF_ID_TYPE_GF_TC 0xF08
#define REG_CRF_ID_TYPE_MR 0x810
#define REG_CRF_ID_TYPE_FM 0x910
+#define REG_CRF_ID_TYPE_FMI 0x930
+#define REG_CRF_ID_TYPE_FMR 0x900
#define HPM_DEBUG 0xA03440
#define PERSISTENCE_BIT BIT(12)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index dd277a4fa8dd..9f1228b5a384 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -748,6 +748,18 @@ struct iwl_imr_data {
__le64 imr_base_addr;
};
+#define IWL_TRANS_CURRENT_PC_NAME_MAX_BYTES 32
+
+/**
+ * struct iwl_pc_data - program counter details
+ * @pc_name: cpu name
+ * @pc_address: cpu program counter
+ */
+struct iwl_pc_data {
+ u8 pc_name[IWL_TRANS_CURRENT_PC_NAME_MAX_BYTES];
+ u32 pc_address;
+};
+
/**
* struct iwl_trans_debug - transport debug related data
*
@@ -777,6 +789,8 @@ struct iwl_imr_data {
* @ucode_preset: preset based on ucode
* @dump_file_name_ext: dump file name extension
* @dump_file_name_ext_valid: dump file name extension if valid or not
+ * @num_pc: number of program counter for cpu
+ * @pc_data: details of the program counter
*/
struct iwl_trans_debug {
u8 n_dest_reg;
@@ -817,6 +831,8 @@ struct iwl_trans_debug {
struct iwl_imr_data imr_data;
u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME];
bool dump_file_name_ext_valid;
+ u32 num_pc;
+ struct iwl_pc_data *pc_data;
};
struct iwl_dma_ptr {
@@ -981,7 +997,7 @@ struct iwl_trans_txqs {
* 0 indicates that frag SKBs (NETIF_F_SG) aren't supported.
* @hw_rf_id a u32 with the device RF ID
* @hw_crf_id a u32 with the device CRF ID
- * @hw_cdb_id a u32 with the device CDB ID
+ * @hw_wfpm_id a u32 with the device wfpm ID
* @hw_id: a u32 with the ID of the device / sub-device.
* Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
@@ -1024,7 +1040,8 @@ struct iwl_trans {
u32 hw_rev_step;
u32 hw_rf_id;
u32 hw_crf_id;
- u32 hw_cdb_id;
+ u32 hw_cnv_id;
+ u32 hw_wfpm_id;
u32 hw_id;
char hw_id_str[52];
u32 sku_id[3];
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h
index ae66192feefe..655d95d3a068 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h
+++ b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (C) 2021 Intel Corporation
+ * Copyright (C) 2021 - 2022 Intel Corporation
*/
#ifndef __iwl_mei_h__
@@ -301,7 +301,7 @@ struct iwl_mei_colloc_info {
struct iwl_mei_ops {
void (*me_conn_status)(void *priv,
const struct iwl_mei_conn_info *conn_info);
- void (*rfkill)(void *priv, bool blocked);
+ void (*rfkill)(void *priv, bool blocked, bool csme_taking_ownership);
void (*roaming_forbidden)(void *priv, bool forbidden);
void (*sap_connected)(void *priv);
void (*nic_stolen)(void *priv);
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c
index 67dfb77fedf7..0a29fb013005 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c
@@ -31,6 +31,11 @@ MODULE_LICENSE("GPL");
#define MEI_WLAN_UUID UUID_LE(0x13280904, 0x7792, 0x4fcb, \
0xa1, 0xaa, 0x5e, 0x70, 0xcb, 0xb1, 0xe8, 0x65)
+/* After CSME takes ownership, it won't release it for 60 seconds to avoid
+ * frequent ownership transitions.
+ */
+#define MEI_OWNERSHIP_RETAKE_TIMEOUT_MS msecs_to_jiffies(60000)
+
/*
* Since iwlwifi calls iwlmei without any context, hold a pointer to the
* mei_cl_device structure here.
@@ -156,6 +161,8 @@ struct iwl_mei_filters {
* accessed without the mutex.
* @netdev_work: used to defer registering and unregistering of the netdev to
* avoid taking the rtnl lock in the SAP messages handlers.
+ * @ownership_dwork: used to re-ask for NIC ownership after ownership was taken
+ * by CSME or when a previous ownership request failed.
* @sap_seq_no: the sequence number for the SAP messages
* @seq_no: the sequence number for the SAP messages
* @dbgfs_dir: the debugfs dir entry
@@ -179,6 +186,7 @@ struct iwl_mei {
bool pldr_active;
spinlock_t data_q_lock;
struct work_struct netdev_work;
+ struct delayed_work ownership_dwork;
atomic_t sap_seq_no;
atomic_t seq_no;
@@ -716,7 +724,7 @@ iwl_mei_handle_conn_status(struct mei_cl_device *cldev,
status->link_prot_state);
else
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv,
- status->link_prot_state);
+ status->link_prot_state, false);
}
static void iwl_mei_set_init_conf(struct iwl_mei *mei)
@@ -788,7 +796,7 @@ static void iwl_mei_handle_amt_state(struct mei_cl_device *cldev,
if (mei->amt_enabled)
iwl_mei_set_init_conf(mei);
else if (iwl_mei_cache.ops)
- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false);
+ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false);
schedule_work(&mei->netdev_work);
@@ -829,10 +837,12 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev,
*/
mei->csme_taking_ownership = true;
- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true);
+ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true, true);
} else {
iwl_mei_send_sap_msg(cldev,
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
}
}
@@ -882,7 +892,7 @@ static void iwl_mei_handle_rx_host_own_req(struct mei_cl_device *cldev,
/* We can now start the connection, unblock rfkill */
if (iwl_mei_cache.ops)
- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false);
+ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false);
}
static void iwl_mei_handle_pldr_ack(struct mei_cl_device *cldev,
@@ -1447,7 +1457,13 @@ int iwl_mei_get_ownership(void)
ret = wait_event_timeout(mei->get_ownership_wq,
mei->got_ownership, HZ / 2);
- return (!ret) ? -ETIMEDOUT : 0;
+ if (!ret) {
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
out:
mutex_unlock(&iwl_mei_mutex);
return ret;
@@ -1738,6 +1754,8 @@ void iwl_mei_device_state(bool up)
iwl_mei_send_sap_msg(mei->cldev,
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
mei->csme_taking_ownership = false;
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
out:
mutex_unlock(&iwl_mei_mutex);
}
@@ -1773,7 +1791,8 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
if (iwl_mei_is_connected()) {
if (mei->amt_enabled)
iwl_mei_send_sap_msg(mei->cldev,
- SAP_MSG_NOTIF_WIFIDR_UP);
+ SAP_MSG_NOTIF_WIFIDR_UP,
+ false);
ops->rfkill(priv, mei->link_prot_state);
}
}
@@ -1894,6 +1913,11 @@ static void iwl_mei_dbgfs_unregister(struct iwl_mei *mei) {}
#endif /* CONFIG_DEBUG_FS */
+static void iwl_mei_ownership_dwork(struct work_struct *wk)
+{
+ iwl_mei_get_ownership();
+}
+
#define ALLOC_SHARED_MEM_RETRY_MAX_NUM 3
/*
@@ -1923,6 +1947,7 @@ static int iwl_mei_probe(struct mei_cl_device *cldev,
init_waitqueue_head(&mei->pldr_wq);
spin_lock_init(&mei->data_q_lock);
INIT_WORK(&mei->netdev_work, iwl_mei_netdev_work);
+ INIT_DELAYED_WORK(&mei->ownership_dwork, iwl_mei_ownership_dwork);
mei_cldev_set_drvdata(cldev, mei);
mei->cldev = cldev;
@@ -2087,7 +2112,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
spin_unlock_bh(&mei->data_q_lock);
if (iwl_mei_cache.ops)
- iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false);
+ iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false);
/*
* mei_cldev_disable will return only after all the MEI Rx is done.
@@ -2105,6 +2130,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
cancel_work_sync(&mei->send_csa_msg_wk);
cancel_delayed_work_sync(&mei->csa_throttle_end_wk);
cancel_work_sync(&mei->netdev_work);
+ cancel_delayed_work_sync(&mei->ownership_dwork);
/*
* If someone waits for the ownership, let him know that we are going
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 40adf789c8fc..37aa4676dc94 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -564,6 +564,7 @@ static void iwl_mvm_wowlan_get_tkip_data(struct ieee80211_hw *hw,
}
for (i = 0; i < IWL_NUM_RSC; i++) {
+ ieee80211_get_key_rx_seq(key, i, &seq);
/* wrapping isn't allowed, AP must rekey */
if (seq.tkip.iv32 > cur_rx_iv32)
cur_rx_iv32 = seq.tkip.iv32;
@@ -2017,6 +2018,12 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
{
u32 i;
+ if (!data) {
+ IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");
+ status = NULL;
+ return;
+ }
+
if (len < sizeof(*data)) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
@@ -2705,10 +2712,15 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
struct iwl_d3_data *d3_data = data;
u32 len;
int ret;
+ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,
+ PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ IWL_FW_CMD_VER_UNKNOWN);
+
switch (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {
case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION): {
- struct iwl_wowlan_info_notif *notif = (void *)pkt->data;
+ struct iwl_wowlan_info_notif *notif;
if (d3_data->notif_received & IWL_D3_NOTIF_WOWLAN_INFO) {
/* We might get two notifications due to dual bss */
@@ -2717,10 +2729,32 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
break;
}
+ if (wowlan_info_ver < 2) {
+ struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data;
+
+ notif = kmemdup(notif_v1,
+ offsetofend(struct iwl_wowlan_info_notif,
+ received_beacons),
+ GFP_ATOMIC);
+
+ if (!notif)
+ return false;
+
+ notif->tid_tear_down = notif_v1->tid_tear_down;
+ notif->station_id = notif_v1->station_id;
+
+ } else {
+ notif = (void *)pkt->data;
+ }
+
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;
len = iwl_rx_packet_payload_len(pkt);
iwl_mvm_parse_wowlan_info_notif(mvm, notif, d3_data->status,
len);
+
+ if (wowlan_info_ver < 2)
+ kfree(notif);
+
if (d3_data->status &&
d3_data->status->wakeup_reasons & IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT)
/* We are supposed to get also wake packet notif */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 527daaf46f96..84a488538427 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -340,6 +340,26 @@ static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+
+static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ int err, pos;
+ char buf[12];
+ u32 value;
+
+ err = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
+ DSM_FUNC_ENABLE_6E,
+ &iwl_guid, &value);
+ if (err)
+ return err;
+
+ pos = sprintf(buf, "0x%08x\n", value);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
#endif
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
@@ -1898,6 +1918,7 @@ MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
#ifdef CONFIG_ACPI
MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
+MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
#endif
MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
@@ -1940,6 +1961,11 @@ static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
if (ret < 0)
return ret;
+ if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
+ ret = -EIO;
+ goto out;
+ }
+
rsp = (void *)hcmd.resp_pkt->data;
if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
ret = -ENXIO;
@@ -2016,6 +2042,11 @@ static ssize_t iwl_dbgfs_mem_write(struct file *file,
if (ret < 0)
return ret;
+ if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
+ ret = -EIO;
+ goto out;
+ }
+
rsp = (void *)hcmd.resp_pkt->data;
if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
ret = -ENXIO;
@@ -2092,6 +2123,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);
#ifdef CONFIG_ACPI
MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
+ MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400);
#endif
MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 379da4bec5dd..3963a0d4ed04 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -25,6 +25,10 @@ struct iwl_mvm_smooth_entry {
u64 host_time;
};
+enum iwl_mvm_pasn_flags {
+ IWL_MVM_PASN_FLAG_HAS_HLTK = BIT(0),
+};
+
struct iwl_mvm_ftm_pasn_entry {
struct list_head list;
u8 addr[ETH_ALEN];
@@ -33,6 +37,7 @@ struct iwl_mvm_ftm_pasn_entry {
u8 cipher;
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
+ u32 flags;
};
int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -79,14 +84,24 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
rcu_read_unlock();
}
- if (tk_len != expected_tk_len || hltk_len != sizeof(pasn->hltk)) {
+ if (tk_len != expected_tk_len ||
+ (hltk_len && hltk_len != sizeof(pasn->hltk))) {
IWL_ERR(mvm, "Invalid key length: tk_len=%u hltk_len=%u\n",
tk_len, hltk_len);
goto out;
}
+ if (!expected_tk_len && !hltk_len) {
+ IWL_ERR(mvm, "TK and HLTK not set\n");
+ goto out;
+ }
+
memcpy(pasn->addr, addr, sizeof(pasn->addr));
- memcpy(pasn->hltk, hltk, sizeof(pasn->hltk));
+
+ if (hltk_len) {
+ memcpy(pasn->hltk, hltk, sizeof(pasn->hltk));
+ pasn->flags |= IWL_MVM_PASN_FLAG_HAS_HLTK;
+ }
if (tk && tk_len)
memcpy(pasn->tk, tk, sizeof(pasn->tk));
@@ -691,7 +706,11 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
continue;
target->cipher = entry->cipher;
- memcpy(target->hltk, entry->hltk, sizeof(target->hltk));
+
+ if (entry->flags & IWL_MVM_PASN_FLAG_HAS_HLTK)
+ memcpy(target->hltk, entry->hltk, sizeof(target->hltk));
+ else
+ memset(target->hltk, 0, sizeof(target->hltk));
if (vif->cfg.assoc &&
!memcmp(vif->bss_conf.bssid, target->bssid,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index c37d793d6a4a..1b6fb73ddfc7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -317,6 +317,8 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
.addr = addr,
.hltk = hltk,
};
+ struct iwl_mvm_pasn_hltk_data *hltk_data_ptr = NULL;
+
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
WIDE_ID(LOCATION_GROUP, TOF_RESPONDER_DYN_CONFIG_CMD),
2);
@@ -328,12 +330,21 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
return -ENOTSUPP;
}
- hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
- if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
- IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
+ if ((!hltk || !hltk_len) && (!tk || !tk_len)) {
+ IWL_ERR(mvm, "TK and HLTK not set\n");
return -EINVAL;
}
+ if (hltk && hltk_len) {
+ hltk_data.cipher = iwl_mvm_cipher_to_location_cipher(cipher);
+ if (hltk_data.cipher == IWL_LOCATION_CIPHER_INVALID) {
+ IWL_ERR(mvm, "invalid cipher: %u\n", cipher);
+ return -EINVAL;
+ }
+
+ hltk_data_ptr = &hltk_data;
+ }
+
if (tk && tk_len) {
sta = kzalloc(sizeof(*sta), GFP_KERNEL);
if (!sta)
@@ -350,7 +361,7 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm,
list_add_tail(&sta->list, &mvm->resp_pasn_list);
}
- ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, &hltk_data);
+ ret = iwl_mvm_ftm_responder_dyn_cfg_v3(mvm, vif, NULL, hltk_data_ptr);
if (ret && sta)
iwl_mvm_resp_del_pasn_sta(mvm, vif, sta);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 7fe733dcc748..b35c96cf7ad2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -321,6 +321,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
bool run_in_rfkill =
ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
+ u8 count;
+ struct iwl_pc_data *pc_data;
if (ucode_type == IWL_UCODE_REGULAR &&
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
@@ -393,6 +395,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
/* LMAC/UMAC PC info */
if (trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_22000) {
+ pc_data = trans->dbg.pc_data;
+ for (count = 0; count < trans->dbg.num_pc;
+ count++, pc_data++)
+ IWL_ERR(mvm, "%s: 0x%x\n",
+ pc_data->pc_name,
+ pc_data->pc_address);
+ } else if (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_9000) {
IWL_ERR(mvm, "UMAC PC: 0x%x\n",
iwl_read_umac_prph(trans,
@@ -467,111 +477,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return 0;
}
-static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
-{
- struct iwl_notification_wait init_wait;
- struct iwl_nvm_access_complete_cmd nvm_complete = {};
- struct iwl_init_extended_cfg_cmd init_cfg = {
- .init_flags = cpu_to_le32(BIT(IWL_INIT_NVM)),
- };
- static const u16 init_complete[] = {
- INIT_COMPLETE_NOTIF,
- };
- int ret;
-
- if (mvm->trans->cfg->tx_with_siso_diversity)
- init_cfg.init_flags |= cpu_to_le32(BIT(IWL_INIT_PHY));
-
- lockdep_assert_held(&mvm->mutex);
-
- mvm->rfkill_safe_init_done = false;
-
- iwl_init_notification_wait(&mvm->notif_wait,
- &init_wait,
- init_complete,
- ARRAY_SIZE(init_complete),
- iwl_wait_init_complete,
- NULL);
-
- iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
-
- /* Will also start the device */
- ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
- if (ret) {
- IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
- goto error;
- }
- iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
- NULL);
-
- /* Send init config command to mark that we are sending NVM access
- * commands
- */
- ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
- INIT_EXTENDED_CFG_CMD),
- CMD_SEND_IN_RFKILL,
- sizeof(init_cfg), &init_cfg);
- if (ret) {
- IWL_ERR(mvm, "Failed to run init config command: %d\n",
- ret);
- goto error;
- }
-
- /* Load NVM to NIC if needed */
- if (mvm->nvm_file_name) {
- ret = iwl_read_external_nvm(mvm->trans, mvm->nvm_file_name,
- mvm->nvm_sections);
- if (ret)
- goto error;
- ret = iwl_mvm_load_nvm_to_nic(mvm);
- if (ret)
- goto error;
- }
-
- if (IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
- ret = iwl_nvm_init(mvm);
- if (ret) {
- IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
- goto error;
- }
- }
-
- ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
- NVM_ACCESS_COMPLETE),
- CMD_SEND_IN_RFKILL,
- sizeof(nvm_complete), &nvm_complete);
- if (ret) {
- IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
- ret);
- goto error;
- }
-
- /* We wait for the INIT complete notification */
- ret = iwl_wait_notification(&mvm->notif_wait, &init_wait,
- MVM_UCODE_ALIVE_TIMEOUT);
- if (ret)
- return ret;
-
- /* Read the NVM only at driver load time, no need to do this twice */
- if (!IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
- mvm->nvm_data = iwl_get_nvm(mvm->trans, mvm->fw);
- if (IS_ERR(mvm->nvm_data)) {
- ret = PTR_ERR(mvm->nvm_data);
- mvm->nvm_data = NULL;
- IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
- return ret;
- }
- }
-
- mvm->rfkill_safe_init_done = true;
-
- return 0;
-
-error:
- iwl_remove_notification(&mvm->notif_wait, &init_wait);
- return ret;
-}
-
#ifdef CONFIG_ACPI
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
struct iwl_phy_specific_cfg *phy_filters)
@@ -698,6 +603,118 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, cmd_size, &phy_cfg_cmd);
}
+static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm)
+{
+ struct iwl_notification_wait init_wait;
+ struct iwl_nvm_access_complete_cmd nvm_complete = {};
+ struct iwl_init_extended_cfg_cmd init_cfg = {
+ .init_flags = cpu_to_le32(BIT(IWL_INIT_NVM)),
+ };
+ static const u16 init_complete[] = {
+ INIT_COMPLETE_NOTIF,
+ };
+ int ret;
+
+ if (mvm->trans->cfg->tx_with_siso_diversity)
+ init_cfg.init_flags |= cpu_to_le32(BIT(IWL_INIT_PHY));
+
+ lockdep_assert_held(&mvm->mutex);
+
+ mvm->rfkill_safe_init_done = false;
+
+ iwl_init_notification_wait(&mvm->notif_wait,
+ &init_wait,
+ init_complete,
+ ARRAY_SIZE(init_complete),
+ iwl_wait_init_complete,
+ NULL);
+
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
+
+ /* Will also start the device */
+ ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
+ goto error;
+ }
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
+ NULL);
+
+ /* Send init config command to mark that we are sending NVM access
+ * commands
+ */
+ ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
+ INIT_EXTENDED_CFG_CMD),
+ CMD_SEND_IN_RFKILL,
+ sizeof(init_cfg), &init_cfg);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to run init config command: %d\n",
+ ret);
+ goto error;
+ }
+
+ /* Load NVM to NIC if needed */
+ if (mvm->nvm_file_name) {
+ ret = iwl_read_external_nvm(mvm->trans, mvm->nvm_file_name,
+ mvm->nvm_sections);
+ if (ret)
+ goto error;
+ ret = iwl_mvm_load_nvm_to_nic(mvm);
+ if (ret)
+ goto error;
+ }
+
+ if (IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
+ ret = iwl_nvm_init(mvm);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
+ goto error;
+ }
+ }
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ NVM_ACCESS_COMPLETE),
+ CMD_SEND_IN_RFKILL,
+ sizeof(nvm_complete), &nvm_complete);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
+ ret);
+ goto error;
+ }
+
+ ret = iwl_send_phy_cfg_cmd(mvm);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to run PHY configuration: %d\n",
+ ret);
+ goto error;
+ }
+
+ /* We wait for the INIT complete notification */
+ ret = iwl_wait_notification(&mvm->notif_wait, &init_wait,
+ MVM_UCODE_ALIVE_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* Read the NVM only at driver load time, no need to do this twice */
+ if (!IWL_MVM_PARSE_NVM && !mvm->nvm_data) {
+ mvm->nvm_data = iwl_get_nvm(mvm->trans, mvm->fw);
+ if (IS_ERR(mvm->nvm_data)) {
+ ret = PTR_ERR(mvm->nvm_data);
+ mvm->nvm_data = NULL;
+ IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
+ return ret;
+ }
+ }
+
+ mvm->rfkill_safe_init_done = true;
+
+ return 0;
+
+error:
+ iwl_remove_notification(&mvm->notif_wait, &init_wait);
+ return ret;
+}
+
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm)
{
struct iwl_notification_wait calib_wait;
@@ -1538,12 +1555,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
ret = iwl_send_phy_db_data(mvm->phy_db);
if (ret)
goto error;
+ ret = iwl_send_phy_cfg_cmd(mvm);
+ if (ret)
+ goto error;
}
- ret = iwl_send_phy_cfg_cmd(mvm);
- if (ret)
- goto error;
-
ret = iwl_mvm_send_bt_init_conf(mvm);
if (ret)
goto error;
@@ -1711,8 +1727,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
iwl_mvm_tas_init(mvm);
iwl_mvm_leds_sync(mvm);
- iwl_mvm_ftm_initiator_smooth_config(mvm);
-
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) {
if (iwl_mvm_eval_dsm_rfi(mvm) == DSM_VALUE_RFI_ENABLE)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 82fad042a281..cc90f2884cff 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -225,16 +225,20 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* that we should share it with another interface.
*/
- /* Currently, MAC ID 0 should be used only for the managed/IBSS vif */
- switch (vif->type) {
- case NL80211_IFTYPE_ADHOC:
- break;
- case NL80211_IFTYPE_STATION:
- if (!vif->p2p)
+ /* MAC ID 0 should be used only for the managed/IBSS vif with non-MLO
+ * FW API
+ */
+ if (!mvm->mld_api_is_used) {
+ switch (vif->type) {
+ case NL80211_IFTYPE_ADHOC:
break;
- fallthrough;
- default:
- __clear_bit(0, data.available_mac_ids);
+ case NL80211_IFTYPE_STATION:
+ if (!vif->p2p)
+ break;
+ fallthrough;
+ default:
+ __clear_bit(0, data.available_mac_ids);
+ }
}
ieee80211_iterate_active_interfaces_atomic(
@@ -870,17 +874,44 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size)
return ie - beacon;
}
-static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info,
- struct ieee80211_vif *vif)
+u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_vif *vif)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_supported_band *sband;
unsigned long basic = vif->bss_conf.basic_rates;
u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT;
+ u32 link_id = u32_get_bits(info->control.flags,
+ IEEE80211_TX_CTRL_MLO_LINK);
+ u8 band = info->band;
u8 rate;
u32 i;
- sband = mvm->hw->wiphy->bands[info->band];
+ if (link_id == IEEE80211_LINK_UNSPECIFIED && vif->valid_links) {
+ for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) {
+ if (!mvmvif->link[i])
+ continue;
+ /* shouldn't do this when >1 link is active */
+ WARN_ON_ONCE(link_id != IEEE80211_LINK_UNSPECIFIED);
+ link_id = i;
+ }
+ }
+
+ if (link_id < IEEE80211_LINK_UNSPECIFIED) {
+ struct ieee80211_bss_conf *link_conf;
+
+ rcu_read_lock();
+ link_conf = rcu_dereference(vif->link_conf[link_id]);
+ if (link_conf) {
+ basic = link_conf->basic_rates;
+ if (link_conf->chandef.chan)
+ band = link_conf->chandef.chan->band;
+ }
+ rcu_read_unlock();
+ }
+
+ sband = mvm->hw->wiphy->bands[band];
for_each_set_bit(i, &basic, BITS_PER_LONG) {
u16 hw = sband->bitrates[i].hw_value;
@@ -892,7 +923,9 @@ static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
}
}
- if (info->band == NL80211_BAND_2GHZ && !vif->p2p) {
+ if (band == NL80211_BAND_2GHZ && !vif->p2p &&
+ vif->type != NL80211_IFTYPE_P2P_DEVICE &&
+ !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) {
if (lowest_cck != IWL_RATE_COUNT)
rate = lowest_cck;
else if (lowest_ofdm != IWL_RATE_COUNT)
@@ -1102,10 +1135,10 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
sizeof(beacon_cmd));
}
-int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct sk_buff *beacon,
- struct ieee80211_bss_conf *link_conf)
+static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct sk_buff *beacon,
+ struct ieee80211_bss_conf *link_conf)
{
if (WARN_ON(!beacon))
return -EINVAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index aaa7e3c561a0..0f01b62357c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -227,14 +227,18 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
static const u8 he_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
};
static const u8 tm_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT |
WLAN_EXT_CAPA3_TIMING_MEASUREMENT_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
@@ -301,6 +305,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
ieee80211_hw_set(hw, STA_MMPDU_TXQ);
+ /* Set this early since we need to have it for the check below */
+ if (mvm->mld_api_is_used &&
+ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
+
/* With MLD FW API, it tracks timing by itself,
* no need for any timing from the host
*/
@@ -409,6 +418,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
+ wiphy_ext_feature_set(hw->wiphy,
+ NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
@@ -1061,6 +1072,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
mvm->monitor_on = false;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ mvm->beacon_inject_active = false;
+#endif
/* keep statistics ticking */
iwl_mvm_accu_radio_stats(mvm);
@@ -3305,8 +3319,8 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
lockdep_is_held(&mvm->mutex));
sta_id = link_sta->sta_id;
if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[sta_id])) {
- rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id],
- ERR_PTR(-ENOENT));
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id],
+ ERR_PTR(-ENOENT));
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[sta_id], NULL);
}
}
@@ -3568,24 +3582,22 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
*/
static void iwl_mvm_rs_rate_init_all_links(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- bool update)
+ struct ieee80211_sta *sta)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
struct ieee80211_bss_conf *conf =
- link_conf_dereference_protected(vif, link_id);
+ link_conf_dereference_check(vif, link_id);
struct ieee80211_link_sta *link_sta =
- link_sta_dereference_protected(sta, link_id);
+ link_sta_dereference_check(sta, link_id);
if (!conf || !link_sta || !mvmvif->link[link_id]->phy_ctxt)
continue;
- iwl_mvm_rs_rate_init(mvm, sta, conf, link_sta,
- mvmvif->link[link_id]->phy_ctxt->channel->band,
- update);
+ iwl_mvm_rs_rate_init(mvm, vif, sta, conf, link_sta,
+ mvmvif->link[link_id]->phy_ctxt->channel->band);
}
}
@@ -3662,6 +3674,7 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_mvm_sta_state_ops *callbacks)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int i;
int ret;
@@ -3697,6 +3710,9 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
}
ieee80211_sta_recalc_aggregates(sta);
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ mvmvif->ap_sta = sta;
+
return 0;
}
@@ -3753,7 +3769,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
}
out:
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, false);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
return callbacks->update_sta(mvm, vif, sta);
}
@@ -3786,7 +3802,9 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
}
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, true);
+ mvm_sta->authorized = true;
+
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
return 0;
}
@@ -3798,14 +3816,17 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
int ret;
lockdep_assert_held(&mvm->mutex);
+ mvmsta->authorized = false;
+
/* once we move into assoc state, need to update rate scale to
* disable using wide bandwidth
*/
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, false);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
if (!sta->tdls) {
/* Set this but don't call iwl_mvm_mac_ctxt_changed()
@@ -3924,8 +3945,10 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
ret = 0;
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) {
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
iwl_mvm_stop_session_protection(mvm, vif);
+ mvmvif->ap_sta = NULL;
+ }
ret = callbacks->rm_sta(mvm, vif, sta);
if (sta->tdls) {
iwl_mvm_recalc_tdls_state(mvm, vif, false);
@@ -3968,15 +3991,11 @@ void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u32 changed)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (changed & (IEEE80211_RC_BW_CHANGED |
IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED))
- iwl_mvm_rs_rate_init(mvm, sta,
- &vif->bss_conf, &sta->deflink,
- mvmvif->deflink.phy_ctxt->channel->band,
- true);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
if (vif->type == NL80211_IFTYPE_STATION &&
changed & IEEE80211_RC_NSS_CHANGED)
@@ -4094,7 +4113,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvmsta = NULL;
- struct iwl_mvm_key_pn *ptk_pn;
+ struct iwl_mvm_key_pn *ptk_pn = NULL;
int keyidx = key->keyidx;
u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
@@ -4252,6 +4271,10 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
if (ret) {
IWL_WARN(mvm, "set key failed\n");
key->hw_key_idx = STA_KEY_IDX_INVALID;
+ if (ptk_pn) {
+ RCU_INIT_POINTER(mvmsta->ptk_pn[keyidx], NULL);
+ kfree(ptk_pn);
+ }
/*
* can't add key for RX, but we don't need it
* in the device for TX so still return 0,
@@ -5588,6 +5611,7 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_sta *mvmsta;
struct ieee80211_sta *sta;
+ bool ap_sta_done = false;
int i;
u32 msk = 0;
@@ -5616,8 +5640,14 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (mvmsta->vif != vif)
continue;
+ if (sta == mvmvif->ap_sta) {
+ if (ap_sta_done)
+ continue;
+ ap_sta_done = true;
+ }
+
/* make sure only TDLS peers or the AP are flushed */
- WARN_ON_ONCE(i != mvmvif->deflink.ap_sta_id && !sta->tdls);
+ WARN_ON_ONCE(sta != mvmvif->ap_sta && !sta->tdls);
if (drop) {
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
@@ -6129,7 +6159,7 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (iwl_mvm_has_new_tx_csum(mvm))
return iwl_mvm_tx_csum_bz(mvm, head, true) ==
iwl_mvm_tx_csum_bz(mvm, skb, true);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index f4785c0a0b84..8853821b3716 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -14,23 +14,41 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
struct ieee80211_key_conf *keyconf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *link_info = &mvmvif->deflink;
- if (vif->type == NL80211_IFTYPE_AP &&
- !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
- return BIT(mvmvif->deflink.mcast_sta.sta_id);
+ lockdep_assert_held(&mvm->mutex);
- if (sta) {
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
- return BIT(mvmsta->deflink.sta_id);
+ if (keyconf->link_id >= 0) {
+ link_info = mvmvif->link[keyconf->link_id];
+ if (!link_info)
+ return 0;
}
- if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA)
- return BIT(mvmvif->deflink.ap_sta_id);
+ /* AP group keys are per link and should be on the mcast STA */
+ if (vif->type == NL80211_IFTYPE_AP &&
+ !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+ return BIT(link_info->mcast_sta.sta_id);
+
+ /* for client mode use the AP STA also for group keys */
+ if (!sta && vif->type == NL80211_IFTYPE_STATION)
+ sta = mvmvif->ap_sta;
+
+ /* During remove the STA was removed and the group keys come later
+ * (which sounds like a bad sequence, but remember that to mac80211 the
+ * group keys have no sta pointer), so we don't have a STA now.
+ * Since this happens for group keys only, just use the link_info as
+ * the group keys are per link; make sure that is the case by checking
+ * we do have a link_id or are not doing MLO.
+ * Of course the same can be done during add as well, but we must do
+ * it during remove, since we don't have the mvmvif->ap_sta pointer.
+ */
+ if (!sta && (keyconf->link_id >= 0 || !vif->valid_links))
+ return BIT(link_info->ap_sta_id);
+
+ /* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
- /* invalid */
- return 0;
+ /* pass link_id to filter by it if not -1 (GTK on client) */
+ return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
}
static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
@@ -41,6 +59,8 @@ static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 flags = 0;
+ lockdep_assert_held(&mvm->mutex);
+
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
@@ -68,22 +88,68 @@ static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
break;
}
- rcu_read_lock();
- if (!sta && vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
- u8 sta_id = mvmvif->deflink.ap_sta_id;
-
- sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
- }
+ if (!sta && vif->type == NL80211_IFTYPE_STATION)
+ sta = mvmvif->ap_sta;
if (!IS_ERR_OR_NULL(sta) && sta->mfp)
flags |= IWL_SEC_KEY_FLAG_MFP;
- rcu_read_unlock();
return flags;
}
+struct iwl_mvm_sta_key_update_data {
+ struct ieee80211_sta *sta;
+ u32 old_sta_mask;
+ u32 new_sta_mask;
+ int err;
+};
+
+static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
+{
+ u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
+ struct iwl_mvm_sta_key_update_data *data = _data;
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_sec_key_cmd cmd = {
+ .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
+ .u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
+ .u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
+ .u.modify.key_id = cpu_to_le32(key->keyidx),
+ .u.modify.key_flags =
+ cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
+ };
+ int err;
+
+ /* only need to do this for pairwise keys (link_id == -1) */
+ if (sta != data->sta || key->link_id >= 0)
+ return;
+
+ err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
+
+ if (err)
+ data->err = err;
+}
+
+int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 old_sta_mask,
+ u32 new_sta_mask)
+{
+ struct iwl_mvm_sta_key_update_data data = {
+ .sta = sta,
+ .old_sta_mask = old_sta_mask,
+ .new_sta_mask = new_sta_mask,
+ };
+
+ ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
+ &data);
+ return data.err;
+}
+
static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
u32 key_flags, u32 keyidx, u32 flags)
{
@@ -118,6 +184,9 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key)))
return -EINVAL;
+ if (WARN_ON(!sta_mask))
+ return -EINVAL;
+
if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key,
@@ -164,6 +233,9 @@ static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
int ret;
+ if (WARN_ON(!sta_mask))
+ return -EINVAL;
+
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
flags);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index ab0ba85936b4..1717fb52dc12 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -4,6 +4,16 @@
*/
#include "mvm.h"
+static void iwl_mvm_mld_set_he_support(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct iwl_mac_config_cmd *cmd)
+{
+ if (vif->type == NL80211_IFTYPE_AP)
+ cmd->he_ap_support = cpu_to_le16(1);
+ else
+ cmd->he_support = cpu_to_le16(1);
+}
+
static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mac_config_cmd *cmd,
@@ -41,7 +51,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
* and enable both when we have MLO.
*/
if (vif->valid_links) {
- cmd->he_support = cpu_to_le32(1);
+ iwl_mvm_mld_set_he_support(mvm, vif, cmd);
cmd->eht_support = cpu_to_le32(1);
return;
}
@@ -53,7 +63,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
continue;
if (link_conf->he_support)
- cmd->he_support = cpu_to_le32(1);
+ iwl_mvm_mld_set_he_support(mvm, vif, cmd);
/* it's not reasonable to have EHT without HE and FW API doesn't
* support it. Ignore EHT in this case.
@@ -157,7 +167,6 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 action)
{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mac_config_cmd cmd = {};
WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
@@ -168,9 +177,6 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
MAC_CFG_FILTER_ACCEPT_GRP);
- /* TODO: Assumes that the beacon id == mac context id */
- cmd.go_ibss.beacon_template = cpu_to_le32(mvmvif->id);
-
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
}
@@ -210,9 +216,6 @@ static int iwl_mvm_mld_mac_ctxt_cmd_ap_go(struct iwl_mvm *mvm,
MAC_CFG_FILTER_ACCEPT_PROBE_REQ,
MAC_CFG_FILTER_ACCEPT_BEACON);
- /* TODO: Assume that the beacon id == mac context id */
- cmd.go_ibss.beacon_template = cpu_to_le32(mvmvif->id);
-
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 203f2513e7ea..fbc2d5ed1006 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -256,6 +256,30 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
if (ret)
goto out;
+ /* Initialize rate control for the AP station, since we might be
+ * doing a link switch here - we cannot initialize it before since
+ * this needs the phy context assigned (and in FW?), and we cannot
+ * do it later because it needs to be initialized as soon as we're
+ * able to TX on the link, i.e. when active.
+ *
+ * Firmware restart isn't quite correct yet for MLO, but we don't
+ * need to do it in that case anyway since it will happen from the
+ * normal station state callback.
+ */
+ if (mvmvif->ap_sta &&
+ !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ struct ieee80211_link_sta *link_sta;
+
+ rcu_read_lock();
+ link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]);
+
+ if (!WARN_ON_ONCE(!link_sta))
+ iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta,
+ link_conf, link_sta,
+ phy_ctxt->channel->band);
+ rcu_read_unlock();
+ }
+
/* then activate */
ret = iwl_mvm_link_changed(mvm, vif, link_conf,
LINK_CONTEXT_MODIFY_ACTIVE |
@@ -882,7 +906,10 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
n_active++;
}
- if (n_active > 1)
+ if (vif->type == NL80211_IFTYPE_AP &&
+ n_active > mvm->fw->ucode_capa.num_beacons)
+ return -EOPNOTSUPP;
+ else if (n_active > 1)
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 78d4f186cd99..0bfdf4462755 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -4,6 +4,43 @@
*/
#include "mvm.h"
#include "time-sync.h"
+#include "sta.h"
+
+u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int filter_link_id)
+{
+ struct iwl_mvm_sta *mvmsta;
+ unsigned int link_id;
+ u32 result = 0;
+
+ if (!sta)
+ return 0;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ /* it's easy when the STA is not an MLD */
+ if (!sta->valid_links)
+ return BIT(mvmsta->deflink.sta_id);
+
+ /* but if it is an MLD, get the mask of all the FW STAs it has ... */
+ for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
+ struct iwl_mvm_link_sta *link_sta;
+
+ /* unless we have a specific link in mind */
+ if (filter_link_id >= 0 && link_id != filter_link_id)
+ continue;
+
+ link_sta =
+ rcu_dereference_check(mvmsta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (!link_sta)
+ continue;
+
+ result |= BIT(link_sta->sta_id);
+ }
+
+ return result;
+}
static int iwl_mvm_mld_send_sta_cmd(struct iwl_mvm *mvm,
struct iwl_mvm_sta_cfg_cmd *cmd)
@@ -262,19 +299,22 @@ int iwl_mvm_mld_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
IWL_MAX_TID_COUNT, NULL);
}
-static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm, int sta_id,
+static int iwl_mvm_mld_disable_txq(struct iwl_mvm *mvm, u32 sta_mask,
u16 *queueptr, u8 tid)
{
int queue = *queueptr;
int ret = 0;
+ if (tid == IWL_MAX_TID_COUNT)
+ tid = IWL_MGMT_TID;
+
if (mvm->sta_remove_requires_queue_remove) {
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP,
SCD_QUEUE_CONFIG_CMD);
struct iwl_scd_queue_cfg_cmd remove_cmd = {
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
.u.remove.tid = cpu_to_le32(tid),
- .u.remove.sta_mask = cpu_to_le32(BIT(sta_id)),
+ .u.remove.sta_mask = cpu_to_le32(sta_mask),
};
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,
@@ -304,7 +344,7 @@ static int iwl_mvm_mld_rm_int_sta(struct iwl_mvm *mvm,
if (flush)
iwl_mvm_flush_sta(mvm, int_sta, true);
- iwl_mvm_mld_disable_txq(mvm, int_sta->sta_id, queuptr, tid);
+ iwl_mvm_mld_disable_txq(mvm, BIT(int_sta->sta_id), queuptr, tid);
ret = iwl_mvm_mld_rm_sta_from_fw(mvm, int_sta->sta_id);
if (ret)
@@ -387,7 +427,6 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_mvm_sta_cfg_cmd cmd = {
.sta_id = cpu_to_le32(mvm_link_sta->sta_id),
.station_type = cpu_to_le32(mvm_sta->sta_type),
- .mfp = cpu_to_le32(sta->mfp),
};
u32 agg_size = 0, mpdu_dens = 0;
@@ -720,6 +759,7 @@ static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ u32 sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
int i;
lockdep_assert_held(&mvm->mutex);
@@ -728,7 +768,7 @@ static void iwl_mvm_mld_disable_sta_queues(struct iwl_mvm *mvm,
if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
continue;
- iwl_mvm_mld_disable_txq(mvm, mvm_sta->deflink.sta_id,
+ iwl_mvm_mld_disable_txq(mvm, sta_mask,
&mvm_sta->tid_data[i].txq_id, i);
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
}
@@ -870,11 +910,12 @@ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
rcu_read_unlock();
}
-static int iwl_mvm_mld_update_sta_queue(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta,
- u32 old_sta_mask,
- u32 new_sta_mask)
+static int iwl_mvm_mld_update_sta_queues(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ u32 old_sta_mask,
+ u32 new_sta_mask)
{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_scd_queue_cfg_cmd cmd = {
.operation = cpu_to_le32(IWL_SCD_QUEUE_MODIFY),
.u.modify.old_sta_mask = cpu_to_le32(old_sta_mask),
@@ -910,6 +951,70 @@ static int iwl_mvm_mld_update_sta_queue(struct iwl_mvm *mvm,
return 0;
}
+static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
+ u32 old_sta_mask,
+ u32 new_sta_mask)
+{
+ struct iwl_rx_baid_cfg_cmd cmd = {
+ .action = cpu_to_le32(IWL_RX_BAID_ACTION_MODIFY),
+ .modify.old_sta_id_mask = cpu_to_le32(old_sta_mask),
+ .modify.new_sta_id_mask = cpu_to_le32(new_sta_mask),
+ };
+ u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
+ int baid;
+
+ BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
+
+ for (baid = 0; baid < ARRAY_SIZE(mvm->baid_map); baid++) {
+ struct iwl_mvm_baid_data *data;
+ int ret;
+
+ data = rcu_dereference_protected(mvm->baid_map[baid],
+ lockdep_is_held(&mvm->mutex));
+ if (!data)
+ continue;
+
+ if (!(data->sta_mask & old_sta_mask))
+ continue;
+
+ WARN_ONCE(data->sta_mask != old_sta_mask,
+ "BAID data for %d corrupted - expected 0x%x found 0x%x\n",
+ baid, old_sta_mask, data->sta_mask);
+
+ cmd.modify.tid = cpu_to_le32(data->tid);
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
+ data->sta_mask = new_sta_mask;
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int iwl_mvm_mld_update_sta_resources(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 old_sta_mask,
+ u32 new_sta_mask)
+{
+ int ret;
+
+ ret = iwl_mvm_mld_update_sta_queues(mvm, sta,
+ old_sta_mask,
+ new_sta_mask);
+ if (ret)
+ return ret;
+
+ ret = iwl_mvm_mld_update_sta_keys(mvm, vif, sta,
+ old_sta_mask,
+ new_sta_mask);
+ if (ret)
+ return ret;
+
+ return iwl_mvm_mld_update_sta_baids(mvm, old_sta_mask, new_sta_mask);
+}
+
int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -946,9 +1051,10 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
}
if (sta_mask_to_rem) {
- ret = iwl_mvm_mld_update_sta_queue(mvm, mvm_sta,
- current_sta_mask,
- current_sta_mask & ~sta_mask_to_rem);
+ ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
+ current_sta_mask,
+ current_sta_mask &
+ ~sta_mask_to_rem);
if (WARN_ON(ret))
goto err;
@@ -1020,12 +1126,15 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
goto err;
link_sta_added_to_fw |= BIT(link_id);
+
+ iwl_mvm_rs_add_sta_link(mvm, mvm_sta_link);
}
if (sta_mask_added) {
- ret = iwl_mvm_mld_update_sta_queue(mvm, mvm_sta,
- current_sta_mask,
- current_sta_mask | sta_mask_added);
+ ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
+ current_sta_mask,
+ current_sta_mask |
+ sta_mask_added);
if (WARN_ON(ret))
goto err;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index e32ce876951f..6e7470d3a826 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -434,6 +434,8 @@ struct iwl_mvm_vif {
/* TCP Checksum Offload */
netdev_features_t features;
+ struct ieee80211_sta *ap_sta;
+
/* we can only have 2 GTK + 2 IGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[4];
@@ -678,7 +680,7 @@ __aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
/**
* struct iwl_mvm_baid_data - BA session data
- * @sta_id: station id
+ * @sta_mask: current station mask for the BAID
* @tid: tid of the session
* @baid baid of the session
* @timeout: the timeout set in the addba request
@@ -692,7 +694,7 @@ __aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
*/
struct iwl_mvm_baid_data {
struct rcu_head rcu_head;
- u8 sta_id;
+ u32 sta_mask;
u8 tid;
u8 baid;
u16 timeout;
@@ -824,6 +826,12 @@ struct iwl_time_sync_data {
bool active;
};
+struct iwl_mei_scan_filter {
+ bool is_mei_limited_scan;
+ struct sk_buff_head scan_res;
+ struct work_struct scan_work;
+};
+
struct iwl_mvm {
/* for logger access */
struct device *dev;
@@ -1175,6 +1183,8 @@ struct iwl_mvm {
bool pldr_sync;
struct iwl_time_sync_data time_sync;
+
+ struct iwl_mei_scan_filter mei_scan_filter;
};
/* Extract MVM priv from op_mode and _hw */
@@ -1401,24 +1411,8 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw)
{
- return (iwl_fw_lookup_cmd_ver(fw, LINK_CONFIG_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN) &&
- (iwl_fw_lookup_cmd_ver(fw, MAC_CONFIG_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN) &&
- (iwl_fw_lookup_cmd_ver(fw, STA_CONFIG_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN) &&
- (iwl_fw_lookup_cmd_ver(fw, AUX_STA_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN) &&
- (iwl_fw_lookup_cmd_ver(fw, STA_REMOVE_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN) &&
- (iwl_fw_lookup_cmd_ver(fw, STA_DISABLE_TX_CMD,
- IWL_FW_CMD_VER_UNKNOWN) !=
- IWL_FW_CMD_VER_UNKNOWN);
+ return fw_has_capa(&fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT);
}
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
@@ -1522,6 +1516,19 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT);
}
+static inline bool iwl_mvm_has_new_tx_csum(struct iwl_mvm *mvm)
+{
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
+ return false;
+
+ if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
+ CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
+ mvm->trans->hw_rev_step <= SILICON_B_STEP)
+ return false;
+
+ return true;
+}
+
extern const u8 iwl_mvm_ac_to_tx_fifo[];
extern const u8 iwl_mvm_ac_to_gen2_tx_fifo[];
@@ -1781,16 +1788,15 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
-int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct sk_buff *beacon,
- struct ieee80211_bss_conf *link_conf);
int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
struct sk_buff *beacon,
void *data, int len);
u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct ieee80211_vif *vif);
+u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_vif *vif);
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw,
u8 rate_idx);
void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
@@ -2306,6 +2312,7 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const struct ieee80211_sta *sta,
u16 tid);
+void iwl_mvm_mei_scan_filter_init(struct iwl_mei_scan_filter *mei_scan_filter);
void iwl_mvm_ptp_init(struct iwl_mvm *mvm);
void iwl_mvm_ptp_remove(struct iwl_mvm *mvm);
@@ -2334,6 +2341,11 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_vif_link_info *link,
unsigned int link_id);
+int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 old_sta_mask,
+ u32 new_sta_mask);
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
struct iwl_rfi_lut_entry *rfi_table);
@@ -2512,6 +2524,22 @@ static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm)
sw_rfkill);
}
+static inline bool iwl_mvm_mei_filter_scan(struct iwl_mvm *mvm,
+ struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+
+ if (mvm->mei_scan_filter.is_mei_limited_scan &&
+ (ieee80211_is_probe_resp(mgmt->frame_control) ||
+ ieee80211_is_beacon(mgmt->frame_control))) {
+ skb_queue_tail(&mvm->mei_scan_filter.scan_res, skb);
+ schedule_work(&mvm->mei_scan_filter.scan_work);
+ return true;
+ }
+
+ return false;
+}
+
void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool forbidden);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 56a4e9d6ae33..32625bfacaae 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -472,8 +472,8 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
HCMD_NAME(BT_COEX_UPDATE_REDUCED_TXP),
HCMD_NAME(BT_COEX_CI),
- HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION),
+ HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
HCMD_NAME(PHY_CONFIGURATION_CMD),
HCMD_NAME(CALIB_RES_NOTIF_PHY_DB),
HCMD_NAME(PHY_DB_CMD),
@@ -1020,10 +1020,14 @@ static void iwl_mvm_me_conn_status(void *priv, const struct iwl_mei_conn_info *c
kfree_rcu(prev_conn_info, rcu_head);
}
-static void iwl_mvm_mei_rfkill(void *priv, bool blocked)
+static void iwl_mvm_mei_rfkill(void *priv, bool blocked,
+ bool csme_taking_ownership)
{
struct iwl_mvm *mvm = priv;
+ if (blocked && !csme_taking_ownership)
+ return;
+
mvm->mei_rfkill_blocked = blocked;
if (!mvm->hw_registered)
return;
@@ -1367,12 +1371,16 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
else
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
+ iwl_mvm_ftm_initiator_smooth_config(mvm);
+
iwl_mvm_init_time_sync(&mvm->time_sync);
mvm->debugfs_dir = dbgfs_dir;
mvm->mei_registered = !iwl_mei_register(mvm, &mei_ops);
+ iwl_mvm_mei_scan_filter_init(&mvm->mei_scan_filter);
+
if (iwl_mvm_start_get_nvm(mvm)) {
/*
* Getting NVM failed while CSME is the owner, but we are
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index c8ba2fe3e4a2..c3a00bfbeef2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -61,12 +61,14 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta)
}
static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
struct ieee80211_supported_band *sband)
{
struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
+ const struct ieee80211_sta_he_cap *sband_he_cap;
bool vht_ena = vht_cap->vht_supported;
u16 flags = 0;
@@ -92,17 +94,19 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
- if (sband->iftype_data && sband->iftype_data->he_cap.has_he &&
- !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &
- IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
+ sband_he_cap = ieee80211_get_he_iftype_cap(sband,
+ ieee80211_vif_type_p2p(vif));
+ if (sband_he_cap &&
+ !(sband_he_cap->he_cap_elem.phy_cap_info[1] &
+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
if (he_cap->has_he &&
(he_cap->he_cap_elem.phy_cap_info[3] &
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK &&
- sband->iftype_data &&
- sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[3] &
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK))
+ sband_he_cap &&
+ sband_he_cap->he_cap_elem.phy_cap_info[3] &
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK))
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
return flags;
@@ -283,7 +287,8 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
}
static void
-rs_fw_eht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
+rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
+ const struct ieee80211_link_sta *link_sta,
struct ieee80211_supported_band *sband,
struct iwl_tlc_config_cmd_v4 *cmd)
{
@@ -299,7 +304,8 @@ rs_fw_eht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20;
/* peer is 20Mhz only */
- if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
+ if (vif->type == NL80211_IFTYPE_AP &&
+ !(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
mcs_rx_20 = eht_rx_mcs->only_20mhz;
} else {
@@ -361,7 +367,8 @@ rs_fw_eht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
sizeof(cmd->ht_rates[IWL_TLC_NSS_2]));
}
-static void rs_fw_set_supp_rates(struct ieee80211_link_sta *link_sta,
+static void rs_fw_set_supp_rates(struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
struct ieee80211_supported_band *sband,
struct iwl_tlc_config_cmd_v4 *cmd)
{
@@ -383,7 +390,7 @@ static void rs_fw_set_supp_rates(struct ieee80211_link_sta *link_sta,
/* HT/VHT rates */
if (link_sta->eht_cap.has_eht) {
cmd->mode = IWL_TLC_MNG_MODE_EHT;
- rs_fw_eht_set_enabled_rates(link_sta, sband, cmd);
+ rs_fw_eht_set_enabled_rates(vif, link_sta, sband, cmd);
} else if (he_cap->has_he) {
cmd->mode = IWL_TLC_MNG_MODE_HE;
rs_fw_he_set_enabled_rates(link_sta, sband, cmd);
@@ -557,10 +564,12 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
return 0;
}
-void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- struct ieee80211_bss_conf *link_conf,
- struct ieee80211_link_sta *link_sta,
- enum nl80211_band band, bool update)
+void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_link_sta *link_sta,
+ enum nl80211_band band)
{
struct ieee80211_hw *hw = mvm->hw;
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -570,10 +579,9 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_mvm_link_sta *mvm_link_sta;
struct iwl_lq_sta_rs_fw *lq_sta;
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
- .max_ch_width = update ?
- rs_fw_bw_from_sta_bw(link_sta) :
- IWL_TLC_MNG_CH_WIDTH_20MHZ,
- .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, link_sta,
+ .max_ch_width = mvmsta->authorized ?
+ rs_fw_bw_from_sta_bw(link_sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
+ .flags = cpu_to_le16(rs_fw_get_config_flags(mvm, vif, link_sta,
sband)),
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
.sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta),
@@ -601,7 +609,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- rs_fw_set_supp_rates(link_sta, sband, &cfg_cmd);
+ rs_fw_set_supp_rates(vif, link_sta, sband, &cfg_cmd);
/*
* since TLC offload works with one mode we can assume
@@ -671,6 +679,26 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
return 0;
}
+void iwl_mvm_rs_add_sta_link(struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *link_sta)
+{
+ struct iwl_lq_sta_rs_fw *lq_sta;
+
+ lq_sta = &link_sta->lq_sta.rs_fw;
+
+ lq_sta->pers.drv = mvm;
+ lq_sta->pers.sta_id = link_sta->sta_id;
+ lq_sta->pers.chains = 0;
+ memset(lq_sta->pers.chain_signal, 0,
+ sizeof(lq_sta->pers.chain_signal));
+ lq_sta->pers.last_rssi = S8_MIN;
+ lq_sta->last_rate_n_flags = 0;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ lq_sta->pers.dbg_fixed_rate = 0;
+#endif
+}
+
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
{
unsigned int link_id;
@@ -678,25 +706,12 @@ void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
- struct iwl_lq_sta_rs_fw *lq_sta;
struct iwl_mvm_link_sta *link =
rcu_dereference_protected(mvmsta->link[link_id],
lockdep_is_held(&mvm->mutex));
if (!link)
continue;
- lq_sta = &link->lq_sta.rs_fw;
-
- lq_sta->pers.drv = mvm;
- lq_sta->pers.sta_id = link->sta_id;
- lq_sta->pers.chains = 0;
- memset(lq_sta->pers.chain_signal, 0,
- sizeof(lq_sta->pers.chain_signal));
- lq_sta->pers.last_rssi = S8_MIN;
- lq_sta->last_rate_n_flags = 0;
-
-#ifdef CONFIG_MAC80211_DEBUGFS
- lq_sta->pers.dbg_fixed_rate = 0;
-#endif
+ iwl_mvm_rs_add_sta_link(mvm, link);
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index ab82965bc0f4..a4c1e3bf4ff1 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -3015,9 +3015,9 @@ static void rs_drv_rate_update(void *mvm_r,
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
ieee80211_stop_tx_ba_session(sta, tid);
- iwl_mvm_rs_rate_init(mvm, sta,
+ iwl_mvm_rs_rate_init(mvm, mvmsta->vif, sta,
&mvmsta->vif->bss_conf, &sta->deflink,
- sband->band, true);
+ sband->band);
}
static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
@@ -4101,13 +4101,16 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
.capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW,
};
-void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
- enum nl80211_band band, bool update)
+ enum nl80211_band band)
{
if (iwl_mvm_has_tlc_offload(mvm)) {
- rs_fw_rate_init(mvm, sta, link_conf, link_sta, band, update);
+ iwl_mvm_rs_fw_rate_init(mvm, vif, sta, link_conf,
+ link_sta, band);
} else {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index f99603b0f693..1ca375a5cf6b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -394,10 +394,12 @@ struct iwl_lq_sta {
((_c) << RS_DRV_DATA_LQ_COLOR_POS)))
/* Initialize station's rate scaling information after adding station */
-void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
- enum nl80211_band band, bool update);
+ enum nl80211_band band);
/* Notify RS about Tx status */
void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
@@ -432,11 +434,18 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm);
#endif
+struct iwl_mvm_link_sta;
+
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta);
-void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- struct ieee80211_bss_conf *link_conf,
- struct ieee80211_link_sta *link_sta,
- enum nl80211_band band, bool update);
+void iwl_mvm_rs_add_sta_link(struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *link_sta);
+
+void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_link_sta *link_sta,
+ enum nl80211_band band);
int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool enable);
void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index e08dca8d2baa..b38b24246675 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -383,9 +383,10 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
* 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 &&
+ if (is_multicast_ether_addr(hdr->addr1) &&
+ vif->type == NL80211_IFTYPE_STATION &&
!mvmvif->authorized &&
- is_multicast_ether_addr(hdr->addr1)) {
+ ieee80211_has_protected(hdr->frame_control)) {
IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n");
kfree_skb(skb);
rcu_read_unlock();
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 5d803e537b00..e1d02c260e69 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -106,28 +106,12 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
/*
* For non monitor interface strip the bytes the RADA might not have
- * removed. As monitor interface cannot exist with other interfaces
- * this removal is safe.
+ * removed (it might be disabled, e.g. for mgmt frames). As a monitor
+ * interface cannot exist with other interfaces, this removal is safe
+ * and sufficient, in monitor mode there's no decryption being done.
*/
- if (mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) {
- u32 pkt_flags = le32_to_cpu(pkt->len_n_flags);
-
- /*
- * If RADA was not enabled then decryption was not performed so
- * the MIC cannot be removed.
- */
- if (!(pkt_flags & FH_RSCSR_RADA_EN)) {
- if (WARN_ON(crypt_len > mic_crc_len))
- return -EINVAL;
-
- mic_crc_len -= crypt_len;
- }
-
- if (WARN_ON(mic_crc_len > len))
- return -EINVAL;
-
+ if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS))
len -= mic_crc_len;
- }
/* If frame is small enough to fit in skb->head, pull it completely.
* If not, only pull ieee80211_hdr (including crypto if present, and
@@ -172,8 +156,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
* Starting from Bz hardware, it calculates starting directly after
* the MAC header, so that matches mac80211's expectation.
*/
- if (skb->ip_summed == CHECKSUM_COMPLETE &&
- mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ) {
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
struct {
u8 hdr[6];
__be16 type;
@@ -188,7 +171,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
shdr->type != htons(ETH_P_PAE) &&
shdr->type != htons(ETH_P_TDLS))))
skb->ip_summed = CHECKSUM_NONE;
- else
+ else if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
/* mac80211 assumes full CSUM including SNAP header */
skb_postpush_rcsum(skb, shdr, sizeof(*shdr));
}
@@ -412,9 +395,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (!(status & IWL_RX_MPDU_STATUS_MIC_OK))
return -1;
- stats->flag |= RX_FLAG_DECRYPTED;
- if (pkt_flags & FH_RSCSR_RADA_EN)
- stats->flag |= RX_FLAG_MIC_STRIPPED;
+ stats->flag |= RX_FLAG_DECRYPTED | RX_FLAG_MIC_STRIPPED;
*crypt_len = IEEE80211_CCMP_HDR_LEN;
return 0;
case IWL_RX_MPDU_STATUS_SEC_TKIP:
@@ -706,7 +687,7 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
if (expired) {
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
- u8 sta_id = baid_data->sta_id;
+ u8 sta_id = ffs(baid_data->sta_mask) - 1;
rcu_read_lock();
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[sta_id]);
@@ -741,6 +722,7 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
struct ieee80211_sta *sta;
struct iwl_mvm_reorder_buffer *reorder_buf;
u8 baid = data->baid;
+ u32 sta_id;
if (WARN_ONCE(baid >= IWL_MAX_BAID, "invalid BAID: %x\n", baid))
return;
@@ -751,7 +733,9 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
if (WARN_ON_ONCE(!ba_data))
goto out;
- sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
+ /* pick any STA ID to find the pointer */
+ sta_id = ffs(ba_data->sta_mask) - 1;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
goto out;
@@ -778,6 +762,7 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
struct ieee80211_sta *sta;
struct iwl_mvm_reorder_buffer *reorder_buf;
struct iwl_mvm_baid_data *ba_data;
+ u32 sta_id;
IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
baid, nssn);
@@ -795,7 +780,9 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
goto out;
}
- sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
+ /* pick any STA ID to find the pointer */
+ sta_id = ffs(ba_data->sta_mask) - 1;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
goto out;
@@ -936,7 +923,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
{
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
- struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_baid_data *baid_data;
struct iwl_mvm_reorder_buffer *buffer;
struct sk_buff *tail;
@@ -948,6 +934,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
u8 sub_frame_idx = desc->amsdu_info &
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
struct iwl_mvm_reorder_buf_entry *entries;
+ u32 sta_mask;
int index;
u16 nssn, sn;
u8 baid;
@@ -970,8 +957,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
"Got valid BAID without a valid station assigned\n"))
return false;
- mvm_sta = iwl_mvm_sta_from_mac80211(sta);
-
/* not a data packet or a bar */
if (!ieee80211_is_back_req(hdr->frame_control) &&
(!ieee80211_is_data_qos(hdr->frame_control) ||
@@ -989,11 +974,14 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
return false;
}
+ rcu_read_lock();
+ sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
+ rcu_read_unlock();
+
if (WARN(tid != baid_data->tid ||
- mvm_sta->deflink.sta_id != baid_data->sta_id,
- "baid 0x%x is mapped to sta:%d tid:%d, but was received for sta:%d tid:%d\n",
- baid, baid_data->sta_id, baid_data->tid, mvm_sta->deflink.sta_id,
- tid))
+ !(sta_mask & baid_data->sta_mask),
+ "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
+ baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))
return false;
nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
@@ -2600,10 +2588,10 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
}
if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc) &&
- likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)))
+ likely(!iwl_mvm_time_sync_frame(mvm, skb, hdr->addr2)) &&
+ likely(!iwl_mvm_mei_filter_scan(mvm, skb)))
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta,
link_sta);
-
out:
rcu_read_unlock();
}
@@ -2777,9 +2765,10 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
goto out;
}
- if (WARN(tid != baid_data->tid || sta_id != baid_data->sta_id,
- "baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\n",
- baid, baid_data->sta_id, baid_data->tid, sta_id,
+ if (WARN(tid != baid_data->tid || sta_id > IWL_MVM_STATION_COUNT_MAX ||
+ !(baid_data->sta_mask & BIT(sta_id)),
+ "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but BAR release received for sta:%d tid:%d\n",
+ baid, baid_data->sta_mask, baid_data->tid, sta_id,
tid))
goto out;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 07045092c717..175615755d9d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -45,6 +45,9 @@
/* minimal number of 2GHz and 5GHz channels in the regular scan request */
#define IWL_MVM_6GHZ_PASSIVE_SCAN_MIN_CHANS 4
+/* Number of iterations on the channel for mei filtered scan */
+#define IWL_MEI_SCAN_NUM_ITER 5U
+
struct iwl_mvm_scan_timing_params {
u32 suspend_time;
u32 max_out_time;
@@ -98,6 +101,7 @@ struct iwl_mvm_scan_params {
bool scan_6ghz;
bool enable_6ghz_passive;
bool respect_p2p_go, respect_p2p_go_hb;
+ u8 bssid[ETH_ALEN] __aligned(2);
};
static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm)
@@ -240,8 +244,9 @@ iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm,
* set all scan requests as fast-balance scan
*/
if (vif && vif->type == NL80211_IFTYPE_STATION &&
- vif->bss_conf.dtim_period < 220 &&
- data.is_dcm_with_p2p_go)
+ data.is_dcm_with_p2p_go &&
+ ((vif->bss_conf.beacon_int *
+ vif->bss_conf.dtim_period) < 220))
return IWL_SCAN_TYPE_FAST_BALANCE;
}
@@ -759,7 +764,7 @@ iwl_mvm_build_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(frame->da);
- eth_broadcast_addr(frame->bssid);
+ ether_addr_copy(frame->bssid, params->bssid);
frame->seq_ctrl = 0;
pos = frame->u.probe_req.variable;
@@ -2081,6 +2086,11 @@ static u8 iwl_mvm_scan_umac_flags2(struct iwl_mvm *mvm,
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB;
}
+ if (params->scan_6ghz &&
+ fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT))
+ flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT;
+
return flags;
}
@@ -2292,7 +2302,7 @@ iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
iwl_mvm_scan_umac_dwell_v11(mvm, gp, params);
- IWL_DEBUG_SCAN(mvm, "Gerenal: flags=0x%x, flags2=0x%x\n",
+ IWL_DEBUG_SCAN(mvm, "General: flags=0x%x, flags2=0x%x\n",
gen_flags, gen_flags2);
gp->flags = cpu_to_le16(gen_flags);
@@ -2617,6 +2627,89 @@ static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
IWL_SCAN_UMAC_HANDLER(12),
};
+static void iwl_mvm_mei_scan_work(struct work_struct *wk)
+{
+ struct iwl_mei_scan_filter *scan_filter =
+ container_of(wk, struct iwl_mei_scan_filter, scan_work);
+ struct iwl_mvm *mvm =
+ container_of(scan_filter, struct iwl_mvm, mei_scan_filter);
+ struct iwl_mvm_csme_conn_info *info;
+ struct sk_buff *skb;
+ u8 bssid[ETH_ALEN];
+
+ mutex_lock(&mvm->mutex);
+ info = iwl_mvm_get_csme_conn_info(mvm);
+ memcpy(bssid, info->conn_info.bssid, ETH_ALEN);
+ mutex_unlock(&mvm->mutex);
+
+ while ((skb = skb_dequeue(&scan_filter->scan_res))) {
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+
+ if (!memcmp(mgmt->bssid, bssid, ETH_ALEN))
+ ieee80211_rx_irqsafe(mvm->hw, skb);
+ else
+ kfree_skb(skb);
+ }
+}
+
+void iwl_mvm_mei_scan_filter_init(struct iwl_mei_scan_filter *mei_scan_filter)
+{
+ skb_queue_head_init(&mei_scan_filter->scan_res);
+ INIT_WORK(&mei_scan_filter->scan_work, iwl_mvm_mei_scan_work);
+}
+
+/* In case CSME is connected and has link protection set, this function will
+ * override the scan request to scan only the associated channel and only for
+ * the associated SSID.
+ */
+static void iwl_mvm_mei_limited_scan(struct iwl_mvm *mvm,
+ struct iwl_mvm_scan_params *params)
+{
+ struct iwl_mvm_csme_conn_info *info = iwl_mvm_get_csme_conn_info(mvm);
+ struct iwl_mei_conn_info *conn_info;
+ struct ieee80211_channel *chan;
+ int scan_iters, i;
+
+ if (!info) {
+ IWL_DEBUG_SCAN(mvm, "mei_limited_scan: no connection info\n");
+ return;
+ }
+
+ conn_info = &info->conn_info;
+ if (!info->conn_info.lp_state || !info->conn_info.ssid_len)
+ return;
+
+ if (!params->n_channels || !params->n_ssids)
+ return;
+
+ mvm->mei_scan_filter.is_mei_limited_scan = true;
+
+ chan = ieee80211_get_channel(mvm->hw->wiphy,
+ ieee80211_channel_to_frequency(conn_info->channel,
+ conn_info->band));
+ if (!chan) {
+ IWL_DEBUG_SCAN(mvm,
+ "Failed to get CSME channel (chan=%u band=%u)\n",
+ conn_info->channel, conn_info->band);
+ return;
+ }
+
+ /* The mei filtered scan must find the AP, otherwise CSME will
+ * take the NIC ownership. Add several iterations on the channel to
+ * make the scan more robust.
+ */
+ scan_iters = min(IWL_MEI_SCAN_NUM_ITER, params->n_channels);
+ params->n_channels = scan_iters;
+ for (i = 0; i < scan_iters; i++)
+ params->channels[i] = chan;
+
+ IWL_DEBUG_SCAN(mvm, "Mei scan: num iterations=%u\n", scan_iters);
+
+ params->n_ssids = 1;
+ params->ssids[0].ssid_len = conn_info->ssid_len;
+ memcpy(params->ssids[0].ssid, conn_info->ssid, conn_info->ssid_len);
+}
+
static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_host_cmd *hcmd,
@@ -2629,6 +2722,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
memset(mvm->scan_cmd, 0, mvm->scan_cmd_size);
+ iwl_mvm_mei_limited_scan(mvm, params);
+
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
hcmd->id = SCAN_OFFLOAD_REQUEST_CMD;
@@ -2795,6 +2890,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
params.pass_all = true;
params.n_match_sets = 0;
params.match_sets = NULL;
+ ether_addr_copy(params.bssid, req->bssid);
params.scan_plans = &scan_plan;
params.n_scan_plans = 1;
@@ -2888,6 +2984,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
params.pass_all = iwl_mvm_scan_pass_all(mvm, req);
params.n_match_sets = req->n_match_sets;
params.match_sets = req->match_sets;
+ eth_broadcast_addr(params.bssid);
if (!req->n_scan_plans)
return -EINVAL;
@@ -2983,6 +3080,8 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
u32 uid = __le32_to_cpu(notif->uid);
bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED);
+ mvm->mei_scan_filter.is_mei_limited_scan = false;
+
if (WARN_ON(!(mvm->scan_uid_status[uid] & mvm->scan_status)))
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index 7c5f41e40e7a..98f330fcf678 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -8,7 +8,7 @@
/* For counting bound interfaces */
struct iwl_mvm_active_iface_iterator_data {
struct ieee80211_vif *ignore_vif;
- u8 sta_vif_ap_sta_id;
+ struct ieee80211_sta *sta_vif_ap_sta;
enum iwl_sf_state sta_vif_state;
u32 num_active_macs;
};
@@ -30,7 +30,7 @@ static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
data->num_active_macs++;
if (vif->type == NL80211_IFTYPE_STATION) {
- data->sta_vif_ap_sta_id = mvmvif->deflink.ap_sta_id;
+ data->sta_vif_ap_sta = mvmvif->ap_sta;
if (vif->cfg.assoc)
data->sta_vif_state = SF_FULL_ON;
else
@@ -172,13 +172,12 @@ static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
}
}
-static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
+static int iwl_mvm_sf_config(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum iwl_sf_state new_state)
{
struct iwl_sf_cfg_cmd sf_cmd = {
.state = cpu_to_le32(new_state),
};
- struct ieee80211_sta *sta;
int ret = 0;
if (mvm->cfg->disable_dummy_notification)
@@ -196,20 +195,12 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
break;
case SF_FULL_ON:
- if (sta_id == IWL_MVM_INVALID_STA) {
+ if (!sta) {
IWL_ERR(mvm,
"No station: Cannot switch SF to FULL_ON\n");
return -EINVAL;
}
- rcu_read_lock();
- sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
- if (IS_ERR_OR_NULL(sta)) {
- IWL_ERR(mvm, "Invalid station id\n");
- rcu_read_unlock();
- return -EINVAL;
- }
iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta);
- rcu_read_unlock();
break;
case SF_INIT_OFF:
iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
@@ -237,13 +228,12 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
bool remove_vif)
{
enum iwl_sf_state new_state;
- u8 sta_id = IWL_MVM_INVALID_STA;
struct iwl_mvm_vif *mvmvif = NULL;
struct iwl_mvm_active_iface_iterator_data data = {
.ignore_vif = changed_vif,
.sta_vif_state = SF_UNINIT,
- .sta_vif_ap_sta_id = IWL_MVM_INVALID_STA,
};
+ struct ieee80211_sta *sta = NULL;
/*
* Ignore the call if we are in HW Restart flow, or if the handled
@@ -273,7 +263,7 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
* and we filled the relevant data during iteration
*/
new_state = data.sta_vif_state;
- sta_id = data.sta_vif_ap_sta_id;
+ sta = data.sta_vif_ap_sta;
} else {
if (WARN_ON(!changed_vif))
return -EINVAL;
@@ -282,7 +272,7 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
} else if (changed_vif->cfg.assoc &&
changed_vif->bss_conf.dtim_period) {
mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
- sta_id = mvmvif->deflink.ap_sta_id;
+ sta = mvmvif->ap_sta;
new_state = SF_FULL_ON;
} else {
new_state = SF_INIT_OFF;
@@ -294,8 +284,5 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
new_state = SF_UNINIT;
}
- /* For MLO it's ok to use deflink->sta_id as it's needed only to get
- * a pointer to mac80211 sta
- */
- return iwl_mvm_sf_config(mvm, sta_id, new_state);
+ return iwl_mvm_sf_config(mvm, sta, new_state);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 50e224883af0..5469d634e289 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -251,6 +251,7 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvm_sta;
unsigned long timeout;
+ unsigned int sta_id;
rcu_read_lock();
@@ -269,7 +270,8 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
}
/* Timer expired */
- sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[ba_data->sta_id]);
+ sta_id = ffs(ba_data->sta_mask) - 1; /* don't care which one */
+ sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[sta_id]);
/*
* sta should be valid unless the following happens:
@@ -356,10 +358,14 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
SCD_QUEUE_CONFIG_CMD);
struct iwl_scd_queue_cfg_cmd remove_cmd = {
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
- .u.remove.tid = cpu_to_le32(tid),
.u.remove.sta_mask = cpu_to_le32(BIT(sta_id)),
};
+ if (tid == IWL_MAX_TID_COUNT)
+ tid = IWL_MGMT_TID;
+
+ remove_cmd.u.remove.tid = cpu_to_le32(tid);
+
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,
sizeof(remove_cmd),
&remove_cmd);
@@ -2146,7 +2152,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
sta->type = type;
/* put a non-NULL value so iterating over the stations won't stop */
- rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL));
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL));
return 0;
}
@@ -2227,11 +2233,13 @@ static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm, u32 lmac_id)
{
int ret;
+ u32 qmask = mvm->aux_queue == IWL_MVM_INVALID_QUEUE ? 0 :
+ BIT(mvm->aux_queue);
lockdep_assert_held(&mvm->mutex);
/* Allocate aux station and assign to it the aux queue */
- ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
+ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, qmask,
NL80211_IFTYPE_UNSPECIFIED,
IWL_STA_AUX_ACTIVITY);
if (ret)
@@ -2750,10 +2758,11 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
}
static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta,
+ struct ieee80211_sta *sta,
bool start, int tid, u16 ssn,
u16 buf_size)
{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_add_sta_cmd cmd = {
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
.sta_id = mvm_sta->deflink.sta_id,
@@ -2798,7 +2807,7 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm,
}
static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
- struct iwl_mvm_sta *mvm_sta,
+ struct ieee80211_sta *sta,
bool start, int tid, u16 ssn,
u16 buf_size, int baid)
{
@@ -2813,7 +2822,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
if (start) {
cmd.alloc.sta_id_mask =
- cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
+ cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));
cmd.alloc.tid = tid;
cmd.alloc.ssn = cpu_to_le16(ssn);
cmd.alloc.win_size = cpu_to_le16(buf_size);
@@ -2823,7 +2832,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove));
} else {
cmd.remove.sta_id_mask =
- cpu_to_le32(BIT(mvm_sta->deflink.sta_id));
+ cpu_to_le32(iwl_mvm_sta_fw_id_mask(mvm, sta, -1));
cmd.remove.tid = cpu_to_le32(tid);
}
@@ -2846,16 +2855,16 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm,
return baid;
}
-static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta,
+static int iwl_mvm_fw_baid_op(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool start, int tid, u16 ssn, u16 buf_size,
int baid)
{
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BAID_ML_SUPPORT))
- return iwl_mvm_fw_baid_op_cmd(mvm, mvm_sta, start,
+ return iwl_mvm_fw_baid_op_cmd(mvm, sta, start,
tid, ssn, buf_size, baid);
- return iwl_mvm_fw_baid_op_sta(mvm, mvm_sta, start,
+ return iwl_mvm_fw_baid_op_sta(mvm, sta, start,
tid, ssn, buf_size);
}
@@ -2925,7 +2934,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* Don't send command to remove (start=0) BAID during restart */
if (start || !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
- baid = iwl_mvm_fw_baid_op(mvm, mvm_sta, start, tid, ssn, buf_size,
+ baid = iwl_mvm_fw_baid_op(mvm, sta, start, tid, ssn, buf_size,
baid);
if (baid < 0) {
@@ -2947,7 +2956,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
iwl_mvm_rx_agg_session_expired, 0);
baid_data->mvm = mvm;
baid_data->tid = tid;
- baid_data->sta_id = mvm_sta->deflink.sta_id;
+ baid_data->sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
mvm_sta->tid_to_baid[tid] = baid;
if (timeout)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 7b9e91935aa0..a61d4f88125f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -356,6 +356,7 @@ struct iwl_mvm_link_sta {
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
* @sta_type: station type
+ * @authorized: indicates station is authorized
* @sta_state: station state according to enum %ieee80211_sta_state
* @bt_reduced_txpower: is reduced tx power enabled for this station
* @next_status_eosp: the next reclaimed packet is a PS-Poll response and
@@ -409,6 +410,7 @@ struct iwl_mvm_sta {
enum ieee80211_sta_state sta_state;
bool bt_reduced_txpower;
bool next_status_eosp;
+ bool authorized;
spinlock_t lock;
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT + 1];
u8 tid_to_baid[IWL_MAX_TID_COUNT];
@@ -642,6 +644,8 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
u16 old_links, u16 new_links);
+u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int filter_link_id);
/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 2c842938656d..10d7178f1071 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -184,10 +184,7 @@ static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
bool amsdu)
{
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ ||
- (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
- CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- mvm->trans->hw_rev_step == SILICON_A_STEP))
+ if (!iwl_mvm_has_new_tx_csum(mvm))
return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu);
return iwl_mvm_tx_csum_bz(mvm, skb, amsdu);
}
@@ -332,22 +329,23 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
sta ? iwl_mvm_sta_from_mac80211(sta)->sta_state : -1);
rate_idx = info->control.rates[0].idx;
+
+ /* For non 2 GHZ band, remap mac80211 rate indices into driver
+ * indices.
+ */
+ if (info->band != NL80211_BAND_2GHZ ||
+ (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
+ rate_idx += IWL_FIRST_OFDM_RATE;
+
+ /* For 2.4 GHZ band, check that there is no need to remap */
+ BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
}
/* if the rate isn't a well known legacy rate, take the lowest one */
if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY)
- rate_idx = rate_lowest_index(
- &mvm->nvm_data->bands[info->band], sta);
-
- /*
- * For non 2 GHZ band, remap mac80211 rate
- * indices into driver indices
- */
- if (info->band != NL80211_BAND_2GHZ)
- rate_idx += IWL_FIRST_OFDM_RATE;
-
- /* For 2.4 GHZ band, check that there is no need to remap */
- BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
+ rate_idx = iwl_mvm_mac_ctxt_get_lowest_rate(mvm,
+ info,
+ info->control.vif);
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate_idx);
@@ -606,8 +604,9 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
struct iwl_mvm_vif_link_info *link,
struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr)
+ struct sk_buff *skb)
{
+ struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
switch (info->control.vif->type) {
@@ -624,7 +623,7 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
* reason 7 ("Class 3 frame received from nonassociated STA").
*/
if (ieee80211_is_mgmt(fc) &&
- (!ieee80211_is_bufferable_mmpdu(fc) ||
+ (!ieee80211_is_bufferable_mmpdu(skb) ||
ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
return link->mgmt_queue;
@@ -757,7 +756,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
sta_id = link->mcast_sta.sta_id;
queue = iwl_mvm_get_ctrl_vif_queue(mvm, link, &info,
- hdr);
+ skb);
} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
queue = mvm->snif_queue;
sta_id = mvm->snif_sta.sta_id;
@@ -805,10 +804,11 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, unsigned int tid)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- enum nl80211_band band = mvmsta->vif->bss_conf.chandef.chan->band;
u8 ac = tid_to_mac80211_ac[tid];
+ enum nl80211_band band;
unsigned int txf;
- int lmac = iwl_mvm_get_lmac_id(mvm->fw, band);
+ unsigned int val;
+ int lmac;
/* For HE redirect to trigger based fifos */
if (sta->deflink.he_cap.has_he && !WARN_ON(!iwl_mvm_has_new_tx_api(mvm)))
@@ -822,7 +822,37 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
* We also want to have the start of the next packet inside the
* fifo to be able to send bursts.
*/
- return min_t(unsigned int, mvmsta->max_amsdu_len,
+ val = mvmsta->max_amsdu_len;
+
+ if (hweight16(sta->valid_links) <= 1) {
+ if (sta->valid_links) {
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link = ffs(sta->valid_links) - 1;
+
+ rcu_read_lock();
+ link_conf = rcu_dereference(mvmsta->vif->link_conf[link]);
+ if (WARN_ON(!link_conf))
+ band = NL80211_BAND_2GHZ;
+ else
+ band = link_conf->chandef.chan->band;
+ rcu_read_unlock();
+ } else {
+ band = mvmsta->vif->bss_conf.chandef.chan->band;
+ }
+
+ lmac = iwl_mvm_get_lmac_id(mvm->fw, band);
+ } else if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) {
+ /* for real MLO restrict to both LMACs if they exist */
+ lmac = IWL_LMAC_5G_INDEX;
+ val = min_t(unsigned int, val,
+ mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
+ lmac = IWL_LMAC_24G_INDEX;
+ } else {
+ lmac = IWL_LMAC_24G_INDEX;
+ }
+
+ return min_t(unsigned int, val,
mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256);
}
@@ -1256,8 +1286,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ret)
return ret;
- if (WARN_ON(skb_queue_empty(&mpdus_skbs)))
- return ret;
+ WARN_ON(skb_queue_empty(&mpdus_skbs));
while (!skb_queue_empty(&mpdus_skbs)) {
skb = __skb_dequeue(&mpdus_skbs);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 6c935d73943a..dba112394838 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -504,6 +504,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
/* Bz devices */
{IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)},
+ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)},
#endif /* CONFIG_IWLMVM */
@@ -513,16 +514,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
- _rf_id, _no_160, _cores, _cdb, _jacket, _cfg, _name) \
- { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
- .name = _name, .mac_type = _mac_type, .rf_type = _rf_type, \
- .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
+ _rf_id, _rf_step, _no_160, _cores, _cdb, _jacket, _cfg, \
+ _name) \
+ { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
+ .name = _name, .mac_type = _mac_type, .rf_type = _rf_type, .rf_step = _rf_step, \
+ .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
.mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket }
#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
- _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name)
+ _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name)
static const struct iwl_dev_info iwl_dev_info_table[] = {
#if IS_ENABLED(CONFIG_IWLMVM)
@@ -565,7 +567,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650i_name),
IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
- IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650s_name),
IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
@@ -694,87 +695,87 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_2ac_cfg_soc, iwl9560_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9461_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9461_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9462_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9462_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9270_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9270_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9162_160_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9162_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9260_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9260_2ac_cfg, iwl9260_name),
@@ -782,176 +783,176 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
/* Qu B step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* QnJ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
@@ -959,397 +960,408 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
/* Qu B step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qu_b0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qu_b0_hr_b0, iwl_ax203_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qu_c0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qu_c0_hr_b0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qu_c0_hr_b0, iwl_ax201_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_quz_a0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_quz_a0_hr_b0, iwl_ax203_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_quz_a0_hr_b0, iwl_ax201_name),
/* QnJ with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name),
/* SnJ with Jf */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_jf_b0, iwl9560_name),
/* SnJ with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_hr_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_hr_b0, iwl_ax201_name),
/* Ma */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_hr_b0, iwl_ax201_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_gf4_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_mr_a0, iwl_ax221_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_fm_a0, iwl_ax231_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_mr_a0, iwl_ax221_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_ma_b0_hr_b0, iwl_ax201_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_ma_b0_gf_a0, iwl_ax211_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
+ iwl_cfg_ma_b0_gf4_a0, iwl_ax211_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_ma_b0_mr_a0, iwl_ax221_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_ma_b0_fm_a0, iwl_ax231_name),
/* So with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Gf */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* Bz */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_bz_a0_hr_a0, iwl_bz_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bz_a0_hr_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bz_a0_gf_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
iwl_cfg_bz_a0_gf4_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bz_a0_mr_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bz_a0_fm_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_NO_JACKET,
iwl_cfg_bz_a0_fm4_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bz_a0_fm_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bz_a0_fm4_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
iwl_cfg_gl_b0_fm_b0, iwl_bz_name),
/* BZ Z step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bz_z0_gf_a0, iwl_bz_name),
/* BNJ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_a0_fm_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_b0_fm_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_a0_fm4_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_b0_fm4_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_a0_gf_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_b0_gf_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_a0_gf4_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
iwl_cfg_bnj_b0_gf4_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_bnj_a0_hr_a0, iwl_bz_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_bnj_a0_hr_b0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_bnj_b0_hr_b0, iwl_bz_name),
-
-/* SoF with JF2 */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
-
-/* SoF with JF */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+ IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_bnj_b0_hr_a0, iwl_bz_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
+ IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ iwl_cfg_bnj_b0_hr_b0, iwl_bz_name),
/* SoF with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* SoF with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* So with GF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* So with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+ IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* So with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+ IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
@@ -1357,22 +1369,22 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
/* For now we use the same FW as MR, but this will change in the future. */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_ma_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
iwl_cfg_snj_a0_ms_a0, iwl_ax204_name)
@@ -1407,8 +1419,16 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
/* Read crf info */
iwl_trans->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
+ /* Read cnv info */
+ iwl_trans->hw_cnv_id =
+ iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
+
/* Read cdb info (also contains the jacket info if needed in the future */
- iwl_trans->hw_cdb_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
+ iwl_trans->hw_wfpm_id =
+ iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
+ IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n",
+ iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id,
+ iwl_trans->hw_wfpm_id);
iwl_trans_release_nic_access(iwl_trans);
@@ -1424,7 +1444,11 @@ static int map_crf_id(struct iwl_trans *iwl_trans)
{
int ret = 0;
u32 val = iwl_trans->hw_crf_id;
- u32 cdb = iwl_trans->hw_cdb_id;
+ u32 step_id = REG_CRF_ID_STEP(val);
+ u32 slave_id = REG_CRF_ID_SLAVE(val);
+ u32 jacket_id_cnv = REG_CRF_ID_SLAVE(iwl_trans->hw_cnv_id);
+ u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(iwl_trans->hw_wfpm_id);
+ u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(iwl_trans->hw_wfpm_id);
/* Map between crf id to rf id */
switch (REG_CRF_ID_TYPE(val)) {
@@ -1434,9 +1458,12 @@ static int map_crf_id(struct iwl_trans *iwl_trans)
case REG_CRF_ID_TYPE_JF_2:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
break;
- case REG_CRF_ID_TYPE_HR_NONE_CDB:
+ case REG_CRF_ID_TYPE_HR_NONE_CDB_1X1:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
break;
+ case REG_CRF_ID_TYPE_HR_NONE_CDB:
+ iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
+ break;
case REG_CRF_ID_TYPE_HR_CDB:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
break;
@@ -1446,27 +1473,43 @@ static int map_crf_id(struct iwl_trans *iwl_trans)
case REG_CRF_ID_TYPE_MR:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12);
break;
- case REG_CRF_ID_TYPE_FM:
- iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
- break;
+ case REG_CRF_ID_TYPE_FM:
+ case REG_CRF_ID_TYPE_FMI:
+ case REG_CRF_ID_TYPE_FMR:
+ iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
+ break;
default:
ret = -EIO;
IWL_ERR(iwl_trans,
- "Can find a correct rfid for crf id 0x%x\n",
+ "Can't find a correct rfid for crf id 0x%x\n",
REG_CRF_ID_TYPE(val));
goto out;
}
+ /* Set Step-id */
+ iwl_trans->hw_rf_id |= (step_id << 8);
+
/* Set CDB capabilities */
- if (cdb & BIT(4)) {
+ if (cdb_id_wfpm || slave_id) {
iwl_trans->hw_rf_id += BIT(28);
IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
}
- IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n",
- iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val));
+ /* Set Jacket capabilities */
+ if (jacket_id_wfpm || jacket_id_cnv) {
+ iwl_trans->hw_rf_id += BIT(29);
+ IWL_INFO(iwl_trans, "Adding jacket to rf id\n");
+ }
+ IWL_INFO(iwl_trans,
+ "Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n",
+ REG_CRF_ID_TYPE(val), step_id, slave_id, iwl_trans->hw_rf_id);
+ IWL_INFO(iwl_trans,
+ "Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n",
+ cdb_id_wfpm, jacket_id_wfpm, iwl_trans->hw_wfpm_id);
+ IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n",
+ jacket_id_cnv, iwl_trans->hw_cnv_id);
out:
return ret;
@@ -1477,8 +1520,8 @@ out:
static const struct iwl_dev_info *
iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
- u16 mac_type, u8 mac_step,
- u16 rf_type, u8 cdb, u8 jacket, u8 rf_id, u8 no_160, u8 cores)
+ u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
+ u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step)
{
int num_devices = ARRAY_SIZE(iwl_dev_info_table);
int i;
@@ -1529,6 +1572,10 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
dev_info->cores != cores)
continue;
+ if (dev_info->rf_step != (u8)IWL_CFG_ANY &&
+ dev_info->rf_step != rf_step)
+ continue;
+
return dev_info;
}
@@ -1600,6 +1647,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_free_trans;
}
+ IWL_INFO(iwl_trans, "PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
+ pdev->device, pdev->subsystem_device,
+ iwl_trans->hw_rev, iwl_trans->hw_rf_id);
+
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
CSR_HW_REV_TYPE(iwl_trans->hw_rev),
iwl_trans->hw_rev_step,
@@ -1608,8 +1659,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
CSR_HW_RFID_IS_JACKET(iwl_trans->hw_rf_id),
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
IWL_SUBDEVICE_NO_160(pdev->subsystem_device),
- IWL_SUBDEVICE_CORES(pdev->subsystem_device));
-
+ IWL_SUBDEVICE_CORES(pdev->subsystem_device),
+ CSR_HW_RFID_STEP(iwl_trans->hw_rf_id));
if (dev_info) {
iwl_trans->cfg = dev_info->cfg;
iwl_trans->name = dev_info->name;
@@ -1729,6 +1780,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_trans *trans = pci_get_drvdata(pdev);
+ if (!trans)
+ return;
+
iwl_drv_stop(trans->drv);
iwl_trans_pcie_free(trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index f7e4f868363d..69b95ad5993b 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -497,6 +497,7 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans);
void iwl_pcie_rx_free(struct iwl_trans *trans);
void iwl_pcie_free_rbs_pool(struct iwl_trans *trans);
void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq);
+void iwl_pcie_rx_napi_sync(struct iwl_trans *trans);
void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
struct iwl_rxq *rxq);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 9c9f87fe8377..0d7890f99a5f 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -1053,6 +1053,22 @@ static int iwl_pcie_napi_poll_msix(struct napi_struct *napi, int budget)
return ret;
}
+void iwl_pcie_rx_napi_sync(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int i;
+
+ if (unlikely(!trans_pcie->rxq))
+ return;
+
+ for (i = 0; i < trans->num_rx_queues; i++) {
+ struct iwl_rxq *rxq = &trans_pcie->rxq[i];
+
+ if (rxq && rxq->napi.poll)
+ napi_synchronize(&rxq->napi);
+ }
+}
+
static int _iwl_pcie_rx_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 1e263154e9eb..73b395841ca8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -156,6 +156,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans,
"DEVICE_ENABLED bit was set and is now cleared\n");
+ iwl_pcie_rx_napi_sync(trans);
iwl_txq_gen2_tx_free(trans);
iwl_pcie_rx_stop(trans);
}
@@ -350,7 +351,7 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr)
mutex_unlock(&trans_pcie->mutex);
}
-static void iwl_pcie_set_ltr(struct iwl_trans *trans)
+static bool iwl_pcie_set_ltr(struct iwl_trans *trans)
{
u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |
u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
@@ -371,18 +372,77 @@ static void iwl_pcie_set_ltr(struct iwl_trans *trans)
trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) &&
!trans->trans_cfg->integrated) {
iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val);
- } else if (trans->trans_cfg->integrated &&
- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
+ return true;
+ }
+
+ if (trans->trans_cfg->integrated &&
+ trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) {
iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL);
iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val);
+ return true;
+ }
+
+ if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+ /* First clear the interrupt, just in case */
+ iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
+ MSIX_HW_INT_CAUSES_REG_IML);
+ /* In this case, unfortunately the same ROM bug exists in the
+ * device (not setting LTR correctly), but we don't have control
+ * over the settings from the host due to some hardware security
+ * features. The only workaround we've been able to come up with
+ * so far is to try to keep the CPU and device busy by polling
+ * it and the IML (image loader) completed interrupt.
+ */
+ return false;
+ }
+
+ /* nothing needs to be done on other devices */
+ return true;
+}
+
+static void iwl_pcie_spin_for_iml(struct iwl_trans *trans)
+{
+/* in practice, this seems to complete in around 20-30ms at most, wait 100 */
+#define IML_WAIT_TIMEOUT (HZ / 10)
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ unsigned long end_time = jiffies + IML_WAIT_TIMEOUT;
+ u32 value, loops = 0;
+ bool irq = false;
+
+ if (WARN_ON(!trans_pcie->iml))
+ return;
+
+ value = iwl_read32(trans, CSR_LTR_LAST_MSG);
+ IWL_DEBUG_INFO(trans, "Polling for IML load - CSR_LTR_LAST_MSG=0x%x\n",
+ value);
+
+ while (time_before(jiffies, end_time)) {
+ if (iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD) &
+ MSIX_HW_INT_CAUSES_REG_IML) {
+ irq = true;
+ break;
+ }
+ /* Keep the CPU and device busy. */
+ value = iwl_read32(trans, CSR_LTR_LAST_MSG);
+ loops++;
}
+
+ IWL_DEBUG_INFO(trans,
+ "Polled for IML load: irq=%d, loops=%d, CSR_LTR_LAST_MSG=0x%x\n",
+ irq, loops, value);
+
+ /* We don't fail here even if we timed out - maybe we get lucky and the
+ * interrupt comes in later (and we get alive from firmware) and then
+ * we're all happy - but if not we'll fail on alive timeout or get some
+ * other error out.
+ */
}
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
const struct fw_img *fw, bool run_in_rfkill)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- bool hw_rfkill;
+ bool hw_rfkill, keep_ram_busy;
int ret;
/* This may fail if AMT took ownership of the device */
@@ -443,7 +503,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
if (ret)
goto out;
- iwl_pcie_set_ltr(trans);
+ keep_ram_busy = !iwl_pcie_set_ltr(trans);
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);
@@ -455,6 +515,9 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);
}
+ if (keep_ram_busy)
+ iwl_pcie_spin_for_iml(trans);
+
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 0a9af1ad1f20..b281850fbf7a 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -599,7 +599,6 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
{
int ret;
- int t = 0;
int iter;
IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
@@ -616,6 +615,8 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
usleep_range(1000, 2000);
for (iter = 0; iter < 10; iter++) {
+ int t = 0;
+
/* If HW is not ready, prepare the conditions to check again */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PREPARE);
@@ -1260,6 +1261,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans,
"DEVICE_ENABLED bit was set and is now cleared\n");
+ iwl_pcie_rx_napi_sync(trans);
iwl_pcie_tx_stop(trans);
iwl_pcie_rx_stop(trans);
@@ -1522,19 +1524,16 @@ static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+ if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND :
UREG_DOORBELL_TO_ISR6_RESUME);
- } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
iwl_write32(trans, CSR_IPC_SLEEP_CONTROL,
suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND :
CSR_IPC_SLEEP_CONTROL_RESUME);
- iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
- UREG_DOORBELL_TO_ISR6_SLEEP_CTRL);
- } else {
+ else
return 0;
- }
ret = wait_event_timeout(trans_pcie->sx_waitq,
trans_pcie->sx_complete, 2 * HZ);
@@ -2863,7 +2862,7 @@ static bool iwl_write_to_user_buf(char __user *user_buf, ssize_t count,
void *buf, ssize_t *size,
ssize_t *bytes_copied)
{
- int buf_size_left = count - *bytes_copied;
+ ssize_t buf_size_left = count - *bytes_copied;
buf_size_left = buf_size_left - (buf_size_left % sizeof(u32));
if (*size > buf_size_left)
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
index 726185d6fab8..d1c39c214f95 100644
--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
@@ -1554,14 +1554,18 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs)
{
struct iwl_txq *txq = trans->txqs.txq[txq_id];
- int tfd_num = iwl_txq_get_cmd_index(txq, ssn);
- int read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr);
- int last_to_free;
+ int tfd_num, read_ptr, last_to_free;
/* This function is not meant to release cmd queue*/
if (WARN_ON(txq_id == trans->txqs.cmd.q_id))
return;
+ if (WARN_ON(!txq))
+ return;
+
+ tfd_num = iwl_txq_get_cmd_index(txq, ssn);
+ read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr);
+
spin_lock_bh(&txq->lock);
if (!test_bit(txq_id, trans->txqs.queue_used)) {
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index da281cd1d36f..465190ebaf1c 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -402,8 +402,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
*info = le32_to_cpu(desc->info);
if (mt76_queue_is_wed_rx(q)) {
- u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
- le32_to_cpu(desc->buf1));
+ u32 buf1 = le32_to_cpu(desc->buf1);
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
if (!t)
@@ -424,6 +424,8 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
MT_DMA_CTL_DROP));
+
+ *drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
}
} else {
buf = e->buf;
@@ -576,7 +578,9 @@ free:
free_skb:
status.skb = tx_info.skb;
hw = mt76_tx_status_get_hw(dev, tx_info.skb);
+ spin_lock_bh(&dev->rx_lock);
ieee80211_tx_status_ext(hw, &status);
+ spin_unlock_bh(&dev->rx_lock);
return ret;
}
@@ -849,7 +853,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
!(dev->drv->rx_check(dev, data, len)))
goto free_frag;
- skb = build_skb(data, q->buf_size);
+ skb = napi_build_skb(data, q->buf_size);
if (!skb)
goto free_frag;
diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h
index 4b9bc7f462b8..1b090d78cd05 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.h
+++ b/drivers/net/wireless/mediatek/mt76/dma.h
@@ -19,6 +19,7 @@
#define MT_DMA_CTL_TO_HOST_A BIT(12)
#define MT_DMA_CTL_DROP BIT(14)
#define MT_DMA_CTL_TOKEN GENMASK(31, 16)
+#define MT_DMA_CTL_WO_DROP BIT(8)
#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
#define MT_DMA_PPE_ENTRY GENMASK(30, 16)
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 34abf70f44af..467afef98ba2 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -418,7 +418,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
SET_IEEE80211_DEV(hw, dev->dev);
SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
- wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
+ wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
+ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_AP_UAPSD;
@@ -1066,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
status->enc_flags = mstat.enc_flags;
status->encoding = mstat.encoding;
status->bw = mstat.bw;
- status->he_ru = mstat.he_ru;
- status->he_gi = mstat.he_gi;
- status->he_dcm = mstat.he_dcm;
+ if (status->encoding == RX_ENC_EHT) {
+ status->eht.ru = mstat.eht.ru;
+ status->eht.gi = mstat.eht.gi;
+ } else {
+ status->he_ru = mstat.he_ru;
+ status->he_gi = mstat.he_gi;
+ status->he_dcm = mstat.he_dcm;
+ }
status->rate_idx = mstat.rate_idx;
status->nss = mstat.nss;
status->band = mstat.band;
@@ -1303,7 +1309,8 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
if (ps)
set_bit(MT_WCID_FLAG_PS, &wcid->flags);
- dev->drv->sta_ps(dev, sta, ps);
+ if (dev->drv->sta_ps)
+ dev->drv->sta_ps(dev, sta, ps);
if (!ps)
clear_bit(MT_WCID_FLAG_PS, &wcid->flags);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 183b0fc5a2d4..6b07b8fafec2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -621,12 +621,22 @@ struct mt76_rx_status {
u16 freq;
u32 flag;
u8 enc_flags;
- u8 encoding:2, bw:3, he_ru:3;
- u8 he_gi:2, he_dcm:1;
+ u8 encoding:3, bw:4;
+ union {
+ struct {
+ u8 he_ru:3;
+ u8 he_gi:2;
+ u8 he_dcm:1;
+ };
+ struct {
+ u8 ru:4;
+ u8 gi:2;
+ } eht;
+ };
+
u8 amsdu:1, first_amsdu:1, last_amsdu:1;
u8 rate_idx;
- u8 nss;
- u8 band;
+ u8 nss:5, band:3;
s8 signal;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
@@ -778,6 +788,7 @@ struct mt76_dev {
spinlock_t rx_lock;
struct napi_struct napi[__MT_RXQ_MAX];
struct sk_buff_head rx_skb[__MT_RXQ_MAX];
+ struct tasklet_struct irq_tasklet;
struct list_head txwi_cache;
struct list_head rxwi_cache;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index 70a7f84af028..12e0af52082a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1279,8 +1279,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
if (wcidx >= MT7603_WTBL_STA || !sta)
goto out;
- if (mt7603_fill_txs(dev, msta, &info, txs_data))
+ if (mt7603_fill_txs(dev, msta, &info, txs_data)) {
+ spin_lock_bh(&dev->mt76.rx_lock);
ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
+ spin_unlock_bh(&dev->mt76.rx_lock);
+ }
out:
rcu_read_unlock();
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
index f1914431ff7f..0ce01ccc5dce 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
@@ -76,7 +76,8 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
if (napi_complete(napi))
- mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev));
+ mt76_connac_irq_enable(&dev->mt76,
+ mt7615_tx_mcu_int_mask(dev));
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
@@ -297,7 +298,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
else
mask |= MT_INT_MCU_CMD;
- mt7615_irq_enable(dev, mask);
+ mt76_connac_irq_enable(&dev->mt76, mask);
mt7615_dma_start(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
index 6dbaaf95ee38..68e88224b8b1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
@@ -47,6 +47,9 @@ static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
void *buf;
u32 val;
+ if (is_mt7663(&dev->mt76))
+ len = MT7663_EEPROM_SIZE;
+
val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
if (val & MT_EFUSE_BASE_CTRL_EMPTY)
return 0;
@@ -72,6 +75,8 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
{
int ret;
+ BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE);
+
ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
if (ret < 0)
return ret;
@@ -336,7 +341,7 @@ int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
ret = mt7615_check_eeprom(&dev->mt76);
if (ret && dev->mt76.otp.data) {
memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
- MT7615_EEPROM_SIZE);
+ dev->mt76.otp.size);
} else {
dev->flash_eeprom = true;
mt7615_cal_free_data(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
index a024dee10362..a67fbb90f5b3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h
@@ -46,7 +46,7 @@ enum mt7615_eeprom_field {
MT7615_EE_MAX = 0x3bf,
MT7622_EE_MAX = 0x3db,
- MT7663_EE_MAX = 0x400,
+ MT7663_EE_MAX = 0x600,
};
#define MT_EE_RATE_POWER_MASK GENMASK(5, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 5fa6f097ec30..621e69f07e3c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -396,6 +396,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 51a968a6afdc..da1d17b73a25 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -655,11 +655,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
return 0;
}
-void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
-{
-}
-EXPORT_SYMBOL_GPL(mt7615_sta_ps);
-
static u16
mt7615_mac_tx_rate_val(struct mt7615_dev *dev,
struct mt76_phy *mphy,
@@ -1530,8 +1525,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
if (wcid->phy_idx && dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
- if (mt7615_fill_txs(dev, msta, &info, txs_data))
+ if (mt7615_fill_txs(dev, msta, &info, txs_data)) {
+ spin_lock_bh(&dev->mt76.rx_lock);
ieee80211_tx_status_noskb(mphy->hw, sta, &info);
+ spin_unlock_bh(&dev->mt76.rx_lock);
+ }
out:
rcu_read_unlock();
@@ -2352,7 +2350,7 @@ void mt7615_coredump_work(struct work_struct *work)
break;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
- if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
+ if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {
dev_kfree_skb(skb);
continue;
}
@@ -2362,6 +2360,8 @@ void mt7615_coredump_work(struct work_struct *work)
dev_kfree_skb(skb);
}
- dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
- GFP_KERNEL);
+
+ if (dump)
+ dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
+ GFP_KERNEL);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
index 880c9f74a7f1..d08fbe64c262 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h
@@ -19,18 +19,6 @@
#define MT_RXD0_NORMAL_GROUP_3 BIT(27)
#define MT_RXD0_NORMAL_GROUP_4 BIT(28)
-enum rx_pkt_type {
- PKT_TYPE_TXS,
- PKT_TYPE_TXRXV,
- PKT_TYPE_NORMAL,
- PKT_TYPE_RX_DUP_RFB,
- PKT_TYPE_RX_TMR,
- PKT_TYPE_RETRIEVE,
- PKT_TYPE_TXRX_NOTIFY,
- PKT_TYPE_RX_EVENT,
- PKT_TYPE_NORMAL_MCU,
-};
-
#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index eea398c79a98..8d745c9730c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -163,16 +163,16 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(OFFLOAD) ||
cmd == MCU_UNI_CMD(SUSPEND)) {
- struct mt7615_mcu_uni_event *event;
+ struct mt76_connac_mcu_uni_event *event;
skb_pull(skb, sizeof(*rxd));
- event = (struct mt7615_mcu_uni_event *)skb->data;
+ event = (struct mt76_connac_mcu_uni_event *)skb->data;
ret = le32_to_cpu(event->status);
} else if (cmd == MCU_CE_QUERY(REG_READ)) {
- struct mt7615_mcu_reg_event *event;
+ struct mt76_connac_mcu_reg_event *event;
skb_pull(skb, sizeof(*rxd));
- event = (struct mt7615_mcu_reg_event *)skb->data;
+ event = (struct mt76_connac_mcu_reg_event *)skb->data;
ret = (int)le32_to_cpu(event->val);
}
@@ -861,7 +861,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
else
mvif->sta_added = true;
}
- mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, new_entry);
+ mt76_connac_mcu_sta_basic_tlv(&dev->mt76, sskb, vif, sta, enable,
+ new_entry);
if (enable && sta)
mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
MT76_STA_INFO_STATE_ASSOC);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
index 615956acc6b5..8e9604be0792 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
@@ -206,17 +206,6 @@ enum {
MCU_ATE_SET_TX_POWER_CONTROL = 0x15,
};
-struct mt7615_mcu_uni_event {
- u8 cid;
- u8 pad[3];
- __le32 status; /* 0: success, others: fail */
-} __packed;
-
-struct mt7615_mcu_reg_event {
- __le32 reg;
- __le32 val;
-} __packed;
-
struct mt7615_roc_tlv {
u8 bss_idx;
u8 token;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
index 83173efb56dc..ac036a072439 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
@@ -66,9 +66,7 @@ const u32 mt7663e_reg_map[] = {
static void
mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
- struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-
- mt7615_irq_enable(dev, MT_INT_RX_DONE(q));
+ mt76_connac_irq_enable(mdev, MT_INT_RX_DONE(q));
}
static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
@@ -80,14 +78,14 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
static void mt7615_irq_tasklet(struct tasklet_struct *t)
{
- struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet);
+ struct mt7615_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev);
u32 mcu_int;
@@ -181,7 +179,6 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
.rx_check = mt7615_rx_check,
.rx_skb = mt7615_queue_rx_skb,
.rx_poll_complete = mt7615_rx_poll_complete,
- .sta_ps = mt7615_sta_ps,
.sta_add = mt7615_mac_sta_add,
.sta_remove = mt7615_mac_sta_remove,
.update_survey = mt7615_update_channel,
@@ -202,7 +199,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
dev = container_of(mdev, struct mt7615_dev, mt76);
mt76_mmio_init(&dev->mt76, mem_base);
- tasklet_setup(&dev->irq_tasklet, mt7615_irq_tasklet);
+ tasklet_setup(&mdev->irq_tasklet, mt7615_irq_tasklet);
dev->reg_map = map;
dev->ops = ops;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 9e58f6924493..582d1b5b7cb3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -51,6 +51,7 @@
#define MT7663_FIRMWARE_N9 "mediatek/mt7663_n9_rebb.bin"
#define MT7615_EEPROM_SIZE 1024
+#define MT7663_EEPROM_SIZE 1536
#define MT7615_TOKEN_SIZE 4096
#define MT_FRAC_SCALE 12
@@ -245,8 +246,6 @@ struct mt7615_dev {
};
const struct mt76_bus_ops *bus_ops;
- struct tasklet_struct irq_tasklet;
-
struct mt7615_phy phy;
u64 omac_mask;
@@ -412,13 +411,6 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb);
int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev);
int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl);
-static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
-{
- mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
-
- tasklet_schedule(&dev->irq_tasklet);
-}
-
static inline bool mt7615_firmware_offload(struct mt7615_dev *dev)
{
return dev->fw_ver > MT7615_FIRMWARE_V2;
@@ -518,7 +510,6 @@ void mt7615_tx_token_put(struct mt7615_dev *dev);
bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
-void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
index b808248943ea..9f43e673518b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
@@ -94,7 +94,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]);
}
- tasklet_kill(&dev->irq_tasklet);
+ tasklet_kill(&mdev->irq_tasklet);
mt7615_dma_reset(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
index 0680e002b981..f607eee3fb47 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
@@ -122,7 +122,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev)
mt7615_tx_token_put(dev);
mt7615_dma_cleanup(dev);
- tasklet_disable(&dev->irq_tasklet);
+ tasklet_disable(&dev->mt76.irq_tasklet);
mt76_free_device(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
index 304212f5f8da..fc547a0031ea 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
@@ -84,7 +84,6 @@ static int mt7663s_probe(struct sdio_func *func,
.tx_status_data = mt7663_usb_sdio_tx_status_data,
.rx_skb = mt7615_queue_rx_skb,
.rx_check = mt7615_rx_check,
- .sta_ps = mt7615_sta_ps,
.sta_add = mt7615_mac_sta_add,
.sta_remove = mt7615_mac_sta_remove,
.update_survey = mt7615_update_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
index f2d651d7adff..04963b9f7498 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
@@ -120,7 +120,6 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
.tx_status_data = mt7663_usb_sdio_tx_status_data,
.rx_skb = mt7615_queue_rx_skb,
.rx_check = mt7615_rx_check,
- .sta_ps = mt7615_sta_ps,
.sta_add = mt7615_mac_sta_add,
.sta_remove = mt7615_mac_sta_remove,
.update_survey = mt7615_update_channel,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index b339c50bff20..15653b274f83 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -6,6 +6,20 @@
#include "mt76.h"
+enum rx_pkt_type {
+ PKT_TYPE_TXS,
+ PKT_TYPE_TXRXV,
+ PKT_TYPE_NORMAL,
+ PKT_TYPE_RX_DUP_RFB,
+ PKT_TYPE_RX_TMR,
+ PKT_TYPE_RETRIEVE,
+ PKT_TYPE_TXRX_NOTIFY,
+ PKT_TYPE_RX_EVENT,
+ PKT_TYPE_NORMAL_MCU,
+ PKT_TYPE_RX_FW_MONITOR = 0x0c,
+ PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
+};
+
#define MT76_CONNAC_SCAN_IE_LEN 600
#define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL 10
#define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX
@@ -279,6 +293,12 @@ static inline u8 mt76_connac_spe_idx(u8 antenna_mask)
return ant_to_spe[antenna_mask];
}
+static inline void mt76_connac_irq_enable(struct mt76_dev *dev, u32 mask)
+{
+ mt76_set_irq_mask(dev, 0, 0, mask);
+ tasklet_schedule(&dev->irq_tasklet);
+}
+
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
struct mt76_connac_pm *pm);
@@ -353,6 +373,7 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
mutex_unlock(&dev->mutex);
}
+void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss);
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
int ring_base, u32 flags);
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
index f33171bcd343..a5ec0f631385 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h
@@ -32,6 +32,16 @@ enum {
MT_LMAC_PSMP0,
};
+#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
+#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
+#define MT_TX_FREE_LATENCY GENMASK(12, 0)
+/* 0: success, others: dropped */
+#define MT_TX_FREE_STATUS GENMASK(14, 13)
+#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
+#define MT_TX_FREE_PAIR BIT(31)
+/* will support this field in further revision */
+#define MT_TX_FREE_RATE GENMASK(13, 0)
+
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
@@ -166,6 +176,15 @@ enum {
#define MT_TXS7_MPDU_RETRY_CNT GENMASK(31, 23)
+/* RXD DW0 */
+#define MT_RXD0_LENGTH GENMASK(15, 0)
+#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
+#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
+
+#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
+#define MT_RXD0_NORMAL_IP_SUM BIT(23)
+#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
+
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
@@ -308,6 +327,9 @@ enum {
#define MT_CRXV_FOE_HI GENMASK(6, 0)
#define MT_CRXV_FOE_SHIFT 13
+#define MT_CT_PARSE_LEN 72
+#define MT_CT_DMA_BUF_NUM 2
+
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index aed4ee95fb2e..ee0fbfcd07d6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -9,6 +9,27 @@
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
IEEE80211_RADIOTAP_HE_##f)
+void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss)
+{
+ static const u8 ppet16_ppet8_ru3_ru0[] = { 0x1c, 0xc7, 0x71 };
+ u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
+
+ he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
+ FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
+ ru_bit_mask);
+
+ ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
+ nss * hweight8(ru_bit_mask) * 2;
+ ppet_size = DIV_ROUND_UP(ppet_bits, 8);
+
+ for (i = 0; i < ppet_size - 1; i++)
+ he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
+
+ he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
+ (0xff >> (8 - (ppet_bits - 1) % 8));
+}
+EXPORT_SYMBOL_GPL(mt76_connac_gen_ppe_thresh);
+
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
struct mt76_dev *dev = phy->dev;
@@ -267,11 +288,29 @@ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
}
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
+#define __bitrate_mask_check(_mcs, _mode) \
+({ \
+ u8 i = 0; \
+ for (nss = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
+ if (!mask->control[band]._mcs[i]) \
+ continue; \
+ if (hweight16(mask->control[band]._mcs[i]) == 1) { \
+ mode = MT_PHY_TYPE_##_mode; \
+ rateidx = ffs(mask->control[band]._mcs[i]) - 1; \
+ if (mode == MT_PHY_TYPE_HT) \
+ rateidx += 8 * i; \
+ else \
+ nss = i + 1; \
+ goto out; \
+ } \
+ } \
+})
+
u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
struct ieee80211_vif *vif,
bool beacon, bool mcast)
{
- u8 mode = 0, band = mphy->chandef.chan->band;
+ u8 nss = 0, mode = 0, band = mphy->chandef.chan->band;
int rateidx = 0, mcast_rate;
if (!vif)
@@ -286,19 +325,12 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
struct cfg80211_bitrate_mask *mask;
mask = &vif->bss_conf.beacon_tx_rate;
- if (hweight16(mask->control[band].he_mcs[0]) == 1) {
- rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
- mode = MT_PHY_TYPE_HE_SU;
- goto out;
- } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
- rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
- mode = MT_PHY_TYPE_VHT;
- goto out;
- } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
- rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
- mode = MT_PHY_TYPE_HT;
- goto out;
- } else if (hweight32(mask->control[band].legacy) == 1) {
+
+ __bitrate_mask_check(he_mcs, HE_SU);
+ __bitrate_mask_check(vht_mcs, VHT);
+ __bitrate_mask_check(ht_mcs, HT);
+
+ if (hweight32(mask->control[band].legacy) == 1) {
rateidx = ffs(mask->control[band].legacy) - 1;
goto legacy;
}
@@ -314,9 +346,9 @@ legacy:
rateidx = mt76_calculate_default_rate(mphy, rateidx);
mode = rateidx >> 8;
rateidx &= GENMASK(7, 0);
-
out:
- return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
+ return FIELD_PREP(MT_TX_RATE_NSS, nss) |
+ FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
FIELD_PREP(MT_TX_RATE_MODE, mode);
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_tx_rate_val);
@@ -537,7 +569,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
/* Fixed rata is available just for 802.11 txd */
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- bool multicast = is_multicast_ether_addr(hdr->addr1);
+ bool multicast = ieee80211_is_data(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1);
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
multicast);
u32 val = MT_TXD6_FIXED_BW;
@@ -582,6 +615,17 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
stats->tx_retries +=
le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT);
+
+ if (wcid->sta) {
+ struct ieee80211_sta *sta;
+ u8 tid;
+
+ sta = container_of((void *)wcid, struct ieee80211_sta,
+ drv_priv);
+ tid = FIELD_GET(MT_TXS0_TID, txs);
+
+ ieee80211_refresh_tx_agg_session_timer(sta, tid);
+ }
}
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 008ece1b16f8..0f0a519f956f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -363,7 +363,7 @@ void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv);
-void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
+void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
bool enable, bool newly)
@@ -394,7 +394,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
- if (vif->p2p)
+ if (vif->p2p && !is_mt7921(dev))
conn_type = CONNECTION_P2P_GC;
else
conn_type = CONNECTION_INFRA_STA;
@@ -402,7 +402,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
basic->aid = cpu_to_le16(sta->aid);
break;
case NL80211_IFTYPE_STATION:
- if (vif->p2p)
+ if (vif->p2p && !is_mt7921(dev))
conn_type = CONNECTION_P2P_GO;
else
conn_type = CONNECTION_INFRA_AP;
@@ -1029,7 +1029,7 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
return PTR_ERR(skb);
if (info->sta || !info->offload_fw)
- mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta,
+ mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif, info->sta,
info->enable, info->newly);
if (info->sta && info->enable)
mt76_connac_mcu_sta_tlv(phy, skb, info->sta,
@@ -1678,8 +1678,16 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
req->channel_min_dwell_time = cpu_to_le16(duration);
req->channel_dwell_time = cpu_to_le16(duration);
- req->channels_num = min_t(u8, sreq->n_channels, 32);
- req->ext_channels_num = min_t(u8, ext_channels_num, 32);
+ if (sreq->n_channels == 0 || sreq->n_channels > 64) {
+ req->channel_type = 0;
+ req->channels_num = 0;
+ req->ext_channels_num = 0;
+ } else {
+ req->channel_type = 4;
+ req->channels_num = min_t(u8, sreq->n_channels, 32);
+ req->ext_channels_num = min_t(u8, ext_channels_num, 32);
+ }
+
for (i = 0; i < req->channels_num + req->ext_channels_num; i++) {
if (i >= 32)
chan = &req->ext_channels[i - 32];
@@ -1699,7 +1707,6 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
}
chan->channel_num = scan_list[i]->hw_value;
}
- req->channel_type = sreq->n_channels ? 4 : 0;
if (sreq->ie_len > 0) {
memcpy(req->ies, sreq->ie, sreq->ie_len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index a5e6ee4daf92..ca1ce97a6d2f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -127,7 +127,7 @@ struct mt76_connac2_mcu_rxd {
u8 rsv1[2];
u8 s2d_index;
- u8 tlv[0];
+ u8 tlv[];
};
struct mt76_connac2_patch_hdr {
@@ -967,9 +967,6 @@ enum {
DEV_INFO_MAX_NUM
};
-#define MCU_UNI_CMD_EVENT BIT(1)
-#define MCU_UNI_CMD_UNSOLICITED_EVENT BIT(2)
-
/* event table */
enum {
MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
@@ -1224,6 +1221,7 @@ enum {
MCU_UNI_CMD_VOW = 0x37,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
+ MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
};
enum {
@@ -1692,6 +1690,17 @@ struct mt76_connac_config {
u8 data[320];
} __packed;
+struct mt76_connac_mcu_uni_event {
+ u8 cid;
+ u8 pad[3];
+ __le32 status; /* 0: success, others: fail */
+} __packed;
+
+struct mt76_connac_mcu_reg_event {
+ __le32 reg;
+ __le32 val;
+} __packed;
+
static inline enum mcu_cipher_type
mt76_connac_mcu_get_cipher(int cipher)
{
@@ -1779,7 +1788,7 @@ mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len)
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
-void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
+void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable,
bool newly);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index d3f74473e6fb..3e41d809ade3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -631,8 +631,11 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
mt76_tx_status_unlock(mdev, &list);
- if (!status.skb)
+ if (!status.skb) {
+ spin_lock_bh(&dev->mt76.rx_lock);
ieee80211_tx_status_ext(mt76_hw(dev), &status);
+ spin_unlock_bh(&dev->mt76.rx_lock);
+ }
if (!len)
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index 5a46813a59ea..879884ead660 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -958,10 +958,10 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data)
DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
-#define mt7915_txpower_puts(prefix, rate) \
+#define mt7915_txpower_puts(rate) \
({ \
- len += scnprintf(buf + len, sz - len, "%-16s:", #prefix " (tmac)"); \
- for (i = 0; i < mt7915_sku_group_len[rate]; i++, offs++) \
+ len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \
+ for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \
len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \
len += scnprintf(buf + len, sz - len, "\n"); \
})
@@ -1004,41 +1004,41 @@ mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
phy != &dev->phy, phy->mt76->chandef.chan->hw_value);
len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n",
" ", "1m", "2m", "5m", "11m");
- mt7915_txpower_puts(CCK, SKU_CCK);
+ mt7915_txpower_puts(CCK);
len += scnprintf(buf + len, sz - len,
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
"54m");
- mt7915_txpower_puts(OFDM, SKU_OFDM);
+ mt7915_txpower_puts(OFDM);
len += scnprintf(buf + len, sz - len,
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
"mcs5", "mcs6", "mcs7");
- mt7915_txpower_puts(HT20, SKU_HT_BW20);
+ mt7915_txpower_puts(HT_BW20);
len += scnprintf(buf + len, sz - len,
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7", "mcs32");
- mt7915_txpower_puts(HT40, SKU_HT_BW40);
+ mt7915_txpower_puts(HT_BW40);
len += scnprintf(buf + len, sz - len,
"%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
"mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
- mt7915_txpower_puts(VHT20, SKU_VHT_BW20);
- mt7915_txpower_puts(VHT40, SKU_VHT_BW40);
- mt7915_txpower_puts(VHT80, SKU_VHT_BW80);
- mt7915_txpower_puts(VHT160, SKU_VHT_BW160);
- mt7915_txpower_puts(HE26, SKU_HE_RU26);
- mt7915_txpower_puts(HE52, SKU_HE_RU52);
- mt7915_txpower_puts(HE106, SKU_HE_RU106);
- mt7915_txpower_puts(HE242, SKU_HE_RU242);
- mt7915_txpower_puts(HE484, SKU_HE_RU484);
- mt7915_txpower_puts(HE996, SKU_HE_RU996);
- mt7915_txpower_puts(HE996x2, SKU_HE_RU2x996);
+ mt7915_txpower_puts(VHT_BW20);
+ mt7915_txpower_puts(VHT_BW40);
+ mt7915_txpower_puts(VHT_BW80);
+ mt7915_txpower_puts(VHT_BW160);
+ mt7915_txpower_puts(HE_RU26);
+ mt7915_txpower_puts(HE_RU52);
+ mt7915_txpower_puts(HE_RU106);
+ mt7915_txpower_puts(HE_RU242);
+ mt7915_txpower_puts(HE_RU484);
+ mt7915_txpower_puts(HE_RU996);
+ mt7915_txpower_puts(HE_RU2x996);
reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) :
MT_WF_PHY_TPC_CTRL_STAT_MT7916(band);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
index abe17dac9996..43a5456d4b97 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
@@ -87,8 +87,14 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
MT7916_RXQ_BAND0);
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916,
MT7916_RXQ_MCU_WA);
- RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
- MT7916_RXQ_BAND1);
+ if (dev->hif2)
+ RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0,
+ MT_INT_RX_DONE_BAND1_MT7916,
+ MT7916_RXQ_BAND1);
+ else
+ RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0,
+ MT_INT_WED_RX_DONE_BAND1_MT7916,
+ MT7916_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916,
MT7916_RXQ_MCU_WA_MAIN);
TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 5e288116b1b0..ac2049f49bb3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -89,6 +89,7 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) {
dev_err(phy->dev->mt76.dev,
"temp1_max shall be greater than temp1_crit.");
+ mutex_unlock(&phy->dev->mt76.mutex);
return -EINVAL;
}
@@ -202,6 +203,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
phy->cdev = cdev;
}
+ /* initialize critical/maximum high temperature */
+ phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
+ phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
+
if (!IS_REACHABLE(CONFIG_HWMON))
return 0;
@@ -210,10 +215,6 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
- /* initialize critical/maximum high temperature */
- phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
- phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
-
return 0;
}
@@ -368,6 +369,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
if (!is_mt7915(&dev->mt76))
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
@@ -930,27 +932,6 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
}
}
-static void
-mt7915_gen_ppe_thresh(u8 *he_ppet, int nss)
-{
- u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
- 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,
- ru_bit_mask);
-
- ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
- nss * hweight8(ru_bit_mask) * 2;
- ppet_size = DIV_ROUND_UP(ppet_bits, 8);
-
- for (i = 0; i < ppet_size - 1; i++)
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
-
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
- (0xff >> (8 - (ppet_bits - 1) % 8));
-}
-
static int
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data)
@@ -1100,7 +1081,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
- mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);
+ mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
} else {
he_cap_elem->phy_cap_info[9] |=
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
@@ -1179,7 +1160,7 @@ 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);
+ tasklet_disable(&dev->mt76.irq_tasklet);
if (is_mt7986(&dev->mt76))
mt7986_wmac_disable(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 97ca55d283fb..7df8d95fc3fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -73,10 +73,6 @@ static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev,
return &sta->vif->sta.wcid;
}
-void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
-{
-}
-
bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
{
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
@@ -1627,7 +1623,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
}
local_bh_enable();
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
index 6fa9c79f3e5f..ce94f87e2042 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
@@ -6,43 +6,12 @@
#include "../mt76_connac2_mac.h"
-#define MT_CT_PARSE_LEN 72
-#define MT_CT_DMA_BUF_NUM 2
-
-#define MT_RXD0_LENGTH GENMASK(15, 0)
-#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
-
-#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
-#define MT_RXD0_NORMAL_IP_SUM BIT(23)
-#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
-
-enum rx_pkt_type {
- PKT_TYPE_TXS,
- PKT_TYPE_TXRXV,
- PKT_TYPE_NORMAL,
- PKT_TYPE_RX_DUP_RFB,
- PKT_TYPE_RX_TMR,
- PKT_TYPE_RETRIEVE,
- PKT_TYPE_TXRX_NOTIFY,
- PKT_TYPE_RX_EVENT,
- PKT_TYPE_RX_FW_MONITOR = 0x0c,
- PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
-};
-
#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)
+#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
/* 0: success, others: dropped */
-#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
-#define MT_TX_FREE_PAIR BIT(31)
#define MT_TX_FREE_MPDU_HEADER BIT(30)
#define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0)
-/* will support this field in further revision */
-#define MT_TX_FREE_RATE GENMASK(13, 0)
-
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
#define MT_TXS5_F0_QOS BIT(30)
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 784191ec4802..1b361199c061 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -269,7 +269,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
mt7915_init_bitrate_mask(vif);
- memset(&mvif->cap, -1, sizeof(mvif->cap));
mt7915_mcu_add_bss_info(phy, vif, true);
mt7915_mcu_add_sta(dev, vif, NULL, true);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 5545a8bdf1d0..9fcb22fa1f97 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -706,7 +706,6 @@ static void
mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct ieee80211_he_mcs_nss_supp mcs_map;
struct sta_rec_he *he;
@@ -740,7 +739,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
- if (mvif->cap.he_ldpc &&
+ if (vif->bss_conf.he_ldpc &&
(elem->phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
cap |= STA_REC_HE_CAP_LDPC;
@@ -849,7 +848,6 @@ static void
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
@@ -862,9 +860,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
muru = (struct sta_rec_muru *)tlv;
- muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
- mvif->cap.vht_mu_ebfer ||
- mvif->cap.vht_mu_ebfee;
+ muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer ||
+ vif->bss_conf.vht_mu_beamformer ||
+ vif->bss_conf.vht_mu_beamformee;
if (!is_mt7915(&dev->mt76))
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
@@ -997,8 +995,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
- wtbl_hdr, mvif->cap.ht_ldpc,
- mvif->cap.vht_ldpc);
+ wtbl_hdr, vif->bss_conf.ht_ldpc,
+ vif->bss_conf.vht_ldpc);
return 0;
}
@@ -1007,7 +1005,6 @@ static inline bool
mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
{
- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -1021,10 +1018,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
if (bfee)
- return mvif->cap.he_su_ebfee &&
+ return vif->bss_conf.he_su_beamformee &&
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
else
- return mvif->cap.he_su_ebfer &&
+ return vif->bss_conf.he_su_beamformer &&
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
}
@@ -1032,10 +1029,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
u32 cap = sta->deflink.vht_cap.cap;
if (bfee)
- return mvif->cap.vht_su_ebfee &&
+ return vif->bss_conf.vht_su_beamformee &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
else
- return mvif->cap.vht_su_ebfer &&
+ return vif->bss_conf.vht_su_beamformer &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
}
@@ -1530,7 +1527,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_TX_STBC;
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
cap |= STA_CAP_RX_STBC;
- if (mvif->cap.ht_ldpc &&
+ if (vif->bss_conf.ht_ldpc &&
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC;
@@ -1556,7 +1553,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_VHT_TX_STBC;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
cap |= STA_CAP_VHT_RX_STBC;
- if (mvif->cap.vht_ldpc &&
+ if (vif->bss_conf.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC;
@@ -1657,8 +1654,8 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
return PTR_ERR(skb);
/* starec basic */
- mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
- !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
+ mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable,
+ !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
if (!enable)
goto out;
@@ -1876,84 +1873,6 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
}
static void
-mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
- struct sk_buff *skb)
-{
- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
- struct mt7915_vif_cap *vc = &mvif->cap;
- const struct ieee80211_he_cap_elem *he;
- const struct ieee80211_vht_cap *vht;
- const struct ieee80211_ht_cap *ht;
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- const u8 *ie;
- u32 len, bc;
-
- /* Check missing configuration options to allow AP mode in mac80211
- * to remain in sync with hostapd settings, and get a subset of
- * beacon and hardware capabilities.
- */
- if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data)))
- return;
-
- memset(vc, 0, sizeof(*vc));
-
- len = skb->len - (mgmt->u.beacon.variable - skb->data);
-
- ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable,
- len);
- if (ie && ie[1] >= sizeof(*ht)) {
- ht = (void *)(ie + 2);
- vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) &
- IEEE80211_HT_CAP_LDPC_CODING);
- }
-
- ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
- len);
- if (ie && ie[1] >= sizeof(*vht)) {
- u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap;
-
- vht = (void *)(ie + 2);
- bc = le32_to_cpu(vht->vht_cap_info);
-
- vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC);
- vc->vht_su_ebfer =
- (bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
- vc->vht_su_ebfee =
- (bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
- vc->vht_mu_ebfer =
- (bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
- vc->vht_mu_ebfee =
- (bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
- }
-
- ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY,
- mgmt->u.beacon.variable, len);
- if (ie && ie[1] >= sizeof(*he) + 1) {
- const struct ieee80211_sta_he_cap *pc =
- mt76_connac_get_he_phy_cap(phy->mt76, vif);
- const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
-
- he = (void *)(ie + 3);
-
- vc->he_ldpc =
- HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
- vc->he_su_ebfer =
- HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
- HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
- vc->he_su_ebfee =
- HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) &&
- HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
- vc->he_mu_ebfer =
- HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) &&
- HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]);
- }
-}
-
-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)
@@ -2063,8 +1982,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
info = IEEE80211_SKB_CB(skb);
info->hw_queue = FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
- mt7915_mcu_beacon_check_caps(phy, vif, skb);
-
mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
@@ -2370,7 +2287,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
if (ret)
return ret;
- if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76))
+ if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+ is_mt7915(&dev->mt76)) ||
+ !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
ret = mt7915_mcu_set_mwds(dev, 1);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
index 225a19604d3e..45f3558bf31c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
@@ -916,7 +916,7 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
/* TODO: support 2/4/6/8 MSI-X vectors */
static void mt7915_irq_tasklet(struct tasklet_struct *t)
{
- struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
+ struct mt7915_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 intr, intr1, mask;
@@ -989,18 +989,18 @@ 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;
- if (mtk_wed_device_active(wed)) {
+ if (mtk_wed_device_active(wed))
mtk_wed_device_irq_set_mask(wed, 0);
- } else {
+ else
mt76_wr(dev, MT_INT_MASK_CSR, 0);
- if (dev->hif2)
- mt76_wr(dev, MT_INT1_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;
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
@@ -1022,7 +1022,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
.rx_skb = mt7915_queue_rx_skb,
.rx_check = mt7915_rx_check,
.rx_poll_complete = mt7915_rx_poll_complete,
- .sta_ps = mt7915_sta_ps,
.sta_add = mt7915_mac_sta_add,
.sta_remove = mt7915_mac_sta_remove,
.update_survey = mt7915_update_channel,
@@ -1041,7 +1040,7 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
if (ret)
goto error;
- tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
+ tasklet_setup(&mdev->irq_tasklet, mt7915_irq_tasklet);
return dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 3cbfb9b6a305..b3ead3530740 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -147,23 +147,9 @@ struct mt7915_sta {
} twt;
};
-struct mt7915_vif_cap {
- bool ht_ldpc:1;
- bool vht_ldpc:1;
- bool he_ldpc:1;
- bool vht_su_ebfer:1;
- bool vht_su_ebfee:1;
- bool vht_mu_ebfer:1;
- bool vht_mu_ebfee:1;
- bool he_su_ebfer:1;
- bool he_su_ebfee:1;
- bool he_mu_ebfer:1;
-};
-
struct mt7915_vif {
struct mt76_vif mt76; /* must be first */
- struct mt7915_vif_cap cap;
struct mt7915_sta sta;
struct mt7915_phy *phy;
@@ -308,7 +294,6 @@ struct mt7915_dev {
u32 wfdma_mask;
const struct mt76_bus_ops *bus_ops;
- struct tasklet_struct irq_tasklet;
struct mt7915_phy phy;
/* monitor rx chain configured channel */
@@ -581,7 +566,7 @@ static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask)
else
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
}
static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
@@ -631,7 +616,6 @@ void mt7915_tx_token_put(struct mt7915_dev *dev);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
-void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
void mt7915_stats_work(struct work_struct *work);
int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
index 2ac0a0f2859c..32c137066e7f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
@@ -1239,6 +1239,8 @@ static const struct of_device_id mt7986_wmac_of_match[] = {
{},
};
+MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match);
+
struct platform_driver mt7986_wmac_driver = {
.driver = {
.name = "mt7986-wmac",
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
index 35268b0890ad..6f2c4a572572 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h
@@ -24,7 +24,7 @@ struct mt7921_asar_dyn {
u8 names[4];
u8 enable;
u8 nr_tbl;
- struct mt7921_asar_dyn_limit tbl[0];
+ DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl);
} __packed;
struct mt7921_asar_dyn_limit_v2 {
@@ -37,7 +37,7 @@ struct mt7921_asar_dyn_v2 {
u8 enable;
u8 rsvd;
u8 nr_tbl;
- struct mt7921_asar_dyn_limit_v2 tbl[0];
+ DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl);
} __packed;
struct mt7921_asar_geo_band {
@@ -55,7 +55,7 @@ struct mt7921_asar_geo {
u8 names[4];
u8 version;
u8 nr_tbl;
- struct mt7921_asar_geo_limit tbl[0];
+ DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl);
} __packed;
struct mt7921_asar_geo_limit_v2 {
@@ -69,7 +69,7 @@ struct mt7921_asar_geo_v2 {
u8 version;
u8 rsvd;
u8 nr_tbl;
- struct mt7921_asar_geo_limit_v2 tbl[0];
+ DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl);
} __packed;
struct mt7921_asar_cl {
@@ -85,7 +85,7 @@ struct mt7921_asar_fg {
u8 rsvd;
u8 nr_flag;
u8 rsvd1;
- u8 flag[0];
+ u8 flag[];
} __packed;
struct mt7921_acpi_sar {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
index 29d8883268f6..d6b6edba2fec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -2,7 +2,6 @@
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt7921.h"
-#include "eeprom.h"
static int
mt7921_reg_set(void *data, u64 val)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index d1f10f6d9adc..f0a80c2b476a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -3,7 +3,7 @@
#include "mt7921.h"
#include "../dma.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
{
@@ -19,7 +19,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
mt76_connac_tx_cleanup(&dev->mt76);
if (napi_complete(napi))
- mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
+ mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL);
mt76_connac_pm_unref(&dev->mphy, &dev->pm);
return 0;
@@ -66,6 +66,24 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
{
+ /* disable WFDMA0 */
+ mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+
+ if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
+ MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1))
+ return -ETIMEDOUT;
+
+ /* disable dmashdl */
+ mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
+ MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
+ mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
+
if (force) {
/* reset */
mt76_clear(dev, MT_WFDMA0_RST,
@@ -77,24 +95,6 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
MT_WFDMA0_RST_LOGIC_RST);
}
- /* disable dmashdl */
- mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
- MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
- mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
-
- /* disable WFDMA0 */
- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
- MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
- MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
-
- if (!mt76_poll(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
- MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
- return -ETIMEDOUT;
-
return 0;
}
@@ -123,9 +123,9 @@ static int mt7921_dma_enable(struct mt7921_dev *dev)
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
/* enable interrupts for TX/RX rings */
- mt7921_irq_enable(dev,
- MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
- MT_INT_MCU_CMD);
+ mt76_connac_irq_enable(&dev->mt76,
+ MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
+ MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
return 0;
@@ -301,6 +301,10 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev)
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+ mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
+ MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1);
+
/* reset */
mt76_clear(dev, MT_WFDMA0_RST,
MT_WFDMA0_RST_DMASHDL_ALL_RST |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h
deleted file mode 100644
index 4b647278eb30..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt7921/eeprom.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/* Copyright (C) 2020 MediaTek Inc. */
-
-#ifndef __MT7921_EEPROM_H
-#define __MT7921_EEPROM_H
-
-#include "mt7921.h"
-
-enum mt7921_eeprom_field {
- MT_EE_CHIP_ID = 0x000,
- MT_EE_VERSION = 0x002,
- MT_EE_MAC_ADDR = 0x004,
- MT_EE_WIFI_CONF = 0x07c,
- MT_EE_HW_TYPE = 0x55b,
- __MT_EE_MAX = 0x9ff
-};
-
-#define MT_EE_WIFI_CONF_TX_MASK BIT(0)
-#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2)
-
-#define MT_EE_HW_TYPE_ENCAP BIT(0)
-
-enum mt7921_eeprom_band {
- MT_EE_NA,
- MT_EE_5GHZ,
- MT_EE_2GHZ,
- MT_EE_DUAL_BAND,
-};
-
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index cc94531185da..bf1da9fddfab 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -4,9 +4,8 @@
#include <linux/etherdevice.h>
#include <linux/firmware.h>
#include "mt7921.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "mcu.h"
-#include "eeprom.h"
static const struct ieee80211_iface_limit if_limits[] = {
{
@@ -32,11 +31,13 @@ static const struct ieee80211_iface_combination if_comb[] = {
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
{
.max = 2,
- .types = BIT(NL80211_IFTYPE_STATION),
+ .types = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT)
},
{
.max = 1,
- .types = BIT(NL80211_IFTYPE_AP),
+ .types = BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_GO)
}
};
@@ -100,7 +101,9 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
WIPHY_FLAG_4ADDR_STATION);
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO);
wiphy->max_remain_on_channel_duration = 5000;
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_scan_ssids = 4;
@@ -121,6 +124,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
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_ACK_SIGNAL_SUPPORT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
@@ -169,7 +173,8 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
}
-u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
+static u8
+mt7921_get_offload_capability(struct device *dev, const char *fw_wm)
{
const struct mt76_connac2_fw_trailer *hdr;
struct mt7921_realease_info *rel_info;
@@ -223,7 +228,31 @@ out:
return offload_caps;
}
-EXPORT_SYMBOL_GPL(mt7921_check_offload_capability);
+
+struct ieee80211_ops *
+mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features)
+{
+ struct ieee80211_ops *ops;
+
+ ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL);
+ if (!ops)
+ return NULL;
+
+ *fw_features = mt7921_get_offload_capability(dev, drv_data);
+ if (!(*fw_features & MT7921_FW_CAP_CNM)) {
+ ops->remain_on_channel = NULL;
+ ops->cancel_remain_on_channel = NULL;
+ ops->add_chanctx = NULL;
+ ops->remove_chanctx = NULL;
+ ops->change_chanctx = NULL;
+ ops->assign_vif_chanctx = NULL;
+ ops->unassign_vif_chanctx = NULL;
+ ops->mgd_prepare_tx = NULL;
+ ops->mgd_complete_tx = NULL;
+ }
+ return ops;
+}
+EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops);
int mt7921_mac_init(struct mt7921_dev *dev)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 557c20190c2b..1675bf520481 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -6,9 +6,20 @@
#include <linux/timekeeping.h>
#include "mt7921.h"
#include "../dma.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "mcu.h"
+#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
+#define MT_WTBL_TXRX_RATE_G2_HE 24
+#define MT_WTBL_TXRX_RATE_G2 12
+
+#define MT_WTBL_AC0_CTT_OFFSET 20
+
+static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
+{
+ return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
+}
+
static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
u16 idx, bool unicast)
{
@@ -32,11 +43,6 @@ static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev,
return &sta->vif->sta.wcid;
}
-void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
-{
-}
-EXPORT_SYMBOL_GPL(mt7921_sta_ps);
-
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask)
{
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
deleted file mode 100644
index 8afec600364f..000000000000
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/* Copyright (C) 2020 MediaTek Inc. */
-
-#ifndef __MT7921_MAC_H
-#define __MT7921_MAC_H
-
-#include "../mt76_connac2_mac.h"
-
-#define MT_CT_PARSE_LEN 72
-#define MT_CT_DMA_BUF_NUM 2
-
-#define MT_RXD0_LENGTH GENMASK(15, 0)
-#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
-#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
-
-#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
-#define MT_RXD0_NORMAL_IP_SUM BIT(23)
-#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
-
-enum rx_pkt_type {
- PKT_TYPE_TXS,
- PKT_TYPE_TXRXV,
- PKT_TYPE_NORMAL,
- PKT_TYPE_RX_DUP_RFB,
- PKT_TYPE_RX_TMR,
- PKT_TYPE_RETRIEVE,
- PKT_TYPE_TXRX_NOTIFY,
- PKT_TYPE_RX_EVENT,
- PKT_TYPE_NORMAL_MCU,
-};
-
-#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
-#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
-#define MT_TX_FREE_LATENCY GENMASK(12, 0)
-/* 0: success, others: dropped */
-#define MT_TX_FREE_STATUS GENMASK(14, 13)
-#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
-#define MT_TX_FREE_PAIR BIT(31)
-/* will support this field in further revision */
-#define MT_TX_FREE_RATE GENMASK(13, 0)
-
-#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
-#define MT_WTBL_TXRX_RATE_G2_HE 24
-#define MT_WTBL_TXRX_RATE_G2 12
-
-#define MT_WTBL_AC0_CTT_OFFSET 20
-
-static inline u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset)
-{
- return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4;
-}
-
-#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 42933a6b7334..3b6adb29cbef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -9,27 +9,6 @@
#include "mt7921.h"
#include "mcu.h"
-static void
-mt7921_gen_ppe_thresh(u8 *he_ppet, int nss)
-{
- u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
- 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,
- ru_bit_mask);
-
- ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
- nss * hweight8(ru_bit_mask) * 2;
- ppet_size = DIV_ROUND_UP(ppet_bits, 8);
-
- for (i = 0; i < ppet_size - 1; i++)
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
-
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
- (0xff >> (8 - (ppet_bits - 1) % 8));
-}
-
static int
mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data)
@@ -168,7 +147,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
- mt7921_gen_ppe_thresh(he_cap->ppe_thres, nss);
+ mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
} else {
he_cap_elem->phy_cap_info[9] |=
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
@@ -702,10 +681,25 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
unsigned int *total_flags,
u64 multicast)
{
+#define MT7921_FILTER_FCSFAIL BIT(2)
+#define MT7921_FILTER_CONTROL BIT(5)
+#define MT7921_FILTER_OTHER_BSS BIT(6)
+#define MT7921_FILTER_ENABLE BIT(31)
+
struct mt7921_dev *dev = mt7921_hw_dev(hw);
+ u32 flags = MT7921_FILTER_ENABLE;
+
+#define MT7921_FILTER(_fif, _type) do { \
+ if (*total_flags & (_fif)) \
+ flags |= MT7921_FILTER_##_type; \
+ } while (0)
+
+ MT7921_FILTER(FIF_FCSFAIL, FCSFAIL);
+ MT7921_FILTER(FIF_CONTROL, CONTROL);
+ MT7921_FILTER(FIF_OTHER_BSS, OTHER_BSS);
mt7921_mutex_acquire(dev);
- mt7921_mcu_set_rxfilter(dev, *total_flags, 0, 0);
+ mt7921_mcu_set_rxfilter(dev, flags, 0, 0);
mt7921_mutex_release(dev);
*total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL);
@@ -1694,7 +1688,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac,
if (ctx != mvif->ctx)
return;
- if (vif->type & NL80211_IFTYPE_MONITOR)
+ if (vif->type == NL80211_IFTYPE_MONITOR)
mt7921_mcu_config_sniffer(mvif, ctx);
else
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index c5e7ad06f877..c69ce6df4956 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -5,9 +5,8 @@
#include <linux/firmware.h>
#include "mt7921.h"
#include "mt7921_trace.h"
-#include "eeprom.h"
#include "mcu.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#define MT_STA_BFER BIT(0)
#define MT_STA_BFEE BIT(1)
@@ -16,24 +15,6 @@ static bool mt7921_disable_clc;
module_param_named(disable_clc, mt7921_disable_clc, bool, 0644);
MODULE_PARM_DESC(disable_clc, "disable CLC support");
-static int
-mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
-{
- struct mt7921_mcu_eeprom_info *res;
- u8 *buf;
-
- if (!skb)
- return -EINVAL;
-
- skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
-
- res = (struct mt7921_mcu_eeprom_info *)skb->data;
- buf = dev->eeprom.data + le32_to_cpu(res->addr);
- memcpy(buf, res->data, 16);
-
- return 0;
-}
-
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq)
{
@@ -60,27 +41,25 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
skb_pull(skb, sizeof(*rxd) + 4);
ret = le32_to_cpu(*(__le32 *)skb->data);
- } else if (cmd == MCU_EXT_CMD(EFUSE_ACCESS)) {
- ret = mt7921_mcu_parse_eeprom(mdev, skb);
} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||
cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||
cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||
cmd == MCU_UNI_CMD(HIF_CTRL) ||
cmd == MCU_UNI_CMD(OFFLOAD) ||
cmd == MCU_UNI_CMD(SUSPEND)) {
- struct mt7921_mcu_uni_event *event;
+ struct mt76_connac_mcu_uni_event *event;
skb_pull(skb, sizeof(*rxd));
- event = (struct mt7921_mcu_uni_event *)skb->data;
+ event = (struct mt76_connac_mcu_uni_event *)skb->data;
ret = le32_to_cpu(event->status);
/* skip invalid event */
if (mcu_cmd != event->cid)
ret = -EAGAIN;
} else if (cmd == MCU_CE_QUERY(REG_READ)) {
- struct mt7921_mcu_reg_event *event;
+ struct mt76_connac_mcu_reg_event *event;
skb_pull(skb, sizeof(*rxd));
- event = (struct mt7921_mcu_reg_event *)skb->data;
+ event = (struct mt76_connac_mcu_reg_event *)skb->data;
ret = (int)le32_to_cpu(event->val);
} else {
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
index 96dc870fd35e..9b0aa3b70f0e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
@@ -50,22 +50,11 @@ struct mt7921_mcu_eeprom_info {
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
-struct mt7921_mcu_uni_event {
- u8 cid;
- u8 pad[3];
- __le32 status; /* 0: success, others: fail */
-} __packed;
-
enum {
MT_EBF = BIT(0), /* explicit beamforming */
MT_IBF = BIT(1) /* implicit beamforming */
};
-struct mt7921_mcu_reg_event {
- __le32 reg;
- __le32 val;
-} __packed;
-
struct mt7921_mcu_ant_id_config {
u8 ant_id[4];
} __packed;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 1af70dac723b..149acb1662d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -266,6 +266,17 @@ struct mt7921_phy {
bool roc_grant;
};
+enum mt7921_eeprom_field {
+ MT_EE_CHIP_ID = 0x000,
+ MT_EE_VERSION = 0x002,
+ MT_EE_MAC_ADDR = 0x004,
+ MT_EE_WIFI_CONF = 0x07c,
+ MT_EE_HW_TYPE = 0x55b,
+ __MT_EE_MAX = 0x9ff
+};
+
+#define MT_EE_HW_TYPE_ENCAP BIT(0)
+
#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev))
#define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev))
#define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev))
@@ -287,7 +298,6 @@ struct mt7921_dev {
const struct mt76_bus_ops *bus_ops;
struct mt7921_phy phy;
- struct tasklet_struct irq_tasklet;
struct work_struct reset_work;
bool hw_full_reset:1;
@@ -391,13 +401,6 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
-static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
-{
- mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
-
- tasklet_schedule(&dev->irq_tasklet);
-}
-
static inline u32
mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr)
{
@@ -478,7 +481,6 @@ void mt7921_tx_token_put(struct mt7921_dev *dev);
bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
-void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
void mt7921_stats_work(struct work_struct *work);
void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
void mt7921_update_channel(struct mt76_phy *mphy);
@@ -593,5 +595,6 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
enum mt7921_roc_req type, u8 token_id);
int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
u8 token_id);
-u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm);
+struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev,
+ void *drv_data, u8 *fw_features);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 5c23c827abe4..ddb1fa4ee01d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -8,7 +8,7 @@
#include <linux/pci.h>
#include "mt7921.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "mcu.h"
#include "../trace.h"
@@ -31,14 +31,12 @@ MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
static void
mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-
if (q == MT_RXQ_MAIN)
- mt7921_irq_enable(dev, MT_INT_RX_DONE_DATA);
+ mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA);
else if (q == MT_RXQ_MCU_WA)
- mt7921_irq_enable(dev, MT_INT_RX_DONE_WM2);
+ mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2);
else
- mt7921_irq_enable(dev, MT_INT_RX_DONE_WM);
+ mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM);
}
static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
@@ -50,7 +48,7 @@ static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
@@ -115,14 +113,15 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
napi_disable(&dev->mt76.napi[i]);
cancel_delayed_work_sync(&pm->ps_work);
cancel_work_sync(&pm->wake_work);
+ cancel_work_sync(&dev->reset_work);
mt7921_tx_token_put(dev);
- mt7921_mcu_drv_pmctrl(dev);
+ __mt7921_mcu_drv_pmctrl(dev);
mt7921_dma_cleanup(dev);
mt7921_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
- tasklet_disable(&dev->irq_tasklet);
+ tasklet_disable(&dev->mt76.irq_tasklet);
}
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
@@ -243,7 +242,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.rx_check = mt7921_rx_check,
.rx_skb = mt7921_queue_rx_skb,
.rx_poll_complete = mt7921_rx_poll_complete,
- .sta_ps = mt7921_sta_ps,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
@@ -256,13 +254,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
.drv_own = mt7921e_mcu_drv_pmctrl,
.fw_own = mt7921e_mcu_fw_pmctrl,
};
-
struct ieee80211_ops *ops;
struct mt76_bus_ops *bus_ops;
struct mt7921_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
+ u16 cmd;
ret = pcim_enable_device(pdev);
if (ret)
@@ -272,6 +270,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_MEMORY)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ }
pci_set_master(pdev);
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
@@ -285,27 +288,13 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
if (mt7921_disable_aspm)
mt76_pci_disable_aspm(pdev);
- features = mt7921_check_offload_capability(&pdev->dev, (const char *)
- id->driver_data);
- ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
- GFP_KERNEL);
+ ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data,
+ &features);
if (!ops) {
ret = -ENOMEM;
goto err_free_pci_vec;
}
- if (!(features & MT7921_FW_CAP_CNM)) {
- ops->remain_on_channel = NULL;
- ops->cancel_remain_on_channel = NULL;
- ops->add_chanctx = NULL;
- ops->remove_chanctx = NULL;
- ops->change_chanctx = NULL;
- ops->assign_vif_chanctx = NULL;
- ops->unassign_vif_chanctx = NULL;
- ops->mgd_prepare_tx = NULL;
- ops->mgd_complete_tx = NULL;
- }
-
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev) {
ret = -ENOMEM;
@@ -318,7 +307,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
dev->fw_features = features;
dev->hif_ops = &mt7921_pcie_ops;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
- tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
+ tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
@@ -430,7 +419,7 @@ static int mt7921_pci_suspend(struct device *device)
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
synchronize_irq(pdev->irq);
- tasklet_kill(&dev->irq_tasklet);
+ tasklet_kill(&mdev->irq_tasklet);
err = mt7921_mcu_fw_pmctrl(dev);
if (err)
@@ -474,8 +463,9 @@ static int mt7921_pci_resume(struct device *device)
/* enable interrupt */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
- mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
- MT_INT_MCU_CMD);
+ mt76_connac_irq_enable(&dev->mt76,
+ MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
+ MT_INT_MCU_CMD);
mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
/* put dma enabled */
@@ -509,17 +499,7 @@ failed:
static void mt7921_pci_shutdown(struct pci_dev *pdev)
{
- struct mt76_dev *mdev = pci_get_drvdata(pdev);
- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
- struct mt76_connac_pm *pm = &dev->pm;
-
- cancel_delayed_work_sync(&pm->ps_work);
- cancel_work_sync(&pm->wake_work);
-
- /* chip cleanup before reboot */
- mt7921_mcu_drv_pmctrl(dev);
- mt7921_dma_cleanup(dev);
- mt7921_wfsys_reset(dev);
+ mt7921_pci_remove(pdev);
}
static DEFINE_SIMPLE_DEV_PM_OPS(mt7921_pm_ops, mt7921_pci_suspend, mt7921_pci_resume);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
index 8dd60408b117..6053a2556c20 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
@@ -3,7 +3,7 @@
#include "mt7921.h"
#include "../dma.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
index 8ce4252b8ae7..a77a309c0d60 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
@@ -13,7 +13,7 @@
#include "mt7921.h"
#include "../sdio.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "mcu.h"
static const struct sdio_device_id mt7921s_table[] = {
@@ -99,7 +99,6 @@ static int mt7921s_probe(struct sdio_func *func,
.tx_status_data = mt7921_usb_sdio_tx_status_data,
.rx_skb = mt7921_queue_rx_skb,
.rx_check = mt7921_rx_check,
- .sta_ps = mt7921_sta_ps,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
@@ -122,33 +121,17 @@ static int mt7921s_probe(struct sdio_func *func,
.drv_own = mt7921s_mcu_drv_pmctrl,
.fw_own = mt7921s_mcu_fw_pmctrl,
};
-
struct ieee80211_ops *ops;
struct mt7921_dev *dev;
struct mt76_dev *mdev;
u8 features;
int ret;
- features = mt7921_check_offload_capability(&func->dev, (const char *)
- id->driver_data);
-
- ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
- GFP_KERNEL);
+ ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data,
+ &features);
if (!ops)
return -ENOMEM;
- if (!(features & MT7921_FW_CAP_CNM)) {
- ops->remain_on_channel = NULL;
- ops->cancel_remain_on_channel = NULL;
- ops->add_chanctx = NULL;
- ops->remove_chanctx = NULL;
- ops->change_chanctx = NULL;
- ops->assign_vif_chanctx = NULL;
- ops->unassign_vif_chanctx = NULL;
- ops->mgd_prepare_tx = NULL;
- ops->mgd_complete_tx = NULL;
- }
-
mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev)
return -ENOMEM;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c
index 1b3adb3d91e8..cff9925c41ea 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c
@@ -4,7 +4,7 @@
#include <linux/iopoll.h>
#include <linux/mmc/sdio_func.h>
#include "mt7921.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "../sdio.h"
static void mt7921s_enable_irq(struct mt76_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c
index 5c1489766d9f..177679ce1c80 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c
@@ -8,7 +8,7 @@
#include "mt7921.h"
#include "../sdio.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
#include "mcu.h"
#include "regs.h"
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index 8fef09ed29c9..1f302c430339 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -10,7 +10,7 @@
#include "mt7921.h"
#include "mcu.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
static const struct usb_device_id mt7921u_device_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
@@ -18,6 +18,9 @@ static const struct usb_device_id mt7921u_device_table[] = {
/* Comfast CF-952AX */
{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
+ /* Netgear, Inc. [A8000,AXE3000] */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
{ },
};
@@ -183,7 +186,6 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
.tx_status_data = mt7921_usb_sdio_tx_status_data,
.rx_skb = mt7921_queue_rx_skb,
.rx_check = mt7921_rx_check,
- .sta_ps = mt7921_sta_ps,
.sta_add = mt7921_mac_sta_add,
.sta_assoc = mt7921_mac_sta_assoc,
.sta_remove = mt7921_mac_sta_remove,
@@ -210,27 +212,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
u8 features;
int ret;
- features = mt7921_check_offload_capability(&usb_intf->dev, (const char *)
- id->driver_info);
- ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops),
- GFP_KERNEL);
+ ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info,
+ &features);
if (!ops)
return -ENOMEM;
- if (!(features & MT7921_FW_CAP_CNM)) {
- ops->remain_on_channel = NULL;
- ops->cancel_remain_on_channel = NULL;
- ops->add_chanctx = NULL;
- ops->remove_chanctx = NULL;
- ops->change_chanctx = NULL;
- ops->assign_vif_chanctx = NULL;
- ops->unassign_vif_chanctx = NULL;
- ops->mgd_prepare_tx = NULL;
- ops->mgd_complete_tx = NULL;
- }
-
ops->stop = mt7921u_stop;
-
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
if (!mdev)
return -ENOMEM;
@@ -272,7 +259,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
ret = mt7921u_dma_init(dev, false);
if (ret)
- return ret;
+ goto error;
hw = mt76_hw(dev);
/* check hw sg support in order to enable AMSDU */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
index efbd3954c883..50eb6e7fd6b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
@@ -10,7 +10,7 @@
#include "mt7921.h"
#include "mcu.h"
-#include "mac.h"
+#include "../mt76_connac2_mac.h"
static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
index 79fb47a73c91..1afa2f662e47 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
@@ -2,6 +2,7 @@
config MT7996E
tristate "MediaTek MT7996 (PCIe) support"
select MT76_CONNAC_LIB
+ select WANT_DEV_COREDUMP
select RELAY
depends on MAC80211
depends on PCI
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Makefile b/drivers/net/wireless/mediatek/mt76/mt7996/Makefile
index bcb9a3c53149..07c8b555c1ac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/Makefile
@@ -4,3 +4,5 @@ obj-$(CONFIG_MT7996E) += mt7996e.o
mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o
+
+mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c
new file mode 100644
index 000000000000..ccab0d7b9be4
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2023 MediaTek Inc. */
+
+#include <linux/devcoredump.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/utsname.h>
+#include "coredump.h"
+
+static bool coredump_memdump;
+module_param(coredump_memdump, bool, 0644);
+MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory");
+
+static const struct mt7996_mem_region mt7996_mem_regions[] = {
+ {
+ .start = 0x00800000,
+ .len = 0x0004ffff,
+ .name = "ULM0",
+ },
+ {
+ .start = 0x00900000,
+ .len = 0x00037fff,
+ .name = "ULM1",
+ },
+ {
+ .start = 0x02200000,
+ .len = 0x0003ffff,
+ .name = "ULM2",
+ },
+ {
+ .start = 0x00400000,
+ .len = 0x00067fff,
+ .name = "SRAM",
+ },
+ {
+ .start = 0xe0000000,
+ .len = 0x0015ffff,
+ .name = "CRAM0",
+ },
+ {
+ .start = 0xe0160000,
+ .len = 0x0011bfff,
+ .name = "CRAM1",
+ },
+};
+
+const struct mt7996_mem_region*
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
+{
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7990:
+ case 0x7991:
+ *num = ARRAY_SIZE(mt7996_mem_regions);
+ return &mt7996_mem_regions[0];
+ default:
+ return NULL;
+ }
+}
+
+static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
+{
+ const struct mt7996_mem_region *mem_region;
+ size_t size = 0;
+ u32 num;
+ int i;
+
+ mem_region = mt7996_coredump_get_mem_layout(dev, &num);
+ if (!mem_region)
+ return 0;
+
+ for (i = 0; i < num; i++) {
+ size += mem_region->len;
+ mem_region++;
+ }
+
+ /* reserve space for the headers */
+ size += num * sizeof(struct mt7996_mem_hdr);
+ /* make sure it is aligned 4 bytes for debug message print out */
+ size = ALIGN(size, 4);
+
+ return size;
+}
+
+struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
+{
+ struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
+
+ lockdep_assert_held(&dev->dump_mutex);
+
+ if (coredump_memdump &&
+ !mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500))
+ return NULL;
+
+ guid_gen(&crash_data->guid);
+ ktime_get_real_ts64(&crash_data->timestamp);
+
+ return crash_data;
+}
+
+static void
+mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
+ bool *exception)
+{
+ u32 count;
+
+ count = mt76_rr(dev, MT_FW_ASSERT_CNT);
+
+ /* normal mode: driver can manually trigger assert for detail info */
+ if (!count)
+ strscpy(dump->fw_state, "normal", sizeof(dump->fw_state));
+ else
+ strscpy(dump->fw_state, "exception", sizeof(dump->fw_state));
+
+ *exception = !!count;
+}
+
+static void
+mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump,
+ bool exception)
+{
+ u32 oldest, i, idx;
+
+ strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current));
+
+ /* 0: WM PC log output */
+ mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0);
+ /* choose 33th PC log buffer to read current PC index */
+ mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f);
+
+ /* read current PC */
+ dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
+
+ /* stop call stack record */
+ if (!exception) {
+ mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
+ mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
+ }
+
+ oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL,
+ GENMASK(20, 16)) + 2;
+ for (i = 0; i < 16; i++) {
+ idx = ((oldest + 2 * i + 1) % 32);
+ dump->pc_stack[i + 1] =
+ mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4);
+ }
+
+ oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL,
+ GENMASK(20, 16)) + 2;
+ for (i = 0; i < 16; i++) {
+ idx = ((oldest + 2 * i + 1) % 32);
+ dump->lr_stack[i] =
+ mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4);
+ }
+
+ /* start call stack record */
+ if (!exception) {
+ mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
+ mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
+ }
+}
+
+static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
+{
+ struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
+ struct mt7996_coredump *dump;
+ struct mt7996_coredump_mem *dump_mem;
+ size_t len, sofar = 0, hdr_len = sizeof(*dump);
+ unsigned char *buf;
+ bool exception;
+
+ len = hdr_len;
+
+ if (coredump_memdump && crash_data->memdump_buf_len)
+ len += sizeof(*dump_mem) + crash_data->memdump_buf_len;
+
+ sofar += hdr_len;
+
+ /* this is going to get big when we start dumping memory and such,
+ * so go ahead and use vmalloc.
+ */
+ buf = vzalloc(len);
+ if (!buf)
+ return NULL;
+
+ mutex_lock(&dev->dump_mutex);
+
+ dump = (struct mt7996_coredump *)(buf);
+ dump->len = len;
+
+ /* plain text */
+ strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic));
+ strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel));
+ strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version,
+ sizeof(dump->fw_ver));
+
+ guid_copy(&dump->guid, &crash_data->guid);
+ dump->tv_sec = crash_data->timestamp.tv_sec;
+ dump->tv_nsec = crash_data->timestamp.tv_nsec;
+ dump->device_id = mt76_chip(&dev->mt76);
+
+ mt7996_coredump_fw_state(dev, dump, &exception);
+ mt7996_coredump_fw_stack(dev, dump, exception);
+
+ /* gather memory content */
+ dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
+ dump_mem->len = crash_data->memdump_buf_len;
+ if (coredump_memdump && crash_data->memdump_buf_len)
+ memcpy(dump_mem->data, crash_data->memdump_buf,
+ crash_data->memdump_buf_len);
+
+ mutex_unlock(&dev->dump_mutex);
+
+ return dump;
+}
+
+int mt7996_coredump_submit(struct mt7996_dev *dev)
+{
+ struct mt7996_coredump *dump;
+
+ dump = mt7996_coredump_build(dev);
+ if (!dump) {
+ dev_warn(dev->mt76.dev, "no crash dump data found\n");
+ return -ENODATA;
+ }
+
+ dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL);
+
+ return 0;
+}
+
+int mt7996_coredump_register(struct mt7996_dev *dev)
+{
+ struct mt7996_crash_data *crash_data;
+
+ crash_data = vzalloc(sizeof(*dev->coredump.crash_data));
+ if (!crash_data)
+ return -ENOMEM;
+
+ dev->coredump.crash_data = crash_data;
+
+ if (coredump_memdump) {
+ crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev);
+ if (!crash_data->memdump_buf_len)
+ /* no memory content */
+ return 0;
+
+ crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
+ if (!crash_data->memdump_buf) {
+ vfree(crash_data);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+void mt7996_coredump_unregister(struct mt7996_dev *dev)
+{
+ if (dev->coredump.crash_data->memdump_buf) {
+ vfree(dev->coredump.crash_data->memdump_buf);
+ dev->coredump.crash_data->memdump_buf = NULL;
+ dev->coredump.crash_data->memdump_buf_len = 0;
+ }
+
+ vfree(dev->coredump.crash_data);
+ dev->coredump.crash_data = NULL;
+}
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h
new file mode 100644
index 000000000000..af2ba219b1b5
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/coredump.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: ISC */
+/* Copyright (C) 2023 MediaTek Inc. */
+
+#ifndef _COREDUMP_H_
+#define _COREDUMP_H_
+
+#include "mt7996.h"
+
+struct mt7996_coredump {
+ char magic[16];
+
+ u32 len;
+
+ guid_t guid;
+
+ /* time-of-day stamp */
+ u64 tv_sec;
+ /* time-of-day stamp, nano-seconds */
+ u64 tv_nsec;
+ /* kernel version */
+ char kernel[64];
+ /* firmware version */
+ char fw_ver[ETHTOOL_FWVERS_LEN];
+
+ u32 device_id;
+
+ /* exception state */
+ char fw_state[12];
+
+ /* program counters */
+ char pc_current[16];
+ u32 pc_stack[17];
+ /* link registers */
+ u32 lr_stack[16];
+
+ /* memory content */
+ u8 data[];
+} __packed;
+
+struct mt7996_coredump_mem {
+ u32 len;
+ u8 data[];
+} __packed;
+
+struct mt7996_mem_hdr {
+ u32 start;
+ u32 len;
+ u8 data[];
+};
+
+struct mt7996_mem_region {
+ u32 start;
+ size_t len;
+
+ const char *name;
+};
+
+#ifdef CONFIG_DEV_COREDUMP
+
+const struct mt7996_mem_region *
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num);
+struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev);
+int mt7996_coredump_submit(struct mt7996_dev *dev);
+int mt7996_coredump_register(struct mt7996_dev *dev);
+void mt7996_coredump_unregister(struct mt7996_dev *dev);
+
+#else /* CONFIG_DEV_COREDUMP */
+
+static inline const struct mt7996_mem_region *
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
+{
+ return NULL;
+}
+
+static inline int mt7996_coredump_submit(struct mt7996_dev *dev)
+{
+ return 0;
+}
+
+static inline struct
+mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
+{
+ return NULL;
+}
+
+static inline int mt7996_coredump_register(struct mt7996_dev *dev)
+{
+ return 0;
+}
+
+static inline void mt7996_coredump_unregister(struct mt7996_dev *dev)
+{
+}
+
+#endif /* CONFIG_DEV_COREDUMP */
+
+#endif /* _COREDUMP_H_ */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index 9c5e9ac1c335..513ab4ba41c9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
/* test knob of system error recovery */
static ssize_t
-mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
+mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
struct mt7996_phy *phy = file->private_data;
struct mt7996_dev *dev = phy->dev;
- u8 band_idx = phy->mt76->band_idx;
+ bool band = phy->mt76->band_idx;
char buf[16];
int ret = 0;
u16 val;
@@ -73,17 +73,47 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
return -EINVAL;
switch (val) {
- case SER_SET_RECOVER_L1:
- case SER_SET_RECOVER_L2:
- 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 = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx);
+ /*
+ * 0: grab firmware current SER state.
+ * 1: trigger & enable system error L1 recovery.
+ * 2: trigger & enable system error L2 recovery.
+ * 3: trigger & enable system error L3 rx abort.
+ * 4: trigger & enable system error L3 tx abort
+ * 5: trigger & enable system error L3 tx disable.
+ * 6: trigger & enable system error L3 bf recovery.
+ * 7: trigger & enable system error L4 mdp recovery.
+ * 8: trigger & enable system error full recovery.
+ * 9: trigger firmware crash.
+ */
+ case UNI_CMD_SER_QUERY:
+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
+ break;
+ case UNI_CMD_SER_SET_RECOVER_L1:
+ case UNI_CMD_SER_SET_RECOVER_L2:
+ case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
+ case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
+ case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
+ case UNI_CMD_SER_SET_RECOVER_L3_BF:
+ case UNI_CMD_SER_SET_RECOVER_L4_MDP:
+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
if (ret)
return ret;
- ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx);
+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
+ break;
+
+ /* enable full chip reset */
+ case UNI_CMD_SER_SET_RECOVER_FULL:
+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
+ dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
+ mt7996_reset(dev);
+ break;
+
+ /* WARNING: trigger firmware crash */
+ case UNI_CMD_SER_SET_SYSTEM_ASSERT:
+ ret = mt7996_mcu_trigger_assert(dev);
+ if (ret)
+ return ret;
break;
default:
break;
@@ -92,9 +122,97 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
return ret ? ret : count;
}
-static const struct file_operations mt7996_fw_ser_ops = {
- .write = mt7996_fw_ser_set,
- /* TODO: ser read */
+static ssize_t
+mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mt7996_phy *phy = file->private_data;
+ struct mt7996_dev *dev = phy->dev;
+ char *buff;
+ int desc = 0;
+ ssize_t ret;
+ static const size_t bufsz = 1024;
+
+ buff = kmalloc(bufsz, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ /* HELP */
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "Please echo the correct value ...\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "0: grab firmware transient SER state\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "1: trigger system error L1 recovery\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "2: trigger system error L2 recovery\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "3: trigger system error L3 rx abort\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "4: trigger system error L3 tx abort\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "5: trigger system error L3 tx disable\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "6: trigger system error L3 bf recovery\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "7: trigger system error L4 mdp recovery\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "8: trigger system error full recovery\n");
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "9: trigger firmware crash\n");
+
+ /* SER statistics */
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "\nlet's dump firmware SER statistics...\n");
+ 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_WISR6_B2 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_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));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_LMAC_WISR7_B2 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "\nSYS_RESET_COUNT: WM %d, WA %d\n",
+ dev->recovery.wm_reset_count,
+ dev->recovery.wa_reset_count);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+ kfree(buff);
+ return ret;
+}
+
+static const struct file_operations mt7996_sys_recovery_ops = {
+ .write = mt7996_sys_recovery_set,
+ .read = mt7996_sys_recovery_get,
.open = simple_open,
.llseek = default_llseek,
};
@@ -674,6 +792,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
debugfs_create_file("xmit-queues", 0400, dir, phy,
&mt7996_xmit_queues_fops);
debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops);
+ debugfs_create_file("sys_recovery", 0600, dir, phy,
+ &mt7996_sys_recovery_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);
@@ -684,7 +804,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
&fops_implicit_txbf);
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
mt7996_twt_stats);
- debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops);
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
if (phy->mt76->cap.has_5ghz) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
index c09fe4274935..534143465d9b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
@@ -352,6 +352,70 @@ int mt7996_dma_init(struct mt7996_dev *dev)
return 0;
}
+void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
+{
+ struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
+ struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
+ u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+ int i;
+
+ mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+
+ if (dev->hif2)
+ mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+
+ usleep_range(1000, 2000);
+
+ for (i = 0; i < __MT_TXQ_MAX; i++) {
+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+ if (phy2)
+ mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
+ if (phy3)
+ mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
+ }
+
+ for (i = 0; i < __MT_MCUQ_MAX; i++)
+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
+
+ mt76_for_each_q_rx(&dev->mt76, i)
+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
+
+ mt76_tx_status_check(&dev->mt76, true);
+
+ /* reset wfsys */
+ if (force)
+ mt7996_wfsys_reset(dev);
+
+ mt7996_dma_disable(dev, force);
+
+ /* reset hw queues */
+ for (i = 0; i < __MT_TXQ_MAX; i++) {
+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
+ if (phy2)
+ mt76_queue_reset(dev, phy2->q_tx[i]);
+ if (phy3)
+ mt76_queue_reset(dev, phy3->q_tx[i]);
+ }
+
+ for (i = 0; i < __MT_MCUQ_MAX; i++)
+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
+
+ mt76_for_each_q_rx(&dev->mt76, i) {
+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
+ }
+
+ mt76_tx_status_check(&dev->mt76, true);
+
+ mt76_for_each_q_rx(&dev->mt76, i)
+ mt76_queue_rx_reset(dev, i);
+
+ mt7996_dma_enable(dev);
+}
+
void mt7996_dma_cleanup(struct mt7996_dev *dev)
{
mt7996_dma_disable(dev, true);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c
index 2e48c5a40f81..544b6c6f1ea3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c
@@ -138,10 +138,6 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
case MT_EE_BAND_SEL_6GHZ:
phy->mt76->cap.has_6ghz = true;
break;
- case MT_EE_BAND_SEL_5GHZ_6GHZ:
- phy->mt76->cap.has_5ghz = true;
- phy->mt76->cap.has_6ghz = true;
- break;
default:
ret = -EINVAL;
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h
index 8da599e0abea..0c749774f6b1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/eeprom.h
@@ -31,11 +31,11 @@ enum mt7996_eeprom_field {
#define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0)
#define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
-#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(5, 3)
-#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(2, 0)
+#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
+#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
#define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3)
-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(5, 3)
-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(2, 0)
+#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
+#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)
#define MT_EE_RATE_DELTA_MASK GENMASK(5, 0)
#define MT_EE_RATE_DELTA_SIGN BIT(6)
@@ -46,7 +46,6 @@ enum mt7996_eeprom_band {
MT_EE_BAND_SEL_2GHZ,
MT_EE_BAND_SEL_5GHZ,
MT_EE_BAND_SEL_6GHZ,
- MT_EE_BAND_SEL_5GHZ_6GHZ,
};
static inline int
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index 946da93eed32..f1b48cdda58f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -8,6 +8,7 @@
#include "mt7996.h"
#include "mac.h"
#include "mcu.h"
+#include "coredump.h"
#include "eeprom.h"
static const struct ieee80211_iface_limit if_limits[] = {
@@ -99,9 +100,8 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
mt7996_led_set_config(led_cdev, 0xff, 0);
}
-static void
-mt7996_init_txpower(struct mt7996_dev *dev,
- struct ieee80211_supported_band *sband)
+void mt7996_init_txpower(struct mt7996_dev *dev,
+ struct ieee80211_supported_band *sband)
{
int i, nss = hweight8(dev->mphy.antenna_mask);
int nss_delta = mt76_tx_power_nss_delta(nss);
@@ -182,6 +182,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
if (!mdev->dev->of_node ||
!of_property_read_bool(mdev->dev->of_node,
@@ -196,10 +197,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
hw->max_tx_fragments = 4;
- if (phy->mt76->cap.has_2ghz)
+ if (phy->mt76->cap.has_2ghz) {
phy->mt76->sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
+ phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
+ IEEE80211_HT_MPDU_DENSITY_2;
+ }
if (phy->mt76->cap.has_5ghz) {
phy->mt76->sband_5g.sband.ht_cap.cap |=
@@ -211,6 +215,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
+ IEEE80211_HT_MPDU_DENSITY_1;
}
mt76_set_stream_caps(phy->mt76, true);
@@ -250,7 +256,21 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
}
-static void mt7996_mac_init(struct mt7996_dev *dev)
+static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
+ u16 rate = mt76_rates[i].hw_value;
+ u16 idx = MT7996_BASIC_RATES_TBL + i;
+
+ rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
+ FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
+ mt7996_mac_set_fixed_rate_table(dev, idx, rate);
+ }
+}
+
+void mt7996_mac_init(struct mt7996_dev *dev)
{
#define HIF_TXD_V2_1 4
int i;
@@ -282,9 +302,11 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
for (i = MT_BAND0; i <= MT_BAND2; i++)
mt7996_mac_init_band(dev, i);
+
+ mt7996_mac_init_basic_rates(dev);
}
-static int mt7996_txbf_init(struct mt7996_dev *dev)
+int mt7996_txbf_init(struct mt7996_dev *dev)
{
int ret;
@@ -553,27 +575,6 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
}
static void
-mt7996_gen_ppe_thresh(u8 *he_ppet, int nss)
-{
- u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
- 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,
- ru_bit_mask);
-
- ppet_bits = IEEE80211_PPE_THRES_INFO_PPET_SIZE *
- nss * hweight8(ru_bit_mask) * 2;
- ppet_size = DIV_ROUND_UP(ppet_bits, 8);
-
- for (i = 0; i < ppet_size - 1; i++)
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3];
-
- he_ppet[i + 1] = ppet16_ppet8_ru3_ru0[i % 3] &
- (0xff >> (8 - (ppet_bits - 1) % 8));
-}
-
-static void
mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data,
enum nl80211_iftype iftype)
@@ -678,7 +679,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
- mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss);
+ mt76_connac_gen_ppe_thresh(he_cap->ppe_thres, nss);
} else {
he_cap_elem->phy_cap_info[9] |=
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
@@ -689,7 +690,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
- cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
+ cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
@@ -858,6 +859,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7996_mac_reset_work);
+ INIT_WORK(&dev->dump_work, mt7996_mac_dump_work);
+ mutex_init(&dev->dump_mutex);
ret = mt7996_init_hardware(dev);
if (ret)
@@ -886,18 +889,25 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
- return mt7996_init_debugfs(&dev->phy);
+ dev->recovery.hw_init_done = true;
+
+ ret = mt7996_init_debugfs(&dev->phy);
+ if (ret)
+ return ret;
+
+ return mt7996_coredump_register(dev);
}
void mt7996_unregister_device(struct mt7996_dev *dev)
{
mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
+ mt7996_coredump_unregister(dev);
mt76_unregister_device(&dev->mt76);
mt7996_mcu_exit(dev);
mt7996_tx_token_put(dev);
mt7996_dma_cleanup(dev);
- tasklet_disable(&dev->irq_tasklet);
+ tasklet_disable(&dev->mt76.irq_tasklet);
mt76_free_device(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c9a9f0e31771..130eb7b4fd91 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -5,6 +5,7 @@
#include <linux/etherdevice.h>
#include <linux/timekeeping.h>
+#include "coredump.h"
#include "mt7996.h"
#include "../dma.h"
#include "mac.h"
@@ -78,10 +79,6 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
return &sta->vif->sta.wcid;
}
-void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
-{
-}
-
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
{
mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,
@@ -255,17 +252,25 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
mt76_clear(dev, addr, BIT(5));
}
+void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+ u8 tbl_idx, u16 rate_idx)
+{
+ u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
+
+ mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
+ /* use wtbl spe idx */
+ mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
+ mt76_wr(dev, MT_WTBL_ITCR, ctrl);
+}
+
static void
mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
struct ieee80211_radiotap_he *he,
__le32 *rxv)
{
- u32 ru_h, ru_l;
- u8 ru, offs = 0;
+ u32 ru, offs = 0;
- ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
- ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
- ru = (u8)(ru_l | ru_h << 4);
+ ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC);
status->bw = RATE_INFO_BW_HE_RU;
@@ -330,18 +335,23 @@ mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
- le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
+ le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
- he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
+ he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
if (status->bw >= RATE_INFO_BW_40) {
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
- he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
+ he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
}
if (status->bw >= RATE_INFO_BW_80) {
- he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
- he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
+ u32 ru_h, ru_l;
+
+ he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
+
+ ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
+ ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
+ he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
}
}
@@ -364,23 +374,23 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
HE_BITS(DATA2_TXOP_KNOWN),
};
struct ieee80211_radiotap_he *he = NULL;
- u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
+ u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
status->flag |= RX_FLAG_RADIOTAP_HE;
he = skb_push(skb, sizeof(known));
memcpy(he, &known, sizeof(known));
- he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
- HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
- he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
- he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
+ he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
+ HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
+ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
+ he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
le16_encode_bits(ltf_size,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
he->data5 |= HE_BITS(DATA5_TXBF);
- he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
- HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
+ he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
+ HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
switch (mode) {
case MT_PHY_TYPE_HE_SU:
@@ -389,22 +399,22 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
- he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
- HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
+ he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
+ HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_EXT_SU:
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
HE_BITS(DATA1_UL_DL_KNOWN) |
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
- he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
break;
case MT_PHY_TYPE_HE_MU:
he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
HE_BITS(DATA1_UL_DL_KNOWN);
- he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
- he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
+ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
mt7996_mac_decode_he_mu_radiotap(skb, rxv);
@@ -415,10 +425,10 @@ mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
- he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
- HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
- HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
- HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
+ he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
break;
@@ -570,11 +580,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
case MT_PHY_TYPE_EHT_SU:
case MT_PHY_TYPE_EHT_TRIG:
case MT_PHY_TYPE_EHT_MU:
- /* TODO: currently report rx rate with HE rate */
status->nss = nss;
- status->encoding = RX_ENC_HE;
- bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
- i = min_t(int, i & 0xf, 11);
+ status->encoding = RX_ENC_EHT;
+ i &= GENMASK(3, 0);
+
+ if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
+ status->eht.gi = gi;
break;
default:
return -EINVAL;
@@ -630,6 +641,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
u32 rxd4 = le32_to_cpu(rxd[4]);
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
u32 csum_status = *(u32 *)skb->cb;
+ u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP;
+ bool is_mesh = (rxd0 & mesh_mask) == mesh_mask;
bool unicast, insert_ccmp_hdr = false;
u8 remove_pad, amsdu_info, band_idx;
u8 mode = 0, qos_ctl = 0;
@@ -821,19 +834,16 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
int pad_start = 0;
skb_pull(skb, hdr_gap);
- if (!hdr_trans && status->amsdu) {
+ if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) {
pad_start = ieee80211_get_hdrlen_from_skb(skb);
- } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
+ } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) &&
+ get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) {
/* When header translation failure is indicated,
* the hardware will insert an extra 2-byte field
* containing the data length after the protocol
* type field.
*/
- pad_start = 12;
- if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
- pad_start += 4;
- else
- pad_start = 0;
+ pad_start = 16;
}
if (pad_start) {
@@ -854,8 +864,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
hdr = mt76_skb_get_hdr(skb);
fc = hdr->frame_control;
if (ieee80211_is_data_qos(fc)) {
+ u8 *qos = ieee80211_get_qos_ctl(hdr);
+
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
- qos_ctl = *ieee80211_get_qos_ctl(hdr);
+ qos_ctl = *qos;
+
+ /* Mesh DA/SA/Length will be stripped after hardware
+ * de-amsdu, so here needs to clear amsdu present bit
+ * to mark it as a normal mesh frame.
+ */
+ if (ieee80211_has_a4(fc) && is_mesh && status->amsdu)
+ *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
}
} else {
status->flag |= RX_FLAG_8023;
@@ -979,12 +998,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
}
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
- struct ieee80211_key_conf *key, u32 changed)
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key, int pid,
+ enum mt76_txq_id qid, u32 changed)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct mt76_phy *mphy = &dev->mphy;
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
@@ -996,22 +1016,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
BSS_CHANGED_FILS_DISCOVERY));
if (vif) {
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-
omac_idx = mvif->mt76.omac_idx;
wmm_idx = mvif->mt76.wmm_idx;
band_idx = mvif->mt76.band_idx;
}
- mphy = mt76_dev_phy(&dev->mt76, band_idx);
-
if (inband_disc) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_ALTX0;
} else if (beacon) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_BCN0;
- } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
+ } else if (qid >= MT_TXQ_PSD) {
p_fmt = MT_TX_TYPE_CT;
q_idx = MT_LMAC_ALTX0;
} else {
@@ -1062,18 +1078,17 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
- /* Fixed rata is available just for 802.11 txd */
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- bool multicast = is_multicast_ether_addr(hdr->addr1);
- u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
- multicast);
+ bool mcast = ieee80211_is_data(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1);
+ u8 idx = mvif->basic_rates_idx;
- /* fix to bw 20 */
- val = MT_TXD6_FIXED_BW |
- FIELD_PREP(MT_TXD6_BW, 0) |
- FIELD_PREP(MT_TXD6_TX_RATE, rate);
+ if (mcast && mvif->mcast_rates_idx)
+ idx = mvif->mcast_rates_idx;
+ else if (beacon && mvif->beacon_rates_idx)
+ idx = mvif->beacon_rates_idx;
- txwi[6] |= cpu_to_le32(val);
+ txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx);
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
}
@@ -1117,11 +1132,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return id;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
- memset(txwi_ptr, 0, MT_TXD_SIZE);
- /* Transmit non qos data by 802.11 header and need to fill txd by host*/
- if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
- key, 0);
+ mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
+ pid, qid, 0);
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
for (i = 0; i < nbuf; i++) {
@@ -1130,10 +1142,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
txp->fw.nbuf = nbuf;
- txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
-
- if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
- txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
+ txp->fw.flags =
+ cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD);
if (!key)
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
@@ -1704,7 +1714,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
bool ret;
ret = wait_event_timeout(dev->reset_wait,
- (READ_ONCE(dev->reset_state) & state),
+ (READ_ONCE(dev->recovery.state) & state),
MT7996_RESET_TIMEOUT);
WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
@@ -1753,68 +1763,207 @@ mt7996_update_beacons(struct mt7996_dev *dev)
mt7996_update_vif_beacon, phy3->hw);
}
-static void
-mt7996_dma_reset(struct mt7996_dev *dev)
+void mt7996_tx_token_put(struct mt7996_dev *dev)
{
- struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
- struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
- int i;
+ struct mt76_txwi_cache *txwi;
+ int id;
- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+ spin_lock_bh(&dev->mt76.token_lock);
+ idr_for_each_entry(&dev->mt76.token, txwi, id) {
+ mt7996_txwi_free(dev, txwi, NULL, NULL);
+ dev->mt76.token_count--;
+ }
+ spin_unlock_bh(&dev->mt76.token_lock);
+ idr_destroy(&dev->mt76.token);
+}
- if (dev->hif2)
- mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+static int
+mt7996_mac_restart(struct mt7996_dev *dev)
+{
+ struct mt7996_phy *phy2, *phy3;
+ struct mt76_dev *mdev = &dev->mt76;
+ int i, ret;
- usleep_range(1000, 2000);
+ phy2 = mt7996_phy2(dev);
+ phy3 = mt7996_phy3(dev);
- for (i = 0; i < __MT_TXQ_MAX; i++) {
- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
- if (phy2)
- mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
- if (phy3)
- mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
+ if (dev->hif2) {
+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
}
- for (i = 0; i < __MT_MCUQ_MAX; i++)
- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
+ if (dev_is_pci(mdev->dev)) {
+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
+ if (dev->hif2)
+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
+ }
- mt76_for_each_q_rx(&dev->mt76, i)
- mt76_queue_rx_reset(dev, i);
+ set_bit(MT76_RESET, &dev->mphy.state);
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ wake_up(&dev->mt76.mcu.wait);
+ if (phy2) {
+ set_bit(MT76_RESET, &phy2->mt76->state);
+ set_bit(MT76_MCU_RESET, &phy2->mt76->state);
+ }
+ if (phy3) {
+ set_bit(MT76_RESET, &phy3->mt76->state);
+ set_bit(MT76_MCU_RESET, &phy3->mt76->state);
+ }
+
+ /* lock/unlock all queues to ensure that no tx is pending */
+ mt76_txq_schedule_all(&dev->mphy);
+ if (phy2)
+ mt76_txq_schedule_all(phy2->mt76);
+ if (phy3)
+ mt76_txq_schedule_all(phy3->mt76);
+
+ /* disable all tx/rx napi */
+ mt76_worker_disable(&dev->mt76.tx_worker);
+ mt76_for_each_q_rx(mdev, i) {
+ if (mdev->q_rx[i].ndesc)
+ napi_disable(&dev->mt76.napi[i]);
+ }
+ napi_disable(&dev->mt76.tx_napi);
+
+ /* token reinit */
+ mt7996_tx_token_put(dev);
+ idr_init(&dev->mt76.token);
+
+ mt7996_dma_reset(dev, true);
- mt76_tx_status_check(&dev->mt76, true);
+ local_bh_disable();
+ mt76_for_each_q_rx(mdev, i) {
+ if (mdev->q_rx[i].ndesc) {
+ napi_enable(&dev->mt76.napi[i]);
+ napi_schedule(&dev->mt76.napi[i]);
+ }
+ }
+ local_bh_enable();
+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
+
+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
+ if (dev->hif2) {
+ mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
+ }
+ if (dev_is_pci(mdev->dev)) {
+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
+ if (dev->hif2)
+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
+ }
+
+ /* load firmware */
+ ret = mt7996_mcu_init_firmware(dev);
+ if (ret)
+ goto out;
- /* re-init prefetch settings after reset */
- mt7996_dma_prefetch(dev);
+ /* set the necessary init items */
+ ret = mt7996_mcu_set_eeprom(dev);
+ if (ret)
+ goto out;
- mt76_set(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+ mt7996_mac_init(dev);
+ mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
+ mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
+ mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
+ ret = mt7996_txbf_init(dev);
- if (dev->hif2)
- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
+ ret = mt7996_run(dev->mphy.hw);
+ if (ret)
+ goto out;
+ }
+
+ if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
+ ret = mt7996_run(phy2->mt76->hw);
+ if (ret)
+ goto out;
+ }
+
+ if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
+ ret = mt7996_run(phy3->mt76->hw);
+ if (ret)
+ goto out;
+ }
+
+out:
+ /* reset done */
+ clear_bit(MT76_RESET, &dev->mphy.state);
+ if (phy2)
+ clear_bit(MT76_RESET, &phy2->mt76->state);
+ if (phy3)
+ clear_bit(MT76_RESET, &phy3->mt76->state);
+
+ local_bh_disable();
+ napi_enable(&dev->mt76.tx_napi);
+ napi_schedule(&dev->mt76.tx_napi);
+ local_bh_enable();
+
+ mt76_worker_enable(&dev->mt76.tx_worker);
+ return ret;
}
-void mt7996_tx_token_put(struct mt7996_dev *dev)
+static void
+mt7996_mac_full_reset(struct mt7996_dev *dev)
{
- struct mt76_txwi_cache *txwi;
- int id;
+ struct mt7996_phy *phy2, *phy3;
+ int i;
- spin_lock_bh(&dev->mt76.token_lock);
- idr_for_each_entry(&dev->mt76.token, txwi, id) {
- mt7996_txwi_free(dev, txwi, NULL, NULL);
- dev->mt76.token_count--;
+ phy2 = mt7996_phy2(dev);
+ phy3 = mt7996_phy3(dev);
+ dev->recovery.hw_full_reset = true;
+
+ wake_up(&dev->mt76.mcu.wait);
+ ieee80211_stop_queues(mt76_hw(dev));
+ if (phy2)
+ ieee80211_stop_queues(phy2->mt76->hw);
+ if (phy3)
+ ieee80211_stop_queues(phy3->mt76->hw);
+
+ cancel_delayed_work_sync(&dev->mphy.mac_work);
+ if (phy2)
+ cancel_delayed_work_sync(&phy2->mt76->mac_work);
+ if (phy3)
+ cancel_delayed_work_sync(&phy3->mt76->mac_work);
+
+ mutex_lock(&dev->mt76.mutex);
+ for (i = 0; i < 10; i++) {
+ if (!mt7996_mac_restart(dev))
+ break;
}
- spin_unlock_bh(&dev->mt76.token_lock);
- idr_destroy(&dev->mt76.token);
+ mutex_unlock(&dev->mt76.mutex);
+
+ if (i == 10)
+ dev_err(dev->mt76.dev, "chip full reset failed\n");
+
+ ieee80211_restart_hw(mt76_hw(dev));
+ if (phy2)
+ ieee80211_restart_hw(phy2->mt76->hw);
+ if (phy3)
+ ieee80211_restart_hw(phy3->mt76->hw);
+
+ ieee80211_wake_queues(mt76_hw(dev));
+ if (phy2)
+ ieee80211_wake_queues(phy2->mt76->hw);
+ if (phy3)
+ ieee80211_wake_queues(phy3->mt76->hw);
+
+ dev->recovery.hw_full_reset = false;
+ ieee80211_queue_delayed_work(mt76_hw(dev),
+ &dev->mphy.mac_work,
+ MT7996_WATCHDOG_TIME);
+ if (phy2)
+ ieee80211_queue_delayed_work(phy2->mt76->hw,
+ &phy2->mt76->mac_work,
+ MT7996_WATCHDOG_TIME);
+ if (phy3)
+ ieee80211_queue_delayed_work(phy3->mt76->hw,
+ &phy3->mt76->mac_work,
+ MT7996_WATCHDOG_TIME);
}
-/* system error recovery */
void mt7996_mac_reset_work(struct work_struct *work)
{
struct mt7996_phy *phy2, *phy3;
@@ -1825,9 +1974,36 @@ void mt7996_mac_reset_work(struct work_struct *work)
phy2 = mt7996_phy2(dev);
phy3 = mt7996_phy3(dev);
- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
+ /* chip full reset */
+ if (dev->recovery.restart) {
+ /* disable WA/WM WDT */
+ mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
+ MT_MCU_CMD_WDT_MASK);
+
+ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
+ dev->recovery.wa_reset_count++;
+ else
+ dev->recovery.wm_reset_count++;
+
+ mt7996_mac_full_reset(dev);
+
+ /* enable mcu irq */
+ mt7996_irq_enable(dev, MT_INT_MCU_CMD);
+ mt7996_irq_disable(dev, 0);
+
+ /* enable WA/WM WDT */
+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
+
+ dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
+ dev->recovery.restart = false;
+ return;
+ }
+
+ if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
return;
+ dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
+ wiphy_name(dev->mt76.hw->wiphy));
ieee80211_stop_queues(mt76_hw(dev));
if (phy2)
ieee80211_stop_queues(phy2->mt76->hw);
@@ -1856,7 +2032,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
- mt7996_dma_reset(dev);
+ mt7996_dma_reset(dev, false);
mt7996_tx_token_put(dev);
idr_init(&dev->mt76.token);
@@ -1879,7 +2055,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
}
local_bh_enable();
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
@@ -1911,6 +2087,101 @@ void mt7996_mac_reset_work(struct work_struct *work)
ieee80211_queue_delayed_work(phy3->mt76->hw,
&phy3->mt76->mac_work,
MT7996_WATCHDOG_TIME);
+ dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
+ wiphy_name(dev->mt76.hw->wiphy));
+}
+
+/* firmware coredump */
+void mt7996_mac_dump_work(struct work_struct *work)
+{
+ const struct mt7996_mem_region *mem_region;
+ struct mt7996_crash_data *crash_data;
+ struct mt7996_dev *dev;
+ struct mt7996_mem_hdr *hdr;
+ size_t buf_len;
+ int i;
+ u32 num;
+ u8 *buf;
+
+ dev = container_of(work, struct mt7996_dev, dump_work);
+
+ mutex_lock(&dev->dump_mutex);
+
+ crash_data = mt7996_coredump_new(dev);
+ if (!crash_data) {
+ mutex_unlock(&dev->dump_mutex);
+ goto skip_coredump;
+ }
+
+ mem_region = mt7996_coredump_get_mem_layout(dev, &num);
+ if (!mem_region || !crash_data->memdump_buf_len) {
+ mutex_unlock(&dev->dump_mutex);
+ goto skip_memdump;
+ }
+
+ buf = crash_data->memdump_buf;
+ buf_len = crash_data->memdump_buf_len;
+
+ /* dumping memory content... */
+ memset(buf, 0, buf_len);
+ for (i = 0; i < num; i++) {
+ if (mem_region->len > buf_len) {
+ dev_warn(dev->mt76.dev, "%s len %zu is too large\n",
+ mem_region->name, mem_region->len);
+ break;
+ }
+
+ /* reserve space for the header */
+ hdr = (void *)buf;
+ buf += sizeof(*hdr);
+ buf_len -= sizeof(*hdr);
+
+ mt7996_memcpy_fromio(dev, buf, mem_region->start,
+ mem_region->len);
+
+ hdr->start = mem_region->start;
+ hdr->len = mem_region->len;
+
+ if (!mem_region->len)
+ /* note: the header remains, just with zero length */
+ break;
+
+ buf += mem_region->len;
+ buf_len -= mem_region->len;
+
+ mem_region++;
+ }
+
+ mutex_unlock(&dev->dump_mutex);
+
+skip_memdump:
+ mt7996_coredump_submit(dev);
+skip_coredump:
+ queue_work(dev->mt76.wq, &dev->reset_work);
+}
+
+void mt7996_reset(struct mt7996_dev *dev)
+{
+ if (!dev->recovery.hw_init_done)
+ return;
+
+ if (dev->recovery.hw_full_reset)
+ return;
+
+ /* wm/wa exception: do full recovery */
+ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
+ dev->recovery.restart = true;
+ dev_info(dev->mt76.dev,
+ "%s indicated firmware crash, attempting recovery\n",
+ wiphy_name(dev->mt76.hw->wiphy));
+
+ mt7996_irq_disable(dev, MT_INT_MCU_CMD);
+ queue_work(dev->mt76.wq, &dev->dump_work);
+ return;
+ }
+
+ queue_work(dev->mt76.wq, &dev->reset_work);
+ wake_up(&dev->reset_wait);
}
void mt7996_mac_update_stats(struct mt7996_phy *phy)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
index 27184cbac619..bc4e6c55373e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
@@ -12,6 +12,8 @@
#define MT_RXD0_LENGTH GENMASK(15, 0)
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
+#define MT_RXD0_MESH BIT(18)
+#define MT_RXD0_MHCP BIT(19)
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
@@ -20,18 +22,6 @@
#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
-enum rx_pkt_type {
- PKT_TYPE_TXS,
- PKT_TYPE_TXRXV,
- PKT_TYPE_NORMAL,
- PKT_TYPE_RX_DUP_RFB,
- PKT_TYPE_RX_TMR,
- PKT_TYPE_RETRIEVE,
- PKT_TYPE_TXRX_NOTIFY,
- PKT_TYPE_RX_EVENT,
- PKT_TYPE_RX_FW_MONITOR = 0x0c,
-};
-
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
@@ -102,8 +92,7 @@ enum rx_pkt_type {
#define MT_PRXV_NSTS GENMASK(10, 7)
#define MT_PRXV_TXBF BIT(11)
#define MT_PRXV_HT_AD_CODE BIT(12)
-#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
-#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
+#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
@@ -113,34 +102,32 @@ enum rx_pkt_type {
#define MT_PRXV_TX_MODE GENMASK(14, 11)
#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
#define MT_PRXV_DCM BIT(5)
-#define MT_PRXV_NUM_RX BIT(8, 6)
/* C-RXV */
-#define MT_CRXV_HT_STBC GENMASK(1, 0)
-#define MT_CRXV_TX_MODE GENMASK(7, 4)
-#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
-#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
-#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
-#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
-#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
-#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
-#define MT_CRXV_HE_UPLINK BIT(31)
-#define MT_CRXV_HE_RU0 GENMASK(7, 0)
-#define MT_CRXV_HE_RU1 GENMASK(15, 8)
-#define MT_CRXV_HE_RU2 GENMASK(23, 16)
-#define MT_CRXV_HE_RU3 GENMASK(31, 24)
-
-#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
+#define MT_CRXV_HE_NUM_USER GENMASK(26, 20)
+#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27)
+#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30)
+
+#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
+#define MT_CRXV_HE_UPLINK BIT(2)
+
+#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
+#define MT_CRXV_HE_BEAM_CHNG BIT(29)
+
+#define MT_CRXV_HE_DOPPLER BIT(0)
+#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
+#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
-#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
-#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
-#define MT_CRXV_HE_BEAM_CHNG BIT(13)
-#define MT_CRXV_HE_DOPPLER BIT(16)
+#define MT_CRXV_HE_RU0 GENMASK(8, 0)
+#define MT_CRXV_HE_RU1 GENMASK(17, 9)
+#define MT_CRXV_HE_RU2 GENMASK(26, 18)
+#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
+#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
enum tx_header_format {
MT_HDR_FORMAT_802_3,
@@ -239,14 +226,11 @@ enum tx_mgnt_type {
#define MT_TXD6_TX_SRC GENMASK(31, 30)
#define MT_TXD6_VTA BIT(28)
-#define MT_TXD6_FIXED_BW BIT(25)
-#define MT_TXD6_BW GENMASK(24, 22)
+#define MT_TXD6_BW GENMASK(25, 22)
#define MT_TXD6_TX_RATE GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
-#define MT_TXD6_SPE_ID_IDX BIT(10)
-#define MT_TXD6_ANT_ID GENMASK(7, 4)
#define MT_TXD6_DIS_MAT BIT(3)
#define MT_TXD6_DAS BIT(2)
#define MT_TXD6_AMSDU_CAP BIT(1)
@@ -260,7 +244,7 @@ enum tx_mgnt_type {
#define MT_TXD7_UDP_TCP_SUM BIT(15)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
-#define MT_TX_RATE_STBC BIT(13)
+#define MT_TX_RATE_STBC BIT(14)
#define MT_TX_RATE_NSS GENMASK(13, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 1ba22d147949..f306e9c50ea3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -5,6 +5,7 @@
#include "mt7996.h"
#include "mcu.h"
+#include "mac.h"
static bool mt7996_dev_running(struct mt7996_dev *dev)
{
@@ -22,17 +23,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
}
-static int mt7996_start(struct ieee80211_hw *hw)
+int mt7996_run(struct ieee80211_hw *hw)
{
struct mt7996_dev *dev = mt7996_hw_dev(hw);
struct mt7996_phy *phy = mt7996_hw_phy(hw);
bool running;
int ret;
- flush_work(&dev->init_work);
-
- mutex_lock(&dev->mt76.mutex);
-
running = mt7996_dev_running(dev);
if (!running) {
ret = mt7996_mcu_set_hdr_trans(dev, true);
@@ -52,10 +49,6 @@ static int mt7996_start(struct ieee80211_hw *hw)
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
- ieee80211_iterate_interfaces(dev->mt76.hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7996_mcu_set_pm, dev->mt76.hw);
-
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
MT7996_WATCHDOG_TIME);
@@ -63,6 +56,18 @@ static int mt7996_start(struct ieee80211_hw *hw)
mt7996_mac_reset_counters(phy);
out:
+ return ret;
+}
+
+static int mt7996_start(struct ieee80211_hw *hw)
+{
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ int ret;
+
+ flush_work(&dev->init_work);
+
+ mutex_lock(&dev->mt76.mutex);
+ ret = mt7996_run(hw);
mutex_unlock(&dev->mt76.mutex);
return ret;
@@ -79,10 +84,6 @@ static void mt7996_stop(struct ieee80211_hw *hw)
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
- ieee80211_iterate_interfaces(dev->mt76.hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7996_mcu_set_pm, dev->mt76.hw);
-
mutex_unlock(&dev->mt76.mutex);
}
@@ -219,8 +220,12 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
vif->offload_flags = 0;
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
+ if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
+ mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
+ else
+ mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;
+
mt7996_init_bitrate_mask(vif);
- memset(&mvif->cap, -1, sizeof(mvif->cap));
mt7996_mcu_add_bss_info(phy, vif, true);
mt7996_mcu_add_sta(dev, vif, NULL, true);
@@ -496,11 +501,41 @@ mt7996_update_bss_color(struct ieee80211_hw *hw,
}
}
+static u8
+mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ bool beacon, bool mcast)
+{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt76_phy *mphy = hw->priv;
+ u16 rate;
+ u8 i, idx, ht;
+
+ rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
+ ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
+
+ if (beacon && ht) {
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+
+ /* must odd index */
+ idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
+ mt7996_mac_set_fixed_rate_table(dev, idx, rate);
+ return idx;
+ }
+
+ idx = FIELD_GET(MT_TX_RATE_IDX, rate);
+ for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
+ if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
+ return MT7996_BASIC_RATES_TBL + i;
+
+ return mvif->basic_rates_idx;
+}
+
static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u64 changed)
{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_dev *dev = mt7996_hw_dev(hw);
@@ -532,6 +567,14 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
}
}
+ if (changed & BSS_CHANGED_MCAST_RATE)
+ mvif->mcast_rates_idx =
+ mt7996_get_rates_table(hw, vif, false, true);
+
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ mvif->basic_rates_idx =
+ mt7996_get_rates_table(hw, vif, false, false);
+
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
mt7996_mcu_add_bss_info(phy, vif, true);
mt7996_mcu_add_sta(dev, vif, NULL, true);
@@ -548,8 +591,12 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
mt7996_update_bss_color(hw, vif, &info->he_bss_color);
if (changed & (BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED))
+ BSS_CHANGED_BEACON_ENABLED)) {
+ mvif->beacon_rates_idx =
+ mt7996_get_rates_table(hw, vif, true, false);
+
mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
+ }
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
changed & BSS_CHANGED_FILS_DISCOVERY)
@@ -891,6 +938,7 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
mt7996_set_stream_vht_txbf_caps(phy);
mt7996_set_stream_he_eht_caps(phy);
+ /* TODO: update bmc_wtbl spe_idx when antenna changes */
mutex_unlock(&dev->mt76.mutex);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index dbe30832fd88..88e2f9d0e513 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -422,7 +422,8 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
if (hdr->band && dev->mt76.phys[hdr->band])
mphy = dev->mt76.phys[hdr->band];
- tail = skb->data + le16_to_cpu(rxd->len);
+ tail = skb->data + skb->len;
+ data += sizeof(struct header);
while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) {
switch (le16_to_cpu(tlv->tag)) {
case UNI_EVENT_IE_COUNTDOWN_CSA:
@@ -596,25 +597,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
}
static void
-mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7996_phy *phy)
+mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ struct mt7996_phy *phy)
{
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct bss_rate_tlv *bmc;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
enum nl80211_band band = chandef->chan->band;
struct tlv *tlv;
+ u8 idx = mvif->mcast_rates_idx ?
+ mvif->mcast_rates_idx : mvif->basic_rates_idx;
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc));
bmc = (struct bss_rate_tlv *)tlv;
- if (band == NL80211_BAND_2GHZ) {
- bmc->short_preamble = true;
- } else {
- bmc->bc_trans = cpu_to_le16(0x8080);
- bmc->mc_trans = cpu_to_le16(0x8080);
- bmc->bc_fixed_rate = 1;
- bmc->mc_fixed_rate = 1;
- bmc->short_preamble = 1;
- }
+
+ bmc->short_preamble = (band == NL80211_BAND_2GHZ);
+ bmc->bc_fixed_rate = idx;
+ bmc->mc_fixed_rate = idx;
}
static void
@@ -822,7 +822,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
if (enable) {
mt7996_mcu_bss_rfch_tlv(skb, vif, phy);
- mt7996_mcu_bss_bmc_tlv(skb, phy);
+ mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
mt7996_mcu_bss_ra_tlv(skb, vif, phy);
mt7996_mcu_bss_txcmd_tlv(skb, true);
@@ -1022,6 +1022,7 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct tlv *tlv;
if (vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_MESH_POINT &&
vif->type != NL80211_IFTYPE_AP)
return;
@@ -1053,7 +1054,6 @@ static inline bool
mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
{
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
int sts = hweight16(phy->mt76->chainmask);
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -1068,10 +1068,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
if (bfee)
- return mvif->cap.eht_su_ebfee &&
+ return vif->bss_conf.eht_su_beamformee &&
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
else
- return mvif->cap.eht_su_ebfer &&
+ return vif->bss_conf.eht_su_beamformer &&
EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
}
@@ -1079,10 +1079,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
if (bfee)
- return mvif->cap.he_su_ebfee &&
+ return vif->bss_conf.he_su_beamformee &&
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
else
- return mvif->cap.he_su_ebfer &&
+ return vif->bss_conf.he_su_beamformer &&
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
}
@@ -1090,10 +1090,10 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
u32 cap = sta->deflink.vht_cap.cap;
if (bfee)
- return mvif->cap.vht_su_ebfee &&
+ return vif->bss_conf.vht_su_beamformee &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
else
- return mvif->cap.vht_su_ebfer &&
+ return vif->bss_conf.vht_su_beamformer &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
}
@@ -1471,6 +1471,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
hdr_trans->to_ds = true;
hdr_trans->from_ds = true;
}
+
+ if (vif->type == NL80211_IFTYPE_MESH_POINT) {
+ hdr_trans->to_ds = true;
+ hdr_trans->from_ds = true;
+ hdr_trans->mesh = true;
+ }
}
static enum mcu_mmps_mode
@@ -1572,7 +1578,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
cap |= STA_CAP_TX_STBC;
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
cap |= STA_CAP_RX_STBC;
- if (mvif->cap.ht_ldpc &&
+ if (vif->bss_conf.ht_ldpc &&
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC;
@@ -1598,7 +1604,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
cap |= STA_CAP_VHT_TX_STBC;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
cap |= STA_CAP_VHT_RX_STBC;
- if (mvif->cap.vht_ldpc &&
+ if (vif->bss_conf.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC;
@@ -1694,8 +1700,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
return PTR_ERR(skb);
/* starec basic */
- mt76_connac_mcu_sta_basic_tlv(skb, vif, sta, enable,
- !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
+ mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable,
+ !rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
if (!enable)
goto out;
@@ -1906,105 +1912,10 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
}
buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
+ mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
BSS_CHANGED_BEACON);
- memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
-}
-static void
-mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
- struct sk_buff *skb)
-{
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- struct mt7996_vif_cap *vc = &mvif->cap;
- const struct ieee80211_eht_cap_elem_fixed *eht;
- const struct ieee80211_he_cap_elem *he;
- const struct ieee80211_vht_cap *vht;
- const struct ieee80211_ht_cap *ht;
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- const u8 *ie;
- u32 len, bc;
-
- /* Check missing configuration options to allow AP mode in mac80211
- * to remain in sync with hostapd settings, and get a subset of
- * beacon and hardware capabilities.
- */
- if (WARN_ON_ONCE(skb->len <= (mgmt->u.beacon.variable - skb->data)))
- return;
-
- memset(vc, 0, sizeof(*vc));
-
- len = skb->len - (mgmt->u.beacon.variable - skb->data);
-
- ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable,
- len);
- if (ie && ie[1] >= sizeof(*ht)) {
- ht = (void *)(ie + 2);
- vc->ht_ldpc |= !!(le16_to_cpu(ht->cap_info) &
- IEEE80211_HT_CAP_LDPC_CODING);
- }
-
- ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
- len);
- if (ie && ie[1] >= sizeof(*vht)) {
- u32 pc = phy->mt76->sband_5g.sband.vht_cap.cap;
-
- vht = (void *)(ie + 2);
- bc = le32_to_cpu(vht->vht_cap_info);
-
- vc->vht_ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC);
- vc->vht_su_ebfer =
- (bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
- vc->vht_su_ebfee =
- (bc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
- vc->vht_mu_ebfer =
- (bc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
- vc->vht_mu_ebfee =
- (bc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
- (pc & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
- }
-
- ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY,
- mgmt->u.beacon.variable, len);
- if (ie && ie[1] >= sizeof(*he) + 1) {
- const struct ieee80211_sta_he_cap *pc =
- mt76_connac_get_he_phy_cap(phy->mt76, vif);
- const struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
-
- he = (void *)(ie + 3);
-
- vc->he_ldpc =
- HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
- vc->he_su_ebfer =
- HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
- HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
- vc->he_su_ebfee =
- HE_PHY(CAP4_SU_BEAMFORMEE, he->phy_cap_info[4]) &&
- HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
- vc->he_mu_ebfer =
- HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) &&
- HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]);
- }
-
- ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY,
- mgmt->u.beacon.variable, len);
- if (ie && ie[1] >= sizeof(*eht) + 1) {
- const struct ieee80211_sta_eht_cap *pc =
- mt76_connac_get_eht_phy_cap(phy->mt76, vif);
- const struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
-
- eht = (void *)(ie + 3);
-
- vc->eht_su_ebfer =
- EHT_PHY(CAP0_SU_BEAMFORMER, eht->phy_cap_info[0]) &&
- EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
- vc->eht_su_ebfee =
- EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) &&
- EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
- }
+ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
@@ -2045,8 +1956,6 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
- mt7996_mcu_beacon_check_caps(phy, vif, skb);
-
mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
/* TODO: subtag - 11v MBSSID */
mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
@@ -2115,8 +2024,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
- changed);
+ mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
@@ -2523,17 +2431,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
MCU_WM_UNI_CMD(VOW), true);
}
-int mt7996_mcu_init(struct mt7996_dev *dev)
+int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
{
- static const struct mt76_mcu_ops mt7996_mcu_ops = {
- .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
- .mcu_skb_send_msg = mt7996_mcu_send_message,
- .mcu_parse_response = mt7996_mcu_parse_response,
- };
int ret;
- dev->mt76.mcu_ops = &mt7996_mcu_ops;
-
/* force firmware operation mode into normal state,
* which should be set before firmware download stage.
*/
@@ -2574,6 +2475,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
MCU_WA_PARAM_RED, 0, 0);
}
+int mt7996_mcu_init(struct mt7996_dev *dev)
+{
+ static const struct mt76_mcu_ops mt7996_mcu_ops = {
+ .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
+ .mcu_skb_send_msg = mt7996_mcu_send_message,
+ .mcu_parse_response = mt7996_mcu_parse_response,
+ };
+
+ dev->mt76.mcu_ops = &mt7996_mcu_ops;
+
+ return mt7996_mcu_init_firmware(dev);
+}
+
void mt7996_mcu_exit(struct mt7996_dev *dev)
{
mt7996_mcu_restart(&dev->mt76);
@@ -3133,7 +3047,7 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
break;
default:
break;
- };
+ }
buf += le16_to_cpu(tlv->len);
}
@@ -3576,32 +3490,6 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
&req, sizeof(req), true);
}
-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif)
-{
-#define EXIT_PM_STATE 0
-#define ENTER_PM_STATE 1
- struct ieee80211_hw *hw = priv;
- struct mt7996_dev *dev = mt7996_hw_dev(hw);
- struct mt7996_phy *phy = mt7996_hw_phy(hw);
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- struct bss_power_save *ps;
- struct sk_buff *skb;
- struct tlv *tlv;
- bool running = test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
-
- skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
- MT7996_BSS_UPDATE_MAX_SIZE);
- if (IS_ERR(skb))
- return;
-
- tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PS, sizeof(*ps));
- ps = (struct bss_power_save *)tlv;
- ps->profile = running ? EXIT_PM_STATE : ENTER_PM_STATE;
-
- mt76_mcu_skb_send_msg(&dev->mt76, skb,
- MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
-}
-
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
{
struct {
@@ -3733,6 +3621,22 @@ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
return 0;
}
+int mt7996_mcu_trigger_assert(struct mt7996_dev *dev)
+{
+ struct {
+ __le16 tag;
+ __le16 len;
+ u8 enable;
+ u8 rsv[3];
+ } __packed req = {
+ .len = cpu_to_le16(sizeof(req) - 4),
+ .enable = true,
+ };
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ASSERT_DUMP),
+ &req, sizeof(req), false);
+}
+
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
{
struct {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index dd0c5ac52703..d7075a4d0667 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -396,7 +396,7 @@ struct sta_rec_hdr_trans {
u8 from_ds;
u8 to_ds;
u8 dis_rx_hdr_tran;
- u8 rsv;
+ u8 mesh;
} __packed;
struct hdr_trans_en {
@@ -648,23 +648,21 @@ enum {
};
enum {
- UNI_CMD_SER_QUERY = 0x0,
- UNI_CMD_SER_SET = 0x2,
- UNI_CMD_SER_TRIGGER = 0x3,
-};
-
-enum {
- SER_QUERY,
+ UNI_CMD_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,
+ UNI_CMD_SER_SET_RECOVER_L1,
+ UNI_CMD_SER_SET_RECOVER_L2,
+ UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT,
+ UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT,
+ UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
+ UNI_CMD_SER_SET_RECOVER_L3_BF,
+ UNI_CMD_SER_SET_RECOVER_L4_MDP,
+ UNI_CMD_SER_SET_RECOVER_FULL,
+ UNI_CMD_SER_SET_SYSTEM_ASSERT,
/* action */
- SER_ENABLE = 2,
- SER_RECOVER
+ UNI_CMD_SER_ENABLE = 1,
+ UNI_CMD_SER_SET,
+ UNI_CMD_SER_TRIGGER
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
index 902370a2a639..3a591a7b47ae 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
@@ -162,6 +162,14 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
return mt7996_reg_map_l2(dev, addr);
}
+void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
+ size_t len)
+{
+ u32 addr = __mt7996_reg_addr(dev, offset);
+
+ memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
+}
+
static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
@@ -251,7 +259,7 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
/* TODO: support 2/4/6/8 MSI-X vectors */
static void mt7996_irq_tasklet(struct tasklet_struct *t)
{
- struct mt7996_dev *dev = from_tasklet(dev, t, irq_tasklet);
+ struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
u32 i, intr, mask, intr1;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
@@ -289,10 +297,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
u32 val = mt76_rr(dev, MT_MCU_CMD);
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);
- wake_up(&dev->reset_wait);
+ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
+ dev->recovery.state = val;
+ mt7996_reset(dev);
}
}
}
@@ -308,7 +315,7 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
return IRQ_HANDLED;
}
@@ -320,6 +327,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE |
+ MT_DRV_AMSDU_OFFLOAD |
MT_DRV_HW_MGMT_TXQ,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
@@ -330,7 +338,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
.rx_skb = mt7996_queue_rx_skb,
.rx_check = mt7996_rx_check,
.rx_poll_complete = mt7996_rx_poll_complete,
- .sta_ps = mt7996_sta_ps,
.sta_add = mt7996_mac_sta_add,
.sta_remove = mt7996_mac_sta_remove,
.update_survey = mt7996_update_channel,
@@ -349,7 +356,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
if (ret)
goto error;
- tasklet_setup(&dev->irq_tasklet, mt7996_irq_tasklet);
+ tasklet_setup(&mdev->irq_tasklet, mt7996_irq_tasklet);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 018dfd2b36b0..4d7dcb95a620 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -43,6 +43,10 @@
#define MT7996_MAX_STA_TWT_AGRT 8
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
+/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+#define MT7996_BASIC_RATES_TBL 11
+#define MT7996_BEACON_RATES_TBL 25
+
struct mt7996_vif;
struct mt7996_sta;
struct mt7996_dfs_pulse;
@@ -112,30 +116,18 @@ struct mt7996_sta {
} twt;
};
-struct mt7996_vif_cap {
- bool ht_ldpc:1;
- bool vht_ldpc:1;
- bool he_ldpc:1;
- bool vht_su_ebfer:1;
- bool vht_su_ebfee:1;
- bool vht_mu_ebfer:1;
- bool vht_mu_ebfee:1;
- bool he_su_ebfer:1;
- bool he_su_ebfee:1;
- bool he_mu_ebfer:1;
- bool eht_su_ebfer:1;
- bool eht_su_ebfee:1;
-};
-
struct mt7996_vif {
struct mt76_vif mt76; /* must be first */
- struct mt7996_vif_cap cap;
struct mt7996_sta sta;
struct mt7996_phy *phy;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct cfg80211_bitrate_mask bitrate_mask;
+
+ u8 basic_rates_idx;
+ u8 mcast_rates_idx;
+ u8 beacon_rates_idx;
};
/* per-phy stats. */
@@ -192,6 +184,15 @@ struct mib_stats {
u32 tx_amsdu_cnt;
};
+/* crash-dump */
+struct mt7996_crash_data {
+ guid_t guid;
+ struct timespec64 timestamp;
+
+ u8 *memdump_buf;
+ size_t memdump_buf_len;
+};
+
struct mt7996_hif {
struct list_head list;
@@ -238,7 +239,6 @@ struct mt7996_dev {
u32 q_wfdma_mask;
const struct mt76_bus_ops *bus_ops;
- struct tasklet_struct irq_tasklet;
struct mt7996_phy phy;
/* monitor rx chain configured channel */
@@ -251,9 +251,25 @@ struct mt7996_dev {
struct work_struct init_work;
struct work_struct rc_work;
+ struct work_struct dump_work;
struct work_struct reset_work;
wait_queue_head_t reset_wait;
- u32 reset_state;
+ struct {
+ u32 state;
+ u32 wa_reset_count;
+ u32 wm_reset_count;
+ bool hw_full_reset:1;
+ bool hw_init_done:1;
+ bool restart:1;
+ } recovery;
+
+ /* protects coredump data */
+ struct mutex dump_mutex;
+#ifdef CONFIG_DEV_COREDUMP
+ struct {
+ struct mt7996_crash_data *crash_data;
+ } coredump;
+#endif
struct list_head sta_rc_list;
struct list_head sta_poll_list;
@@ -386,9 +402,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
struct ieee80211_channel *chan);
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
int mt7996_dma_init(struct mt7996_dev *dev);
+void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
void mt7996_dma_prefetch(struct mt7996_dev *dev);
void mt7996_dma_cleanup(struct mt7996_dev *dev);
+void mt7996_init_txpower(struct mt7996_dev *dev,
+ struct ieee80211_supported_band *sband);
+int mt7996_txbf_init(struct mt7996_dev *dev);
+void mt7996_reset(struct mt7996_dev *dev);
+int mt7996_run(struct ieee80211_hw *hw);
int mt7996_mcu_init(struct mt7996_dev *dev);
+int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
struct mt7996_vif *mvif,
struct mt7996_twt_flow *flow,
@@ -432,7 +455,6 @@ int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev,
int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
const struct mt7996_dfs_pattern *pattern);
int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
@@ -445,6 +467,7 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
+int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
@@ -468,7 +491,7 @@ static inline void mt7996_irq_enable(struct mt7996_dev *dev, u32 mask)
else
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
- tasklet_schedule(&dev->irq_tasklet);
+ tasklet_schedule(&dev->mt76.irq_tasklet);
}
static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
@@ -479,6 +502,10 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
}
+void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
+ size_t len);
+
+void mt7996_mac_init(struct mt7996_dev *dev);
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
void mt7996_mac_reset_counters(struct mt7996_phy *phy);
@@ -486,9 +513,12 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable);
+void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
+ u8 tbl_idx, u16 rate_idx);
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
- struct ieee80211_key_conf *key, u32 changed);
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key, int pid,
+ enum mt76_txq_id qid, u32 changed);
void mt7996_mac_set_timing(struct mt7996_phy *phy);
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@@ -496,6 +526,7 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7996_mac_work(struct work_struct *work);
void mt7996_mac_reset_work(struct work_struct *work);
+void mt7996_mac_dump_work(struct work_struct *work);
void mt7996_mac_sta_rc_work(struct work_struct *work);
void mt7996_mac_update_stats(struct mt7996_phy *phy);
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
@@ -512,7 +543,6 @@ void mt7996_tx_token_put(struct mt7996_dev *dev);
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
-void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
void mt7996_stats_work(struct work_struct *work);
int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
index 7a28cae34e34..d1d3d154195d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h
@@ -228,6 +228,13 @@ enum base_rev {
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
#define MT_WTBL_UPDATE_BUSY BIT(31)
+#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0)
+#define MT_WTBL_ITCR_WR BIT(16)
+#define MT_WTBL_ITCR_EXEC BIT(31)
+#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8)
+#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc)
+#define MT_WTBL_SPE_IDX_SEL BIT(6)
+
/* WTBL */
#define MT_WTBL_BASE 0x820d8000
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
@@ -317,6 +324,8 @@ enum base_rev {
#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
+
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
@@ -444,6 +453,10 @@ enum base_rev {
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
+#define MT_MCU_CMD_WA_WDT BIT(31)
+#define MT_MCU_CMD_WM_WDT BIT(30)
+#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
+
/* l1/l2 remap */
#define MT_HIF_REMAP_L1 0x155024
#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
@@ -468,9 +481,28 @@ enum base_rev {
#define MT_INFRA_MCU_END 0x7c3fffff
/* FW MODE SYNC */
-#define MT_SWDEF_MODE 0x9143c
+#define MT_FW_ASSERT_CNT 0x02208274
+#define MT_FW_DUMP_STATE 0x02209e90
+
+#define MT_SWDEF_BASE 0x00401400
+
+#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
+#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
+#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_WISR6_BN2_STATS MT_SWDEF(0x060)
+#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064)
+#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068)
+#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06c)
+
/* LED */
#define MT_LED_TOP_BASE 0x18013000
#define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
@@ -486,6 +518,13 @@ enum base_rev {
#define MT_LED_EN(_n) MT_LED_PHYS(0x40 + ((_n) * 4))
+/* CONN DBG */
+#define MT_CONN_DBG_CTL_BASE 0x18023000
+#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs))
+#define MT_CONN_DBG_CTL_OUT_SEL MT_CONN_DBG_CTL(0x604)
+#define MT_CONN_DBG_CTL_PC_LOG_SEL MT_CONN_DBG_CTL(0x60c)
+#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x610)
+
#define MT_LED_GPIO_MUX2 0x70005058 /* GPIO 18 */
#define MT_LED_GPIO_MUX3 0x7000505C /* GPIO 26 */
#define MT_LED_GPIO_SEL_MASK GENMASK(11, 8)
@@ -506,7 +545,7 @@ enum base_rev {
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
#define MT_HW_REV 0x70010204
-#define MT_WF_SUBSYS_RST 0x70002600
+#define MT_WF_SUBSYS_RST 0x70028600
/* PCIE MAC */
#define MT_PCIE_MAC_BASE 0x74030000
@@ -539,4 +578,12 @@ enum base_rev {
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
#define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
+/* CONN MCU EXCP CON */
+#define MT_MCU_WM_EXCP_BASE 0x89050000
+#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs))
+#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100)
+#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104)
+#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200)
+#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204)
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 1f309d05380a..72b3ec715e47 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -77,7 +77,9 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
}
hw = mt76_tx_status_get_hw(dev, skb);
+ spin_lock_bh(&dev->rx_lock);
ieee80211_tx_status_ext(hw, &status);
+ spin_unlock_bh(&dev->rx_lock);
}
rcu_read_unlock();
}
@@ -263,7 +265,9 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
if (cb->pktid < MT_PACKET_ID_FIRST) {
hw = mt76_tx_status_get_hw(dev, skb);
status.sta = wcid_to_sta(wcid);
+ spin_lock_bh(&dev->rx_lock);
ieee80211_tx_status_ext(hw, &status);
+ spin_unlock_bh(&dev->rx_lock);
goto out;
}
@@ -330,7 +334,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
!ieee80211_is_data(hdr->frame_control) &&
- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
+ !ieee80211_is_bufferable_mmpdu(skb)) {
qid = MT_TXQ_PSD;
}
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 9d48c69ffece..8eafbf1cee71 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -27,7 +27,7 @@
#define RTL8XXXU_MAX_REG_POLL 500
#define USB_INTR_CONTENT_LENGTH 56
-#define RTL8XXXU_OUT_ENDPOINTS 4
+#define RTL8XXXU_OUT_ENDPOINTS 6
#define REALTEK_USB_READ 0xc0
#define REALTEK_USB_WRITE 0x40
@@ -1923,6 +1923,11 @@ struct rtl8xxxu_fileops {
u8 has_tx_report:1;
u8 gen2_thermal_meter:1;
u8 needs_full_init:1;
+ u8 init_reg_rxfltmap:1;
+ u8 init_reg_pkt_life_time:1;
+ u8 init_reg_hmtfr:1;
+ u8 ampdu_max_time;
+ u8 ustime_tsf_edca;
u32 adda_1t_init;
u32 adda_1t_path_on;
u32 adda_2t_path_on_a;
@@ -1948,10 +1953,22 @@ u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr);
int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val);
int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val);
int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val);
+int rtl8xxxu_write8_set(struct rtl8xxxu_priv *priv, u16 addr, u8 bits);
+int rtl8xxxu_write8_clear(struct rtl8xxxu_priv *priv, u16 addr, u8 bits);
+int rtl8xxxu_write16_set(struct rtl8xxxu_priv *priv, u16 addr, u16 bits);
+int rtl8xxxu_write16_clear(struct rtl8xxxu_priv *priv, u16 addr, u16 bits);
+int rtl8xxxu_write32_set(struct rtl8xxxu_priv *priv, u16 addr, u32 bits);
+int rtl8xxxu_write32_clear(struct rtl8xxxu_priv *priv, u16 addr, u32 bits);
+int rtl8xxxu_write32_mask(struct rtl8xxxu_priv *priv, u16 addr,
+ u32 mask, u32 val);
+
u32 rtl8xxxu_read_rfreg(struct rtl8xxxu_priv *priv,
enum rtl8xxxu_rfpath path, u8 reg);
int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv,
enum rtl8xxxu_rfpath path, u8 reg, u32 data);
+int rtl8xxxu_write_rfreg_mask(struct rtl8xxxu_priv *priv,
+ enum rtl8xxxu_rfpath path, u8 reg,
+ u32 mask, u32 val);
void rtl8xxxu_save_regs(struct rtl8xxxu_priv *priv, const u32 *regs,
u32 *backup, int count);
void rtl8xxxu_restore_regs(struct rtl8xxxu_priv *priv, const u32 *regs,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
index 6a82ec47568e..8986783ae8fa 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
@@ -568,10 +568,6 @@ static int rtl8188eu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->default_crystal_cap = efuse->xtal_k & 0x3f;
- dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
- dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name);
- dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
-
return 0;
}
@@ -1883,6 +1879,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = {
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
.has_tx_report = 1,
+ .init_reg_pkt_life_time = 1,
.gen2_thermal_meter = 1,
.adda_1t_init = 0x0b1b25a0,
.adda_1t_path_on = 0x0bdb25a0,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
index 82dee1fed477..dbdfd7787465 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
@@ -734,9 +734,6 @@ static int rtl8188fu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->default_crystal_cap = efuse->xtal_k & 0x3f;
- dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
- dev_info(&priv->udev->dev, "Product: %.7s\n", efuse->device_name);
-
return 0;
}
@@ -1746,6 +1743,11 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.has_tx_report = 1,
.gen2_thermal_meter = 1,
.needs_full_init = 1,
+ .init_reg_rxfltmap = 1,
+ .init_reg_pkt_life_time = 1,
+ .init_reg_hmtfr = 1,
+ .ampdu_max_time = 0x70,
+ .ustime_tsf_edca = 0x28,
.adda_1t_init = 0x03c00014,
.adda_1t_path_on = 0x03c00014,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
index caeba56241fc..b30a9a513cb8 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
@@ -441,11 +441,6 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
efuse->ht20_max_power_offset,
sizeof(efuse->ht20_max_power_offset));
- dev_info(&priv->udev->dev, "Vendor: %.7s\n",
- efuse->vendor_name);
- dev_info(&priv->udev->dev, "Product: %.20s\n",
- efuse->device_name);
-
priv->power_base = &rtl8192c_power_base;
if (efuse->rf_regulatory & 0x20) {
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index 4498748164af..fcc2926ea938 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -601,43 +601,9 @@ rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
}
}
-static void rtl8192eu_log_next_device_info(struct rtl8xxxu_priv *priv,
- char *record_name,
- char *device_info,
- unsigned int *record_offset)
-{
- char *record = device_info + *record_offset;
-
- /* A record is [ total length | 0x03 | value ] */
- unsigned char l = record[0];
-
- /*
- * The whole device info section seems to be 80 characters, make sure
- * we don't read further.
- */
- if (*record_offset + l > 80) {
- dev_warn(&priv->udev->dev,
- "invalid record length %d while parsing \"%s\" at offset %u.\n",
- l, record_name, *record_offset);
- return;
- }
-
- if (l >= 2) {
- char value[80];
-
- memcpy(value, &record[2], l - 2);
- value[l - 2] = '\0';
- dev_info(&priv->udev->dev, "%s: %s\n", record_name, value);
- *record_offset = *record_offset + l;
- } else {
- dev_info(&priv->udev->dev, "%s not available.\n", record_name);
- }
-}
-
static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
{
struct rtl8192eu_efuse *efuse = &priv->efuse_wifi.efuse8192eu;
- unsigned int record_offset;
int i;
if (efuse->rtl_id != cpu_to_le16(0x8129))
@@ -684,26 +650,6 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->default_crystal_cap = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
- /*
- * device_info section seems to be laid out as records
- * [ total length | 0x03 | value ] so:
- * - vendor length + 2
- * - 0x03
- * - vendor string (not null terminated)
- * - product length + 2
- * - 0x03
- * - product string (not null terminated)
- * Then there is one or 2 0x00 on all the 4 devices I own or found
- * dumped online.
- * As previous version of the code handled an optional serial
- * string, I now assume there may be a third record if the
- * length is not 0.
- */
- record_offset = 0;
- rtl8192eu_log_next_device_info(priv, "Vendor", efuse->device_info, &record_offset);
- rtl8192eu_log_next_device_info(priv, "Product", efuse->device_info, &record_offset);
- rtl8192eu_log_next_device_info(priv, "Serial", efuse->device_info, &record_offset);
-
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
index 920466e39604..22d4704dd31e 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
@@ -1865,6 +1865,15 @@ struct rtl8xxxu_fileops rtl8710bu_fops = {
.has_tx_report = 1,
.gen2_thermal_meter = 1,
.needs_full_init = 1,
+ .init_reg_rxfltmap = 1,
+ .init_reg_pkt_life_time = 1,
+ .init_reg_hmtfr = 1,
+ .ampdu_max_time = 0x5e,
+ /*
+ * The RTL8710BU vendor driver uses 0x50 here and it works fine,
+ * but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why?
+ */
+ .ustime_tsf_edca = 0x28,
.adda_1t_init = 0x03c00016,
.adda_1t_path_on = 0x03c00016,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
index d219be19d07f..15a30e496221 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
@@ -222,10 +222,6 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
priv->power_base = &rtl8723a_power_base;
- dev_info(&priv->udev->dev, "Vendor: %.7s\n",
- efuse->vendor_name);
- dev_info(&priv->udev->dev, "Product: %.41s\n",
- efuse->device_name);
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
index d99538eb8398..abc56c7de6f7 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
@@ -494,9 +494,6 @@ static int rtl8723bu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->default_crystal_cap = priv->efuse_wifi.efuse8723bu.xtal_k & 0x3f;
- dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
- dev_info(&priv->udev->dev, "Product: %.41s\n", efuse->device_name);
-
return 0;
}
@@ -1741,6 +1738,9 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.has_tx_report = 1,
.gen2_thermal_meter = 1,
.needs_full_init = 1,
+ .init_reg_hmtfr = 1,
+ .ampdu_max_time = 0x5e,
+ .ustime_tsf_edca = 0x50,
.adda_1t_init = 0x01c00014,
.adda_1t_path_on = 0x01c00014,
.adda_2t_path_on_a = 0x01c00014,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index c152b228606f..fd8c8c6d53d6 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -786,6 +786,85 @@ int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val)
return ret;
}
+int rtl8xxxu_write8_set(struct rtl8xxxu_priv *priv, u16 addr, u8 bits)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, addr);
+ val8 |= bits;
+ return rtl8xxxu_write8(priv, addr, val8);
+}
+
+int rtl8xxxu_write8_clear(struct rtl8xxxu_priv *priv, u16 addr, u8 bits)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, addr);
+ val8 &= ~bits;
+ return rtl8xxxu_write8(priv, addr, val8);
+}
+
+int rtl8xxxu_write16_set(struct rtl8xxxu_priv *priv, u16 addr, u16 bits)
+{
+ u16 val16;
+
+ val16 = rtl8xxxu_read16(priv, addr);
+ val16 |= bits;
+ return rtl8xxxu_write16(priv, addr, val16);
+}
+
+int rtl8xxxu_write16_clear(struct rtl8xxxu_priv *priv, u16 addr, u16 bits)
+{
+ u16 val16;
+
+ val16 = rtl8xxxu_read16(priv, addr);
+ val16 &= ~bits;
+ return rtl8xxxu_write16(priv, addr, val16);
+}
+
+int rtl8xxxu_write32_set(struct rtl8xxxu_priv *priv, u16 addr, u32 bits)
+{
+ u32 val32;
+
+ val32 = rtl8xxxu_read32(priv, addr);
+ val32 |= bits;
+ return rtl8xxxu_write32(priv, addr, val32);
+}
+
+int rtl8xxxu_write32_clear(struct rtl8xxxu_priv *priv, u16 addr, u32 bits)
+{
+ u32 val32;
+
+ val32 = rtl8xxxu_read32(priv, addr);
+ val32 &= ~bits;
+ return rtl8xxxu_write32(priv, addr, val32);
+}
+
+int rtl8xxxu_write32_mask(struct rtl8xxxu_priv *priv, u16 addr,
+ u32 mask, u32 val)
+{
+ u32 orig, new, shift;
+
+ shift = __ffs(mask);
+
+ orig = rtl8xxxu_read32(priv, addr);
+ new = (orig & ~mask) | ((val << shift) & mask);
+ return rtl8xxxu_write32(priv, addr, new);
+}
+
+int rtl8xxxu_write_rfreg_mask(struct rtl8xxxu_priv *priv,
+ enum rtl8xxxu_rfpath path, u8 reg,
+ u32 mask, u32 val)
+{
+ u32 orig, new, shift;
+
+ shift = __ffs(mask);
+
+ orig = rtl8xxxu_read_rfreg(priv, path, reg);
+ new = (orig & ~mask) | ((val << shift) & mask);
+ return rtl8xxxu_write_rfreg(priv, path, reg, new);
+}
+
static int
rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len)
{
@@ -1663,6 +1742,8 @@ int rtl8xxxu_config_endpoints_no_sie(struct rtl8xxxu_priv *priv)
struct device *dev = &priv->udev->dev;
switch (priv->nr_out_eps) {
+ case 6:
+ case 5:
case 4:
case 3:
priv->ep_tx_low_queue = 1;
@@ -1916,7 +1997,7 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
/*
* Init H2C command
*/
- if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B)
+ if (priv->fops->init_reg_hmtfr)
rtl8xxxu_write8(priv, REG_HMTFR, 0x0f);
exit:
return ret;
@@ -3864,11 +3945,8 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8);
rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14);
- if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8710B)
- val8 = 0x5e;
- else if (priv->rtl_chip == RTL8188F)
- val8 = 0x70; /* 0x5e would make it very slow */
- rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, val8);
+ rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B,
+ priv->fops->ampdu_max_time);
rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff);
rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18);
rtl8xxxu_write8(priv, REG_PIFS, 0x00);
@@ -3876,16 +3954,8 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY);
rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666);
}
- /*
- * The RTL8710BU vendor driver uses 0x50 here and it works fine,
- * but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why?
- */
- if (priv->rtl_chip == RTL8723B)
- val8 = 0x50;
- else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B)
- val8 = 0x28; /* 0x50 would make the upload slow */
- rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, val8);
- rtl8xxxu_write8(priv, REG_USTIME_EDCA, val8);
+ rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, priv->fops->ustime_tsf_edca);
+ rtl8xxxu_write8(priv, REG_USTIME_EDCA, priv->fops->ustime_tsf_edca);
/* to prevent mac is reseted by bus. */
val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL);
@@ -4102,7 +4172,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
rtl8xxxu_write32(priv, REG_RCR, val32);
- if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
+ if (fops->init_reg_rxfltmap) {
/* Accept all data frames */
rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
@@ -4187,8 +4257,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (fops->init_aggregation)
fops->init_aggregation(priv);
- if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E ||
- priv->rtl_chip == RTL8710B) {
+ if (fops->init_reg_pkt_life_time) {
rtl8xxxu_write16(priv, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
rtl8xxxu_write16(priv, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
}
@@ -6965,10 +7034,8 @@ exit:
rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff);
- if (priv->rtl_chip == RTL8188E)
- rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6955341e);
- else
- rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e);
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1,
+ OFDM0_X_AGC_CORE1_IGI_MASK, 0x1e);
return ret;
diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 651ab56d9c6b..29eb2f8e0eb7 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -16,6 +16,9 @@ config RTW88_CORE
config RTW88_PCI
tristate
+config RTW88_SDIO
+ tristate
+
config RTW88_USB
tristate
@@ -42,6 +45,17 @@ config RTW88_8822BE
802.11ac PCIe wireless network adapter
+config RTW88_8822BS
+ tristate "Realtek 8822BS SDIO wireless network adapter"
+ depends on MMC
+ select RTW88_CORE
+ select RTW88_SDIO
+ select RTW88_8822B
+ help
+ Select this option will enable support for 8822BS chipset
+
+ 802.11ac SDIO wireless network adapter
+
config RTW88_8822BU
tristate "Realtek 8822BU USB wireless network adapter"
depends on USB
@@ -64,6 +78,17 @@ config RTW88_8822CE
802.11ac PCIe wireless network adapter
+config RTW88_8822CS
+ tristate "Realtek 8822CS SDIO wireless network adapter"
+ depends on MMC
+ select RTW88_CORE
+ select RTW88_SDIO
+ select RTW88_8822C
+ help
+ Select this option will enable support for 8822CS chipset
+
+ 802.11ac SDIO wireless network adapter
+
config RTW88_8822CU
tristate "Realtek 8822CU USB wireless network adapter"
depends on USB
@@ -108,6 +133,17 @@ config RTW88_8821CE
802.11ac PCIe wireless network adapter
+config RTW88_8821CS
+ tristate "Realtek 8821CS SDIO wireless network adapter"
+ depends on MMC
+ select RTW88_CORE
+ select RTW88_SDIO
+ select RTW88_8821C
+ help
+ Select this option will enable support for 8821CS chipset
+
+ 802.11ac SDIO wireless network adapter
+
config RTW88_8821CU
tristate "Realtek 8821CU USB wireless network adapter"
depends on USB
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index fe7293ee87b4..82979b30ae8d 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -26,6 +26,9 @@ rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o
rtw88_8822be-objs := rtw8822be.o
+obj-$(CONFIG_RTW88_8822BS) += rtw88_8822bs.o
+rtw88_8822bs-objs := rtw8822bs.o
+
obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o
rtw88_8822bu-objs := rtw8822bu.o
@@ -35,6 +38,9 @@ rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o
obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o
rtw88_8822ce-objs := rtw8822ce.o
+obj-$(CONFIG_RTW88_8822CS) += rtw88_8822cs.o
+rtw88_8822cs-objs := rtw8822cs.o
+
obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o
rtw88_8822cu-objs := rtw8822cu.o
@@ -53,11 +59,17 @@ rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o
obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
rtw88_8821ce-objs := rtw8821ce.o
+obj-$(CONFIG_RTW88_8821CS) += rtw88_8821cs.o
+rtw88_8821cs-objs := rtw8821cs.o
+
obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o
rtw88_8821cu-objs := rtw8821cu.o
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
rtw88_pci-objs := pci.o
+obj-$(CONFIG_RTW88_SDIO) += rtw88_sdio.o
+rtw88_sdio-objs := sdio.o
+
obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
rtw88_usb-objs := usb.o
diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h
index 066792dd96af..a9149c6c2b48 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.h
+++ b/drivers/net/wireless/realtek/rtw88/debug.h
@@ -24,6 +24,7 @@ enum rtw_debug_mask {
RTW_DBG_ADAPTIVITY = 0x00008000,
RTW_DBG_HW_SCAN = 0x00010000,
RTW_DBG_STATE = 0x00020000,
+ RTW_DBG_SDIO = 0x00040000,
RTW_DBG_ALL = 0xffffffff
};
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 82295ac6402e..2a8ccc8a7f60 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -1393,6 +1393,10 @@ static void rtw_build_rsvd_page_iter(void *data, u8 *mac,
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
struct rtw_rsvd_page *rsvd_pkt;
+ /* AP not yet started, don't gather its rsvd pages */
+ if (vif->type == NL80211_IFTYPE_AP && !rtwdev->ap_active)
+ return;
+
list_for_each_entry(rsvd_pkt, &rtwvif->rsvd_page_list, vif_list) {
if (rsvd_pkt->type == RSVD_BEACON)
list_add(&rsvd_pkt->build_list,
@@ -1614,6 +1618,7 @@ void rtw_fw_update_beacon_work(struct work_struct *work)
mutex_lock(&rtwdev->mutex);
rtw_fw_download_rsvd_page(rtwdev);
+ rtw_send_rsvd_page_h2c(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
@@ -2155,11 +2160,19 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
}
rtw_fw_set_scan_offload(rtwdev, &cs_option, rtwvif, &chan_list);
out:
+ if (rtwdev->ap_active) {
+ ret = rtw_download_beacon(rtwdev);
+ if (ret)
+ rtw_err(rtwdev, "HW scan download beacon failed\n");
+ }
+
return ret;
}
-void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+void rtw_hw_scan_abort(struct rtw_dev *rtwdev)
{
+ struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
+
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
return;
@@ -2244,6 +2257,7 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
if (rtw_is_op_chan(rtwdev, chan)) {
rtw_store_op_chan(rtwdev, false);
ieee80211_wake_queues(rtwdev->hw);
+ rtw_core_enable_beacon(rtwdev, true);
}
} else if (id == RTW_SCAN_NOTIFY_ID_PRESWITCH) {
if (IS_CH_5G_BAND(chan)) {
@@ -2262,8 +2276,10 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
* if next channel is non-op channel.
*/
if (!rtw_is_op_chan(rtwdev, chan) &&
- rtw_is_op_chan(rtwdev, hal->current_channel))
+ rtw_is_op_chan(rtwdev, hal->current_channel)) {
+ rtw_core_enable_beacon(rtwdev, false);
ieee80211_stop_queues(rtwdev->hw);
+ }
}
rtw_dbg(rtwdev, RTW_DBG_HW_SCAN,
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 0a386e6d6e0d..397cbc3f6af6 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -868,5 +868,5 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool enable);
void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb);
-void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
+void rtw_hw_scan_abort(struct rtw_dev *rtwdev);
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index f3a566cf979b..a168f36c38ec 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -7,6 +7,7 @@
#include "reg.h"
#include "fw.h"
#include "debug.h"
+#include "sdio.h"
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
u8 primary_ch_idx)
@@ -60,6 +61,7 @@ EXPORT_SYMBOL(rtw_set_channel_mac);
static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
{
+ unsigned int retry;
u32 value32;
u8 value8;
@@ -77,6 +79,28 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
case RTW_HCI_TYPE_PCIE:
rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
break;
+ case RTW_HCI_TYPE_SDIO:
+ rtw_write8_clr(rtwdev, REG_SDIO_HSUS_CTRL, BIT_HCI_SUS_REQ);
+
+ for (retry = 0; retry < RTW_PWR_POLLING_CNT; retry++) {
+ if (rtw_read8(rtwdev, REG_SDIO_HSUS_CTRL) & BIT_HCI_RESUME_RDY)
+ break;
+
+ usleep_range(10, 50);
+ }
+
+ if (retry == RTW_PWR_POLLING_CNT) {
+ rtw_err(rtwdev, "failed to poll REG_SDIO_HSUS_CTRL[1]");
+ return -ETIMEDOUT;
+ }
+
+ if (rtw_sdio_is_sdio30_supported(rtwdev))
+ rtw_write8_set(rtwdev, REG_HCI_OPT_CTRL + 2,
+ BIT_SDIO_PAD_E5 >> 16);
+ else
+ rtw_write8_clr(rtwdev, REG_HCI_OPT_CTRL + 2,
+ BIT_SDIO_PAD_E5 >> 16);
+ break;
case RTW_HCI_TYPE_USB:
break;
default:
@@ -248,6 +272,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
{
const struct rtw_chip_info *chip = rtwdev->chip;
const struct rtw_pwr_seq_cmd **pwr_seq;
+ u32 imr = 0;
u8 rpwm;
bool cur_pwr;
int ret;
@@ -273,17 +298,24 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
if (pwr_on == cur_pwr)
return -EALREADY;
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) {
+ imr = rtw_read32(rtwdev, REG_SDIO_HIMR);
+ rtw_write32(rtwdev, REG_SDIO_HIMR, 0);
+ }
+
+ if (!pwr_on)
+ clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
+
pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
- if (ret)
- return ret;
- if (pwr_on)
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
+ rtw_write32(rtwdev, REG_SDIO_HIMR, imr);
+
+ if (!ret && pwr_on)
set_bit(RTW_FLAG_POWERON, rtwdev->flags);
- else
- clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
- return 0;
+ return ret;
}
static int __rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
@@ -454,6 +486,9 @@ static void download_firmware_reg_backup(struct rtw_dev *rtwdev,
rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200);
rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val);
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
+ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
+
/* Disable beacon related functions */
tmp = rtw_read8(rtwdev, REG_BCN_CTRL);
bckp[bckp_idx].len = 1;
@@ -1066,8 +1101,12 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
if (rtw_chip_wcpu_11ac(rtwdev))
rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
- if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB)
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) {
+ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
+ rtw_write32(rtwdev, REG_SDIO_TX_CTRL, 0);
+ } else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) {
rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN);
+ }
return 0;
}
@@ -1080,7 +1119,7 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev)
u8 csi_buf_pg_num = chip->csi_buf_pg_num;
/* config rsvd page num */
- fifo->rsvd_drv_pg_num = 8;
+ fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num;
fifo->txff_pg_num = chip->txff_size >> 7;
if (rtw_chip_wcpu_11n(rtwdev))
fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num;
diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h
index 3172aa5ac4de..58c3dccc14bb 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.h
+++ b/drivers/net/wireless/realtek/rtw88/mac.h
@@ -7,7 +7,6 @@
#define RTW_HW_PORT_NUM 5
#define cut_version_to_mask(cut) (0x1 << ((cut) + 1))
-#define SDIO_LOCAL_OFFSET 0x10250000
#define DDMA_POLLING_COUNT 1000
#define C2H_PKT_BUF 256
#define REPORT_BUF 128
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 3b92ac611d3f..7aa6edad0d01 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -155,25 +155,30 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
enum rtw_net_type net_type;
u32 config = 0;
- u8 port = 0;
+ u8 port;
u8 bcn_ctrl = 0;
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
- rtwvif->port = port;
rtwvif->stats.tx_unicast = 0;
rtwvif->stats.rx_unicast = 0;
rtwvif->stats.tx_cnt = 0;
rtwvif->stats.rx_cnt = 0;
rtwvif->scan_req = NULL;
memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
- rtwvif->conf = &rtw_vif_port[port];
rtw_txq_init(rtwdev, vif->txq);
INIT_LIST_HEAD(&rtwvif->rsvd_page_list);
mutex_lock(&rtwdev->mutex);
+ port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
+ if (port >= RTW_PORT_NUM)
+ return -EINVAL;
+ set_bit(port, rtwdev->hw_port);
+
+ rtwvif->port = port;
+ rtwvif->conf = &rtw_vif_port[port];
rtw_leave_lps_deep(rtwdev);
switch (vif->type) {
@@ -195,6 +200,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
break;
default:
WARN_ON(1);
+ clear_bit(rtwvif->port, rtwdev->hw_port);
mutex_unlock(&rtwdev->mutex);
return -EINVAL;
}
@@ -206,6 +212,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
rtwvif->bcn_ctrl = bcn_ctrl;
config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
+ rtw_core_port_switch(rtwdev, vif);
mutex_unlock(&rtwdev->mutex);
@@ -236,6 +243,7 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
rtwvif->bcn_ctrl = 0;
config |= PORT_SET_BCN_CTRL;
rtw_vif_port_config(rtwdev, rtwvif, config);
+ clear_bit(rtwvif->port, rtwdev->hw_port);
mutex_unlock(&rtwdev->mutex);
}
@@ -385,7 +393,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
* when disconnected by peer
*/
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
- rtw_hw_scan_abort(rtwdev, vif);
+ rtw_hw_scan_abort(rtwdev);
+
}
config |= PORT_SET_NET_TYPE;
@@ -395,7 +404,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) {
ether_addr_copy(rtwvif->bssid, conf->bssid);
config |= PORT_SET_BSSID;
- if (is_zero_ether_addr(rtwvif->bssid))
+ if (!rtw_core_check_sta_active(rtwdev))
rtw_clear_op_chan(rtwdev);
else
rtw_store_op_chan(rtwdev, true);
@@ -409,6 +418,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON) {
rtw_set_dtim_period(rtwdev, conf->dtim_period);
rtw_fw_download_rsvd_page(rtwdev);
+ rtw_send_rsvd_page_h2c(rtwdev);
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
@@ -441,12 +451,27 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw,
const struct rtw_chip_info *chip = rtwdev->chip;
mutex_lock(&rtwdev->mutex);
+ rtwdev->ap_active = true;
+ rtw_store_op_chan(rtwdev, true);
chip->ops->phy_calibration(rtwdev);
mutex_unlock(&rtwdev->mutex);
return 0;
}
+static void rtw_ops_stop_ap(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct rtw_dev *rtwdev = hw->priv;
+
+ mutex_lock(&rtwdev->mutex);
+ rtwdev->ap_active = false;
+ if (!rtw_core_check_sta_active(rtwdev))
+ rtw_clear_op_chan(rtwdev);
+ mutex_unlock(&rtwdev->mutex);
+}
+
static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
unsigned int link_id, u16 ac,
@@ -849,7 +874,7 @@ static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
rtw_hw_scan_start(rtwdev, vif, req);
ret = rtw_hw_scan_offload(rtwdev, vif, true);
if (ret) {
- rtw_hw_scan_abort(rtwdev, vif);
+ rtw_hw_scan_abort(rtwdev);
rtw_err(rtwdev, "HW scan failed with status: %d\n", ret);
}
mutex_unlock(&rtwdev->mutex);
@@ -869,7 +894,7 @@ static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw,
return;
mutex_lock(&rtwdev->mutex);
- rtw_hw_scan_abort(rtwdev, vif);
+ rtw_hw_scan_abort(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
@@ -908,6 +933,7 @@ const struct ieee80211_ops rtw_ops = {
.configure_filter = rtw_ops_configure_filter,
.bss_info_changed = rtw_ops_bss_info_changed,
.start_ap = rtw_ops_start_ap,
+ .stop_ap = rtw_ops_stop_ap,
.conf_tx = rtw_ops_conf_tx,
.sta_add = rtw_ops_sta_add,
.sta_remove = rtw_ops_sta_remove,
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index b2e78737bd5d..5bf6b4581557 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -18,6 +18,7 @@
#include "debug.h"
#include "bf.h"
#include "sar.h"
+#include "sdio.h"
bool rtw_disable_lps_deep_mode;
EXPORT_SYMBOL(rtw_disable_lps_deep_mode);
@@ -102,6 +103,26 @@ static struct ieee80211_rate rtw_ratetable[] = {
{.bitrate = 540, .hw_value = 0x0b,},
};
+static const struct ieee80211_iface_limit rtw_iface_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP),
+ }
+};
+
+static const struct ieee80211_iface_combination rtw_iface_combs[] = {
+ {
+ .limits = rtw_iface_limits,
+ .n_limits = ARRAY_SIZE(rtw_iface_limits),
+ .max_interfaces = 2,
+ .num_different_channels = 1,
+ }
+};
+
u16 rtw_desc_to_bitrate(u8 desc_rate)
{
struct ieee80211_rate rate;
@@ -256,7 +277,7 @@ static void rtw_watch_dog_work(struct work_struct *work)
* threshold.
*/
if (rtwdev->ps_enabled && data.rtwvif && !ps_active &&
- !rtwdev->beacon_loss)
+ !rtwdev->beacon_loss && !rtwdev->ap_active)
rtw_enter_lps(rtwdev, data.rtwvif->port);
rtwdev->watch_dog_cnt++;
@@ -609,6 +630,7 @@ free:
rcu_read_unlock();
rtw_iterate_stas_atomic(rtwdev, rtw_reset_sta_iter, rtwdev);
rtw_iterate_vifs_atomic(rtwdev, rtw_reset_vif_iter, rtwdev);
+ bitmap_zero(rtwdev->hw_port, RTW_PORT_NUM);
rtw_enter_ips(rtwdev);
}
@@ -828,6 +850,9 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
rtw_update_channel(rtwdev, center_chan, primary_chan, band, bandwidth);
+ if (rtwdev->scan_info.op_chan)
+ rtw_store_op_chan(rtwdev, true);
+
chip->ops->set_channel(rtwdev, center_chan, bandwidth,
hal->current_primary_channel_index);
@@ -1785,6 +1810,10 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
rtwdev->hci.rpwm_addr = 0x03d9;
rtwdev->hci.cpwm_addr = 0x03da;
break;
+ case RTW_HCI_TYPE_SDIO:
+ rtwdev->hci.rpwm_addr = REG_SDIO_HRPWM1;
+ rtwdev->hci.cpwm_addr = REG_SDIO_HCPWM1_V2;
+ break;
case RTW_HCI_TYPE_USB:
rtwdev->hci.rpwm_addr = 0xfe58;
rtwdev->hci.cpwm_addr = 0xfe57;
@@ -1979,7 +2008,7 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev)
if (!rfe_def)
return -ENODEV;
- rtw_phy_setup_phy_cond(rtwdev, 0);
+ rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type);
rtw_phy_init_tx_power(rtwdev);
if (rfe_def->agc_btg_tbl)
@@ -2158,9 +2187,11 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
int max_tx_headroom = 0;
int ret;
- /* TODO: USB & SDIO may need extra room? */
max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz;
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
+ max_tx_headroom += RTW_SDIO_DATA_PTR_ALIGN;
+
hw->extra_tx_headroom = max_tx_headroom;
hw->queues = IEEE80211_NUM_ACS;
hw->txq_data_size = sizeof(struct rtw_txq);
@@ -2194,6 +2225,11 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS;
hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev);
+ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) {
+ hw->wiphy->iface_combinations = rtw_iface_combs;
+ hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs);
+ }
+
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SCAN_RANDOM_SN);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
@@ -2243,6 +2279,121 @@ void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(rtw_unregister_hw);
+static
+void rtw_swap_reg_nbytes(struct rtw_dev *rtwdev, const struct rtw_hw_reg *reg1,
+ const struct rtw_hw_reg *reg2, u8 nbytes)
+{
+ u8 i;
+
+ for (i = 0; i < nbytes; i++) {
+ u8 v1 = rtw_read8(rtwdev, reg1->addr + i);
+ u8 v2 = rtw_read8(rtwdev, reg2->addr + i);
+
+ rtw_write8(rtwdev, reg1->addr + i, v2);
+ rtw_write8(rtwdev, reg2->addr + i, v1);
+ }
+}
+
+static
+void rtw_swap_reg_mask(struct rtw_dev *rtwdev, const struct rtw_hw_reg *reg1,
+ const struct rtw_hw_reg *reg2)
+{
+ u32 v1, v2;
+
+ v1 = rtw_read32_mask(rtwdev, reg1->addr, reg1->mask);
+ v2 = rtw_read32_mask(rtwdev, reg2->addr, reg2->mask);
+ rtw_write32_mask(rtwdev, reg2->addr, reg2->mask, v1);
+ rtw_write32_mask(rtwdev, reg1->addr, reg1->mask, v2);
+}
+
+struct rtw_iter_port_switch_data {
+ struct rtw_dev *rtwdev;
+ struct rtw_vif *rtwvif_ap;
+};
+
+static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct rtw_iter_port_switch_data *iter_data = data;
+ struct rtw_dev *rtwdev = iter_data->rtwdev;
+ struct rtw_vif *rtwvif_target = (struct rtw_vif *)vif->drv_priv;
+ struct rtw_vif *rtwvif_ap = iter_data->rtwvif_ap;
+ const struct rtw_hw_reg *reg1, *reg2;
+
+ if (rtwvif_target->port != RTW_PORT_0)
+ return;
+
+ rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n",
+ rtwvif_ap->port, rtwvif_target->port);
+
+ reg1 = &rtwvif_ap->conf->net_type;
+ reg2 = &rtwvif_target->conf->net_type;
+ rtw_swap_reg_mask(rtwdev, reg1, reg2);
+
+ reg1 = &rtwvif_ap->conf->mac_addr;
+ reg2 = &rtwvif_target->conf->mac_addr;
+ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, ETH_ALEN);
+
+ reg1 = &rtwvif_ap->conf->bssid;
+ reg2 = &rtwvif_target->conf->bssid;
+ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, ETH_ALEN);
+
+ reg1 = &rtwvif_ap->conf->bcn_ctrl;
+ reg2 = &rtwvif_target->conf->bcn_ctrl;
+ rtw_swap_reg_nbytes(rtwdev, reg1, reg2, 1);
+
+ swap(rtwvif_target->port, rtwvif_ap->port);
+ swap(rtwvif_target->conf, rtwvif_ap->conf);
+}
+
+void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+{
+ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+ struct rtw_iter_port_switch_data iter_data;
+
+ if (vif->type != NL80211_IFTYPE_AP || rtwvif->port == RTW_PORT_0)
+ return;
+
+ iter_data.rtwdev = rtwdev;
+ iter_data.rtwvif_ap = rtwvif;
+ rtw_iterate_vifs(rtwdev, rtw_port_switch_iter, &iter_data);
+}
+
+static void rtw_check_sta_active_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+ bool *active = data;
+
+ if (*active)
+ return;
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return;
+
+ if (vif->cfg.assoc || !is_zero_ether_addr(rtwvif->bssid))
+ *active = true;
+}
+
+bool rtw_core_check_sta_active(struct rtw_dev *rtwdev)
+{
+ bool sta_active = false;
+
+ rtw_iterate_vifs(rtwdev, rtw_check_sta_active_iter, &sta_active);
+
+ return rtwdev->ap_active || sta_active;
+}
+
+void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
+{
+ if (!rtwdev->ap_active)
+ return;
+
+ if (enable)
+ rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+ else
+ rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+}
+
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless core module");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index d4a53d556745..a563285e90ed 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -88,7 +88,7 @@ enum rtw_supported_band {
RTW_BAND_60G = BIT(NL80211_BAND_60GHZ),
};
-/* now, support upto 80M bw */
+/* now, support up to 80M bw */
#define RTW_MAX_CHANNEL_WIDTH RTW_CHANNEL_WIDTH_80
enum rtw_bandwidth {
@@ -395,6 +395,15 @@ enum rtw_snr {
RTW_SNR_NUM
};
+enum rtw_port {
+ RTW_PORT_0 = 0,
+ RTW_PORT_1 = 1,
+ RTW_PORT_2 = 2,
+ RTW_PORT_3 = 3,
+ RTW_PORT_4 = 4,
+ RTW_PORT_NUM
+};
+
enum rtw_wow_flags {
RTW_WOW_FLAG_EN_MAGIC_PKT,
RTW_WOW_FLAG_EN_REKEY_PKT,
@@ -1168,6 +1177,7 @@ struct rtw_chip_info {
u32 txff_size;
u32 rxff_size;
u32 fw_rxff_size;
+ u16 rsvd_drv_pg_num;
u8 band;
u8 page_size;
u8 csi_buf_pg_num;
@@ -1871,7 +1881,7 @@ enum rtw_sar_bands {
RTW_SAR_BAND_NR,
};
-/* the union is reserved for other knids of SAR sources
+/* the union is reserved for other kinds of SAR sources
* which might not re-use same format with array common.
*/
union rtw_sar_cfg {
@@ -1890,7 +1900,9 @@ struct rtw_hal {
u8 cut_version;
u8 mp_chip;
u8 oem_id;
+ u8 pkg_type;
struct rtw_phy_cond phy_cond;
+ bool rfe_btg;
u8 ps_mode;
u8 current_channel;
@@ -2020,7 +2032,7 @@ struct rtw_dev {
struct rtw_tx_report tx_report;
struct {
- /* incicate the mail box to use with fw */
+ /* indicate the mail box to use with fw */
u8 last_box_num;
u32 seq;
} h2c;
@@ -2036,6 +2048,7 @@ struct rtw_dev {
u8 sta_cnt;
u32 rts_threshold;
+ DECLARE_BITMAP(hw_port, RTW_PORT_NUM);
DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM);
DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS);
@@ -2047,6 +2060,7 @@ struct rtw_dev {
bool need_rfk;
struct completion fw_scan_density;
+ bool ap_active;
/* hci related data, must be last */
u8 priv[] __aligned(sizeof(void *));
@@ -2188,4 +2202,7 @@ void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool config_1ss);
void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
u8 primary_channel, enum rtw_supported_band band,
enum rtw_bandwidth bandwidth);
+void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
+bool rtw_core_check_sta_active(struct rtw_dev *rtwdev);
+void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable);
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 8852b24d6c2a..2a2ae2081f34 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -87,6 +87,7 @@
#define BIT_LTE_MUX_CTRL_PATH BIT(26)
#define REG_HCI_OPT_CTRL 0x0074
#define BIT_USB_SUS_DIS BIT(8)
+#define BIT_SDIO_PAD_E5 BIT(18)
#define REG_AFE_CTRL_4 0x0078
#define BIT_CK320M_AFE_EN BIT(4)
@@ -185,6 +186,9 @@
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
#define REG_TXDMA_PQ_MAP 0x010C
#define BIT_RXDMA_ARBBW_EN BIT(0)
+#define BIT_RXSHFT_EN BIT(1)
+#define BIT_RXDMA_AGG_EN BIT(2)
+#define BIT_TXDMA_BW_EN BIT(3)
#define BIT_SHIFT_TXDMA_BEQ_MAP 8
#define BIT_MASK_TXDMA_BEQ_MAP 0x3
#define BIT_TXDMA_BEQ_MAP(x) \
@@ -283,10 +287,18 @@
#define REG_H2C_TAIL 0x0248
#define REG_H2C_READ_ADDR 0x024C
#define REG_H2C_INFO 0x0254
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define BIT_RXDMA_AGG_PG_TH GENMASK(7, 0)
+#define BIT_DMA_AGG_TO_V1 GENMASK(15, 8)
+#define BIT_EN_PRE_CALC BIT(29)
#define REG_RXPKT_NUM 0x0284
#define BIT_RXDMA_REQ BIT(19)
#define BIT_RW_RELEASE BIT(18)
#define BIT_RXDMA_IDLE BIT(17)
+#define REG_RXDMA_STATUS 0x0288
+#define REG_RXDMA_DPR 0x028C
+#define REG_RXDMA_MODE 0x0290
+#define BIT_DMA_MODE BIT(1)
#define REG_RXPKTNUM 0x02B0
#define REG_INT_MIG 0x0304
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 2d2f768bae2e..06e7454c9ca6 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -2743,6 +2743,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.ptct_efuse_size = 96 + 1,
.txff_size = 32768,
.rxff_size = 16384,
+ .rsvd_drv_pg_num = 8,
.txgi_factor = 1,
.is_pwr_by_rate_dec = true,
.max_power_index = 0x3f,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index 7ae0541d7b99..adf224618a2a 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -47,13 +47,14 @@ enum rtw8821ce_rf_set {
static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
+ struct rtw_hal *hal = &rtwdev->hal;
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw8821c_efuse *map;
int i;
map = (struct rtw8821c_efuse *)log_map;
- efuse->rfe_option = map->rfe_option;
+ efuse->rfe_option = map->rfe_option & 0x1f;
efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
@@ -70,6 +71,19 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g;
efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g;
+ hal->pkg_type = map->rfe_option & BIT(5) ? 1 : 0;
+
+ switch (efuse->rfe_option) {
+ case 0x2:
+ case 0x4:
+ case 0x7:
+ case 0xa:
+ case 0xc:
+ case 0xf:
+ hal->rfe_btg = true;
+ break;
+ }
+
for (i = 0; i < 4; i++)
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
@@ -295,6 +309,7 @@ static void rtw8821c_switch_rf_set(struct rtw_dev *rtwdev, u8 rf_set)
static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
{
+ struct rtw_hal *hal = &rtwdev->hal;
u32 rf_reg18;
rf_reg18 = rtw_read_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK);
@@ -326,11 +341,10 @@ static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
}
if (channel <= 14) {
- if (rtwdev->efuse.rfe_option == 0)
- rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG);
- else if (rtwdev->efuse.rfe_option == 2 ||
- rtwdev->efuse.rfe_option == 4)
+ if (hal->rfe_btg)
rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_BTG);
+ else
+ rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x1);
rtw_write_rf(rtwdev, RF_PATH_A, 0x64, 0xf, 0xf);
} else {
@@ -1546,7 +1560,6 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
[2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
[4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
[6] = RTW_DEF_RFE(8821c, 0, 0),
- [34] = RTW_DEF_RFE(8821c, 0, 0),
};
static struct rtw_hw_reg rtw8821c_dig[] = {
@@ -1920,6 +1933,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
.ptct_efuse_size = 96,
.txff_size = 65536,
.rxff_size = 16384,
+ .rsvd_drv_pg_num = 8,
.txgi_factor = 1,
.is_pwr_by_rate_dec = true,
.max_power_index = 0x3f,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c
new file mode 100644
index 000000000000..a359413369a4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include "main.h"
+#include "rtw8821c.h"
+#include "sdio.h"
+
+static const struct sdio_device_id rtw_8821cs_id_table[] = {
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8821CS),
+ .driver_data = (kernel_ulong_t)&rtw8821c_hw_spec,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, rtw_8821cs_id_table);
+
+static struct sdio_driver rtw_8821cs_driver = {
+ .name = "rtw_8821cs",
+ .probe = rtw_sdio_probe,
+ .remove = rtw_sdio_remove,
+ .id_table = rtw_8821cs_id_table,
+ .drv = {
+ .pm = &rtw_sdio_pm_ops,
+ .shutdown = rtw_sdio_shutdown,
+ }
+};
+module_sdio_driver(rtw_8821cs_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cs driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 531b67787e2e..3017a9760da8 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -2540,6 +2540,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
.txff_size = 262144,
.rxff_size = 24576,
.fw_rxff_size = 12288,
+ .rsvd_drv_pg_num = 8,
.txgi_factor = 1,
.is_pwr_by_rate_dec = true,
.max_power_index = 0x3f,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c
new file mode 100644
index 000000000000..31d8645f83bd
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) Jernej Skrabec <jernej.skrabec@gmail.com>
+ */
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include "main.h"
+#include "rtw8822b.h"
+#include "sdio.h"
+
+static const struct sdio_device_id rtw_8822bs_id_table[] = {
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8822BS),
+ .driver_data = (kernel_ulong_t)&rtw8822b_hw_spec,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, rtw_8822bs_id_table);
+
+static struct sdio_driver rtw_8822bs_driver = {
+ .name = "rtw_8822bs",
+ .probe = rtw_sdio_probe,
+ .remove = rtw_sdio_remove,
+ .id_table = rtw_8822bs_id_table,
+ .drv = {
+ .pm = &rtw_sdio_pm_ops,
+ .shutdown = rtw_sdio_shutdown,
+ }
+};
+module_sdio_driver(rtw_8822bs_driver);
+
+MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@gmail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bs driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index 5a2c004b12df..cd965edc29ce 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -5358,6 +5358,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
.txff_size = 262144,
.rxff_size = 24576,
.fw_rxff_size = 12288,
+ .rsvd_drv_pg_num = 16,
.txgi_factor = 2,
.is_pwr_by_rate_dec = false,
.max_power_index = 0x7f,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c
new file mode 100644
index 000000000000..975e81c824f2
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include "main.h"
+#include "rtw8822c.h"
+#include "sdio.h"
+
+static const struct sdio_device_id rtw_8822cs_id_table[] = {
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8822CS),
+ .driver_data = (kernel_ulong_t)&rtw8822c_hw_spec,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, rtw_8822cs_id_table);
+
+static struct sdio_driver rtw_8822cs_driver = {
+ .name = "rtw_8822cs",
+ .probe = rtw_sdio_probe,
+ .remove = rtw_sdio_remove,
+ .id_table = rtw_8822cs_id_table,
+ .drv = {
+ .pm = &rtw_sdio_pm_ops,
+ .shutdown = rtw_sdio_shutdown,
+ }
+};
+module_sdio_driver(rtw_8822cs_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cs driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
new file mode 100644
index 000000000000..af0459a79899
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -0,0 +1,1394 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright (C) 2021 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@gmail.com>
+ *
+ * Based on rtw88/pci.c:
+ * Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include "main.h"
+#include "debug.h"
+#include "fw.h"
+#include "ps.h"
+#include "reg.h"
+#include "rx.h"
+#include "sdio.h"
+#include "tx.h"
+
+#define RTW_SDIO_INDIRECT_RW_RETRIES 50
+
+static bool rtw_sdio_is_bus_addr(u32 addr)
+{
+ return !!(addr & RTW_SDIO_BUS_MSK);
+}
+
+static bool rtw_sdio_bus_claim_needed(struct rtw_sdio *rtwsdio)
+{
+ return !rtwsdio->irq_thread ||
+ rtwsdio->irq_thread != current;
+}
+
+static u32 rtw_sdio_to_bus_offset(struct rtw_dev *rtwdev, u32 addr)
+{
+ switch (addr & RTW_SDIO_BUS_MSK) {
+ case WLAN_IOREG_OFFSET:
+ addr &= WLAN_IOREG_REG_MSK;
+ addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_MAC_REG);
+ break;
+ case SDIO_LOCAL_OFFSET:
+ addr &= SDIO_LOCAL_REG_MSK;
+ addr |= FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_SDIO_REG);
+ break;
+ default:
+ rtw_warn(rtwdev, "Cannot convert addr 0x%08x to bus offset",
+ addr);
+ }
+
+ return addr;
+}
+
+static bool rtw_sdio_use_memcpy_io(struct rtw_dev *rtwdev, u32 addr,
+ u8 alignment)
+{
+ return IS_ALIGNED(addr, alignment) &&
+ test_bit(RTW_FLAG_POWERON, rtwdev->flags);
+}
+
+static void rtw_sdio_writel(struct rtw_dev *rtwdev, u32 val, u32 addr,
+ int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u8 buf[4];
+ int i;
+
+ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 4)) {
+ sdio_writel(rtwsdio->sdio_func, val, addr, err_ret);
+ return;
+ }
+
+ *(__le32 *)buf = cpu_to_le32(val);
+
+ for (i = 0; i < 4; i++) {
+ sdio_writeb(rtwsdio->sdio_func, buf[i], addr + i, err_ret);
+ if (*err_ret)
+ return;
+ }
+}
+
+static void rtw_sdio_writew(struct rtw_dev *rtwdev, u16 val, u32 addr,
+ int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u8 buf[2];
+ int i;
+
+ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 2)) {
+ sdio_writew(rtwsdio->sdio_func, val, addr, err_ret);
+ return;
+ }
+
+ *(__le16 *)buf = cpu_to_le16(val);
+
+ for (i = 0; i < 2; i++) {
+ sdio_writeb(rtwsdio->sdio_func, buf[i], addr + i, err_ret);
+ if (*err_ret)
+ return;
+ }
+}
+
+static u32 rtw_sdio_readl(struct rtw_dev *rtwdev, u32 addr, int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u8 buf[4];
+ int i;
+
+ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 4))
+ return sdio_readl(rtwsdio->sdio_func, addr, err_ret);
+
+ for (i = 0; i < 4; i++) {
+ buf[i] = sdio_readb(rtwsdio->sdio_func, addr + i, err_ret);
+ if (*err_ret)
+ return 0;
+ }
+
+ return le32_to_cpu(*(__le32 *)buf);
+}
+
+static u16 rtw_sdio_readw(struct rtw_dev *rtwdev, u32 addr, int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u8 buf[2];
+ int i;
+
+ if (rtw_sdio_use_memcpy_io(rtwdev, addr, 2))
+ return sdio_readw(rtwsdio->sdio_func, addr, err_ret);
+
+ for (i = 0; i < 2; i++) {
+ buf[i] = sdio_readb(rtwsdio->sdio_func, addr + i, err_ret);
+ if (*err_ret)
+ return 0;
+ }
+
+ return le16_to_cpu(*(__le16 *)buf);
+}
+
+static u32 rtw_sdio_to_io_address(struct rtw_dev *rtwdev, u32 addr,
+ bool direct)
+{
+ if (!direct)
+ return addr;
+
+ if (!rtw_sdio_is_bus_addr(addr))
+ addr |= WLAN_IOREG_OFFSET;
+
+ return rtw_sdio_to_bus_offset(rtwdev, addr);
+}
+
+static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr)
+{
+ return !rtw_sdio_is_sdio30_supported(rtwdev) ||
+ rtw_sdio_is_bus_addr(addr);
+}
+
+static int rtw_sdio_indirect_reg_cfg(struct rtw_dev *rtwdev, u32 addr, u32 cfg)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ unsigned int retry;
+ u32 reg_cfg;
+ int ret;
+ u8 tmp;
+
+ reg_cfg = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_CFG);
+
+ rtw_sdio_writel(rtwdev, addr | cfg | BIT_SDIO_INDIRECT_REG_CFG_UNK20,
+ reg_cfg, &ret);
+ if (ret)
+ return ret;
+
+ for (retry = 0; retry < RTW_SDIO_INDIRECT_RW_RETRIES; retry++) {
+ tmp = sdio_readb(rtwsdio->sdio_func, reg_cfg + 2, &ret);
+ if (!ret && (tmp & BIT(4)))
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static u8 rtw_sdio_indirect_read8(struct rtw_dev *rtwdev, u32 addr,
+ int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u32 reg_data;
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_READ);
+ if (*err_ret)
+ return 0;
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ return sdio_readb(rtwsdio->sdio_func, reg_data, err_ret);
+}
+
+static int rtw_sdio_indirect_read_bytes(struct rtw_dev *rtwdev, u32 addr,
+ u8 *buf, int count)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < count; i++) {
+ buf[i] = rtw_sdio_indirect_read8(rtwdev, addr + i, &ret);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static u16 rtw_sdio_indirect_read16(struct rtw_dev *rtwdev, u32 addr,
+ int *err_ret)
+{
+ u32 reg_data;
+ u8 buf[2];
+
+ if (!IS_ALIGNED(addr, 2)) {
+ *err_ret = rtw_sdio_indirect_read_bytes(rtwdev, addr, buf, 2);
+ if (*err_ret)
+ return 0;
+
+ return le16_to_cpu(*(__le16 *)buf);
+ }
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_READ);
+ if (*err_ret)
+ return 0;
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ return rtw_sdio_readw(rtwdev, reg_data, err_ret);
+}
+
+static u32 rtw_sdio_indirect_read32(struct rtw_dev *rtwdev, u32 addr,
+ int *err_ret)
+{
+ u32 reg_data;
+ u8 buf[4];
+
+ if (!IS_ALIGNED(addr, 4)) {
+ *err_ret = rtw_sdio_indirect_read_bytes(rtwdev, addr, buf, 4);
+ if (*err_ret)
+ return 0;
+
+ return le32_to_cpu(*(__le32 *)buf);
+ }
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_READ);
+ if (*err_ret)
+ return 0;
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ return rtw_sdio_readl(rtwdev, reg_data, err_ret);
+}
+
+static u8 rtw_sdio_read8(struct rtw_dev *rtwdev, u32 addr)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ int ret;
+ u8 val;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ val = sdio_readb(rtwsdio->sdio_func, addr, &ret);
+ else
+ val = rtw_sdio_indirect_read8(rtwdev, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio read8 failed (0x%x): %d", addr, ret);
+
+ return val;
+}
+
+static u16 rtw_sdio_read16(struct rtw_dev *rtwdev, u32 addr)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ int ret;
+ u16 val;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ val = rtw_sdio_readw(rtwdev, addr, &ret);
+ else
+ val = rtw_sdio_indirect_read16(rtwdev, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio read16 failed (0x%x): %d", addr, ret);
+
+ return val;
+}
+
+static u32 rtw_sdio_read32(struct rtw_dev *rtwdev, u32 addr)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ u32 val;
+ int ret;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ val = rtw_sdio_readl(rtwdev, addr, &ret);
+ else
+ val = rtw_sdio_indirect_read32(rtwdev, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio read32 failed (0x%x): %d", addr, ret);
+
+ return val;
+}
+
+static void rtw_sdio_indirect_write8(struct rtw_dev *rtwdev, u8 val, u32 addr,
+ int *err_ret)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ u32 reg_data;
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ sdio_writeb(rtwsdio->sdio_func, val, reg_data, err_ret);
+ if (*err_ret)
+ return;
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_WRITE);
+}
+
+static void rtw_sdio_indirect_write16(struct rtw_dev *rtwdev, u16 val, u32 addr,
+ int *err_ret)
+{
+ u32 reg_data;
+
+ if (!IS_ALIGNED(addr, 2)) {
+ addr = rtw_sdio_to_io_address(rtwdev, addr, true);
+ rtw_sdio_writew(rtwdev, val, addr, err_ret);
+ return;
+ }
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ rtw_sdio_writew(rtwdev, val, reg_data, err_ret);
+ if (*err_ret)
+ return;
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_WRITE |
+ BIT_SDIO_INDIRECT_REG_CFG_WORD);
+}
+
+static void rtw_sdio_indirect_write32(struct rtw_dev *rtwdev, u32 val,
+ u32 addr, int *err_ret)
+{
+ u32 reg_data;
+
+ if (!IS_ALIGNED(addr, 4)) {
+ addr = rtw_sdio_to_io_address(rtwdev, addr, true);
+ rtw_sdio_writel(rtwdev, val, addr, err_ret);
+ return;
+ }
+
+ reg_data = rtw_sdio_to_bus_offset(rtwdev, REG_SDIO_INDIRECT_REG_DATA);
+ rtw_sdio_writel(rtwdev, val, reg_data, err_ret);
+
+ *err_ret = rtw_sdio_indirect_reg_cfg(rtwdev, addr,
+ BIT_SDIO_INDIRECT_REG_CFG_WRITE |
+ BIT_SDIO_INDIRECT_REG_CFG_DWORD);
+}
+
+static void rtw_sdio_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ int ret;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ sdio_writeb(rtwsdio->sdio_func, val, addr, &ret);
+ else
+ rtw_sdio_indirect_write8(rtwdev, val, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio write8 failed (0x%x): %d", addr, ret);
+}
+
+static void rtw_sdio_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ int ret;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ rtw_sdio_writew(rtwdev, val, addr, &ret);
+ else
+ rtw_sdio_indirect_write16(rtwdev, val, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio write16 failed (0x%x): %d", addr, ret);
+}
+
+static void rtw_sdio_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool direct, bus_claim;
+ int ret;
+
+ direct = rtw_sdio_use_direct_io(rtwdev, addr);
+ addr = rtw_sdio_to_io_address(rtwdev, addr, direct);
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ if (direct)
+ rtw_sdio_writel(rtwdev, val, addr, &ret);
+ else
+ rtw_sdio_indirect_write32(rtwdev, val, addr, &ret);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev, "sdio write32 failed (0x%x): %d", addr, ret);
+}
+
+static u32 rtw_sdio_get_tx_addr(struct rtw_dev *rtwdev, size_t size,
+ enum rtw_tx_queue_type queue)
+{
+ u32 txaddr;
+
+ switch (queue) {
+ case RTW_TX_QUEUE_BCN:
+ case RTW_TX_QUEUE_H2C:
+ case RTW_TX_QUEUE_HI0:
+ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_TXFF_HIGH);
+ break;
+ case RTW_TX_QUEUE_VI:
+ case RTW_TX_QUEUE_VO:
+ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_TXFF_NORMAL);
+ break;
+ case RTW_TX_QUEUE_BE:
+ case RTW_TX_QUEUE_BK:
+ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_TXFF_LOW);
+ break;
+ case RTW_TX_QUEUE_MGMT:
+ txaddr = FIELD_PREP(REG_SDIO_CMD_ADDR_MSK,
+ REG_SDIO_CMD_ADDR_TXFF_EXTRA);
+ break;
+ default:
+ rtw_warn(rtwdev, "Unsupported queue for TX addr: 0x%02x\n",
+ queue);
+ return 0;
+ }
+
+ txaddr += DIV_ROUND_UP(size, 4);
+
+ return txaddr;
+};
+
+static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+ u32 rxaddr = rtwsdio->rx_addr++;
+ int ret;
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ ret = sdio_memcpy_fromio(rtwsdio->sdio_func, buf,
+ RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), count);
+ if (ret)
+ rtw_warn(rtwdev,
+ "Failed to read %zu byte(s) from SDIO port 0x%08x",
+ count, rxaddr);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ return ret;
+}
+
+static int rtw_sdio_check_free_txpg(struct rtw_dev *rtwdev, u8 queue,
+ size_t count)
+{
+ unsigned int pages_free, pages_needed;
+
+ if (rtw_chip_wcpu_11n(rtwdev)) {
+ u32 free_txpg;
+
+ free_txpg = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG);
+
+ switch (queue) {
+ case RTW_TX_QUEUE_BCN:
+ case RTW_TX_QUEUE_H2C:
+ case RTW_TX_QUEUE_HI0:
+ case RTW_TX_QUEUE_MGMT:
+ /* high */
+ pages_free = free_txpg & 0xff;
+ break;
+ case RTW_TX_QUEUE_VI:
+ case RTW_TX_QUEUE_VO:
+ /* normal */
+ pages_free = (free_txpg >> 8) & 0xff;
+ break;
+ case RTW_TX_QUEUE_BE:
+ case RTW_TX_QUEUE_BK:
+ /* low */
+ pages_free = (free_txpg >> 16) & 0xff;
+ break;
+ default:
+ rtw_warn(rtwdev, "Unknown mapping for queue %u\n", queue);
+ return -EINVAL;
+ }
+
+ /* add the pages from the public queue */
+ pages_free += (free_txpg >> 24) & 0xff;
+ } else {
+ u32 free_txpg[3];
+
+ free_txpg[0] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG);
+ free_txpg[1] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG + 4);
+ free_txpg[2] = rtw_sdio_read32(rtwdev, REG_SDIO_FREE_TXPG + 8);
+
+ switch (queue) {
+ case RTW_TX_QUEUE_BCN:
+ case RTW_TX_QUEUE_H2C:
+ case RTW_TX_QUEUE_HI0:
+ /* high */
+ pages_free = free_txpg[0] & 0xfff;
+ break;
+ case RTW_TX_QUEUE_VI:
+ case RTW_TX_QUEUE_VO:
+ /* normal */
+ pages_free = (free_txpg[0] >> 16) & 0xfff;
+ break;
+ case RTW_TX_QUEUE_BE:
+ case RTW_TX_QUEUE_BK:
+ /* low */
+ pages_free = free_txpg[1] & 0xfff;
+ break;
+ case RTW_TX_QUEUE_MGMT:
+ /* extra */
+ pages_free = free_txpg[2] & 0xfff;
+ break;
+ default:
+ rtw_warn(rtwdev, "Unknown mapping for queue %u\n", queue);
+ return -EINVAL;
+ }
+
+ /* add the pages from the public queue */
+ pages_free += (free_txpg[1] >> 16) & 0xfff;
+ }
+
+ pages_needed = DIV_ROUND_UP(count, rtwdev->chip->page_size);
+
+ if (pages_needed > pages_free) {
+ rtw_dbg(rtwdev, RTW_DBG_SDIO,
+ "Not enough free pages (%u needed, %u free) in queue %u for %zu bytes\n",
+ pages_needed, pages_free, queue, count);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ enum rtw_tx_queue_type queue)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool bus_claim;
+ size_t txsize;
+ u32 txaddr;
+ int ret;
+
+ txaddr = rtw_sdio_get_tx_addr(rtwdev, skb->len, queue);
+ if (!txaddr)
+ return -EINVAL;
+
+ txsize = sdio_align_size(rtwsdio->sdio_func, skb->len);
+
+ ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);
+ if (ret)
+ return ret;
+
+ if (!IS_ALIGNED((unsigned long)skb->data, RTW_SDIO_DATA_PTR_ALIGN))
+ rtw_warn(rtwdev, "Got unaligned SKB in %s() for queue %u\n",
+ __func__, queue);
+
+ bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
+
+ if (bus_claim)
+ sdio_claim_host(rtwsdio->sdio_func);
+
+ ret = sdio_memcpy_toio(rtwsdio->sdio_func, txaddr, skb->data, txsize);
+
+ if (bus_claim)
+ sdio_release_host(rtwsdio->sdio_func);
+
+ if (ret)
+ rtw_warn(rtwdev,
+ "Failed to write %zu byte(s) to SDIO port 0x%08x",
+ txsize, txaddr);
+
+ return ret;
+}
+
+static void rtw_sdio_init(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ rtwsdio->irq_mask = REG_SDIO_HIMR_RX_REQUEST | REG_SDIO_HIMR_CPWM1;
+}
+
+static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev)
+{
+ u8 size, timeout;
+
+ if (rtw_chip_wcpu_11n(rtwdev)) {
+ size = 0x6;
+ timeout = 0x6;
+ } else {
+ size = 0xff;
+ timeout = 0x1;
+ }
+
+ /* Make the firmware honor the size limit configured below */
+ rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC);
+
+ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
+
+ rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH,
+ FIELD_PREP(BIT_RXDMA_AGG_PG_TH, size) |
+ FIELD_PREP(BIT_DMA_AGG_TO_V1, timeout));
+
+ rtw_write8_set(rtwdev, REG_RXDMA_MODE, BIT_DMA_MODE);
+}
+
+static void rtw_sdio_enable_interrupt(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ rtw_write32(rtwdev, REG_SDIO_HIMR, rtwsdio->irq_mask);
+}
+
+static void rtw_sdio_disable_interrupt(struct rtw_dev *rtwdev)
+{
+ rtw_write32(rtwdev, REG_SDIO_HIMR, 0x0);
+}
+
+static u8 rtw_sdio_get_tx_qsel(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ u8 queue)
+{
+ switch (queue) {
+ case RTW_TX_QUEUE_BCN:
+ return TX_DESC_QSEL_BEACON;
+ case RTW_TX_QUEUE_H2C:
+ return TX_DESC_QSEL_H2C;
+ case RTW_TX_QUEUE_MGMT:
+ if (rtw_chip_wcpu_11n(rtwdev))
+ return TX_DESC_QSEL_HIGH;
+ else
+ return TX_DESC_QSEL_MGMT;
+ case RTW_TX_QUEUE_HI0:
+ return TX_DESC_QSEL_HIGH;
+ default:
+ return skb->priority;
+ }
+}
+
+static int rtw_sdio_setup(struct rtw_dev *rtwdev)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static int rtw_sdio_start(struct rtw_dev *rtwdev)
+{
+ rtw_sdio_enable_rx_aggregation(rtwdev);
+ rtw_sdio_enable_interrupt(rtwdev);
+
+ return 0;
+}
+
+static void rtw_sdio_stop(struct rtw_dev *rtwdev)
+{
+ rtw_sdio_disable_interrupt(rtwdev);
+}
+
+static void rtw_sdio_deep_ps_enter(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ bool tx_empty = true;
+ u8 queue;
+
+ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) {
+ /* Deep PS state is not allowed to TX-DMA */
+ for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) {
+ /* BCN queue is rsvd page, does not have DMA interrupt
+ * H2C queue is managed by firmware
+ */
+ if (queue == RTW_TX_QUEUE_BCN ||
+ queue == RTW_TX_QUEUE_H2C)
+ continue;
+
+ /* check if there is any skb DMAing */
+ if (skb_queue_len(&rtwsdio->tx_queue[queue])) {
+ tx_empty = false;
+ break;
+ }
+ }
+ }
+
+ if (!tx_empty) {
+ rtw_dbg(rtwdev, RTW_DBG_PS,
+ "TX path not empty, cannot enter deep power save state\n");
+ return;
+ }
+
+ set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags);
+ rtw_power_mode_change(rtwdev, true);
+}
+
+static void rtw_sdio_deep_ps_leave(struct rtw_dev *rtwdev)
+{
+ if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+ rtw_power_mode_change(rtwdev, false);
+}
+
+static void rtw_sdio_deep_ps(struct rtw_dev *rtwdev, bool enter)
+{
+ if (enter && !test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+ rtw_sdio_deep_ps_enter(rtwdev);
+
+ if (!enter && test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+ rtw_sdio_deep_ps_leave(rtwdev);
+}
+
+static void rtw_sdio_tx_kick_off(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ queue_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work);
+}
+
+static void rtw_sdio_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+ /* nothing to do */
+}
+
+static void rtw_sdio_interface_cfg(struct rtw_dev *rtwdev)
+{
+ u32 val;
+
+ rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
+
+ val = rtw_read32(rtwdev, REG_SDIO_TX_CTRL);
+ val &= 0xfff8;
+ rtw_write32(rtwdev, REG_SDIO_TX_CTRL, val);
+}
+
+static struct rtw_sdio_tx_data *rtw_sdio_get_tx_data(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ BUILD_BUG_ON(sizeof(struct rtw_sdio_tx_data) >
+ sizeof(info->status.status_driver_data));
+
+ return (struct rtw_sdio_tx_data *)info->status.status_driver_data;
+}
+
+static void rtw_sdio_tx_skb_prepare(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb,
+ enum rtw_tx_queue_type queue)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ unsigned long data_addr, aligned_addr;
+ size_t offset;
+ u8 *pkt_desc;
+
+ pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+
+ data_addr = (unsigned long)pkt_desc;
+ aligned_addr = ALIGN(data_addr, RTW_SDIO_DATA_PTR_ALIGN);
+
+ if (data_addr != aligned_addr) {
+ /* Ensure that the start of the pkt_desc is always aligned at
+ * RTW_SDIO_DATA_PTR_ALIGN.
+ */
+ offset = RTW_SDIO_DATA_PTR_ALIGN - (aligned_addr - data_addr);
+
+ pkt_desc = skb_push(skb, offset);
+
+ /* By inserting padding to align the start of the pkt_desc we
+ * need to inform the firmware that the actual data starts at
+ * a different offset than normal.
+ */
+ pkt_info->offset += offset;
+ }
+
+ memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
+
+ pkt_info->qsel = rtw_sdio_get_tx_qsel(rtwdev, skb, queue);
+
+ rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, pkt_desc);
+}
+
+static int rtw_sdio_write_data(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb,
+ enum rtw_tx_queue_type queue)
+{
+ int ret;
+
+ rtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue);
+
+ ret = rtw_sdio_write_port(rtwdev, skb, queue);
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
+static int rtw_sdio_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
+ u32 size)
+{
+ struct rtw_tx_pkt_info pkt_info = {};
+ struct sk_buff *skb;
+
+ skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size);
+ if (!skb)
+ return -ENOMEM;
+
+ return rtw_sdio_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN);
+}
+
+static int rtw_sdio_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+{
+ struct rtw_tx_pkt_info pkt_info = {};
+ struct sk_buff *skb;
+
+ skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size);
+ if (!skb)
+ return -ENOMEM;
+
+ return rtw_sdio_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C);
+}
+
+static int rtw_sdio_tx_write(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb);
+ struct rtw_sdio_tx_data *tx_data;
+
+ rtw_sdio_tx_skb_prepare(rtwdev, pkt_info, skb, queue);
+
+ tx_data = rtw_sdio_get_tx_data(skb);
+ tx_data->sn = pkt_info->sn;
+
+ skb_queue_tail(&rtwsdio->tx_queue[queue], skb);
+
+ return 0;
+}
+
+static void rtw_sdio_tx_err_isr(struct rtw_dev *rtwdev)
+{
+ u32 val = rtw_read32(rtwdev, REG_TXDMA_STATUS);
+
+ rtw_write32(rtwdev, REG_TXDMA_STATUS, val);
+}
+
+static void rtw_sdio_rx_skb(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ u32 pkt_offset, struct rtw_rx_pkt_stat *pkt_stat,
+ struct ieee80211_rx_status *rx_status)
+{
+ *IEEE80211_SKB_RXCB(skb) = *rx_status;
+
+ if (pkt_stat->is_c2h) {
+ skb_put(skb, pkt_stat->pkt_len + pkt_offset);
+ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
+ return;
+ }
+
+ skb_put(skb, pkt_stat->pkt_len);
+ skb_reserve(skb, pkt_offset);
+
+ rtw_rx_stats(rtwdev, pkt_stat->vif, skb);
+
+ ieee80211_rx_irqsafe(rtwdev->hw, skb);
+}
+
+static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
+ struct ieee80211_rx_status rx_status;
+ struct rtw_rx_pkt_stat pkt_stat;
+ struct sk_buff *skb, *split_skb;
+ u32 pkt_offset, curr_pkt_len;
+ size_t bufsz;
+ u8 *rx_desc;
+ int ret;
+
+ bufsz = sdio_align_size(rtwsdio->sdio_func, rx_len);
+
+ skb = dev_alloc_skb(bufsz);
+ if (!skb)
+ return;
+
+ ret = rtw_sdio_read_port(rtwdev, skb->data, bufsz);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ while (true) {
+ rx_desc = skb->data;
+ chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+ &rx_status);
+ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+ pkt_stat.shift;
+
+ curr_pkt_len = ALIGN(pkt_offset + pkt_stat.pkt_len,
+ RTW_SDIO_DATA_PTR_ALIGN);
+
+ if ((curr_pkt_len + pkt_desc_sz) >= rx_len) {
+ /* Use the original skb (with it's adjusted offset)
+ * when processing the last (or even the only) entry to
+ * have it's memory freed automatically.
+ */
+ rtw_sdio_rx_skb(rtwdev, skb, pkt_offset, &pkt_stat,
+ &rx_status);
+ break;
+ }
+
+ split_skb = dev_alloc_skb(curr_pkt_len);
+ if (!split_skb) {
+ rtw_sdio_rx_skb(rtwdev, skb, pkt_offset, &pkt_stat,
+ &rx_status);
+ break;
+ }
+
+ skb_copy_header(split_skb, skb);
+ memcpy(split_skb->data, skb->data, curr_pkt_len);
+
+ rtw_sdio_rx_skb(rtwdev, split_skb, pkt_offset, &pkt_stat,
+ &rx_status);
+
+ /* Move to the start of the next RX descriptor */
+ skb_reserve(skb, curr_pkt_len);
+ rx_len -= curr_pkt_len;
+ }
+}
+
+static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
+{
+ u32 rx_len, total_rx_bytes = 0;
+
+ while (total_rx_bytes < SZ_64K) {
+ if (rtw_chip_wcpu_11n(rtwdev))
+ rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN);
+ else
+ rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN);
+
+ if (!rx_len)
+ break;
+
+ rtw_sdio_rxfifo_recv(rtwdev, rx_len);
+
+ total_rx_bytes += rx_len;
+ }
+}
+
+static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)
+{
+ struct ieee80211_hw *hw = sdio_get_drvdata(sdio_func);
+ struct rtw_sdio *rtwsdio;
+ struct rtw_dev *rtwdev;
+ u32 hisr;
+
+ rtwdev = hw->priv;
+ rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ rtwsdio->irq_thread = current;
+
+ hisr = rtw_read32(rtwdev, REG_SDIO_HISR);
+
+ if (hisr & REG_SDIO_HISR_TXERR)
+ rtw_sdio_tx_err_isr(rtwdev);
+ if (hisr & REG_SDIO_HISR_RX_REQUEST) {
+ hisr &= ~REG_SDIO_HISR_RX_REQUEST;
+ rtw_sdio_rx_isr(rtwdev);
+ }
+
+ rtw_write32(rtwdev, REG_SDIO_HISR, hisr);
+
+ rtwsdio->irq_thread = NULL;
+}
+
+static int __maybe_unused rtw_sdio_suspend(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct ieee80211_hw *hw = dev_get_drvdata(dev);
+ struct rtw_dev *rtwdev = hw->priv;
+ int ret;
+
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (ret)
+ rtw_err(rtwdev, "Failed to host PM flag MMC_PM_KEEP_POWER");
+
+ return ret;
+}
+
+static int __maybe_unused rtw_sdio_resume(struct device *dev)
+{
+ return 0;
+}
+
+SIMPLE_DEV_PM_OPS(rtw_sdio_pm_ops, rtw_sdio_suspend, rtw_sdio_resume);
+EXPORT_SYMBOL(rtw_sdio_pm_ops);
+
+static int rtw_sdio_claim(struct rtw_dev *rtwdev, struct sdio_func *sdio_func)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ int ret;
+
+ sdio_claim_host(sdio_func);
+
+ ret = sdio_enable_func(sdio_func);
+ if (ret) {
+ rtw_err(rtwdev, "Failed to enable SDIO func");
+ goto err_release_host;
+ }
+
+ ret = sdio_set_block_size(sdio_func, RTW_SDIO_BLOCK_SIZE);
+ if (ret) {
+ rtw_err(rtwdev, "Failed to set SDIO block size to 512");
+ goto err_disable_func;
+ }
+
+ rtwsdio->sdio_func = sdio_func;
+
+ rtwsdio->sdio3_bus_mode = mmc_card_uhs(sdio_func->card);
+
+ sdio_set_drvdata(sdio_func, rtwdev->hw);
+ SET_IEEE80211_DEV(rtwdev->hw, &sdio_func->dev);
+
+ sdio_release_host(sdio_func);
+
+ return 0;
+
+err_disable_func:
+ sdio_disable_func(sdio_func);
+err_release_host:
+ sdio_release_host(sdio_func);
+ return ret;
+}
+
+static void rtw_sdio_declaim(struct rtw_dev *rtwdev,
+ struct sdio_func *sdio_func)
+{
+ sdio_claim_host(sdio_func);
+ sdio_disable_func(sdio_func);
+ sdio_release_host(sdio_func);
+}
+
+static struct rtw_hci_ops rtw_sdio_ops = {
+ .tx_write = rtw_sdio_tx_write,
+ .tx_kick_off = rtw_sdio_tx_kick_off,
+ .setup = rtw_sdio_setup,
+ .start = rtw_sdio_start,
+ .stop = rtw_sdio_stop,
+ .deep_ps = rtw_sdio_deep_ps,
+ .link_ps = rtw_sdio_link_ps,
+ .interface_cfg = rtw_sdio_interface_cfg,
+
+ .read8 = rtw_sdio_read8,
+ .read16 = rtw_sdio_read16,
+ .read32 = rtw_sdio_read32,
+ .write8 = rtw_sdio_write8,
+ .write16 = rtw_sdio_write16,
+ .write32 = rtw_sdio_write32,
+ .write_data_rsvd_page = rtw_sdio_write_data_rsvd_page,
+ .write_data_h2c = rtw_sdio_write_data_h2c,
+};
+
+static int rtw_sdio_request_irq(struct rtw_dev *rtwdev,
+ struct sdio_func *sdio_func)
+{
+ int ret;
+
+ sdio_claim_host(sdio_func);
+ ret = sdio_claim_irq(sdio_func, &rtw_sdio_handle_interrupt);
+ sdio_release_host(sdio_func);
+
+ if (ret) {
+ rtw_err(rtwdev, "failed to claim SDIO IRQ");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rtw_sdio_indicate_tx_status(struct rtw_dev *rtwdev,
+ struct sk_buff *skb)
+{
+ struct rtw_sdio_tx_data *tx_data = rtw_sdio_get_tx_data(skb);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hw *hw = rtwdev->hw;
+
+ /* enqueue to wait for tx report */
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
+ rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
+ return;
+ }
+
+ /* always ACK for others, then they won't be marked as drop */
+ ieee80211_tx_info_clear_status(info);
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ else
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+}
+
+static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev,
+ enum rtw_tx_queue_type queue)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = skb_dequeue(&rtwsdio->tx_queue[queue]);
+ if (!skb)
+ return;
+
+ ret = rtw_sdio_write_port(rtwdev, skb, queue);
+ if (ret) {
+ skb_queue_head(&rtwsdio->tx_queue[queue], skb);
+ return;
+ }
+
+ if (queue <= RTW_TX_QUEUE_VO)
+ rtw_sdio_indicate_tx_status(rtwdev, skb);
+ else
+ dev_kfree_skb_any(skb);
+}
+
+static void rtw_sdio_tx_handler(struct work_struct *work)
+{
+ struct rtw_sdio_work_data *work_data =
+ container_of(work, struct rtw_sdio_work_data, work);
+ struct rtw_sdio *rtwsdio;
+ struct rtw_dev *rtwdev;
+ int limit, queue;
+
+ rtwdev = work_data->rtwdev;
+ rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE))
+ rtw_sdio_deep_ps_leave(rtwdev);
+
+ for (queue = RTK_MAX_TX_QUEUE_NUM - 1; queue >= 0; queue--) {
+ for (limit = 0; limit < 1000; limit++) {
+ rtw_sdio_process_tx_queue(rtwdev, queue);
+
+ if (skb_queue_empty(&rtwsdio->tx_queue[queue]))
+ break;
+ }
+ }
+}
+
+static void rtw_sdio_free_irq(struct rtw_dev *rtwdev,
+ struct sdio_func *sdio_func)
+{
+ sdio_claim_host(sdio_func);
+ sdio_release_irq(sdio_func);
+ sdio_release_host(sdio_func);
+}
+
+static int rtw_sdio_init_tx(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ int i;
+
+ rtwsdio->txwq = create_singlethread_workqueue("rtw88_sdio: tx wq");
+ if (!rtwsdio->txwq) {
+ rtw_err(rtwdev, "failed to create TX work queue\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
+ skb_queue_head_init(&rtwsdio->tx_queue[i]);
+ rtwsdio->tx_handler_data = kmalloc(sizeof(*rtwsdio->tx_handler_data),
+ GFP_KERNEL);
+ if (!rtwsdio->tx_handler_data)
+ goto err_destroy_wq;
+
+ rtwsdio->tx_handler_data->rtwdev = rtwdev;
+ INIT_WORK(&rtwsdio->tx_handler_data->work, rtw_sdio_tx_handler);
+
+ return 0;
+
+err_destroy_wq:
+ destroy_workqueue(rtwsdio->txwq);
+ return -ENOMEM;
+}
+
+static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ int i;
+
+ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
+ skb_queue_purge(&rtwsdio->tx_queue[i]);
+
+ flush_workqueue(rtwsdio->txwq);
+ destroy_workqueue(rtwsdio->txwq);
+ kfree(rtwsdio->tx_handler_data);
+}
+
+int rtw_sdio_probe(struct sdio_func *sdio_func,
+ const struct sdio_device_id *id)
+{
+ struct ieee80211_hw *hw;
+ struct rtw_dev *rtwdev;
+ int drv_data_size;
+ int ret;
+
+ drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_sdio);
+ hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops);
+ if (!hw) {
+ dev_err(&sdio_func->dev, "failed to allocate hw");
+ return -ENOMEM;
+ }
+
+ rtwdev = hw->priv;
+ rtwdev->hw = hw;
+ rtwdev->dev = &sdio_func->dev;
+ rtwdev->chip = (struct rtw_chip_info *)id->driver_data;
+ rtwdev->hci.ops = &rtw_sdio_ops;
+ rtwdev->hci.type = RTW_HCI_TYPE_SDIO;
+
+ ret = rtw_core_init(rtwdev);
+ if (ret)
+ goto err_release_hw;
+
+ rtw_dbg(rtwdev, RTW_DBG_SDIO,
+ "rtw88 SDIO probe: vendor=0x%04x device=%04x class=%02x",
+ id->vendor, id->device, id->class);
+
+ ret = rtw_sdio_claim(rtwdev, sdio_func);
+ if (ret) {
+ rtw_err(rtwdev, "failed to claim SDIO device");
+ goto err_deinit_core;
+ }
+
+ rtw_sdio_init(rtwdev);
+
+ ret = rtw_sdio_init_tx(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to init SDIO TX queue\n");
+ goto err_sdio_declaim;
+ }
+
+ ret = rtw_chip_info_setup(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to setup chip information");
+ goto err_destroy_txwq;
+ }
+
+ ret = rtw_sdio_request_irq(rtwdev, sdio_func);
+ if (ret)
+ goto err_destroy_txwq;
+
+ ret = rtw_register_hw(rtwdev, hw);
+ if (ret) {
+ rtw_err(rtwdev, "failed to register hw");
+ goto err_free_irq;
+ }
+
+ return 0;
+
+err_free_irq:
+ rtw_sdio_free_irq(rtwdev, sdio_func);
+err_destroy_txwq:
+ rtw_sdio_deinit_tx(rtwdev);
+err_sdio_declaim:
+ rtw_sdio_declaim(rtwdev, sdio_func);
+err_deinit_core:
+ rtw_core_deinit(rtwdev);
+err_release_hw:
+ ieee80211_free_hw(hw);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw_sdio_probe);
+
+void rtw_sdio_remove(struct sdio_func *sdio_func)
+{
+ struct ieee80211_hw *hw = sdio_get_drvdata(sdio_func);
+ struct rtw_dev *rtwdev;
+
+ if (!hw)
+ return;
+
+ rtwdev = hw->priv;
+
+ rtw_unregister_hw(rtwdev, hw);
+ rtw_sdio_disable_interrupt(rtwdev);
+ rtw_sdio_free_irq(rtwdev, sdio_func);
+ rtw_sdio_declaim(rtwdev, sdio_func);
+ rtw_sdio_deinit_tx(rtwdev);
+ rtw_core_deinit(rtwdev);
+ ieee80211_free_hw(hw);
+}
+EXPORT_SYMBOL(rtw_sdio_remove);
+
+void rtw_sdio_shutdown(struct device *dev)
+{
+ struct sdio_func *sdio_func = dev_to_sdio_func(dev);
+ const struct rtw_chip_info *chip;
+ struct ieee80211_hw *hw;
+ struct rtw_dev *rtwdev;
+
+ hw = sdio_get_drvdata(sdio_func);
+ if (!hw)
+ return;
+
+ rtwdev = hw->priv;
+ chip = rtwdev->chip;
+
+ if (chip->ops->shutdown)
+ chip->ops->shutdown(rtwdev);
+}
+EXPORT_SYMBOL(rtw_sdio_shutdown);
+
+MODULE_AUTHOR("Martin Blumenstingl");
+MODULE_AUTHOR("Jernej Skrabec");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless SDIO driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.h b/drivers/net/wireless/realtek/rtw88/sdio.h
new file mode 100644
index 000000000000..3c659ed180f0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/sdio.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright (C) 2021 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ * Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@gmail.com>
+ */
+
+#ifndef __REG_SDIO_H_
+#define __REG_SDIO_H_
+
+/* I/O bus domain address mapping */
+#define SDIO_LOCAL_OFFSET 0x10250000
+#define WLAN_IOREG_OFFSET 0x10260000
+#define FIRMWARE_FIFO_OFFSET 0x10270000
+#define TX_HIQ_OFFSET 0x10310000
+#define TX_MIQ_OFFSET 0x10320000
+#define TX_LOQ_OFFSET 0x10330000
+#define TX_EPQ_OFFSET 0x10350000
+#define RX_RX0FF_OFFSET 0x10340000
+
+#define RTW_SDIO_BUS_MSK 0xffff0000
+#define SDIO_LOCAL_REG_MSK 0x00000fff
+#define WLAN_IOREG_REG_MSK 0x0000ffff
+
+/* SDIO Tx Control */
+#define REG_SDIO_TX_CTRL (SDIO_LOCAL_OFFSET + 0x0000)
+
+/*SDIO status timeout*/
+#define REG_SDIO_TIMEOUT (SDIO_LOCAL_OFFSET + 0x0002)
+
+/* SDIO Host Interrupt Mask */
+#define REG_SDIO_HIMR (SDIO_LOCAL_OFFSET + 0x0014)
+#define REG_SDIO_HIMR_RX_REQUEST BIT(0)
+#define REG_SDIO_HIMR_AVAL BIT(1)
+#define REG_SDIO_HIMR_TXERR BIT(2)
+#define REG_SDIO_HIMR_RXERR BIT(3)
+#define REG_SDIO_HIMR_TXFOVW BIT(4)
+#define REG_SDIO_HIMR_RXFOVW BIT(5)
+#define REG_SDIO_HIMR_TXBCNOK BIT(6)
+#define REG_SDIO_HIMR_TXBCNERR BIT(7)
+#define REG_SDIO_HIMR_BCNERLY_INT BIT(16)
+#define REG_SDIO_HIMR_C2HCMD BIT(17)
+#define REG_SDIO_HIMR_CPWM1 BIT(18)
+#define REG_SDIO_HIMR_CPWM2 BIT(19)
+#define REG_SDIO_HIMR_HSISR_IND BIT(20)
+#define REG_SDIO_HIMR_GTINT3_IND BIT(21)
+#define REG_SDIO_HIMR_GTINT4_IND BIT(22)
+#define REG_SDIO_HIMR_PSTIMEOUT BIT(23)
+#define REG_SDIO_HIMR_OCPINT BIT(24)
+#define REG_SDIO_HIMR_ATIMEND BIT(25)
+#define REG_SDIO_HIMR_ATIMEND_E BIT(26)
+#define REG_SDIO_HIMR_CTWEND BIT(27)
+/* the following two are RTL8188 SDIO Specific */
+#define REG_SDIO_HIMR_MCU_ERR BIT(28)
+#define REG_SDIO_HIMR_TSF_BIT32_TOGGLE BIT(29)
+
+/* SDIO Host Interrupt Service Routine */
+#define REG_SDIO_HISR (SDIO_LOCAL_OFFSET + 0x0018)
+#define REG_SDIO_HISR_RX_REQUEST BIT(0)
+#define REG_SDIO_HISR_AVAL BIT(1)
+#define REG_SDIO_HISR_TXERR BIT(2)
+#define REG_SDIO_HISR_RXERR BIT(3)
+#define REG_SDIO_HISR_TXFOVW BIT(4)
+#define REG_SDIO_HISR_RXFOVW BIT(5)
+#define REG_SDIO_HISR_TXBCNOK BIT(6)
+#define REG_SDIO_HISR_TXBCNERR BIT(7)
+#define REG_SDIO_HISR_BCNERLY_INT BIT(16)
+#define REG_SDIO_HISR_C2HCMD BIT(17)
+#define REG_SDIO_HISR_CPWM1 BIT(18)
+#define REG_SDIO_HISR_CPWM2 BIT(19)
+#define REG_SDIO_HISR_HSISR_IND BIT(20)
+#define REG_SDIO_HISR_GTINT3_IND BIT(21)
+#define REG_SDIO_HISR_GTINT4_IND BIT(22)
+#define REG_SDIO_HISR_PSTIMEOUT BIT(23)
+#define REG_SDIO_HISR_OCPINT BIT(24)
+#define REG_SDIO_HISR_ATIMEND BIT(25)
+#define REG_SDIO_HISR_ATIMEND_E BIT(26)
+#define REG_SDIO_HISR_CTWEND BIT(27)
+/* the following two are RTL8188 SDIO Specific */
+#define REG_SDIO_HISR_MCU_ERR BIT(28)
+#define REG_SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
+
+/* HCI Current Power Mode */
+#define REG_SDIO_HCPWM (SDIO_LOCAL_OFFSET + 0x0019)
+/* RXDMA Request Length */
+#define REG_SDIO_RX0_REQ_LEN (SDIO_LOCAL_OFFSET + 0x001C)
+/* OQT Free Page */
+#define REG_SDIO_OQT_FREE_PG (SDIO_LOCAL_OFFSET + 0x001E)
+/* Free Tx Buffer Page */
+#define REG_SDIO_FREE_TXPG (SDIO_LOCAL_OFFSET + 0x0020)
+/* HCI Current Power Mode 1 */
+#define REG_SDIO_HCPWM1 (SDIO_LOCAL_OFFSET + 0x0024)
+/* HCI Current Power Mode 2 */
+#define REG_SDIO_HCPWM2 (SDIO_LOCAL_OFFSET + 0x0026)
+/* Free Tx Page Sequence */
+#define REG_SDIO_FREE_TXPG_SEQ (SDIO_LOCAL_OFFSET + 0x0028)
+/* HTSF Information */
+#define REG_SDIO_HTSFR_INFO (SDIO_LOCAL_OFFSET + 0x0030)
+#define REG_SDIO_HCPWM1_V2 (SDIO_LOCAL_OFFSET + 0x0038)
+/* H2C */
+#define REG_SDIO_H2C (SDIO_LOCAL_OFFSET + 0x0060)
+/* HCI Request Power Mode 1 */
+#define REG_SDIO_HRPWM1 (SDIO_LOCAL_OFFSET + 0x0080)
+/* HCI Request Power Mode 2 */
+#define REG_SDIO_HRPWM2 (SDIO_LOCAL_OFFSET + 0x0082)
+/* HCI Power Save Clock */
+#define REG_SDIO_HPS_CLKR (SDIO_LOCAL_OFFSET + 0x0084)
+/* SDIO HCI Suspend Control */
+#define REG_SDIO_HSUS_CTRL (SDIO_LOCAL_OFFSET + 0x0086)
+#define BIT_HCI_SUS_REQ BIT(0)
+#define BIT_HCI_RESUME_RDY BIT(1)
+/* SDIO Host Extension Interrupt Mask Always */
+#define REG_SDIO_HIMR_ON (SDIO_LOCAL_OFFSET + 0x0090)
+/* SDIO Host Extension Interrupt Status Always */
+#define REG_SDIO_HISR_ON (SDIO_LOCAL_OFFSET + 0x0091)
+
+#define REG_SDIO_INDIRECT_REG_CFG (SDIO_LOCAL_OFFSET + 0x0040)
+#define BIT_SDIO_INDIRECT_REG_CFG_WORD BIT(16)
+#define BIT_SDIO_INDIRECT_REG_CFG_DWORD BIT(17)
+#define BIT_SDIO_INDIRECT_REG_CFG_WRITE BIT(18)
+#define BIT_SDIO_INDIRECT_REG_CFG_READ BIT(19)
+#define BIT_SDIO_INDIRECT_REG_CFG_UNK20 BIT(20)
+#define REG_SDIO_INDIRECT_REG_DATA (SDIO_LOCAL_OFFSET + 0x0044)
+
+/* Sdio Address for SDIO Local Reg, TRX FIFO, MAC Reg */
+#define REG_SDIO_CMD_ADDR_MSK GENMASK(16, 13)
+#define REG_SDIO_CMD_ADDR_SDIO_REG 0
+#define REG_SDIO_CMD_ADDR_MAC_REG 8
+#define REG_SDIO_CMD_ADDR_TXFF_HIGH 4
+#define REG_SDIO_CMD_ADDR_TXFF_LOW 6
+#define REG_SDIO_CMD_ADDR_TXFF_NORMAL 5
+#define REG_SDIO_CMD_ADDR_TXFF_EXTRA 7
+#define REG_SDIO_CMD_ADDR_RXFF 7
+
+#define RTW_SDIO_BLOCK_SIZE 512
+#define RTW_SDIO_ADDR_RX_RX0FF_GEN(_id) (0x0e000 | ((_id) & 0x3))
+
+#define RTW_SDIO_DATA_PTR_ALIGN 8
+
+struct sdio_func;
+struct sdio_device_id;
+
+struct rtw_sdio_tx_data {
+ u8 sn;
+};
+
+struct rtw_sdio_work_data {
+ struct work_struct work;
+ struct rtw_dev *rtwdev;
+};
+
+struct rtw_sdio {
+ struct sdio_func *sdio_func;
+
+ u32 irq_mask;
+ u8 rx_addr;
+ bool sdio3_bus_mode;
+
+ void *irq_thread;
+
+ struct workqueue_struct *txwq;
+ struct rtw_sdio_work_data *tx_handler_data;
+ struct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM];
+};
+
+extern const struct dev_pm_ops rtw_sdio_pm_ops;
+
+int rtw_sdio_probe(struct sdio_func *sdio_func,
+ const struct sdio_device_id *id);
+void rtw_sdio_remove(struct sdio_func *sdio_func);
+void rtw_sdio_shutdown(struct device *dev);
+
+static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev)
+{
+ struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+
+ return rtwsdio->sdio3_bus_mode;
+}
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 68e1b782d199..44a5fafb9905 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -118,6 +118,22 @@ static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
rtw_usb_write(rtwdev, addr, val, 4);
}
+static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)
+{
+ switch (dma_mapping) {
+ case RTW_DMA_MAPPING_HIGH:
+ return 0;
+ case RTW_DMA_MAPPING_NORMAL:
+ return 1;
+ case RTW_DMA_MAPPING_LOW:
+ return 2;
+ case RTW_DMA_MAPPING_EXTRA:
+ return 3;
+ default:
+ return -EINVAL;
+ }
+}
+
static int rtw_usb_parse(struct rtw_dev *rtwdev,
struct usb_interface *interface)
{
@@ -129,6 +145,8 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev,
int num_out_pipes = 0;
int i;
u8 num;
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_rqpn *rqpn;
for (i = 0; i < interface_desc->bNumEndpoints; i++) {
endpoint = &host_interface->endpoint[i].desc;
@@ -183,31 +201,34 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev,
rtwdev->hci.bulkout_num = num_out_pipes;
- switch (num_out_pipes) {
- case 4:
- case 3:
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 2;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 2;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 2;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 2;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = 1;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = 1;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = 0;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 0;
- break;
- case 2:
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 1;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 1;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 1;
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 1;
- break;
- case 1:
- break;
- default:
- rtw_err(rtwdev, "failed to get out_pipes(%d)\n", num_out_pipes);
+ if (num_out_pipes < 1 || num_out_pipes > 4) {
+ rtw_err(rtwdev, "invalid number of endpoints %d\n", num_out_pipes);
return -EINVAL;
}
+ rqpn = &chip->rqpn_table[num_out_pipes];
+
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = dma_mapping_to_ep(rqpn->dma_map_be);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = dma_mapping_to_ep(rqpn->dma_map_bk);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = dma_mapping_to_ep(rqpn->dma_map_bk);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = dma_mapping_to_ep(rqpn->dma_map_be);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = dma_mapping_to_ep(rqpn->dma_map_vi);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = dma_mapping_to_ep(rqpn->dma_map_vi);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = dma_mapping_to_ep(rqpn->dma_map_vo);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = dma_mapping_to_ep(rqpn->dma_map_vo);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID8] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID9] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID10] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID11] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID12] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID13] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID14] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID15] = -EINVAL;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_BEACON] = dma_mapping_to_ep(rqpn->dma_map_hi);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_HIGH] = dma_mapping_to_ep(rqpn->dma_map_hi);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_MGMT] = dma_mapping_to_ep(rqpn->dma_map_mg);
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_H2C] = dma_mapping_to_ep(rqpn->dma_map_hi);
+
return 0;
}
@@ -250,7 +271,7 @@ static void rtw_usb_write_port_tx_complete(struct urb *urb)
static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel)
{
if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep))
- return 0;
+ return -EINVAL;
return rtwusb->qsel_to_ep[qsel];
}
@@ -265,6 +286,9 @@ static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *s
int ret;
int ep = qsel_to_ep(rtwusb, qsel);
+ if (ep < 0)
+ return ep;
+
pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]);
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
@@ -780,6 +804,7 @@ static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
usb_put_dev(rtwusb->udev);
+ kfree(rtwusb->usb_data);
usb_set_intfdata(intf, NULL);
}
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index 90596806bc93..4663db4ce2f6 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -141,6 +141,38 @@ void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
__rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
}
+void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
+ enum rtw89_sub_entity_idx idx,
+ const struct cfg80211_chan_def *chandef)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ enum rtw89_sub_entity_idx cur;
+
+ if (chandef) {
+ cur = atomic_cmpxchg(&hal->roc_entity_idx,
+ RTW89_SUB_ENTITY_IDLE, idx);
+ if (cur != RTW89_SUB_ENTITY_IDLE) {
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "ROC still processing on entity %d\n", idx);
+ return;
+ }
+
+ hal->roc_chandef = *chandef;
+ } else {
+ cur = atomic_cmpxchg(&hal->roc_entity_idx, idx,
+ RTW89_SUB_ENTITY_IDLE);
+ if (cur == idx)
+ return;
+
+ if (cur == RTW89_SUB_ENTITY_IDLE)
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "ROC already finished on entity %d\n", idx);
+ else
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "ROC is processing on entity %d\n", cur);
+ }
+}
+
static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
{
struct cfg80211_chan_def chandef = {0};
@@ -154,6 +186,7 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev)
struct rtw89_hal *hal = &rtwdev->hal;
bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+ atomic_set(&hal->roc_entity_idx, RTW89_SUB_ENTITY_IDLE);
rtw89_config_default_chandef(rtwdev);
}
@@ -229,6 +262,8 @@ void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
}
+ atomic_cmpxchg(&hal->roc_entity_idx, roll, RTW89_SUB_ENTITY_0);
+
drop = roll;
out:
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
index ecbd4503bead..bdf369db5041 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.h
+++ b/drivers/net/wireless/realtek/rtw89/chan.h
@@ -45,6 +45,9 @@ bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx,
const struct cfg80211_chan_def *chandef);
+void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
+ enum rtw89_sub_entity_idx idx,
+ const struct cfg80211_chan_def *chandef);
void rtw89_entity_init(struct rtw89_dev *rtwdev);
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 56a13be2e283..7fc0a26a4d73 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -156,6 +156,28 @@ static struct ieee80211_rate rtw89_bitrates[] = {
{ .bitrate = 540, .hw_value = 0x0b, },
};
+static const struct ieee80211_iface_limit rtw89_iface_limits[] = {
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_AP),
+ },
+};
+
+static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
+ {
+ .limits = rtw89_iface_limits,
+ .n_limits = ARRAY_SIZE(rtw89_iface_limits),
+ .max_interfaces = 2,
+ .num_different_channels = 1,
+ }
+};
+
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate)
{
struct ieee80211_rate rate;
@@ -360,6 +382,15 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev)
rtw89_set_entity_state(rtwdev, true);
}
+void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_chan *chan)
+{
+ const struct cfg80211_chan_def *chandef;
+
+ chandef = rtw89_chandef_get(rtwdev, rtwvif->sub_entity_idx);
+ rtw89_get_channel_params(chandef, chan);
+}
+
static enum rtw89_core_tx_type
rtw89_core_get_tx_type(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
@@ -707,7 +738,7 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev,
else
lowest_rate = RTW89_HW_RATE_OFDM6;
- if (!sta->deflink.supp_rates[chan->band_type])
+ if (!sta || !sta->deflink.supp_rates[chan->band_type])
return lowest_rate;
return __ffs(sta->deflink.supp_rates[chan->band_type]) + lowest_rate;
@@ -867,6 +898,37 @@ void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel)
rtw89_hci_tx_kick_off(rtwdev, ch_dma);
}
+int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
+ int qsel, unsigned int timeout)
+{
+ struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
+ struct rtw89_tx_wait_info *wait;
+ unsigned long time_left;
+ int ret = 0;
+
+ wait = kzalloc(sizeof(*wait), GFP_KERNEL);
+ if (!wait) {
+ rtw89_core_tx_kick_off(rtwdev, qsel);
+ return 0;
+ }
+
+ init_completion(&wait->completion);
+ rcu_assign_pointer(skb_data->wait, wait);
+
+ rtw89_core_tx_kick_off(rtwdev, qsel);
+ time_left = wait_for_completion_timeout(&wait->completion,
+ msecs_to_jiffies(timeout));
+ if (time_left == 0)
+ ret = -ETIMEDOUT;
+ else if (!wait->tx_done)
+ ret = -EAGAIN;
+
+ rcu_assign_pointer(skb_data->wait, NULL);
+ kfree_rcu(wait, rcu_head);
+
+ return ret;
+}
+
int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
struct sk_buff *skb, bool fwdl)
{
@@ -1457,6 +1519,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
struct rtw89_rx_desc_info *desc_info = iter_data->desc_info;
struct sk_buff *skb = iter_data->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu;
const u8 *bssid = iter_data->bssid;
if (rtwdev->scanning &&
@@ -1475,8 +1538,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
return;
- if (ieee80211_is_beacon(hdr->frame_control))
+ if (ieee80211_is_beacon(hdr->frame_control)) {
+ if (vif->type == NL80211_IFTYPE_STATION)
+ rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu);
pkt_stat->beacon_nr++;
+ }
if (!ether_addr_equal(vif->addr, hdr->addr1))
return;
@@ -1979,6 +2045,18 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev,
spin_unlock_bh(&rtwdev->ba_lock);
}
+static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct sk_buff *skb, *tmp;
+
+ skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {
+ skb_unlink(skb, &rtwsta->roc_queue);
+ dev_kfree_skb_any(skb);
+ }
+}
+
static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev,
struct rtw89_txq *rtwtxq)
{
@@ -2118,6 +2196,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv
{
struct ieee80211_hw *hw = rtwdev->hw;
struct ieee80211_txq *txq;
+ struct rtw89_vif *rtwvif;
struct rtw89_txq *rtwtxq;
unsigned long frame_cnt;
unsigned long byte_cnt;
@@ -2127,6 +2206,12 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv
ieee80211_txq_schedule_start(hw, ac);
while ((txq = ieee80211_next_txq(hw, ac))) {
rtwtxq = (struct rtw89_txq *)txq->drv_priv;
+ rtwvif = (struct rtw89_vif *)txq->vif->drv_priv;
+
+ if (rtwvif->offchan) {
+ ieee80211_return_txq(hw, txq, true);
+ continue;
+ }
tx_resource = rtw89_check_and_reclaim_tx_resource(rtwdev, txq->tid);
sched_txq = false;
@@ -2153,8 +2238,7 @@ static void rtw89_ips_work(struct work_struct *work)
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
ips_work);
mutex_lock(&rtwdev->mutex);
- if (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE)
- rtw89_enter_ips(rtwdev);
+ rtw89_enter_ips_by_hwflags(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
@@ -2195,6 +2279,187 @@ static void rtw89_forbid_ba_work(struct work_struct *w)
spin_unlock_bh(&rtwdev->ba_lock);
}
+static void rtw89_core_sta_pending_tx_iter(void *data,
+ struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_vif *rtwvif_target = data, *rtwvif = rtwsta->rtwvif;
+ struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct sk_buff *skb, *tmp;
+ int qsel, ret;
+
+ if (rtwvif->sub_entity_idx != rtwvif_target->sub_entity_idx)
+ return;
+
+ if (skb_queue_len(&rtwsta->roc_queue) == 0)
+ return;
+
+ skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) {
+ skb_unlink(skb, &rtwsta->roc_queue);
+
+ ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
+ if (ret) {
+ rtw89_warn(rtwdev, "pending tx failed with %d\n", ret);
+ dev_kfree_skb_any(skb);
+ } else {
+ rtw89_core_tx_kick_off(rtwdev, qsel);
+ }
+ }
+}
+
+static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif)
+{
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_core_sta_pending_tx_iter,
+ rtwvif);
+}
+
+static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool qos, bool ps)
+{
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+ struct ieee80211_sta *sta;
+ struct ieee80211_hdr *hdr;
+ struct sk_buff *skb;
+ int ret, qsel;
+
+ if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
+ return 0;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
+ if (!sta) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, qos);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (ps)
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+
+ ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
+ if (ret) {
+ rtw89_warn(rtwdev, "nullfunc transmit failed: %d\n", ret);
+ dev_kfree_skb_any(skb);
+ goto out;
+ }
+
+ rcu_read_unlock();
+
+ return rtw89_core_tx_kick_off_and_wait(rtwdev, skb, qsel,
+ RTW89_ROC_TX_TIMEOUT);
+out:
+ rcu_read_unlock();
+
+ return ret;
+}
+
+void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+{
+ struct ieee80211_hw *hw = rtwdev->hw;
+ struct rtw89_roc *roc = &rtwvif->roc;
+ struct cfg80211_chan_def roc_chan;
+ struct rtw89_vif *tmp;
+ int ret;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ ieee80211_queue_delayed_work(hw, &rtwvif->roc.roc_work,
+ msecs_to_jiffies(rtwvif->roc.duration));
+
+ rtw89_leave_ips_by_hwflags(rtwdev);
+ rtw89_leave_lps(rtwdev);
+
+ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "roc send null-1 failed: %d\n", ret);
+
+ rtw89_for_each_rtwvif(rtwdev, tmp)
+ if (tmp->sub_entity_idx == rtwvif->sub_entity_idx)
+ tmp->offchan = true;
+
+ cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT);
+ rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, &roc_chan);
+ rtw89_set_channel(rtwdev);
+ rtw89_write32_clr(rtwdev,
+ rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
+ B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH);
+
+ ieee80211_ready_on_channel(hw);
+}
+
+void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+{
+ struct ieee80211_hw *hw = rtwdev->hw;
+ struct rtw89_roc *roc = &rtwvif->roc;
+ struct rtw89_vif *tmp;
+ int ret;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ ieee80211_remain_on_channel_expired(hw);
+
+ rtw89_leave_ips_by_hwflags(rtwdev);
+ rtw89_leave_lps(rtwdev);
+
+ rtw89_write32_mask(rtwdev,
+ rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
+ B_AX_RX_FLTR_CFG_MASK,
+ rtwdev->hal.rx_fltr);
+
+ roc->state = RTW89_ROC_IDLE;
+ rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, NULL);
+ rtw89_set_channel(rtwdev);
+ ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX,
+ "roc send null-0 failed: %d\n", ret);
+
+ rtw89_for_each_rtwvif(rtwdev, tmp)
+ if (tmp->sub_entity_idx == rtwvif->sub_entity_idx)
+ tmp->offchan = false;
+
+ rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif);
+ queue_work(rtwdev->txq_wq, &rtwdev->txq_work);
+
+ if (hw->conf.flags & IEEE80211_CONF_IDLE)
+ ieee80211_queue_delayed_work(hw, &roc->roc_work,
+ RTW89_ROC_IDLE_TIMEOUT);
+}
+
+void rtw89_roc_work(struct work_struct *work)
+{
+ struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif,
+ roc.roc_work.work);
+ struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_roc *roc = &rtwvif->roc;
+
+ mutex_lock(&rtwdev->mutex);
+
+ switch (roc->state) {
+ case RTW89_ROC_IDLE:
+ rtw89_enter_ips_by_hwflags(rtwdev);
+ break;
+ case RTW89_ROC_MGMT:
+ case RTW89_ROC_NORMAL:
+ rtw89_roc_end(rtwdev, rtwvif);
+ break;
+ default:
+ break;
+ }
+
+ mutex_unlock(&rtwdev->mutex);
+}
+
static enum rtw89_tfc_lv rtw89_get_traffic_level(struct rtw89_dev *rtwdev,
u32 throughput, u64 cnt)
{
@@ -2251,8 +2516,10 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
bool tfc_changed;
tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats);
- rtw89_for_each_rtwvif(rtwdev, rtwvif)
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats);
+ rtw89_fw_h2c_tp_offload(rtwdev, rtwvif);
+ }
return tfc_changed;
}
@@ -2264,9 +2531,15 @@ static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwv
rtwvif->tdls_peer)
return;
+ if (rtwdev->total_sta_assoc > 1)
+ return;
+
+ if (rtwvif->offchan)
+ return;
+
if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE &&
rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE)
- rtw89_enter_lps(rtwdev, rtwvif);
+ rtw89_enter_lps(rtwdev, rtwvif, true);
}
static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev)
@@ -2493,6 +2766,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
rtwsta->rtwvif = rtwvif;
rtwsta->prev_rssi = 0;
INIT_LIST_HEAD(&rtwsta->ba_cam_list);
+ skb_queue_head_init(&rtwsta->roc_queue);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
rtw89_core_txq_init(rtwdev, sta->txq[i]);
@@ -2539,6 +2813,9 @@ int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ if (vif->type == NL80211_IFTYPE_STATION)
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false);
+
rtwdev->total_sta_assoc--;
if (sta->tdls)
rtwvif->tdls_peer--;
@@ -2559,6 +2836,8 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
rtw89_mac_bf_disassoc(rtwdev, vif, sta);
rtw89_core_free_sta_pending_ba(rtwdev, sta);
rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta);
+ rtw89_core_free_sta_pending_roc_tx(rtwdev, sta);
+
if (vif->type == NL80211_IFTYPE_AP || sta->tdls)
rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
if (sta->tdls)
@@ -3180,7 +3459,6 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
int rtw89_core_init(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
- int ret;
u8 band;
INIT_LIST_HEAD(&rtwdev->ba_list);
@@ -3214,6 +3492,8 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work);
INIT_WORK(&rtwdev->ips_work, rtw89_ips_work);
+ INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work);
+
skb_queue_head_init(&rtwdev->c2h_queue);
rtw89_core_ppdu_sts_init(rtwdev);
rtw89_traffic_stats_init(rtwdev, &rtwdev->stats);
@@ -3225,12 +3505,10 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
INIT_WORK(&btc->dhcp_notify_work, rtw89_btc_ntfy_dhcp_packet_work);
INIT_WORK(&btc->icmp_notify_work, rtw89_btc_ntfy_icmp_packet_work);
- ret = rtw89_load_firmware(rtwdev);
- if (ret) {
- rtw89_warn(rtwdev, "no firmware loaded\n");
- destroy_workqueue(rtwdev->txq_wq);
- return ret;
- }
+ init_completion(&rtwdev->fw.req.completion);
+
+ schedule_work(&rtwdev->load_firmware_work);
+
rtw89_ser_init(rtwdev);
rtw89_entity_init(rtwdev);
@@ -3257,8 +3535,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
rtwdev->scanning = true;
rtw89_leave_lps(rtwdev);
- if (hw_scan && (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE))
- rtw89_leave_ips(rtwdev);
+ if (hw_scan)
+ rtw89_leave_ips_by_hwflags(rtwdev);
ether_addr_copy(rtwvif->mac_addr, mac_addr);
rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type);
@@ -3293,6 +3571,8 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
+ int ret;
+ u8 val;
u8 cv;
cv = rtw89_read32_mask(rtwdev, R_AX_SYS_CFG1, B_AX_CHIP_VER_MASK);
@@ -3304,6 +3584,14 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
}
rtwdev->hal.cv = cv;
+
+ if (chip->chip_id == RTL8852B || chip->chip_id == RTL8851B) {
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val);
+ if (!ret)
+ return;
+
+ rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK);
+ }
}
static void rtw89_core_setup_phycap(struct rtw89_dev *rtwdev)
@@ -3315,6 +3603,28 @@ static void rtw89_core_setup_phycap(struct rtw89_dev *rtwdev)
rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv <= CHIP_CBV;
}
+static void rtw89_core_setup_rfe_parms(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ const struct rtw89_rfe_parms_conf *conf = chip->rfe_parms_conf;
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ u8 rfe_type = efuse->rfe_type;
+
+ if (!conf)
+ goto out;
+
+ while (conf->rfe_parms) {
+ if (rfe_type == conf->rfe_type) {
+ rtwdev->rfe_parms = conf->rfe_parms;
+ return;
+ }
+ conf++;
+ }
+
+out:
+ rtwdev->rfe_parms = chip->dflt_parms;
+}
+
static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
{
int ret;
@@ -3336,6 +3646,7 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
return ret;
rtw89_core_setup_phycap(rtwdev);
+ rtw89_core_setup_rfe_parms(rtwdev);
rtw89_mac_pwr_off(rtwdev);
@@ -3415,6 +3726,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
+ if (RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
+ ieee80211_hw_set(hw, CONNECTION_MONITOR);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -3440,6 +3753,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
hw->wiphy->tid_config_support.peer |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
hw->wiphy->tid_config_support.peer |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL);
+ hw->wiphy->max_remain_on_channel_duration = 1000;
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
@@ -3508,22 +3822,24 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
u32 bus_data_size,
const struct rtw89_chip_info *chip)
{
+ struct rtw89_fw_info early_fw = {};
const struct firmware *firmware;
struct ieee80211_hw *hw;
struct rtw89_dev *rtwdev;
struct ieee80211_ops *ops;
u32 driver_data_size;
- u32 early_feat_map = 0;
+ int fw_format = -1;
bool no_chanctx;
- firmware = rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
+ firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw, &fw_format);
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
if (!ops)
goto err;
no_chanctx = chip->support_chanctx_num == 0 ||
- !(early_feat_map & BIT(RTW89_FW_FEATURE_SCAN_OFFLOAD));
+ !RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &early_fw) ||
+ !RTW89_CHK_FW_FEATURE(BEACON_FILTER, &early_fw);
if (no_chanctx) {
ops->add_chanctx = NULL;
@@ -3531,6 +3847,8 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
ops->change_chanctx = NULL;
ops->assign_vif_chanctx = NULL;
ops->unassign_vif_chanctx = NULL;
+ ops->remain_on_channel = NULL;
+ ops->cancel_remain_on_channel = NULL;
}
driver_data_size = sizeof(struct rtw89_dev) + bus_data_size;
@@ -3538,12 +3856,16 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
if (!hw)
goto err;
+ hw->wiphy->iface_combinations = rtw89_iface_combs;
+ hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw89_iface_combs);
+
rtwdev = hw->priv;
rtwdev->hw = hw;
rtwdev->dev = device;
rtwdev->ops = ops;
rtwdev->chip = chip;
- rtwdev->fw.firmware = firmware;
+ rtwdev->fw.req.firmware = firmware;
+ rtwdev->fw.fw_format = fw_format;
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
no_chanctx ? "without" : "with");
@@ -3560,7 +3882,7 @@ EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
{
kfree(rtwdev->ops);
- release_firmware(rtwdev->fw.firmware);
+ release_firmware(rtwdev->fw.req.firmware);
ieee80211_free_hw(rtwdev->hw);
}
EXPORT_SYMBOL(rtw89_free_ieee80211_hw);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 40fb18b613d9..6df386a38fb4 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -108,6 +108,7 @@ enum rtw89_core_chip_id {
RTL8852A,
RTL8852B,
RTL8852C,
+ RTL8851B,
};
enum rtw89_cv {
@@ -569,6 +570,7 @@ enum rtw89_sub_entity_idx {
RTW89_SUB_ENTITY_0 = 0,
NUM_OF_RTW89_SUB_ENTITY,
+ RTW89_SUB_ENTITY_IDLE = NUM_OF_RTW89_SUB_ENTITY,
};
enum rtw89_rf_path {
@@ -957,6 +959,8 @@ struct rtw89_btc_ant_info {
u8 single_pos: 1;/* Single antenna at S0 or S1 */
u8 diversity: 1;
+ u8 btg_pos: 2;
+ u8 stream_cnt: 4;
};
enum rtw89_tfc_dir {
@@ -1413,8 +1417,9 @@ struct rtw89_btc_module {
u8 bt_solo: 1;
u8 bt_pos: 1;
u8 switch_type: 1;
+ u8 wa_type: 3;
- u8 rsvd;
+ u8 kt_ver_adie;
};
#define RTW89_BTC_DM_MAXSTEP 30
@@ -2597,6 +2602,7 @@ struct rtw89_sta {
struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
struct list_head ba_cam_list;
+ struct sk_buff_head roc_queue;
bool use_cfg_mask;
struct cfg80211_bitrate_mask mask;
@@ -2623,11 +2629,39 @@ struct rtw89_phy_rate_pattern {
bool enable;
};
+struct rtw89_tx_wait_info {
+ struct rcu_head rcu_head;
+ struct completion completion;
+ bool tx_done;
+};
+
+struct rtw89_tx_skb_data {
+ struct rtw89_tx_wait_info __rcu *wait;
+ u8 hci_priv[];
+};
+
+#define RTW89_ROC_IDLE_TIMEOUT 500
+#define RTW89_ROC_TX_TIMEOUT 30
+enum rtw89_roc_state {
+ RTW89_ROC_IDLE,
+ RTW89_ROC_NORMAL,
+ RTW89_ROC_MGMT,
+};
+
+struct rtw89_roc {
+ struct ieee80211_channel chan;
+ struct delayed_work roc_work;
+ enum ieee80211_roc_type type;
+ enum rtw89_roc_state state;
+ int duration;
+};
+
#define RTW89_P2P_MAX_NOA_NUM 2
struct rtw89_vif {
struct list_head list;
struct rtw89_dev *rtwdev;
+ struct rtw89_roc roc;
enum rtw89_sub_entity_idx sub_entity_idx;
u8 mac_id;
@@ -2643,6 +2677,7 @@ struct rtw89_vif {
u8 bcn_hit_cond;
u8 hit_rule;
u8 last_noa_nr;
+ bool offchan;
bool trigger;
bool lsig_txop;
u8 tgt_ind;
@@ -2959,6 +2994,41 @@ struct rtw89_txpwr_table {
const struct rtw89_txpwr_table *tbl);
};
+struct rtw89_txpwr_rule_2ghz {
+ const s8 (*lmt)[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
+ const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
+};
+
+struct rtw89_txpwr_rule_5ghz {
+ const s8 (*lmt)[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
+ const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
+};
+
+struct rtw89_txpwr_rule_6ghz {
+ const s8 (*lmt)[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+ const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+};
+
+struct rtw89_rfe_parms {
+ struct rtw89_txpwr_rule_2ghz rule_2ghz;
+ struct rtw89_txpwr_rule_5ghz rule_5ghz;
+ struct rtw89_txpwr_rule_6ghz rule_6ghz;
+};
+
+struct rtw89_rfe_parms_conf {
+ const struct rtw89_rfe_parms *rfe_parms;
+ u8 rfe_type;
+};
+
struct rtw89_page_regs {
u32 hci_fc_ctrl;
u32 ch_page_ctrl;
@@ -3049,7 +3119,8 @@ struct rtw89_phy_ul_tb_info {
struct rtw89_chip_info {
enum rtw89_core_chip_id chip_id;
const struct rtw89_chip_ops *ops;
- const char *fw_name;
+ const char *fw_basename;
+ u8 fw_format_max;
bool try_ce_fw;
u32 fifo_size;
u32 dle_scc_rsvd_size;
@@ -3095,21 +3166,10 @@ struct rtw89_chip_info {
const struct rtw89_phy_dig_gain_table *dig_table;
const struct rtw89_dig_regs *dig_regs;
const struct rtw89_phy_tssi_dbw_table *tssi_dbw_table;
- const s8 (*txpwr_lmt_2g)[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
- const s8 (*txpwr_lmt_5g)[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
- const s8 (*txpwr_lmt_6g)[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
- const s8 (*txpwr_lmt_ru_2g)[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
- const s8 (*txpwr_lmt_ru_5g)[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
- const s8 (*txpwr_lmt_ru_6g)[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+
+ /* NULL if no rfe-specific, or a null-terminated array by rfe_parms */
+ const struct rtw89_rfe_parms_conf *rfe_parms_conf;
+ const struct rtw89_rfe_parms *dflt_parms;
u8 txpwr_factor_rf;
u8 txpwr_factor_mac;
@@ -3146,6 +3206,7 @@ struct rtw89_chip_info {
struct rtw89_reg_def c2h_counter_reg;
const struct rtw89_page_regs *page_regs;
bool cfo_src_fd;
+ bool cfo_hw_comp;
const struct rtw89_reg_def *dcfo_comp;
u8 dcfo_comp_sft;
const struct rtw89_imr_info *imr_info;
@@ -3231,6 +3292,7 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_NO_PACKET_DROP,
RTW89_FW_FEATURE_NO_DEEP_PS,
RTW89_FW_FEATURE_NO_LPS_PG,
+ RTW89_FW_FEATURE_BEACON_FILTER,
};
struct rtw89_fw_suit {
@@ -3265,10 +3327,14 @@ struct rtw89_fw_suit {
GET_FW_HDR_SUBVERSION(fw_hdr), \
GET_FW_HDR_SUBINDEX(fw_hdr))
-struct rtw89_fw_info {
+struct rtw89_fw_req_info {
const struct firmware *firmware;
- struct rtw89_dev *rtwdev;
struct completion completion;
+};
+
+struct rtw89_fw_info {
+ struct rtw89_fw_req_info req;
+ int fw_format;
u8 h2c_seq;
u8 rec_seq;
u8 h2c_counter;
@@ -3350,6 +3416,7 @@ struct rtw89_sub_entity {
struct rtw89_hal {
u32 rx_fltr;
u8 cv;
+ u8 acv;
u32 sw_amsdu_max_size;
u32 antenna_tx;
u32 antenna_rx;
@@ -3358,9 +3425,11 @@ struct rtw89_hal {
bool tx_path_diversity;
bool support_cckpd;
bool support_igi;
+ atomic_t roc_entity_idx;
DECLARE_BITMAP(entity_map, NUM_OF_RTW89_SUB_ENTITY);
struct rtw89_sub_entity sub[NUM_OF_RTW89_SUB_ENTITY];
+ struct cfg80211_chan_def roc_chandef;
bool entity_active;
enum rtw89_entity_mode entity_mode;
@@ -3621,6 +3690,8 @@ struct rtw89_cfo_tracking_info {
s32 cfo_avg_pre;
s32 cfo_avg[CFO_TRACK_MAX_USER];
s32 pre_cfo_avg[CFO_TRACK_MAX_USER];
+ s32 dcfo_avg;
+ s32 dcfo_avg_pre;
u32 packet_count;
u32 packet_count_pre;
s32 residual_cfo_acc;
@@ -3865,10 +3936,7 @@ struct rtw89_early_h2c {
struct rtw89_hw_scan_info {
struct ieee80211_vif *scanning_vif;
struct list_head pkt_list[NUM_NL80211_BANDS];
- u8 op_pri_ch;
- u8 op_chan;
- u8 op_bw;
- u8 op_band;
+ struct rtw89_chan op_chan;
u32 last_chan_idx;
};
@@ -3953,6 +4021,7 @@ struct rtw89_dev {
struct rtw89_hw_scan_info scan_info;
const struct rtw89_chip_info *chip;
const struct rtw89_pci_info *pci_info;
+ const struct rtw89_rfe_parms *rfe_parms;
struct rtw89_hal hal;
struct rtw89_mcc_info mcc;
struct rtw89_mac_info mac;
@@ -3984,6 +4053,7 @@ struct rtw89_dev {
struct sk_buff_head c2h_queue;
struct work_struct c2h_work;
struct work_struct ips_work;
+ struct work_struct load_firmware_work;
struct list_head early_h2c_list;
@@ -4023,6 +4093,7 @@ struct rtw89_dev {
struct delayed_work coex_rfk_chk_work;
struct delayed_work cfo_track_work;
struct delayed_work forbid_ba_work;
+ struct delayed_work roc_work;
struct rtw89_ppdu_sts_info ppdu_sts;
u8 total_sta_assoc;
bool scanning;
@@ -4178,6 +4249,14 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde
rtwdev->hci.ops->clear(rtwdev, pdev);
}
+static inline
+struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ return (struct rtw89_tx_skb_data *)info->status.status_driver_data;
+}
+
static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr)
{
return rtwdev->hci.ops->read8(rtwdev, addr);
@@ -4530,6 +4609,10 @@ const struct cfg80211_chan_def *rtw89_chandef_get(struct rtw89_dev *rtwdev,
enum rtw89_sub_entity_idx idx)
{
struct rtw89_hal *hal = &rtwdev->hal;
+ enum rtw89_sub_entity_idx roc_idx = atomic_read(&hal->roc_entity_idx);
+
+ if (roc_idx == idx)
+ return &hal->roc_chandef;
return &hal->sub[idx].chandef;
}
@@ -4821,11 +4904,32 @@ static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev,
return dev_alloc_skb(length);
}
+static inline void rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev,
+ struct rtw89_tx_skb_data *skb_data,
+ bool tx_done)
+{
+ struct rtw89_tx_wait_info *wait;
+
+ rcu_read_lock();
+
+ wait = rcu_dereference(skb_data->wait);
+ if (!wait)
+ goto out;
+
+ wait->tx_done = tx_done;
+ complete(&wait->completion);
+
+out:
+ rcu_read_unlock();
+}
+
int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel);
int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
struct sk_buff *skb, bool fwdl);
void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel);
+int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
+ int qsel, unsigned int timeout);
void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc);
@@ -4874,6 +4978,8 @@ void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev);
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
void rtw89_set_channel(struct rtw89_dev *rtwdev);
+void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct rtw89_chan *chan);
u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
void rtw89_core_release_bit_map(unsigned long *addr, u8 bit);
void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits);
@@ -4895,6 +5001,9 @@ void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond,
int rtw89_core_start(struct rtw89_dev *rtwdev);
void rtw89_core_stop(struct rtw89_dev *rtwdev);
void rtw89_core_update_beacon_work(struct work_struct *work);
+void rtw89_roc_work(struct work_struct *work);
+void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
const u8 *mac_addr, bool hw_scan);
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 0e0e1483c099..1e5b7a998716 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -3069,18 +3069,13 @@ static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
{
struct rtw89_cpuio_ctrl ctrl_para = {0};
u16 pkt_id;
+ int ret;
rtw89_leave_ps_mode(rtwdev);
- pkt_id = rtw89_mac_dle_buf_req(rtwdev, 0x20, true);
- switch (pkt_id) {
- case 0xffff:
- return -ETIMEDOUT;
- case 0xfff:
- return -ENOMEM;
- default:
- break;
- }
+ ret = rtw89_mac_dle_buf_req(rtwdev, 0x20, true, &pkt_id);
+ if (ret)
+ return ret;
/* intentionally, enqueue two pkt, but has only one pkt id */
ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 5fa6863d36b3..b9b675bf9d05 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -155,8 +155,9 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
struct rtw89_fw_suit *fw_suit, bool nowarn)
{
struct rtw89_fw_info *fw_info = &rtwdev->fw;
- const u8 *mfw = fw_info->firmware->data;
- u32 mfw_len = fw_info->firmware->size;
+ const struct firmware *firmware = fw_info->req.firmware;
+ const u8 *mfw = firmware->data;
+ u32 mfw_len = firmware->size;
const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw;
const struct rtw89_mfw_info *mfw_info;
int i;
@@ -266,40 +267,51 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER),
+ __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER),
};
+static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
+ const struct rtw89_chip_info *chip,
+ u32 ver_code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
+ const struct __fw_feat_cfg *ent = &fw_feat_tbl[i];
+
+ if (chip->chip_id != ent->chip_id)
+ continue;
+
+ if (ent->cond(ver_code, ent->ver_code))
+ RTW89_SET_FW_FEATURE(ent->feature, fw);
+ }
+}
+
static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- const struct __fw_feat_cfg *ent;
const struct rtw89_fw_suit *fw_suit;
u32 suit_ver_code;
- int i;
fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
- for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
- ent = &fw_feat_tbl[i];
- if (chip->chip_id != ent->chip_id)
- continue;
-
- if (ent->cond(suit_ver_code, ent->ver_code))
- RTW89_SET_FW_FEATURE(ent->feature, &rtwdev->fw);
- }
+ rtw89_fw_iterate_feature_cfg(&rtwdev->fw, chip, suit_ver_code);
}
const struct firmware *
rtw89_early_fw_feature_recognize(struct device *device,
const struct rtw89_chip_info *chip,
- u32 *early_feat_map)
+ struct rtw89_fw_info *early_fw,
+ int *used_fw_format)
{
union rtw89_compat_fw_hdr buf = {};
const struct firmware *firmware;
bool full_req = false;
+ char fw_name[64];
+ int fw_format;
u32 ver_code;
int ret;
- int i;
/* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will
* be denied (-EPERM). Then, we don't get right firmware things as
@@ -308,12 +320,22 @@ rtw89_early_fw_feature_recognize(struct device *device,
if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE))
full_req = true;
- if (full_req)
- ret = request_firmware(&firmware, chip->fw_name, device);
- else
- ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
- device, &buf, sizeof(buf),
- 0);
+ for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) {
+ rtw89_fw_get_filename(fw_name, sizeof(fw_name),
+ chip->fw_basename, fw_format);
+
+ if (full_req)
+ ret = request_firmware(&firmware, fw_name, device);
+ else
+ ret = request_partial_firmware_into_buf(&firmware, fw_name,
+ device, &buf, sizeof(buf),
+ 0);
+ if (!ret) {
+ dev_info(device, "loaded firmware %s\n", fw_name);
+ *used_fw_format = fw_format;
+ break;
+ }
+ }
if (ret) {
dev_err(device, "failed to early request firmware: %d\n", ret);
@@ -328,15 +350,7 @@ rtw89_early_fw_feature_recognize(struct device *device,
if (!ver_code)
goto out;
- for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
- const struct __fw_feat_cfg *ent = &fw_feat_tbl[i];
-
- if (chip->chip_id != ent->chip_id)
- continue;
-
- if (ent->cond(ver_code, ent->ver_code))
- *early_feat_map |= BIT(ent->feature);
- }
+ rtw89_fw_iterate_feature_cfg(early_fw, chip, ver_code);
out:
if (full_req)
@@ -631,67 +645,62 @@ int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_info *fw = &rtwdev->fw;
- wait_for_completion(&fw->completion);
- if (!fw->firmware)
+ wait_for_completion(&fw->req.completion);
+ if (!fw->req.firmware)
return -EINVAL;
return 0;
}
-static void rtw89_load_firmware_cb(const struct firmware *firmware, void *context)
+static int rtw89_load_firmware_req(struct rtw89_dev *rtwdev,
+ struct rtw89_fw_req_info *req,
+ const char *fw_name, bool nowarn)
{
- struct rtw89_fw_info *fw = context;
- struct rtw89_dev *rtwdev = fw->rtwdev;
-
- if (!firmware || !firmware->data) {
- rtw89_err(rtwdev, "failed to request firmware\n");
- complete_all(&fw->completion);
- return;
- }
-
- fw->firmware = firmware;
- complete_all(&fw->completion);
-}
-
-int rtw89_load_firmware(struct rtw89_dev *rtwdev)
-{
- struct rtw89_fw_info *fw = &rtwdev->fw;
- const char *fw_name = rtwdev->chip->fw_name;
int ret;
- fw->rtwdev = rtwdev;
- init_completion(&fw->completion);
-
- if (fw->firmware) {
+ if (req->firmware) {
rtw89_debug(rtwdev, RTW89_DBG_FW,
"full firmware has been early requested\n");
- complete_all(&fw->completion);
+ complete_all(&req->completion);
return 0;
}
- ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev,
- GFP_KERNEL, fw, rtw89_load_firmware_cb);
- if (ret) {
- rtw89_err(rtwdev, "failed to async firmware request\n");
- return ret;
- }
+ if (nowarn)
+ ret = firmware_request_nowarn(&req->firmware, fw_name, rtwdev->dev);
+ else
+ ret = request_firmware(&req->firmware, fw_name, rtwdev->dev);
- return 0;
+ complete_all(&req->completion);
+
+ return ret;
+}
+
+void rtw89_load_firmware_work(struct work_struct *work)
+{
+ struct rtw89_dev *rtwdev =
+ container_of(work, struct rtw89_dev, load_firmware_work);
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ char fw_name[64];
+
+ rtw89_fw_get_filename(fw_name, sizeof(fw_name),
+ chip->fw_basename, rtwdev->fw.fw_format);
+
+ rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false);
}
void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_info *fw = &rtwdev->fw;
- rtw89_wait_firmware_completion(rtwdev);
+ cancel_work_sync(&rtwdev->load_firmware_work);
- if (fw->firmware) {
- release_firmware(fw->firmware);
+ if (fw->req.firmware) {
+ release_firmware(fw->req.firmware);
/* assign NULL back in case rtw89_free_ieee80211_hw()
* try to release the same one again.
*/
- fw->firmware = NULL;
+ fw->req.firmware = NULL;
}
}
@@ -1152,9 +1161,18 @@ fail:
static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_hal *hal = &rtwdev->hal;
- u8 ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_B;
- u8 map_b = hal->antenna_tx == RF_AB ? 1 : 0;
+ u8 ntx_path;
+ u8 map_b;
+
+ if (chip->rf_path_num == 1) {
+ ntx_path = RF_A;
+ map_b = 0;
+ } else {
+ ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_B;
+ map_b = hal->antenna_tx == RF_AB ? 1 : 0;
+ }
SET_CMC_TBL_NTX_PATH_EN(skb->data, ntx_path);
SET_CMC_TBL_PATH_MAP_A(skb->data, 0);
@@ -1737,6 +1755,147 @@ fail:
return ret;
}
+int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ bool connect)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+ struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL;
+ struct rtw89_h2c_bcnfltr *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
+ return -EINVAL;
+
+ if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA)
+ return -EINVAL;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n");
+ return -ENOMEM;
+ }
+
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_bcnfltr *)skb->data;
+
+ h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) |
+ le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) |
+ le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) |
+ le32_encode_bits(RTW89_BCN_FLTR_OFFLOAD_MODE_DEFAULT,
+ RTW89_H2C_BCNFLTR_W0_MODE) |
+ le32_encode_bits(RTW89_BCN_LOSS_CNT, RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT) |
+ le32_encode_bits(bss_conf->cqm_rssi_hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) |
+ le32_encode_bits(bss_conf->cqm_rssi_thold + MAX_RSSI,
+ RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) |
+ le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
+ H2C_FUNC_CFG_BCNFLTR, 0, 1, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
+int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu)
+{
+ struct rtw89_h2c_ofld_rssi *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ s8 rssi;
+ int ret;
+
+ if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
+ return -EINVAL;
+
+ if (!phy_ppdu)
+ return -EINVAL;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c rssi\n");
+ return -ENOMEM;
+ }
+
+ rssi = phy_ppdu->rssi_avg >> RSSI_FACTOR;
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_ofld_rssi *)skb->data;
+
+ h2c->w0 = le32_encode_bits(phy_ppdu->mac_id, RTW89_H2C_OFLD_RSSI_W0_MACID) |
+ le32_encode_bits(1, RTW89_H2C_OFLD_RSSI_W0_NUM);
+ h2c->w1 = le32_encode_bits(rssi, RTW89_H2C_OFLD_RSSI_W1_VAL);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
+ H2C_FUNC_OFLD_RSSI, 0, 1, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
+int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+{
+ struct rtw89_traffic_stats *stats = &rtwvif->stats;
+ struct rtw89_h2c_ofld *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ if (rtwvif->net_type != RTW89_NET_TYPE_INFRA)
+ return -EINVAL;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c tp\n");
+ return -ENOMEM;
+ }
+
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_ofld *)skb->data;
+
+ h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) |
+ le32_encode_bits(stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) |
+ le32_encode_bits(stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
+ H2C_FUNC_OFLD_TP, 0, 1, len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
#define H2C_RA_LEN 16
int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi)
{
@@ -1806,8 +1965,6 @@ fail:
return ret;
}
-#define H2C_LEN_CXDRVHDR 2
-#define H2C_LEN_CXDRVINFO_INIT (12 + H2C_LEN_CXDRVHDR)
int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
@@ -1815,44 +1972,52 @@ int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev)
struct rtw89_btc_init_info *init_info = &dm->init_info;
struct rtw89_btc_module *module = &init_info->module;
struct rtw89_btc_ant_info *ant = &module->ant;
+ struct rtw89_h2c_cxinit *h2c;
+ u32 len = sizeof(*h2c);
struct sk_buff *skb;
- u8 *cmd;
int ret;
- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_INIT);
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_init\n");
return -ENOMEM;
}
- skb_put(skb, H2C_LEN_CXDRVINFO_INIT);
- cmd = skb->data;
-
- RTW89_SET_FWCMD_CXHDR_TYPE(cmd, CXDRVINFO_INIT);
- RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_INIT - H2C_LEN_CXDRVHDR);
-
- RTW89_SET_FWCMD_CXINIT_ANT_TYPE(cmd, ant->type);
- RTW89_SET_FWCMD_CXINIT_ANT_NUM(cmd, ant->num);
- RTW89_SET_FWCMD_CXINIT_ANT_ISO(cmd, ant->isolation);
- RTW89_SET_FWCMD_CXINIT_ANT_POS(cmd, ant->single_pos);
- RTW89_SET_FWCMD_CXINIT_ANT_DIVERSITY(cmd, ant->diversity);
-
- RTW89_SET_FWCMD_CXINIT_MOD_RFE(cmd, module->rfe_type);
- RTW89_SET_FWCMD_CXINIT_MOD_CV(cmd, module->cv);
- RTW89_SET_FWCMD_CXINIT_MOD_BT_SOLO(cmd, module->bt_solo);
- RTW89_SET_FWCMD_CXINIT_MOD_BT_POS(cmd, module->bt_pos);
- RTW89_SET_FWCMD_CXINIT_MOD_SW_TYPE(cmd, module->switch_type);
-
- RTW89_SET_FWCMD_CXINIT_WL_GCH(cmd, init_info->wl_guard_ch);
- RTW89_SET_FWCMD_CXINIT_WL_ONLY(cmd, init_info->wl_only);
- RTW89_SET_FWCMD_CXINIT_WL_INITOK(cmd, init_info->wl_init_ok);
- RTW89_SET_FWCMD_CXINIT_DBCC_EN(cmd, init_info->dbcc_en);
- RTW89_SET_FWCMD_CXINIT_CX_OTHER(cmd, init_info->cx_other);
- RTW89_SET_FWCMD_CXINIT_BT_ONLY(cmd, init_info->bt_only);
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_cxinit *)skb->data;
+
+ h2c->hdr.type = CXDRVINFO_INIT;
+ h2c->hdr.len = len - H2C_LEN_CXDRVHDR;
+
+ h2c->ant_type = ant->type;
+ h2c->ant_num = ant->num;
+ h2c->ant_iso = ant->isolation;
+ h2c->ant_info =
+ u8_encode_bits(ant->single_pos, RTW89_H2C_CXINIT_ANT_INFO_POS) |
+ u8_encode_bits(ant->diversity, RTW89_H2C_CXINIT_ANT_INFO_DIVERSITY) |
+ u8_encode_bits(ant->btg_pos, RTW89_H2C_CXINIT_ANT_INFO_BTG_POS) |
+ u8_encode_bits(ant->stream_cnt, RTW89_H2C_CXINIT_ANT_INFO_STREAM_CNT);
+
+ h2c->mod_rfe = module->rfe_type;
+ h2c->mod_cv = module->cv;
+ h2c->mod_info =
+ u8_encode_bits(module->bt_solo, RTW89_H2C_CXINIT_MOD_INFO_BT_SOLO) |
+ u8_encode_bits(module->bt_pos, RTW89_H2C_CXINIT_MOD_INFO_BT_POS) |
+ u8_encode_bits(module->switch_type, RTW89_H2C_CXINIT_MOD_INFO_SW_TYPE) |
+ u8_encode_bits(module->wa_type, RTW89_H2C_CXINIT_MOD_INFO_WA_TYPE);
+ h2c->mod_adie_kt = module->kt_ver_adie;
+ h2c->wl_gch = init_info->wl_guard_ch;
+
+ h2c->info =
+ u8_encode_bits(init_info->wl_only, RTW89_H2C_CXINIT_INFO_WL_ONLY) |
+ u8_encode_bits(init_info->wl_init_ok, RTW89_H2C_CXINIT_INFO_WL_INITOK) |
+ u8_encode_bits(init_info->dbcc_en, RTW89_H2C_CXINIT_INFO_DBCC_EN) |
+ u8_encode_bits(init_info->cx_other, RTW89_H2C_CXINIT_INFO_CX_OTHER) |
+ u8_encode_bits(init_info->bt_only, RTW89_H2C_CXINIT_INFO_BT_ONLY);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, BTFC_SET,
SET_DRV_INFO, 0, 0,
- H2C_LEN_CXDRVINFO_INIT);
+ len);
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {
@@ -2422,46 +2587,51 @@ fail:
return ret;
}
-#define H2C_LEN_SCAN_OFFLOAD 28
int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
struct rtw89_vif *rtwvif)
{
- struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
+ struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
+ struct rtw89_h2c_scanofld *h2c;
+ u32 len = sizeof(*h2c);
struct sk_buff *skb;
- u8 *cmd;
int ret;
- skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_SCAN_OFFLOAD);
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c scan offload\n");
return -ENOMEM;
}
- skb_put(skb, H2C_LEN_SCAN_OFFLOAD);
- cmd = skb->data;
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_scanofld *)skb->data;
+
+ h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) |
+ le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) |
+ le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) |
+ le32_encode_bits(option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION);
+
+ h2c->w1 = le32_encode_bits(true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) |
+ le32_encode_bits(option->target_ch_mode,
+ RTW89_H2C_SCANOFLD_W1_TARGET_CH_MODE) |
+ le32_encode_bits(RTW89_SCAN_IMMEDIATE,
+ RTW89_H2C_SCANOFLD_W1_START_MODE) |
+ le32_encode_bits(RTW89_SCAN_ONCE, RTW89_H2C_SCANOFLD_W1_SCAN_TYPE);
- RTW89_SET_FWCMD_SCANOFLD_MACID(cmd, rtwvif->mac_id);
- RTW89_SET_FWCMD_SCANOFLD_PORT_ID(cmd, rtwvif->port);
- RTW89_SET_FWCMD_SCANOFLD_BAND(cmd, RTW89_PHY_0);
- RTW89_SET_FWCMD_SCANOFLD_OPERATION(cmd, option->enable);
- RTW89_SET_FWCMD_SCANOFLD_NOTIFY_END(cmd, true);
- RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_MODE(cmd, option->target_ch_mode);
- RTW89_SET_FWCMD_SCANOFLD_START_MODE(cmd, RTW89_SCAN_IMMEDIATE);
- RTW89_SET_FWCMD_SCANOFLD_SCAN_TYPE(cmd, RTW89_SCAN_ONCE);
if (option->target_ch_mode) {
- RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_BW(cmd, scan_info->op_bw);
- RTW89_SET_FWCMD_SCANOFLD_TARGET_PRI_CH(cmd,
- scan_info->op_pri_ch);
- RTW89_SET_FWCMD_SCANOFLD_TARGET_CENTRAL_CH(cmd,
- scan_info->op_chan);
- RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_BAND(cmd,
- scan_info->op_band);
+ h2c->w1 |= le32_encode_bits(op->band_width,
+ RTW89_H2C_SCANOFLD_W1_TARGET_CH_BW) |
+ le32_encode_bits(op->primary_channel,
+ RTW89_H2C_SCANOFLD_W1_TARGET_PRI_CH) |
+ le32_encode_bits(op->channel,
+ RTW89_H2C_SCANOFLD_W1_TARGET_CENTRAL_CH);
+ h2c->w0 |= le32_encode_bits(op->band_type,
+ RTW89_H2C_SCANOFLD_W0_TARGET_CH_BAND);
}
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
H2C_FUNC_SCANOFLD, 1, 1,
- H2C_LEN_SCAN_OFFLOAD);
+ len);
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {
@@ -3034,6 +3204,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct cfg80211_scan_request *req = rtwvif->scan_req;
+ struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
struct rtw89_pktofld_info *info;
u8 band, probe_count = 0;
int ret;
@@ -3077,10 +3248,10 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
switch (chan_type) {
case RTW89_CHAN_OPERATE:
- ch_info->central_ch = scan_info->op_chan;
- ch_info->pri_ch = scan_info->op_pri_ch;
- ch_info->ch_band = scan_info->op_band;
- ch_info->bw = scan_info->op_bw;
+ ch_info->central_ch = op->channel;
+ ch_info->pri_ch = op->primary_channel;
+ ch_info->ch_band = op->band_type;
+ ch_info->bw = op->band_width;
ch_info->tx_null = true;
ch_info->num_pkt = 0;
break;
@@ -3098,7 +3269,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
}
static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif *rtwvif, bool connected)
{
struct cfg80211_scan_request *req = rtwvif->scan_req;
struct rtw89_mac_chinfo *ch_info, *tmp;
@@ -3142,7 +3313,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
type = RTW89_CHAN_ACTIVE;
rtw89_hw_scan_add_chan(rtwdev, type, req->n_ssids, ch_info);
- if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK &&
+ if (connected &&
off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME) {
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp) {
@@ -3175,7 +3346,7 @@ out:
}
static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
- struct rtw89_vif *rtwvif)
+ struct rtw89_vif *rtwvif, bool connected)
{
int ret;
@@ -3184,7 +3355,7 @@ static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
rtw89_err(rtwdev, "Update probe request failed\n");
goto out;
}
- ret = rtw89_hw_scan_add_chan_list(rtwdev, rtwvif);
+ ret = rtw89_hw_scan_add_chan_list(rtwdev, rtwvif, connected);
out:
return ret;
}
@@ -3197,6 +3368,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
u32 rx_fltr = rtwdev->hal.rx_fltr;
u8 mac_addr[ETH_ALEN];
+ rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan);
rtwdev->scan_info.scanning_vif = vif;
rtwdev->scan_info.last_chan_idx = 0;
rtwvif->scan_ies = &scan_req->ies;
@@ -3222,6 +3394,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
bool aborted)
{
+ struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
struct cfg80211_scan_info info = {
.aborted = aborted,
};
@@ -3243,11 +3416,9 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
rtwvif = (struct rtw89_vif *)vif->drv_priv;
rtwvif->scan_req = NULL;
rtwvif->scan_ies = NULL;
- rtwdev->scan_info.last_chan_idx = 0;
- rtwdev->scan_info.scanning_vif = NULL;
+ scan_info->last_chan_idx = 0;
+ scan_info->scanning_vif = NULL;
- if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK)
- rtw89_store_op_chan(rtwdev, false);
rtw89_set_channel(rtwdev);
}
@@ -3262,16 +3433,19 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
{
struct rtw89_scan_option opt = {0};
struct rtw89_vif *rtwvif;
+ bool connected;
int ret = 0;
rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
if (!rtwvif)
return -EINVAL;
+ /* This variable implies connected or during attempt to connect */
+ connected = !is_zero_ether_addr(rtwvif->bssid);
opt.enable = enable;
- opt.target_ch_mode = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK;
+ opt.target_ch_mode = connected;
if (enable) {
- ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif);
+ ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected);
if (ret)
goto out;
}
@@ -3280,24 +3454,6 @@ out:
return ret;
}
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
-{
- struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
- const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
- struct rtw89_chan new;
-
- if (backup) {
- scan_info->op_pri_ch = cur->primary_channel;
- scan_info->op_chan = cur->channel;
- scan_info->op_bw = cur->band_width;
- scan_info->op_band = cur->band_type;
- } else {
- rtw89_chan_create(&new, scan_info->op_chan, scan_info->op_pri_ch,
- scan_info->op_band, scan_info->op_bw);
- rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
- }
-}
-
#define H2C_FW_CPU_EXCEPTION_LEN 4
#define H2C_FW_CPU_EXCEPTION_TYPE_DEF 0x5566
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index c3c67ddf61a2..675f85c41471 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -162,6 +162,27 @@ enum rtw89_p2pps_action {
RTW89_P2P_ACT_TERMINATE = 3,
};
+enum rtw89_bcn_fltr_offload_mode {
+ RTW89_BCN_FLTR_OFFLOAD_MODE_0 = 0,
+ RTW89_BCN_FLTR_OFFLOAD_MODE_1,
+ RTW89_BCN_FLTR_OFFLOAD_MODE_2,
+ RTW89_BCN_FLTR_OFFLOAD_MODE_3,
+
+ RTW89_BCN_FLTR_OFFLOAD_MODE_DEFAULT = RTW89_BCN_FLTR_OFFLOAD_MODE_0,
+};
+
+enum rtw89_bcn_fltr_type {
+ RTW89_BCN_FLTR_BEACON_LOSS,
+ RTW89_BCN_FLTR_RSSI,
+ RTW89_BCN_FLTR_NOTIFY,
+};
+
+enum rtw89_bcn_fltr_rssi_event {
+ RTW89_BCN_FLTR_RSSI_NOT_CHANGED,
+ RTW89_BCN_FLTR_RSSI_HIGH,
+ RTW89_BCN_FLTR_RSSI_LOW,
+};
+
#define FWDL_SECTION_MAX_NUM 10
#define FWDL_SECTION_CHKSUM_LEN 8
#define FWDL_SECTION_PER_PKT_LEN 2020
@@ -216,6 +237,8 @@ struct rtw89_h2creg_sch_tx_en {
#define RTW89_SCAN_LIST_LIMIT \
((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD)
+#define RTW89_BCN_LOSS_CNT 10
+
struct rtw89_mac_chinfo {
u8 period;
u8 dwell_time;
@@ -2174,85 +2197,44 @@ static inline void RTW89_SET_FWCMD_CXHDR_LEN(void *cmd, u8 val)
u8p_replace_bits((u8 *)(cmd) + 1, val, GENMASK(7, 0));
}
-static inline void RTW89_SET_FWCMD_CXINIT_ANT_TYPE(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 2, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_ANT_NUM(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 3, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_ANT_ISO(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 4, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_ANT_POS(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 5, val, BIT(0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_ANT_DIVERSITY(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 5, val, BIT(1));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_MOD_RFE(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 6, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_MOD_CV(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 7, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_MOD_BT_SOLO(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_MOD_BT_POS(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(1));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_MOD_SW_TYPE(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(2));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_WL_GCH(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 10, val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_CXINIT_WL_ONLY(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(0));
-}
+struct rtw89_h2c_cxhdr {
+ u8 type;
+ u8 len;
+} __packed;
-static inline void RTW89_SET_FWCMD_CXINIT_WL_INITOK(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(1));
-}
+#define H2C_LEN_CXDRVHDR sizeof(struct rtw89_h2c_cxhdr)
+
+struct rtw89_h2c_cxinit {
+ struct rtw89_h2c_cxhdr hdr;
+ u8 ant_type;
+ u8 ant_num;
+ u8 ant_iso;
+ u8 ant_info;
+ u8 mod_rfe;
+ u8 mod_cv;
+ u8 mod_info;
+ u8 mod_adie_kt;
+ u8 wl_gch;
+ u8 info;
+ u8 rsvd;
+ u8 rsvd1;
+} __packed;
-static inline void RTW89_SET_FWCMD_CXINIT_DBCC_EN(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(2));
-}
+#define RTW89_H2C_CXINIT_ANT_INFO_POS BIT(0)
+#define RTW89_H2C_CXINIT_ANT_INFO_DIVERSITY BIT(1)
+#define RTW89_H2C_CXINIT_ANT_INFO_BTG_POS GENMASK(3, 2)
+#define RTW89_H2C_CXINIT_ANT_INFO_STREAM_CNT GENMASK(7, 4)
-static inline void RTW89_SET_FWCMD_CXINIT_CX_OTHER(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(3));
-}
+#define RTW89_H2C_CXINIT_MOD_INFO_BT_SOLO BIT(0)
+#define RTW89_H2C_CXINIT_MOD_INFO_BT_POS BIT(1)
+#define RTW89_H2C_CXINIT_MOD_INFO_SW_TYPE BIT(2)
+#define RTW89_H2C_CXINIT_MOD_INFO_WA_TYPE GENMASK(5, 3)
-static inline void RTW89_SET_FWCMD_CXINIT_BT_ONLY(void *cmd, u8 val)
-{
- u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(4));
-}
+#define RTW89_H2C_CXINIT_INFO_WL_ONLY BIT(0)
+#define RTW89_H2C_CXINIT_INFO_WL_INITOK BIT(1)
+#define RTW89_H2C_CXINIT_INFO_DBCC_EN BIT(2)
+#define RTW89_H2C_CXINIT_INFO_CX_OTHER BIT(3)
+#define RTW89_H2C_CXINIT_INFO_BT_ONLY BIT(4)
static inline void RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(void *cmd, u8 val)
{
@@ -2749,96 +2731,32 @@ static inline void RTW89_SET_FWCMD_CHINFO_POWER_IDX(void *cmd, u32 val)
le32p_replace_bits((__le32 *)((u8 *)(cmd) + 16), val, GENMASK(15, 0));
}
-static inline void RTW89_SET_FWCMD_SCANOFLD_MACID(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, GENMASK(7, 0));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_NORM_CY(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, GENMASK(15, 8));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_PORT_ID(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, GENMASK(18, 16));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_BAND(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, BIT(19));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_OPERATION(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, GENMASK(21, 20));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_BAND(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd)), val, GENMASK(23, 22));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_NOTIFY_END(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, BIT(0));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_MODE(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, BIT(1));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_START_MODE(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, BIT(2));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_SCAN_TYPE(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, GENMASK(4, 3));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TARGET_CH_BW(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, GENMASK(7, 5));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TARGET_PRI_CH(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, GENMASK(15, 8));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TARGET_CENTRAL_CH(void *cmd,
- u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, GENMASK(23, 16));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_PROBE_REQ_PKT_ID(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 4), val, GENMASK(31, 24));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_NORM_PD(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 8), val, GENMASK(15, 0));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_SLOW_PD(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 8), val, GENMASK(23, 16));
-}
-
-static inline void RTW89_SET_FWCMD_SCANOFLD_TSF_HIGH(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 12), val, GENMASK(31, 0));
-}
+struct rtw89_h2c_scanofld {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 tsf_high;
+ __le32 tsf_low;
+ __le32 w5;
+ __le32 w6;
+} __packed;
-static inline void RTW89_SET_FWCMD_SCANOFLD_TSF_SLOW(void *cmd, u32 val)
-{
- le32p_replace_bits((__le32 *)((u8 *)(cmd) + 16), val, GENMASK(31, 0));
-}
+#define RTW89_H2C_SCANOFLD_W0_MACID GENMASK(7, 0)
+#define RTW89_H2C_SCANOFLD_W0_NORM_CY GENMASK(15, 8)
+#define RTW89_H2C_SCANOFLD_W0_PORT_ID GENMASK(18, 16)
+#define RTW89_H2C_SCANOFLD_W0_BAND BIT(19)
+#define RTW89_H2C_SCANOFLD_W0_OPERATION GENMASK(21, 20)
+#define RTW89_H2C_SCANOFLD_W0_TARGET_CH_BAND GENMASK(23, 22)
+#define RTW89_H2C_SCANOFLD_W1_NOTIFY_END BIT(0)
+#define RTW89_H2C_SCANOFLD_W1_TARGET_CH_MODE BIT(1)
+#define RTW89_H2C_SCANOFLD_W1_START_MODE BIT(2)
+#define RTW89_H2C_SCANOFLD_W1_SCAN_TYPE GENMASK(4, 3)
+#define RTW89_H2C_SCANOFLD_W1_TARGET_CH_BW GENMASK(7, 5)
+#define RTW89_H2C_SCANOFLD_W1_TARGET_PRI_CH GENMASK(15, 8)
+#define RTW89_H2C_SCANOFLD_W1_TARGET_CENTRAL_CH GENMASK(23, 16)
+#define RTW89_H2C_SCANOFLD_W1_PROBE_REQ_PKT_ID GENMASK(31, 24)
+#define RTW89_H2C_SCANOFLD_W2_NORM_PD GENMASK(15, 0)
+#define RTW89_H2C_SCANOFLD_W2_SLOW_PD GENMASK(23, 16)
static inline void RTW89_SET_FWCMD_P2P_MACID(void *cmd, u32 val)
{
@@ -3317,6 +3235,17 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb)
#define RTW89_GET_MAC_C2H_REV_ACK_H2C_SEQ(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16))
+struct rtw89_c2h_mac_bcnfltr_rpt {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID GENMASK(7, 0)
+#define RTW89_C2H_MAC_BCNFLTR_RPT_W2_TYPE GENMASK(9, 8)
+#define RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT GENMASK(11, 10)
+#define RTW89_C2H_MAC_BCNFLTR_RPT_W2_MA GENMASK(23, 16)
+
#define RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 0))
#define RTW89_GET_PHY_C2H_RA_RPT_RETRY_RATIO(c2h) \
@@ -3410,6 +3339,36 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE)
#define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0))
+struct rtw89_h2c_bcnfltr {
+ __le32 w0;
+} __packed;
+
+#define RTW89_H2C_BCNFLTR_W0_MON_RSSI BIT(0)
+#define RTW89_H2C_BCNFLTR_W0_MON_BCN BIT(1)
+#define RTW89_H2C_BCNFLTR_W0_MON_EN BIT(2)
+#define RTW89_H2C_BCNFLTR_W0_MODE GENMASK(4, 3)
+#define RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT GENMASK(11, 8)
+#define RTW89_H2C_BCNFLTR_W0_RSSI_HYST GENMASK(15, 12)
+#define RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD GENMASK(23, 16)
+#define RTW89_H2C_BCNFLTR_W0_MAC_ID GENMASK(31, 24)
+
+struct rtw89_h2c_ofld_rssi {
+ __le32 w0;
+ __le32 w1;
+} __packed;
+
+#define RTW89_H2C_OFLD_RSSI_W0_MACID GENMASK(7, 0)
+#define RTW89_H2C_OFLD_RSSI_W0_NUM GENMASK(15, 8)
+#define RTW89_H2C_OFLD_RSSI_W1_VAL GENMASK(7, 0)
+
+struct rtw89_h2c_ofld {
+ __le32 w0;
+} __packed;
+
+#define RTW89_H2C_OFLD_W0_MAC_ID GENMASK(7, 0)
+#define RTW89_H2C_OFLD_W0_TX_TP GENMASK(17, 8)
+#define RTW89_H2C_OFLD_W0_RX_TP GENMASK(27, 18)
+
#define RTW89_FW_HDR_SIZE 32
#define RTW89_FW_SECTION_HDR_SIZE 16
@@ -3459,6 +3418,15 @@ static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf)
return RTW89_FW_HDR_VER_CODE(&compat->fw_hdr);
}
+static inline void rtw89_fw_get_filename(char *buf, size_t size,
+ const char *fw_basename, int fw_format)
+{
+ if (fw_format <= 0)
+ snprintf(buf, size, "%s.bin", fw_basename);
+ else
+ snprintf(buf, size, "%s-%d.bin", fw_basename, fw_format);
+}
+
#define RTW89_H2C_RF_PAGE_SIZE 500
#define RTW89_H2C_RF_PAGE_NUM 3
struct rtw89_fw_h2c_rf_reg_info {
@@ -3537,6 +3505,9 @@ struct rtw89_fw_h2c_rf_reg_info {
#define H2C_FUNC_ADD_SCANOFLD_CH 0x16
#define H2C_FUNC_SCANOFLD 0x17
#define H2C_FUNC_PKT_DROP 0x1b
+#define H2C_FUNC_CFG_BCNFLTR 0x1e
+#define H2C_FUNC_OFLD_RSSI 0x1f
+#define H2C_FUNC_OFLD_TP 0x20
/* CLASS 10 - Security CAM */
#define H2C_CL_MAC_SEC_CAM 0xa
@@ -3600,9 +3571,10 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
const struct firmware *
rtw89_early_fw_feature_recognize(struct device *device,
const struct rtw89_chip_info *chip,
- u32 *early_feat_map);
+ struct rtw89_fw_info *early_fw,
+ int *used_fw_format);
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
-int rtw89_load_firmware(struct rtw89_dev *rtwdev);
+void rtw89_load_firmware_work(struct work_struct *work);
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev);
void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
@@ -3637,6 +3609,12 @@ int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
u8 ac, u32 val);
int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev);
+int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif,
+ bool connect);
+int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu);
+int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi);
int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev);
@@ -3681,7 +3659,6 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
struct rtw89_mac_c2h_info *c2h_info);
int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable);
void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev);
-void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup);
void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index d0e138f8b880..b8019cfc11b2 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1473,6 +1473,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,},
/* 8852A PCIE WOW */
.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
+ /* 8852B PCIE WOW */
+ .ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
};
EXPORT_SYMBOL(rtw89_mac_size);
@@ -1584,12 +1586,15 @@ static void dle_func_en(struct rtw89_dev *rtwdev, bool enable)
static void dle_clk_en(struct rtw89_dev *rtwdev, bool enable)
{
- if (enable)
- rtw89_write32_set(rtwdev, R_AX_DMAC_CLK_EN,
- B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN);
- else
- rtw89_write32_clr(rtwdev, R_AX_DMAC_CLK_EN,
- B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN);
+ u32 val = B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN;
+
+ if (enable) {
+ if (rtwdev->chip->chip_id == RTL8851B)
+ val |= B_AX_AXIDMA_CLK_EN;
+ rtw89_write32_set(rtwdev, R_AX_DMAC_CLK_EN, val);
+ } else {
+ rtw89_write32_clr(rtwdev, R_AX_DMAC_CLK_EN, val);
+ }
}
static int dle_mix_cfg(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg)
@@ -1854,7 +1859,8 @@ static int preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || !is_qta_poh(rtwdev))
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
+ chip->chip_id == RTL8851B || !is_qta_poh(rtwdev))
return 0;
return preload_init_set(rtwdev, mac_idx, mode);
@@ -1890,7 +1896,8 @@ static void _patch_ss2f_path(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B)
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
+ chip->chip_id == RTL8851B)
return;
rtw89_write32_mask(rtwdev, R_AX_SS2FINFO_PATH, B_AX_SS_DEST_QUEUE_MASK,
@@ -1959,7 +1966,8 @@ static int sec_eng_init(struct rtw89_dev *rtwdev)
/* init TX encryption */
val |= (B_AX_SEC_TX_ENC | B_AX_SEC_RX_DEC);
val |= (B_AX_MC_DEC | B_AX_BC_DEC);
- if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B)
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
+ chip->chip_id == RTL8851B)
val &= ~B_AX_TX_PARTIAL_MODE;
rtw89_write32(rtwdev, R_AX_SEC_ENG_CTRL, val);
@@ -2065,7 +2073,7 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
SIFS_MACTXEN_T1);
- if (rtwdev->chip->chip_id == RTL8852B) {
+ if (rtwdev->chip->chip_id == RTL8852B || rtwdev->chip->chip_id == RTL8851B) {
reg = rtw89_mac_reg_by_idx(R_AX_SCH_EXT_CTRL, mac_idx);
rtw89_write32_set(rtwdev, reg, B_AX_PORT_RST_TSF_ADV);
}
@@ -2805,7 +2813,7 @@ int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
}
EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v1);
-u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd)
+int rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd, u16 *pkt_id)
{
u32 val, reg;
int ret;
@@ -2820,9 +2828,13 @@ u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd)
ret = read_poll_timeout(rtw89_read32, val, val & B_AX_WD_BUF_STAT_DONE,
1, 2000, false, rtwdev, reg);
if (ret)
- return 0xffff;
+ return ret;
+
+ *pkt_id = FIELD_GET(B_AX_WD_BUF_STAT_PKTID_MASK, val);
+ if (*pkt_id == S_WD_BUF_STAT_PKTID_INVALID)
+ return -ENOENT;
- return FIELD_GET(B_AX_WD_BUF_STAT_PKTID_MASK, val);
+ return 0;
}
int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
@@ -2899,10 +2911,10 @@ static int dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode)
dle_quota_cfg(rtwdev, cfg, INVALID_QT_WCPU);
- pkt_id = rtw89_mac_dle_buf_req(rtwdev, 0x20, true);
- if (pkt_id == 0xffff) {
+ ret = rtw89_mac_dle_buf_req(rtwdev, 0x20, true, &pkt_id);
+ if (ret) {
rtw89_err(rtwdev, "[ERR]WDE DLE buf req\n");
- return -ENOMEM;
+ return ret;
}
ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
@@ -2917,10 +2929,10 @@ static int dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode)
return -EFAULT;
}
- pkt_id = rtw89_mac_dle_buf_req(rtwdev, 0x20, false);
- if (pkt_id == 0xffff) {
+ ret = rtw89_mac_dle_buf_req(rtwdev, 0x20, false, &pkt_id);
+ if (ret) {
rtw89_err(rtwdev, "[ERR]PLE DLE buf req\n");
- return -ENOMEM;
+ return ret;
}
ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
@@ -3364,8 +3376,15 @@ static int rtw89_mac_trx_init(struct rtw89_dev *rtwdev)
static void rtw89_disable_fw_watchdog(struct rtw89_dev *rtwdev)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
u32 val32;
+ if (chip_id == RTL8852B || chip_id == RTL8851B) {
+ rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_APB_WRAP_EN);
+ rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_APB_WRAP_EN);
+ return;
+ }
+
rtw89_mac_mem_write(rtwdev, R_AX_WDT_CTRL,
WDT_CTRL_ALL_DIS, RTW89_MAC_MEM_CPU_LOCAL);
@@ -3450,7 +3469,10 @@ static int rtw89_mac_dmac_pre_init(struct rtw89_dev *rtwdev)
B_AX_PKT_BUF_EN;
rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val);
- val = B_AX_DISPATCHER_CLK_EN;
+ if (chip_id == RTL8851B)
+ val = B_AX_DISPATCHER_CLK_EN | B_AX_AXIDMA_CLK_EN;
+ else
+ val = B_AX_DISPATCHER_CLK_EN;
rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val);
if (chip_id != RTL8852C)
@@ -4176,9 +4198,9 @@ rtw89_mac_c2h_macid_pause(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len
static bool rtw89_is_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel)
{
- struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
+ const struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
- return band == scan_info->op_band && channel == scan_info->op_pri_ch;
+ return band == op->band_type && channel == op->primary_channel;
}
static void
@@ -4193,6 +4215,9 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
u16 chan;
int ret;
+ if (!rtwvif)
+ return;
+
tx_fail = RTW89_GET_MAC_C2H_SCANOFLD_TX_FAIL(c2h->data);
status = RTW89_GET_MAC_C2H_SCANOFLD_STATUS(c2h->data);
chan = RTW89_GET_MAC_C2H_SCANOFLD_PRI_CH(c2h->data);
@@ -4225,11 +4250,15 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
}
break;
case RTW89_SCAN_ENTER_CH_NOTIFY:
- rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20);
- rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
if (rtw89_is_op_chan(rtwdev, band, chan)) {
- rtw89_store_op_chan(rtwdev, false);
+ rtw89_assign_entity_chan(rtwdev, rtwvif->sub_entity_idx,
+ &rtwdev->scan_info.op_chan);
ieee80211_wake_queues(rtwdev->hw);
+ } else {
+ rtw89_chan_create(&new, chan, chan, band,
+ RTW89_CHANNEL_WIDTH_20);
+ rtw89_assign_entity_chan(rtwdev, rtwvif->sub_entity_idx,
+ &new);
}
break;
default:
@@ -4238,6 +4267,64 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
}
static void
+rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ struct sk_buff *skb)
+{
+ struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif);
+ enum nl80211_cqm_rssi_threshold_event nl_event;
+ const struct rtw89_c2h_mac_bcnfltr_rpt *c2h =
+ (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data;
+ u8 type, event, mac_id;
+ s8 sig;
+
+ type = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_TYPE);
+ sig = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MA) - MAX_RSSI;
+ event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT);
+ mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID);
+
+ if (mac_id != rtwvif->mac_id)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "C2H bcnfltr rpt macid: %d, type: %d, ma: %d, event: %d\n",
+ mac_id, type, sig, event);
+
+ switch (type) {
+ case RTW89_BCN_FLTR_BEACON_LOSS:
+ if (!rtwdev->scanning && !rtwvif->offchan)
+ ieee80211_connection_loss(vif);
+ else
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+ return;
+ case RTW89_BCN_FLTR_NOTIFY:
+ nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+ break;
+ case RTW89_BCN_FLTR_RSSI:
+ if (event == RTW89_BCN_FLTR_RSSI_LOW)
+ nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+ else if (event == RTW89_BCN_FLTR_RSSI_HIGH)
+ nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+ else
+ return;
+ break;
+ default:
+ return;
+ }
+
+ ieee80211_cqm_rssi_notify(vif, nl_event, sig, GFP_KERNEL);
+}
+
+static void
+rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
+ u32 len)
+{
+ struct rtw89_vif *rtwvif;
+
+ rtw89_for_each_rtwvif(rtwdev, rtwvif)
+ rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h);
+}
+
+static void
rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
rtw89_debug(rtwdev, RTW89_DBG_FW,
@@ -4457,6 +4544,7 @@ void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
[RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause,
[RTW89_MAC_C2H_FUNC_SCANOFLD_RSP] = rtw89_mac_c2h_scanofld_rsp,
[RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT] = rtw89_mac_c2h_tsf32_toggle_rpt,
+ [RTW89_MAC_C2H_FUNC_BCNFLTR_RPT] = rtw89_mac_c2h_bcn_fltr_rpt,
};
static
@@ -4629,11 +4717,13 @@ int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex
int ret;
rtw89_write8_set(rtwdev, R_AX_GPIO_MUXCFG, B_AX_ENBT);
- rtw89_write8_set(rtwdev, R_AX_BTC_FUNC_EN, B_AX_PTA_WL_TX_EN);
+ if (rtwdev->chip->chip_id != RTL8851B)
+ rtw89_write8_set(rtwdev, R_AX_BTC_FUNC_EN, B_AX_PTA_WL_TX_EN);
rtw89_write8_set(rtwdev, R_AX_BT_COEX_CFG_2 + 1, B_AX_GNT_BT_POLARITY >> 8);
rtw89_write8_set(rtwdev, R_AX_CSR_MODE, B_AX_STATIS_BT_EN | B_AX_WL_ACT_MSK);
rtw89_write8_set(rtwdev, R_AX_CSR_MODE + 2, B_AX_BT_CNT_RST >> 16);
- rtw89_write8_clr(rtwdev, R_AX_TRXPTCL_RESP_0 + 3, B_AX_RSP_CHK_BTCCA >> 24);
+ if (rtwdev->chip->chip_id != RTL8851B)
+ rtw89_write8_clr(rtwdev, R_AX_TRXPTCL_RESP_0 + 3, B_AX_RSP_CHK_BTCCA >> 24);
val16 = rtw89_read16(rtwdev, R_AX_CCA_CFG_0);
val16 = (val16 | B_AX_BTCCA_EN) & ~B_AX_BTCCA_BRK_TXOP_EN;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 8064d3953d7f..a8d9847ef0b4 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -359,6 +359,7 @@ enum rtw89_mac_c2h_ofld_func {
RTW89_MAC_C2H_FUNC_MACID_PAUSE,
RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT = 0x6,
RTW89_MAC_C2H_FUNC_SCANOFLD_RSP = 0x9,
+ RTW89_MAC_C2H_FUNC_BCNFLTR_RPT = 0xd,
RTW89_MAC_C2H_FUNC_OFLD_MAX,
};
@@ -815,6 +816,7 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt47;
const struct rtw89_ple_quota ple_qt58;
const struct rtw89_ple_quota ple_qt_52a_wow;
+ const struct rtw89_ple_quota ple_qt_52b_wow;
};
extern const struct rtw89_mac_size_set rtw89_mac_size;
@@ -1116,6 +1118,7 @@ enum rtw89_mac_xtal_si_offset {
XTAL_SI_XTAL_XMD_4 = 0x26,
#define XTAL_SI_LPS_CAP GENMASK(3, 0)
XTAL_SI_CV = 0x41,
+#define XTAL_SI_ACV_MASK GENMASK(3, 0)
XTAL_SI_LOW_ADDR = 0x62,
#define XTAL_SI_LOW_ADDR_MASK GENMASK(7, 0)
XTAL_SI_CTRL = 0x63,
@@ -1146,7 +1149,7 @@ enum rtw89_mac_xtal_si_offset {
int rtw89_mac_write_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask);
int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val);
void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
-u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd);
+int rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd, u16 *pkt_id);
int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 367a7bf319da..ee4588b61b8f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -23,9 +23,19 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct rtw89_dev *rtwdev = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
+ struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct ieee80211_sta *sta = control->sta;
+ u32 flags = IEEE80211_SKB_CB(skb)->flags;
int ret, qsel;
+ if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n");
+ skb_queue_tail(&rtwsta->roc_queue, skb);
+ return;
+ }
+
ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
if (ret) {
rtw89_err(rtwdev, "failed to transmit skb: %d\n", ret);
@@ -95,7 +105,8 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
- (hw->conf.flags & IEEE80211_CONF_IDLE))
+ (hw->conf.flags & IEEE80211_CONF_IDLE) &&
+ !rtwdev->scanning)
rtw89_enter_ips(rtwdev);
mutex_unlock(&rtwdev->mutex);
@@ -114,9 +125,19 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
vif->addr, vif->type, vif->p2p);
mutex_lock(&rtwdev->mutex);
+
+ rtw89_leave_ips_by_hwflags(rtwdev);
+
+ if (RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
+ vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
+ IEEE80211_VIF_SUPPORTS_CQM_RSSI;
+
rtwvif->rtwdev = rtwdev;
+ rtwvif->roc.state = RTW89_ROC_IDLE;
+ rtwvif->offchan = false;
list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
+ INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work);
rtw89_leave_ps_mode(rtwdev);
rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
@@ -163,6 +184,7 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
vif->addr, vif->type, vif->p2p);
cancel_work_sync(&rtwvif->update_beacon_work);
+ cancel_delayed_work_sync(&rtwvif->roc.roc_work);
mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
@@ -170,6 +192,8 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
rtw89_mac_remove_vif(rtwdev, rtwvif);
rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
list_del_init(&rtwvif->list);
+ rtw89_enter_ips_by_hwflags(rtwdev);
+
mutex_unlock(&rtwdev->mutex);
}
@@ -394,7 +418,6 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
rtw89_mac_port_update(rtwdev, rtwvif);
rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif);
- rtw89_store_op_chan(rtwdev, true);
} else {
/* Abort ongoing scan if cancel_scan isn't issued
* when disconnected by peer
@@ -425,6 +448,9 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_P2P_PS)
rtw89_process_p2p_ps(rtwdev, vif);
+ if (changed & BSS_CHANGED_CQM)
+ rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
+
mutex_unlock(&rtwdev->mutex);
}
@@ -795,12 +821,13 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req)
{
struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
int ret = 0;
if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
return 1;
- if (rtwdev->scanning)
+ if (rtwdev->scanning || rtwvif->offchan)
return -EBUSY;
mutex_lock(&rtwdev->mutex);
@@ -903,6 +930,63 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&rtwdev->mutex);
}
+static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration,
+ enum ieee80211_roc_type type)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+ struct rtw89_roc *roc = &rtwvif->roc;
+
+ if (!vif)
+ return -EINVAL;
+
+ mutex_lock(&rtwdev->mutex);
+
+ if (roc->state != RTW89_ROC_IDLE) {
+ mutex_unlock(&rtwdev->mutex);
+ return -EBUSY;
+ }
+
+ if (rtwdev->scanning)
+ rtw89_hw_scan_abort(rtwdev, vif);
+
+ if (type == IEEE80211_ROC_TYPE_MGMT_TX)
+ roc->state = RTW89_ROC_MGMT;
+ else
+ roc->state = RTW89_ROC_NORMAL;
+
+ roc->duration = duration;
+ roc->chan = *chan;
+ roc->type = type;
+
+ rtw89_roc_start(rtwdev, rtwvif);
+
+ mutex_unlock(&rtwdev->mutex);
+
+ return 0;
+}
+
+static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+
+ if (!rtwvif)
+ return -EINVAL;
+
+ cancel_delayed_work_sync(&rtwvif->roc.roc_work);
+
+ mutex_lock(&rtwdev->mutex);
+ rtw89_roc_end(rtwdev, rtwvif);
+ mutex_unlock(&rtwdev->mutex);
+
+ return 0;
+}
+
static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta)
{
struct cfg80211_tid_config *tid_config = data;
@@ -1014,6 +1098,8 @@ const struct ieee80211_ops rtw89_ops = {
.change_chanctx = rtw89_ops_change_chanctx,
.assign_vif_chanctx = rtw89_ops_assign_vif_chanctx,
.unassign_vif_chanctx = rtw89_ops_unassign_vif_chanctx,
+ .remain_on_channel = rtw89_ops_remain_on_channel,
+ .cancel_remain_on_channel = rtw89_ops_cancel_remain_on_channel,
.set_sar_specs = rtw89_ops_set_sar_specs,
.sta_rc_update = rtw89_ops_sta_rc_update,
.set_tid_config = rtw89_ops_set_tid_config,
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 68f0fed6d31e..70b4754667c9 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -364,8 +364,11 @@ static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev,
struct rtw89_pci_tx_ring *tx_ring,
struct sk_buff *skb, u8 tx_status)
{
+ struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
struct ieee80211_tx_info *info;
+ rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE);
+
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
@@ -1203,6 +1206,7 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev,
struct pci_dev *pdev = rtwpci->pdev;
struct sk_buff *skb = tx_req->skb;
struct rtw89_pci_tx_data *tx_data = RTW89_PCI_TX_SKB_CB(skb);
+ struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb);
bool en_wd_info = desc_info->en_wd_info;
u32 txwd_len;
u32 txwp_len;
@@ -1218,6 +1222,7 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev,
}
tx_data->dma = dma;
+ rcu_assign_pointer(skb_data->wait, NULL);
txwp_len = sizeof(*txwp_info);
txwd_len = chip->txwd_body_size;
@@ -1912,9 +1917,10 @@ __get_target(struct rtw89_dev *rtwdev, u16 *target, enum rtw89_pcie_phy phy_rate
static int rtw89_pci_autok_x(struct rtw89_dev *rtwdev)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
int ret;
- if (rtwdev->chip->chip_id != RTL8852B)
+ if (chip_id != RTL8852B && chip_id != RTL8851B)
return 0;
ret = rtw89_write16_mdio_mask(rtwdev, RAC_REG_FLD_0, BAC_AUTOK_N_MASK,
@@ -1924,13 +1930,14 @@ static int rtw89_pci_autok_x(struct rtw89_dev *rtwdev)
static int rtw89_pci_auto_refclk_cal(struct rtw89_dev *rtwdev, bool autook_en)
{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
enum rtw89_pcie_phy phy_rate;
u16 val16, mgn_set, div_set, tar;
u8 val8, bdr_ori;
bool l1_flag = false;
int ret = 0;
- if (rtwdev->chip->chip_id != RTL8852B)
+ if (chip_id != RTL8852B && chip_id != RTL8851B)
return 0;
ret = rtw89_pci_read_config_byte(rtwdev, RTW89_PCIE_PHY_RATE, &val8);
@@ -2107,7 +2114,9 @@ static void rtw89_pci_rxdma_prefth(struct rtw89_dev *rtwdev)
static void rtw89_pci_l1off_pwroff(struct rtw89_dev *rtwdev)
{
- if (rtwdev->chip->chip_id != RTL8852A && rtwdev->chip->chip_id != RTL8852B)
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+
+ if (chip_id != RTL8852A && chip_id != RTL8852B && chip_id != RTL8851B)
return;
rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL, B_AX_L1OFF_PWR_OFF_EN);
@@ -2135,7 +2144,9 @@ static u32 rtw89_pci_l2_rxen_lat(struct rtw89_dev *rtwdev)
static void rtw89_pci_aphy_pwrcut(struct rtw89_dev *rtwdev)
{
- if (rtwdev->chip->chip_id != RTL8852A && rtwdev->chip->chip_id != RTL8852B)
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+
+ if (chip_id != RTL8852A && chip_id != RTL8852B && chip_id != RTL8851B)
return;
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_PSUS_OFF_CAPC_EN);
@@ -2143,8 +2154,9 @@ static void rtw89_pci_aphy_pwrcut(struct rtw89_dev *rtwdev)
static void rtw89_pci_hci_ldo(struct rtw89_dev *rtwdev)
{
- if (rtwdev->chip->chip_id == RTL8852A ||
- rtwdev->chip->chip_id == RTL8852B) {
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
@@ -2157,7 +2169,9 @@ static void rtw89_pci_hci_ldo(struct rtw89_dev *rtwdev)
static int rtw89_pci_dphy_delay(struct rtw89_dev *rtwdev)
{
- if (rtwdev->chip->chip_id != RTL8852B)
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+
+ if (chip_id != RTL8852B && chip_id != RTL8851B)
return 0;
return rtw89_write16_mdio_mask(rtwdev, RAC_REG_REV2, BAC_CMU_EN_DLY_MASK,
@@ -3397,7 +3411,7 @@ static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable)
if (ret)
rtw89_err(rtwdev, "failed to set CLKREQ Delay\n");
- if (chip_id == RTL8852A || chip_id == RTL8852B) {
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
if (enable)
ret = rtw89_pci_config_byte_set(rtwdev,
RTW89_PCIE_L1_CTRL,
@@ -3442,7 +3456,7 @@ static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable)
if (ret)
rtw89_err(rtwdev, "failed to read ASPM Delay\n");
- if (chip_id == RTL8852A || chip_id == RTL8852B) {
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
if (enable)
ret = rtw89_pci_config_byte_set(rtwdev,
RTW89_PCIE_L1_CTRL,
@@ -3522,7 +3536,7 @@ static void rtw89_pci_l1ss_set(struct rtw89_dev *rtwdev, bool enable)
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
int ret;
- if (chip_id == RTL8852A || chip_id == RTL8852B) {
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
if (enable)
ret = rtw89_pci_config_byte_set(rtwdev,
RTW89_PCIE_TIMER_CTRL,
@@ -3721,7 +3735,7 @@ static int __maybe_unused rtw89_pci_suspend(struct device *dev)
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
- if (chip_id == RTL8852A || chip_id == RTL8852B) {
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
@@ -3755,7 +3769,7 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
- if (chip_id == RTL8852A || chip_id == RTL8852B) {
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) {
rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 1e19740db8c5..0e4bd210b100 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -1004,9 +1004,9 @@ rtw89_pci_rxbd_increase(struct rtw89_pci_rx_ring *rx_ring, u32 cnt)
static inline struct rtw89_pci_tx_data *RTW89_PCI_TX_SKB_CB(struct sk_buff *skb)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct rtw89_tx_skb_data *data = RTW89_TX_SKB_CB(skb);
- return (struct rtw89_pci_tx_data *)info->status.status_driver_data;
+ return (struct rtw89_pci_tx_data *)data->hci_priv;
}
static inline struct rtw89_pci_tx_bd_32 *
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index cb0f6cc51d6b..c7e906123416 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1617,29 +1617,35 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
{
- const struct rtw89_chip_info *chip = rtwdev->chip;
+ const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+ const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
+ const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
+ const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
s8 lmt = 0, sar;
switch (band) {
case RTW89_BAND_2G:
- lmt = (*chip->txpwr_lmt_2g)[bw][ntx][rs][bf][regd][ch_idx];
- if (!lmt)
- lmt = (*chip->txpwr_lmt_2g)[bw][ntx][rs][bf]
- [RTW89_WW][ch_idx];
+ lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+ if (lmt)
+ break;
+
+ lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
break;
case RTW89_BAND_5G:
- lmt = (*chip->txpwr_lmt_5g)[bw][ntx][rs][bf][regd][ch_idx];
- if (!lmt)
- lmt = (*chip->txpwr_lmt_5g)[bw][ntx][rs][bf]
- [RTW89_WW][ch_idx];
+ lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+ if (lmt)
+ break;
+
+ lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt = (*chip->txpwr_lmt_6g)[bw][ntx][rs][bf][regd][ch_idx];
- if (!lmt)
- lmt = (*chip->txpwr_lmt_6g)[bw][ntx][rs][bf]
- [RTW89_WW][ch_idx];
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+ if (lmt)
+ break;
+
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -1862,29 +1868,35 @@ void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
u8 ru, u8 ntx, u8 ch)
{
- const struct rtw89_chip_info *chip = rtwdev->chip;
+ const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+ const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
+ const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
+ const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
s8 lmt_ru = 0, sar;
switch (band) {
case RTW89_BAND_2G:
- lmt_ru = (*chip->txpwr_lmt_ru_2g)[ru][ntx][regd][ch_idx];
- if (!lmt_ru)
- lmt_ru = (*chip->txpwr_lmt_ru_2g)[ru][ntx]
- [RTW89_WW][ch_idx];
+ lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+ if (lmt_ru)
+ break;
+
+ lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
break;
case RTW89_BAND_5G:
- lmt_ru = (*chip->txpwr_lmt_ru_5g)[ru][ntx][regd][ch_idx];
- if (!lmt_ru)
- lmt_ru = (*chip->txpwr_lmt_ru_5g)[ru][ntx]
- [RTW89_WW][ch_idx];
+ lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+ if (lmt_ru)
+ break;
+
+ lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt_ru = (*chip->txpwr_lmt_ru_6g)[ru][ntx][regd][ch_idx];
- if (!lmt_ru)
- lmt_ru = (*chip->txpwr_lmt_ru_6g)[ru][ntx]
- [RTW89_WW][ch_idx];
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+ if (lmt_ru)
+ break;
+
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -2405,7 +2417,6 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
bool is_linked = rtwdev->total_sta_assoc > 0;
s32 cfo_avg_312;
s32 dcfo_comp_val;
- u8 dcfo_comp_sft = rtwdev->chip->dcfo_comp_sft;
int sign;
if (!is_linked) {
@@ -2418,8 +2429,8 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
return;
dcfo_comp_val = rtw89_phy_read32_mask(rtwdev, R_DCFO, B_DCFO);
sign = curr_cfo > 0 ? 1 : -1;
- cfo_avg_312 = (curr_cfo << dcfo_comp_sft) / 5 + sign * dcfo_comp_val;
- rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: avg_cfo=%d\n", cfo_avg_312);
+ cfo_avg_312 = curr_cfo / 625 + sign * dcfo_comp_val;
+ rtw89_debug(rtwdev, RTW89_DBG_CFO, "avg_cfo_312=%d step\n", cfo_avg_312);
if (rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV)
cfo_avg_312 = -cfo_avg_312;
rtw89_phy_set_phy_regs(rtwdev, dcfo_comp->addr, dcfo_comp->mask,
@@ -2428,9 +2439,16 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
static void rtw89_dcfo_comp_init(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
rtw89_phy_set_phy_regs(rtwdev, R_DCFO_OPT, B_DCFO_OPT_EN, 1);
rtw89_phy_set_phy_regs(rtwdev, R_DCFO_WEIGHT, B_DCFO_WEIGHT_MSK, 8);
- rtw89_write32_clr(rtwdev, R_AX_PWR_UL_CTRL2, B_AX_PWR_UL_CFO_MASK);
+
+ if (chip->cfo_hw_comp)
+ rtw89_write32_mask(rtwdev, R_AX_PWR_UL_CTRL2,
+ B_AX_PWR_UL_CFO_MASK, 0x6);
+ else
+ rtw89_write32_clr(rtwdev, R_AX_PWR_UL_CTRL2, B_AX_PWR_UL_CFO_MASK);
}
static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev)
@@ -2500,6 +2518,7 @@ static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
static s32 rtw89_phy_average_cfo_calc(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
s32 cfo_khz_all = 0;
s32 cfo_cnt_all = 0;
@@ -2516,6 +2535,8 @@ static s32 rtw89_phy_average_cfo_calc(struct rtw89_dev *rtwdev)
cfo_cnt_all += cfo->cfo_cnt[i];
cfo_all_avg = phy_div(cfo_khz_all, cfo_cnt_all);
cfo->pre_cfo_avg[i] = cfo->cfo_avg[i];
+ cfo->dcfo_avg = phy_div(cfo_khz_all << chip->dcfo_comp_sft,
+ cfo_cnt_all);
}
rtw89_debug(rtwdev, RTW89_DBG_CFO,
"CFO track for macid = %d\n", i);
@@ -2642,7 +2663,9 @@ static void rtw89_phy_cfo_dm(struct rtw89_dev *rtwdev)
s32 new_cfo = 0;
bool x_cap_update = false;
u8 pre_x_cap = cfo->crystal_cap;
+ u8 dcfo_comp_sft = rtwdev->chip->dcfo_comp_sft;
+ cfo->dcfo_avg = 0;
rtw89_debug(rtwdev, RTW89_DBG_CFO, "CFO:total_sta_assoc=%d\n",
rtwdev->total_sta_assoc);
if (rtwdev->total_sta_assoc == 0) {
@@ -2684,18 +2707,19 @@ static void rtw89_phy_cfo_dm(struct rtw89_dev *rtwdev)
rtw89_phy_cfo_crystal_cap_adjust(rtwdev, new_cfo);
cfo->cfo_avg_pre = new_cfo;
+ cfo->dcfo_avg_pre = cfo->dcfo_avg;
x_cap_update = cfo->crystal_cap != pre_x_cap;
rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap_up=%d\n", x_cap_update);
rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap: D:%x C:%x->%x, ofst=%d\n",
cfo->def_x_cap, pre_x_cap, cfo->crystal_cap,
cfo->x_cap_ofst);
if (x_cap_update) {
- if (new_cfo > 0)
- new_cfo -= CFO_SW_COMP_FINE_TUNE;
+ if (cfo->dcfo_avg > 0)
+ cfo->dcfo_avg -= CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
else
- new_cfo += CFO_SW_COMP_FINE_TUNE;
+ cfo->dcfo_avg += CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
}
- rtw89_dcfo_comp(rtwdev, new_cfo);
+ rtw89_dcfo_comp(rtwdev, cfo->dcfo_avg);
rtw89_phy_cfo_statistics_reset(rtwdev);
}
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index 40498812205e..fa94335f699a 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -114,7 +114,8 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
__rtw89_leave_ps_mode(rtwdev);
}
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ bool ps_mode)
{
lockdep_assert_held(&rtwdev->mutex);
@@ -122,7 +123,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
return;
__rtw89_enter_lps(rtwdev, rtwvif->mac_id);
- __rtw89_enter_ps_mode(rtwdev, rtwvif);
+ if (ps_mode)
+ __rtw89_enter_ps_mode(rtwdev, rtwvif);
}
static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
@@ -155,6 +157,9 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev)
set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
+ if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
+ return;
+
rtw89_for_each_rtwvif(rtwdev, rtwvif)
rtw89_mac_vif_deinit(rtwdev, rtwvif);
@@ -166,6 +171,9 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev)
struct rtw89_vif *rtwvif;
int ret;
+ if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
+ return;
+
ret = rtw89_core_start(rtwdev);
if (ret)
rtw89_err(rtwdev, "failed to leave idle state\n");
diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h
index 6ac1f7ea5339..73c008db0426 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.h
+++ b/drivers/net/wireless/realtek/rtw89/ps.h
@@ -5,7 +5,8 @@
#ifndef __RTW89_PS_H_
#define __RTW89_PS_H_
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
+ bool ps_mode);
void rtw89_leave_lps(struct rtw89_dev *rtwdev);
void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev);
void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
@@ -15,4 +16,20 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev);
void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl);
void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
+static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev)
+{
+ struct ieee80211_hw *hw = rtwdev->hw;
+
+ if (hw->conf.flags & IEEE80211_CONF_IDLE)
+ rtw89_leave_ips(rtwdev);
+}
+
+static inline void rtw89_enter_ips_by_hwflags(struct rtw89_dev *rtwdev)
+{
+ struct ieee80211_hw *hw = rtwdev->hw;
+
+ if (hw->conf.flags & IEEE80211_CONF_IDLE)
+ rtw89_enter_ips(rtwdev);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 37a1777a25a3..266e4231b5f3 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -129,6 +129,7 @@
#define R_AX_PLATFORM_ENABLE 0x0088
#define B_AX_AXIDMA_EN BIT(3)
+#define B_AX_APB_WRAP_EN BIT(2)
#define B_AX_WCPU_EN BIT(1)
#define B_AX_PLATFORM_EN BIT(0)
@@ -488,6 +489,7 @@
#define B_AX_DISPATCHER_CLK_EN BIT(18)
#define B_AX_BBRPT_CLK_EN BIT(17)
#define B_AX_MAC_SEC_CLK_EN BIT(16)
+#define B_AX_AXIDMA_CLK_EN BIT(9)
#define PCI_LTR_IDLE_TIMER_1US 0
#define PCI_LTR_IDLE_TIMER_10US 1
@@ -1586,6 +1588,7 @@
#define R_AX_PL_BUF_STATUS 0x9824
#define B_AX_WD_BUF_STAT_DONE BIT(31)
#define B_AX_WD_BUF_STAT_PKTID_MASK GENMASK(11, 0)
+#define S_WD_BUF_STAT_PKTID_INVALID GENMASK(11, 0)
#define R_AX_WD_CPUQ_OP_0 0x9810
#define R_AX_PL_CPUQ_OP_0 0x9830
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c
new file mode 100644
index 000000000000..0abf7978ccab
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c
@@ -0,0 +1,534 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "rtw8851b_rfk_table.h"
+
+static const struct rtw89_reg5_def rtw8851b_dadck_setup_defs[] = {
+ RTW89_DECL_RFK_WM(0xc210, 0x003fc000, 0x80),
+ RTW89_DECL_RFK_WM(0xc224, 0x003fc000, 0x80),
+ RTW89_DECL_RFK_WM(0xc0f8, 0x30000000, 0x3),
+ RTW89_DECL_RFK_WM(0x12b8, BIT(30), 0x1),
+ RTW89_DECL_RFK_WM(0x030c, 0x1f000000, 0x1f),
+ RTW89_DECL_RFK_WM(0x032c, 0xc0000000, 0x0),
+ RTW89_DECL_RFK_WM(0x032c, BIT(22), 0x0),
+ RTW89_DECL_RFK_WM(0x032c, BIT(22), 0x1),
+ RTW89_DECL_RFK_WM(0x032c, BIT(16), 0x0),
+ RTW89_DECL_RFK_WM(0x032c, BIT(20), 0x1),
+ RTW89_DECL_RFK_WM(0x030c, 0x0f000000, 0x3),
+ RTW89_DECL_RFK_WM(0xc0f4, BIT(2), 0x0),
+ RTW89_DECL_RFK_WM(0xc0f4, BIT(4), 0x0),
+ RTW89_DECL_RFK_WM(0xc0f4, BIT(11), 0x1),
+ RTW89_DECL_RFK_WM(0xc0f4, BIT(11), 0x0),
+ RTW89_DECL_RFK_DELAY(1),
+ RTW89_DECL_RFK_WM(0xc0f4, 0x300, 0x1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_dadck_setup_defs);
+
+static const struct rtw89_reg5_def rtw8851b_dadck_post_defs[] = {
+ RTW89_DECL_RFK_WM(0x032c, BIT(16), 0x1),
+ RTW89_DECL_RFK_WM(0x032c, BIT(20), 0x0),
+ RTW89_DECL_RFK_WM(0x030c, 0x1f000000, 0xc),
+ RTW89_DECL_RFK_WM(0x032c, 0xc0000000, 0x1),
+ RTW89_DECL_RFK_WM(0x12b8, BIT(30), 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_dadck_post_defs);
+
+static const struct rtw89_reg5_def rtw8851b_dack_s0_1_defs[] = {
+ RTW89_DECL_RFK_WM(0x12a0, BIT(15), 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x7000, 0x3),
+ RTW89_DECL_RFK_WM(0x12b8, BIT(30), 0x1),
+ RTW89_DECL_RFK_WM(0x030c, BIT(28), 0x1),
+ RTW89_DECL_RFK_WM(0x032c, 0x80000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_dack_s0_1_defs);
+
+static const struct rtw89_reg5_def rtw8851b_dack_s0_2_defs[] = {
+ RTW89_DECL_RFK_WM(0xc004, BIT(0), 0x0),
+ RTW89_DECL_RFK_WM(0x12a0, BIT(15), 0x0),
+ RTW89_DECL_RFK_WM(0x12a0, 0x7000, 0x7),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_dack_s0_2_defs);
+
+static const struct rtw89_reg5_def rtw8851b_dack_manual_off_defs[] = {
+ RTW89_DECL_RFK_WM(0xc0f8, 0x30000000, 0x0),
+ RTW89_DECL_RFK_WM(0xc210, BIT(0), 0x0),
+ RTW89_DECL_RFK_WM(0xc224, BIT(0), 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_dack_manual_off_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_rxclk_80_defs[] = {
+ RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x0101),
+ RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x2),
+ RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x1),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x8),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x5),
+ RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xf),
+ RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0),
+ RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x0f),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x03),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0001),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041),
+ RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x1101),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_rxclk_80_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_rxclk_others_defs[] = {
+ RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x0101),
+ RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x2),
+ RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x0),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x8),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x5),
+ RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xf),
+ RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x2),
+ RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x0f),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x03),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0001),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041),
+ RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x1101),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_rxclk_others_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_txk_2ghz_defs[] = {
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x51, 0x80000, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x51, 0x00800, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x52, 0x00800, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x55, 0x0001f, 0x4),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0xef, 0x00004, 0x1),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x00, 0xffff0, 0x403e),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x00003, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x00070, 0x6),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x1f000, 0x10),
+ RTW89_DECL_RFK_DELAY(1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_txk_2ghz_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_txk_5ghz_defs[] = {
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x60, 0x00007, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x55, 0x0001f, 0x4),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0xef, 0x00004, 0x1),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x00, 0xffff0, 0x403e),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x00003, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x00070, 0x7),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x11, 0x1f000, 0x7),
+ RTW89_DECL_RFK_DELAY(1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_txk_5ghz_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_afebb_restore_defs[] = {
+ RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x0),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00010000, 0x1),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00100000, 0x0),
+ RTW89_DECL_RFK_WM(0x20fc, 0x01000000, 0x1),
+ RTW89_DECL_RFK_WM(0x20fc, 0x10000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5670, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x12a0, 0x000ff000, 0x00),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00010000, 0x0),
+ RTW89_DECL_RFK_WM(0x20fc, 0x01000000, 0x0),
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x10005, 0x00001, 0x1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_afebb_restore_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_macbb_defs[] = {
+ RTW89_DECL_RFK_WRF(RF_PATH_A, 0x10005, 0x00001, 0x0),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00010000, 0x1),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00100000, 0x0),
+ RTW89_DECL_RFK_WM(0x20fc, 0x01000000, 0x1),
+ RTW89_DECL_RFK_WM(0x20fc, 0x10000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5670, MASKDWORD, 0xf801fffd),
+ RTW89_DECL_RFK_WM(0x5670, 0x00004000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00008000, 0x1),
+ RTW89_DECL_RFK_WM(0x5670, 0x80000000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00007000, 0x7),
+ RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x3),
+ RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x9),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x1),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x0),
+ RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x3),
+ RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xa),
+ RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0),
+ RTW89_DECL_RFK_WM(0xc0e8, 0x00000040, 0x1),
+ RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x1f),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x13),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0001),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041),
+ RTW89_DECL_RFK_WM(0x20fc, 0x00100000, 0x1),
+ RTW89_DECL_RFK_WM(0x20fc, 0x10000000, 0x1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_macbb_defs);
+
+static const struct rtw89_reg5_def rtw8851b_iqk_bb_afe_defs[] = {
+ RTW89_DECL_RFK_WM(0x5670, 0x00004000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00008000, 0x1),
+ RTW89_DECL_RFK_WM(0x5670, 0x80000000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00007000, 0x7),
+ RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1),
+ RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x3),
+ RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x2),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x9),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x1),
+ RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x0),
+ RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x3),
+ RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xa),
+ RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0),
+ RTW89_DECL_RFK_WM(0xc0e8, 0x00000040, 0x1),
+ RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x030c, MASKBYTE3, 0x1f),
+ RTW89_DECL_RFK_WM(0x030c, MASKBYTE3, 0x13),
+ RTW89_DECL_RFK_WM(0x032c, MASKHWORD, 0x0001),
+ RTW89_DECL_RFK_WM(0x032c, MASKHWORD, 0x0041),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_bb_afe_defs);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_sys_defs[] = {
+ RTW89_DECL_RFK_WM(0x12bc, 0x000ffff0, 0xb5b5),
+ RTW89_DECL_RFK_WM(0x32bc, 0x000ffff0, 0xb5b5),
+ RTW89_DECL_RFK_WM(0x0300, 0xff000000, 0x16),
+ RTW89_DECL_RFK_WM(0x0304, 0x0000ffff, 0x1f19),
+ RTW89_DECL_RFK_WM(0x0308, 0xff000000, 0x1c),
+ RTW89_DECL_RFK_WM(0x0314, 0xffff0000, 0x2041),
+ RTW89_DECL_RFK_WM(0x0318, 0xffffffff, 0x20012041),
+ RTW89_DECL_RFK_WM(0x0324, 0xffff0000, 0x2001),
+ RTW89_DECL_RFK_WM(0x0020, 0x00006000, 0x3),
+ RTW89_DECL_RFK_WM(0x0024, 0x00006000, 0x3),
+ RTW89_DECL_RFK_WM(0x0704, 0xffff0000, 0x601e),
+ RTW89_DECL_RFK_WM(0x2704, 0xffff0000, 0x601e),
+ RTW89_DECL_RFK_WM(0x0700, 0xf0000000, 0x4),
+ RTW89_DECL_RFK_WM(0x2700, 0xf0000000, 0x4),
+ RTW89_DECL_RFK_WM(0x0650, 0x3c000000, 0x0),
+ RTW89_DECL_RFK_WM(0x2650, 0x3c000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_sys_defs);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_sys_a_defs_2g[] = {
+ RTW89_DECL_RFK_WM(0x120c, 0x000000ff, 0x33),
+ RTW89_DECL_RFK_WM(0x12c0, 0x0ff00000, 0x33),
+ RTW89_DECL_RFK_WM(0x58f8, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5814, 0x20000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_sys_a_defs_2g);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_sys_a_defs_5g[] = {
+ RTW89_DECL_RFK_WM(0x120c, 0x000000ff, 0x44),
+ RTW89_DECL_RFK_WM(0x12c0, 0x0ff00000, 0x44),
+ RTW89_DECL_RFK_WM(0x58f8, 0x40000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5814, 0x20000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_sys_a_defs_5g);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_init_txpwr_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x566c, 0x00001000, 0x0),
+ RTW89_DECL_RFK_WM(0x5800, 0xffffffff, 0x003f807f),
+ RTW89_DECL_RFK_WM(0x580c, 0x0000007f, 0x40),
+ RTW89_DECL_RFK_WM(0x580c, 0x0fffff00, 0x00040),
+ RTW89_DECL_RFK_WM(0x5810, 0xffffffff, 0x59010000),
+ RTW89_DECL_RFK_WM(0x5814, 0x01ffffff, 0x026d000),
+ RTW89_DECL_RFK_WM(0x5814, 0xf8000000, 0x00),
+ RTW89_DECL_RFK_WM(0x5818, 0x00ffffff, 0x2c18e8),
+ RTW89_DECL_RFK_WM(0x5818, 0x07000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5818, 0xf0000000, 0x0),
+ RTW89_DECL_RFK_WM(0x581c, 0x3fffffff, 0x3dc80280),
+ RTW89_DECL_RFK_WM(0x5820, 0xffffffff, 0x00000080),
+ RTW89_DECL_RFK_WM(0x58e8, 0x0000003f, 0x04),
+ RTW89_DECL_RFK_WM(0x580c, 0x10000000, 0x1),
+ RTW89_DECL_RFK_WM(0x580c, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5834, 0x3fffffff, 0x000115f2),
+ RTW89_DECL_RFK_WM(0x5838, 0x7fffffff, 0x0000121),
+ RTW89_DECL_RFK_WM(0x5854, 0x3fffffff, 0x000115f2),
+ RTW89_DECL_RFK_WM(0x5858, 0x7fffffff, 0x0000121),
+ RTW89_DECL_RFK_WM(0x5860, 0x80000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5864, 0x07ffffff, 0x00801ff),
+ RTW89_DECL_RFK_WM(0x5898, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x589c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x58a4, 0x000000ff, 0x16),
+ RTW89_DECL_RFK_WM(0x58b0, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x58b4, 0x7fffffff, 0x0a002000),
+ RTW89_DECL_RFK_WM(0x58b8, 0x7fffffff, 0x00007628),
+ RTW89_DECL_RFK_WM(0x58bc, 0x07ffffff, 0x7a7807f),
+ RTW89_DECL_RFK_WM(0x58c0, 0xfffe0000, 0x003f),
+ RTW89_DECL_RFK_WM(0x58c4, 0xffffffff, 0x0003ffff),
+ RTW89_DECL_RFK_WM(0x58c8, 0x00ffffff, 0x000000),
+ RTW89_DECL_RFK_WM(0x58c8, 0xf0000000, 0x0),
+ RTW89_DECL_RFK_WM(0x58cc, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x58d0, 0x07ffffff, 0x2008101),
+ RTW89_DECL_RFK_WM(0x58d4, 0x000000ff, 0x00),
+ RTW89_DECL_RFK_WM(0x58d4, 0x0003fe00, 0x0ff),
+ RTW89_DECL_RFK_WM(0x58d4, 0x07fc0000, 0x100),
+ RTW89_DECL_RFK_WM(0x58d8, 0xffffffff, 0x8008016c),
+ RTW89_DECL_RFK_WM(0x58dc, 0x0001ffff, 0x0807f),
+ RTW89_DECL_RFK_WM(0x58dc, 0xfff00000, 0x800),
+ RTW89_DECL_RFK_WM(0x58f0, 0x0003ffff, 0x001ff),
+ RTW89_DECL_RFK_WM(0x58f4, 0x000fffff, 0x00000),
+ RTW89_DECL_RFK_WM(0x58f8, 0x000fffff, 0x00000),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_init_txpwr_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_init_txpwr_he_tb_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x58a0, MASKDWORD, 0x000000fe),
+ RTW89_DECL_RFK_WM(0x58e4, 0x0000007f, 0x1f),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_init_txpwr_he_tb_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_dck_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x580c, 0x0fff0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5814, 0x00001000, 0x1),
+ RTW89_DECL_RFK_WM(0x5814, 0x00002000, 0x1),
+ RTW89_DECL_RFK_WM(0x5814, 0x00004000, 0x1),
+ RTW89_DECL_RFK_WM(0x5814, 0x00038000, 0x3),
+ RTW89_DECL_RFK_WM(0x5814, 0x003c0000, 0x5),
+ RTW89_DECL_RFK_WM(0x5814, 0x18000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_dck_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_dac_gain_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x58b0, 0x00000fff, 0x000),
+ RTW89_DECL_RFK_WM(0x5a00, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a04, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a08, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a0c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a10, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a14, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a18, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a1c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a20, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a24, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a28, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a2c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a30, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a34, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a38, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a3c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a40, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a44, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a48, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a4c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a50, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a54, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a58, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a5c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a60, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a64, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a68, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a6c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a70, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a74, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a78, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a7c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a80, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a84, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a88, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a8c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a90, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a94, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a98, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5a9c, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5aa0, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5aa4, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5aa8, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5aac, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5ab0, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5ab4, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5ab8, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5abc, MASKDWORD, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5ac0, MASKDWORD, 0x00000000),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_dac_gain_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_slope_a_defs_2g[] = {
+ RTW89_DECL_RFK_WM(0x5608, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x560c, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x5610, 0x07ffffff, 0x0200e08),
+ RTW89_DECL_RFK_WM(0x5614, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x5618, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x561c, 0x000001ff, 0x007),
+ RTW89_DECL_RFK_WM(0x561c, 0xffff0000, 0x0808),
+ RTW89_DECL_RFK_WM(0x5620, 0xffffffff, 0x08080808),
+ RTW89_DECL_RFK_WM(0x5624, 0xffffffff, 0x08080808),
+ RTW89_DECL_RFK_WM(0x5628, 0xffffffff, 0x08080808),
+ RTW89_DECL_RFK_WM(0x562c, 0x0000ffff, 0x0808),
+ RTW89_DECL_RFK_WM(0x581c, 0x00100000, 0x1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_slope_a_defs_2g);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_slope_a_defs_5g[] = {
+ RTW89_DECL_RFK_WM(0x5608, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x560c, 0x07ffffff, 0x0341a08),
+ RTW89_DECL_RFK_WM(0x5610, 0x07ffffff, 0x0201417),
+ RTW89_DECL_RFK_WM(0x5614, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x5618, 0x07ffffff, 0x0201008),
+ RTW89_DECL_RFK_WM(0x561c, 0x000001ff, 0x008),
+ RTW89_DECL_RFK_WM(0x561c, 0xffff0000, 0x0808),
+ RTW89_DECL_RFK_WM(0x5620, 0xffffffff, 0x0e0e0808),
+ RTW89_DECL_RFK_WM(0x5624, 0xffffffff, 0x08080d18),
+ RTW89_DECL_RFK_WM(0x5628, 0xffffffff, 0x08080808),
+ RTW89_DECL_RFK_WM(0x562c, 0x0000ffff, 0x0808),
+ RTW89_DECL_RFK_WM(0x581c, 0x00100000, 0x1),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_slope_a_defs_5g);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_align_a_2g_defs[] = {
+ RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x000000),
+ RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x2d2400),
+ RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5634, 0x000003ff, 0x000),
+ RTW89_DECL_RFK_WM(0x5634, 0x000ffc00, 0x000),
+ RTW89_DECL_RFK_WM(0x5634, 0x3ff00000, 0x3fa),
+ RTW89_DECL_RFK_WM(0x5638, 0x000003ff, 0x02e),
+ RTW89_DECL_RFK_WM(0x5638, 0x000ffc00, 0x09c),
+ RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x3fb00000),
+ RTW89_DECL_RFK_WM(0x5644, 0x000003ff, 0x02f),
+ RTW89_DECL_RFK_WM(0x5644, 0x000ffc00, 0x09c),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_align_a_2g_defs);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_align_a_5g_defs[] = {
+ RTW89_DECL_RFK_WM(0x5604, 0x80000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5600, 0x3fffffff, 0x000000),
+ RTW89_DECL_RFK_WM(0x5604, 0x003fffff, 0x3b2d24),
+ RTW89_DECL_RFK_WM(0x5630, 0x3fffffff, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5634, 0x000003ff, 0x000),
+ RTW89_DECL_RFK_WM(0x5634, 0x000ffc00, 0x3cb),
+ RTW89_DECL_RFK_WM(0x5634, 0x3ff00000, 0x030),
+ RTW89_DECL_RFK_WM(0x5638, 0x000003ff, 0x73),
+ RTW89_DECL_RFK_WM(0x5638, 0x000ffc00, 0xd4),
+ RTW89_DECL_RFK_WM(0x563c, 0x3fffffff, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5640, 0x3fffffff, 0x00000000),
+ RTW89_DECL_RFK_WM(0x5644, 0x000fffff, 0x00000),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_align_a_5g_defs);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_slope_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x5820, 0x80000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5818, 0x10000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5814, 0x00000800, 0x1),
+ RTW89_DECL_RFK_WM(0x581c, 0x20000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5820, 0x0000f000, 0xf),
+ RTW89_DECL_RFK_WM(0x581c, 0x000003ff, 0x280),
+ RTW89_DECL_RFK_WM(0x581c, 0x000ffc00, 0x200),
+ RTW89_DECL_RFK_WM(0x58b8, 0x007f0000, 0x00),
+ RTW89_DECL_RFK_WM(0x58b8, 0x7f000000, 0x00),
+ RTW89_DECL_RFK_WM(0x58b4, 0x7f000000, 0x0a),
+ RTW89_DECL_RFK_WM(0x58b8, 0x0000007f, 0x28),
+ RTW89_DECL_RFK_WM(0x58b8, 0x00007f00, 0x76),
+ RTW89_DECL_RFK_WM(0x5810, 0x20000000, 0x0),
+ RTW89_DECL_RFK_WM(0x580c, 0x10000000, 0x1),
+ RTW89_DECL_RFK_WM(0x580c, 0x40000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5834, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x5834, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5838, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5838, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x5854, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x5854, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5858, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5858, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x5824, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x5824, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5828, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5828, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x582c, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x582c, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5830, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5830, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x583c, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x583c, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5840, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5840, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x5844, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x5844, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5848, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5848, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x584c, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x584c, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5850, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5850, 0x003ff000, 0x000),
+ RTW89_DECL_RFK_WM(0x585c, 0x0003ffff, 0x115f2),
+ RTW89_DECL_RFK_WM(0x585c, 0x3ffc0000, 0x000),
+ RTW89_DECL_RFK_WM(0x5860, 0x00000fff, 0x121),
+ RTW89_DECL_RFK_WM(0x5860, 0x003ff000, 0x000),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_slope_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_track_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x5820, 0x80000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5818, 0x10000000, 0x0),
+ RTW89_DECL_RFK_WM(0x5814, 0x00000800, 0x0),
+ RTW89_DECL_RFK_WM(0x581c, 0x20000000, 0x1),
+ RTW89_DECL_RFK_WM(0x5864, 0x000003ff, 0x1ff),
+ RTW89_DECL_RFK_WM(0x5864, 0x000ffc00, 0x200),
+ RTW89_DECL_RFK_WM(0x5820, 0x00000fff, 0x080),
+ RTW89_DECL_RFK_WM(0x5814, 0x01000000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_track_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_tssi_mv_avg_defs_a[] = {
+ RTW89_DECL_RFK_WM(0x58e4, 0x00003800, 0x1),
+ RTW89_DECL_RFK_WM(0x58e4, 0x00004000, 0x0),
+ RTW89_DECL_RFK_WM(0x58e4, 0x00008000, 0x1),
+ RTW89_DECL_RFK_WM(0x58e4, 0x000f0000, 0x0),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_tssi_mv_avg_defs_a);
+
+static const struct rtw89_reg5_def rtw8851b_nctl_post_defs[] = {
+ RTW89_DECL_RFK_WM(0x5864, 0x18000000, 0x3),
+ RTW89_DECL_RFK_WM(0x7864, 0x18000000, 0x3),
+ RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x13),
+ RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041),
+ RTW89_DECL_RFK_WM(0x12b8, 0x10000000, 0x1),
+ RTW89_DECL_RFK_WM(0x2008, 0x01ffffff, 0x00fffff),
+ RTW89_DECL_RFK_WM(0x0c60, 0x00000003, 0x3),
+ RTW89_DECL_RFK_WM(0x0c6c, 0x00000001, 0x1),
+ RTW89_DECL_RFK_WM(0x58ac, 0x08000000, 0x1),
+ RTW89_DECL_RFK_WM(0x78ac, 0x08000000, 0x1),
+ RTW89_DECL_RFK_WM(0x0730, 0x00003800, 0x7),
+ RTW89_DECL_RFK_WM(0x2730, 0x00003800, 0x7),
+ RTW89_DECL_RFK_WM(0x0c7c, 0x00e00000, 0x1),
+ RTW89_DECL_RFK_WM(0x58c0, 0x0001ffff, 0x00000),
+ RTW89_DECL_RFK_WM(0x78c0, 0x0001ffff, 0x00000),
+ RTW89_DECL_RFK_WM(0x58fc, 0x3f000000, 0x00),
+ RTW89_DECL_RFK_WM(0x78fc, 0x3f000000, 0x00),
+};
+
+RTW89_DECLARE_RFK_TBL(rtw8851b_nctl_post_defs);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h
new file mode 100644
index 000000000000..febfbecb691c
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_RFK_TABLE_H__
+#define __RTW89_8851B_RFK_TABLE_H__
+
+#include "phy.h"
+
+extern const struct rtw89_rfk_tbl rtw8851b_dadck_setup_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_dadck_post_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_dack_s0_1_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_dack_s0_2_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_dack_manual_off_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_rxclk_80_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_rxclk_others_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_txk_2ghz_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_txk_5ghz_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_afebb_restore_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_bb_afe_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_iqk_macbb_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_a_defs_2g_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_a_defs_5g_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_init_txpwr_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_init_txpwr_he_tb_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_dck_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_dac_gain_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_slope_a_defs_2g_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_slope_a_defs_5g_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_align_a_2g_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_align_a_5g_defs_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_slope_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_track_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_tssi_mv_avg_defs_a_tbl;
+extern const struct rtw89_rfk_tbl rtw8851b_nctl_post_defs_tbl;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
new file mode 100644
index 000000000000..bb724140df4f
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
@@ -0,0 +1,14824 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "phy.h"
+#include "reg.h"
+#include "rtw8851b_table.h"
+
+static const struct rtw89_reg2_def rtw89_8851b_phy_bb_regs[] = {
+ {0x704, 0x601E0500},
+ {0x4000, 0x00000000},
+ {0x4004, 0xCA014000},
+ {0x4008, 0xC751D4F0},
+ {0x400C, 0x44511475},
+ {0x4010, 0x00000000},
+ {0x4014, 0x00000000},
+ {0x47BC, 0x00000380},
+ {0x4018, 0x4F4C084B},
+ {0x401C, 0x084A4E52},
+ {0x4020, 0x4D504E4B},
+ {0x4024, 0x4F4C0849},
+ {0x4028, 0x08484C50},
+ {0x402C, 0x4C50504C},
+ {0x4030, 0x5454084A},
+ {0x4034, 0x084B5654},
+ {0x4038, 0x6A6C605A},
+ {0x403C, 0x4C4C084C},
+ {0x4040, 0x084B4E4D},
+ {0x4044, 0x4E4C4B4B},
+ {0x4048, 0x4B4B084A},
+ {0x404C, 0x084A4E4C},
+ {0x4050, 0x514F4C4A},
+ {0x4054, 0x524E084A},
+ {0x4058, 0x084A5154},
+ {0x405C, 0x53555554},
+ {0x4060, 0x45450845},
+ {0x4064, 0x08454144},
+ {0x4068, 0x40434445},
+ {0x406C, 0x44450845},
+ {0x4070, 0x08444043},
+ {0x4074, 0x42434444},
+ {0x4078, 0x46450844},
+ {0x407C, 0x08444843},
+ {0x4080, 0x4B4E4A47},
+ {0x4084, 0x4F4C084B},
+ {0x4088, 0x084A4E52},
+ {0x408C, 0x4D504E4B},
+ {0x4090, 0x4F4C0849},
+ {0x4094, 0x08484C50},
+ {0x4098, 0x4C50504C},
+ {0x409C, 0x5454084A},
+ {0x40A0, 0x084B5654},
+ {0x40A4, 0x6A6C605A},
+ {0x40A8, 0x4C4C084C},
+ {0x40AC, 0x084B4E4D},
+ {0x40B0, 0x4E4C4B4B},
+ {0x40B4, 0x4B4B084A},
+ {0x40B8, 0x084A4E4C},
+ {0x40BC, 0x514F4C4A},
+ {0x40C0, 0x524E084A},
+ {0x40C4, 0x084A5154},
+ {0x40C8, 0x53555554},
+ {0x40CC, 0x45450845},
+ {0x40D0, 0x08454144},
+ {0x40D4, 0x40434445},
+ {0x40D8, 0x44450845},
+ {0x40DC, 0x08444043},
+ {0x40E0, 0x42434444},
+ {0x40E4, 0x46450844},
+ {0x40E8, 0x08444843},
+ {0x40EC, 0x4B4E4A47},
+ {0x40F0, 0x00000000},
+ {0x4A38, 0x00000000},
+ {0x40F4, 0x00000006},
+ {0x40F8, 0x00000000},
+ {0x40FC, 0x8C30C30C},
+ {0x4100, 0x4C30C30C},
+ {0x4104, 0x0C30C30C},
+ {0x4108, 0x0C30C30C},
+ {0x410C, 0x0C30C30C},
+ {0x4110, 0x0C30C30C},
+ {0x4114, 0x28A28A28},
+ {0x4118, 0x28A28A28},
+ {0x411C, 0x28A28A28},
+ {0x4120, 0x28A28A28},
+ {0x4124, 0x28A28A28},
+ {0x4128, 0x28A28A28},
+ {0x412C, 0x06666666},
+ {0x4130, 0x33333333},
+ {0x4134, 0x33333333},
+ {0x4138, 0x33333333},
+ {0x413C, 0x00000031},
+ {0x4140, 0x5100600A},
+ {0x4144, 0x18363113},
+ {0x4148, 0x1D976DDC},
+ {0x414C, 0x1C072DD7},
+ {0x4150, 0x1127CDF4},
+ {0x4154, 0x1E37BDF1},
+ {0x4158, 0x1FB7F1D6},
+ {0x415C, 0x1EA7DDF9},
+ {0x4160, 0x1FE445DD},
+ {0x4164, 0x1F97F1FE},
+ {0x4168, 0x1FF781ED},
+ {0x416C, 0x1FA7F5FE},
+ {0x4170, 0x1E07B913},
+ {0x4174, 0x1FD7FDFF},
+ {0x4178, 0x1E17B9FA},
+ {0x417C, 0x19A66914},
+ {0x4180, 0x10F65598},
+ {0x4184, 0x14A5A111},
+ {0x4188, 0x1D3765DB},
+ {0x418C, 0x17C685CA},
+ {0x4190, 0x1107C5F3},
+ {0x4194, 0x1B5785EB},
+ {0x4198, 0x1F97ED8F},
+ {0x419C, 0x1BC7A5F3},
+ {0x41A0, 0x1FE43595},
+ {0x41A4, 0x1EB7D9FC},
+ {0x41A8, 0x1FE65DBE},
+ {0x41AC, 0x1EC7D9FC},
+ {0x41B0, 0x1976FCFF},
+ {0x41B4, 0x1F77F5FF},
+ {0x41B8, 0x1976FDEC},
+ {0x41BC, 0x198664EF},
+ {0x41C0, 0x11062D93},
+ {0x41C4, 0x10C4E910},
+ {0x41C8, 0x1CA759DB},
+ {0x41CC, 0x1335A9B5},
+ {0x41D0, 0x1097B9F3},
+ {0x41D4, 0x17B72DE1},
+ {0x41D8, 0x1F67ED42},
+ {0x41DC, 0x18074DE9},
+ {0x41E0, 0x1FD40547},
+ {0x41E4, 0x1D57ADF9},
+ {0x41E8, 0x1FE52182},
+ {0x41EC, 0x1D67B1F9},
+ {0x41F0, 0x14860CE1},
+ {0x41F4, 0x1EC7E9FE},
+ {0x41F8, 0x14860DD6},
+ {0x41FC, 0x195664C7},
+ {0x4200, 0x0005E58A},
+ {0x4204, 0x00000000},
+ {0x4208, 0x00000000},
+ {0x420C, 0x7A000000},
+ {0x4210, 0x0F9F3D7A},
+ {0x4214, 0x0040817C},
+ {0x4218, 0x00E10204},
+ {0x421C, 0x227D94CD},
+ {0x4220, 0x08028A28},
+ {0x4224, 0x00000200},
+ {0x4228, 0x04688000},
+ {0x47C0, 0x00000001},
+ {0x4A48, 0x00000002},
+ {0x4B04, 0x00000000},
+ {0x4B08, 0x00000000},
+ {0x422C, 0x0060B002},
+ {0x4230, 0x9A8249A8},
+ {0x4234, 0x26A1469E},
+ {0x4238, 0x2099A824},
+ {0x423C, 0x2359461C},
+ {0x4240, 0x1631A675},
+ {0x4244, 0x2C6B1D63},
+ {0x4248, 0x0000000E},
+ {0x424C, 0x00000001},
+ {0x4250, 0x00000001},
+ {0x4254, 0x00000000},
+ {0x4258, 0x00000000},
+ {0x425C, 0x00000000},
+ {0x4260, 0x0020000C},
+ {0x4A30, 0x00000000},
+ {0x4264, 0x00000000},
+ {0x4268, 0x00000000},
+ {0x426C, 0x0418317C},
+ {0x4270, 0x2B33135C},
+ {0x4274, 0x00000002},
+ {0x4278, 0x00000000},
+ {0x427C, 0x00000000},
+ {0x4280, 0x00000000},
+ {0x4284, 0x00000000},
+ {0x4288, 0x00000000},
+ {0x428C, 0x00000000},
+ {0x4290, 0x00000000},
+ {0x4294, 0x00000000},
+ {0x4298, 0x00000000},
+ {0x429C, 0x84026000},
+ {0x42A0, 0x0051AC20},
+ {0x4A24, 0x0010C040},
+ {0x42A4, 0x02024008},
+ {0x42A8, 0x00000000},
+ {0x42AC, 0x00000000},
+ {0x42B0, 0x22CE803C},
+ {0x42B4, 0xD8000000},
+ {0x42B8, 0x596FD67E},
+ {0x42BC, 0x7D67D67D},
+ {0x42C0, 0x7D67D65B},
+ {0x42C4, 0x28029F59},
+ {0x42C8, 0x00280280},
+ {0x4AF4, 0x00000000},
+ {0x42CC, 0x00000000},
+ {0x42D0, 0x00000000},
+ {0x42D4, 0x00000003},
+ {0x4AF8, 0x00280000},
+ {0x42D8, 0x00000001},
+ {0x42DC, 0x69AEC800},
+ {0x42E0, 0x8B4CD3D1},
+ {0x42E4, 0xC514534F},
+ {0x42E8, 0x85145145},
+ {0x42EC, 0x45145145},
+ {0x42F0, 0x05145145},
+ {0x42F4, 0x05145145},
+ {0x42F8, 0x05145145},
+ {0x42FC, 0x17659145},
+ {0x4300, 0x176DD5D9},
+ {0x4304, 0x0F65765B},
+ {0x4308, 0x0F3CF3CF},
+ {0x430C, 0x0F3CF3CF},
+ {0x4310, 0x0F3CF3CF},
+ {0x4314, 0x0F3CF3CF},
+ {0x4318, 0x0F3CF3CF},
+ {0x431C, 0x0F3CF3CF},
+ {0x4320, 0x0F3CF3CF},
+ {0x4324, 0x0F44F351},
+ {0x4328, 0x192D7547},
+ {0x432C, 0x0F5CF5CF},
+ {0x4330, 0x051593D9},
+ {0x4334, 0x05145145},
+ {0x4338, 0x05145145},
+ {0x433C, 0x05145145},
+ {0x4340, 0x05145145},
+ {0x4344, 0x05145145},
+ {0x4348, 0x19545145},
+ {0x434C, 0x1B65B5DB},
+ {0x4350, 0x1965965B},
+ {0x4354, 0x0F3CF3CF},
+ {0x4358, 0x0F3CF3CF},
+ {0x435C, 0x0F3CF1CF},
+ {0x4360, 0x0F3CF3CF},
+ {0x4364, 0x0F3CF3CF},
+ {0x4368, 0x0F3CF3CF},
+ {0x436C, 0x0F3CF3CF},
+ {0x4370, 0x0934D2CF},
+ {0x4374, 0x112CB3CF},
+ {0x4378, 0x9777A777},
+ {0x437C, 0xBB7BAC95},
+ {0x4380, 0xB667B889},
+ {0x4384, 0x7B9B8899},
+ {0x4388, 0x7A5567C8},
+ {0x438C, 0x2278CCCC},
+ {0x4390, 0x7C222222},
+ {0x4394, 0x0000029B},
+ {0x4398, 0x001CCCCC},
+ {0x4AAC, 0xCCCCC88C},
+ {0x4AB0, 0x0000AACC},
+ {0x439C, 0x00000000},
+ {0x43A0, 0x00000008},
+ {0x43A4, 0x00000000},
+ {0x43A8, 0x00000000},
+ {0x43AC, 0x00000000},
+ {0x43B0, 0x10000000},
+ {0x43B4, 0x00401001},
+ {0x43B8, 0x00061003},
+ {0x43BC, 0x000024D8},
+ {0x43C0, 0x00000000},
+ {0x43C4, 0x10000020},
+ {0x43C8, 0x20000200},
+ {0x43CC, 0x00000000},
+ {0x43D0, 0x04000000},
+ {0x43D4, 0x44000100},
+ {0x43D8, 0x60804060},
+ {0x43DC, 0x44204210},
+ {0x43E0, 0x82108082},
+ {0x43E4, 0x82108402},
+ {0x43E8, 0xC8082108},
+ {0x43EC, 0xC8202084},
+ {0x43F0, 0x44208208},
+ {0x43F4, 0x84108204},
+ {0x43F8, 0xD0108104},
+ {0x43FC, 0xF8210108},
+ {0x4400, 0x6431E930},
+ {0x4404, 0x02309468},
+ {0x4408, 0x10C61C22},
+ {0x440C, 0x02109469},
+ {0x4410, 0x10C61C22},
+ {0x4414, 0x00041049},
+ {0x4A4C, 0x00060581},
+ {0x4418, 0x00000000},
+ {0x441C, 0x00000000},
+ {0x4420, 0xEC000000},
+ {0x4424, 0xB0200020},
+ {0x4428, 0x00001FF0},
+ {0x4AC8, 0x00000001},
+ {0x4B0C, 0x00000000},
+ {0x4CDC, 0x00000000},
+ {0x442C, 0x00000000},
+ {0x4430, 0x00000000},
+ {0x4434, 0x00000000},
+ {0x4438, 0x00000000},
+ {0x443C, 0x190642D0},
+ {0x4440, 0xA80668A0},
+ {0x4444, 0x60900820},
+ {0x4448, 0x9F28518C},
+ {0x444C, 0x32488A62},
+ {0x4450, 0x9C6E36DC},
+ {0x4454, 0x0000F52B},
+ {0x4A34, 0x00000007},
+ {0x4CE0, 0x68120000},
+ {0x4CE4, 0x1A0681E0},
+ {0x4CE8, 0x94060180},
+ {0x4CEC, 0x000603FF},
+ {0x4CF0, 0xA0502000},
+ {0x4CF4, 0x00001000},
+ {0x4D00, 0x00000044},
+ {0x4B14, 0x00000000},
+ {0x4458, 0x00000000},
+ {0x445C, 0x4801442E},
+ {0x4460, 0x0051A0FA},
+ {0x4B18, 0x0000011F},
+ {0x4B1C, 0x0000011F},
+ {0x4464, 0x00000000},
+ {0x4468, 0x00000000},
+ {0x446C, 0x00000000},
+ {0x4470, 0x00000000},
+ {0x4474, 0x00000000},
+ {0x4478, 0x00000000},
+ {0x447C, 0x00000000},
+ {0x4480, 0x2A0A6040},
+ {0x4484, 0x0A0A6829},
+ {0x4488, 0x00000004},
+ {0x448C, 0x00000000},
+ {0x4490, 0x80000000},
+ {0x4494, 0x10000000},
+ {0x4498, 0xE0000000},
+ {0x4A28, 0x000ED877},
+ {0x4AB4, 0x00000000},
+ {0x4B20, 0x00000000},
+ {0x4B24, 0x00000000},
+ {0x4B28, 0x00000000},
+ {0x4B2C, 0x00000000},
+ {0x449C, 0x0000001E},
+ {0x44A0, 0x02B2C394},
+ {0x44A4, 0x00000400},
+ {0x4A2C, 0x0050240E},
+ {0x4B30, 0x7FFFFD20},
+ {0x4B34, 0x920823FF},
+ {0x4B38, 0x7FFFFFFF},
+ {0x4B3C, 0x01773773},
+ {0x44A8, 0x00000001},
+ {0x44AC, 0x000190C0},
+ {0x44B0, 0x00000000},
+ {0x44B4, 0x00000000},
+ {0x44B8, 0x00000000},
+ {0x44BC, 0x00000000},
+ {0x44C0, 0x00000000},
+ {0x44C4, 0x00000000},
+ {0x44C8, 0x00000000},
+ {0x44CC, 0x00000000},
+ {0x44D0, 0x00000000},
+ {0x44D4, 0x00000000},
+ {0x44D8, 0x00000000},
+ {0x44DC, 0x00000000},
+ {0x44E0, 0x00000000},
+ {0x44E4, 0x00000000},
+ {0x44E8, 0x00000000},
+ {0x44EC, 0x00000000},
+ {0x44F0, 0x00000000},
+ {0x44F4, 0x00000000},
+ {0x44F8, 0x00000000},
+ {0x44FC, 0x00000000},
+ {0x4500, 0x00000000},
+ {0x4504, 0x00000000},
+ {0x4508, 0x00000000},
+ {0x450C, 0x00000000},
+ {0x4510, 0x00000000},
+ {0x4514, 0x00000000},
+ {0x4518, 0x00000000},
+ {0x451C, 0x00000000},
+ {0x4520, 0x00000000},
+ {0x4524, 0x00000000},
+ {0x4528, 0x00000000},
+ {0x452C, 0x00000000},
+ {0x4530, 0x4E830171},
+ {0x4534, 0x00000870},
+ {0x4538, 0x000000FF},
+ {0x453C, 0x00000000},
+ {0x4540, 0x00000000},
+ {0x4544, 0x00000000},
+ {0x4548, 0x00000000},
+ {0x454C, 0x00000000},
+ {0x4550, 0x00000000},
+ {0x4554, 0x00000000},
+ {0x4558, 0x00000000},
+ {0x455C, 0x00000000},
+ {0x4560, 0x40000000},
+ {0x4564, 0x40000000},
+ {0x4568, 0x00000000},
+ {0x456C, 0x20000000},
+ {0x4570, 0x04F040BB},
+ {0x4574, 0x000E53FF},
+ {0x4578, 0x000205CB},
+ {0x457C, 0x00200000},
+ {0x4580, 0x00000040},
+ {0x4584, 0x00000000},
+ {0x4588, 0x00000017},
+ {0x458C, 0x30000000},
+ {0x4590, 0x00000000},
+ {0x4594, 0x00000000},
+ {0x4598, 0x00000001},
+ {0x459C, 0x0003FE00},
+ {0x45A0, 0x00000086},
+ {0x45A4, 0x00000000},
+ {0x45A8, 0xC00001C0},
+ {0x45AC, 0x78038000},
+ {0x45B0, 0x8000004A},
+ {0x45B4, 0x04094800},
+ {0x45B8, 0x00280002},
+ {0x45BC, 0x06748790},
+ {0x45C0, 0x80000000},
+ {0x45C4, 0x00000000},
+ {0x45C8, 0x00000000},
+ {0x45CC, 0x00558670},
+ {0x45D0, 0x002883F0},
+ {0x45D4, 0x00090120},
+ {0x45D8, 0x00000000},
+ {0x45E0, 0xA3A6D3C4},
+ {0x45E4, 0xAB27B126},
+ {0x45E8, 0x00006778},
+ {0x45F4, 0x000001B5},
+ {0x45EC, 0x11110F0A},
+ {0x45F0, 0x00000003},
+ {0x4A0C, 0x0000000A},
+ {0x45F8, 0x0058BC3F},
+ {0x45FC, 0x00000003},
+ {0x462C, 0x00000020},
+ {0x4600, 0x000003D9},
+ {0x45F0, 0x00000004},
+ {0x4604, 0x002B1CB0},
+ {0x4A50, 0xC0000000},
+ {0x4A54, 0x00001000},
+ {0x4A58, 0x00000000},
+ {0x4A18, 0x00000024},
+ {0x4608, 0x00000001},
+ {0x460C, 0x00000000},
+ {0x4A10, 0x00000001},
+ {0x4610, 0x00000001},
+ {0x4614, 0x16E5298F},
+ {0x4618, 0x18C6294A},
+ {0x461C, 0x0E06318A},
+ {0x4620, 0x0E539CE5},
+ {0x4624, 0x00019287},
+ {0x4A14, 0x000000BF},
+ {0x4628, 0x00000001},
+ {0x4630, 0x000001AA},
+ {0x4A18, 0x00001900},
+ {0x4A1C, 0x000002A6},
+ {0x4634, 0x000000A3},
+ {0x4A20, 0x00000086},
+ {0x4638, 0x00045656},
+ {0x49F8, 0x00000000},
+ {0x463C, 0x00000000},
+ {0x4640, 0x00000000},
+ {0x4644, 0x00C8CC00},
+ {0x4648, 0xC400B6B6},
+ {0x464C, 0xDC400FC0},
+ {0x4A44, 0x00000000},
+ {0x4A8C, 0x00000110},
+ {0x4BC4, 0x00000001},
+ {0x4650, 0x08882550},
+ {0x4654, 0x08CC2660},
+ {0x4658, 0x09102660},
+ {0x465C, 0x00000154},
+ {0x45DC, 0xC39E38E8},
+ {0x4660, 0x452607E6},
+ {0x4664, 0x6750DC65},
+ {0x4668, 0xF3F0F1ED},
+ {0x466C, 0x30141506},
+ {0x4670, 0x2C2B2B2B},
+ {0x4674, 0x2C2C2C2C},
+ {0x4678, 0xDDB738E8},
+ {0x467C, 0x543618FB},
+ {0x4680, 0x4F31DC6F},
+ {0x4684, 0xFBEBDA00},
+ {0x4688, 0x1A10FF04},
+ {0x468C, 0x282A3000},
+ {0x4690, 0x2A29292A},
+ {0x4694, 0x04FA2A2A},
+ {0x4698, 0xEE0F04D1},
+ {0x469C, 0x99E91436},
+ {0x46A0, 0x0701E79E},
+ {0x46A4, 0x08D77CFF},
+ {0x46A8, 0x321AFF14},
+ {0x46AC, 0x60313447},
+ {0x46B0, 0x63666666},
+ {0x46B4, 0x35374425},
+ {0x46B8, 0x35883042},
+ {0x46BC, 0x5177C252},
+ {0x4720, 0x7FFFFD63},
+ {0x4724, 0xB58D11FF},
+ {0x4728, 0x47FFFFFF},
+ {0x472C, 0x0E7893B6},
+ {0x4730, 0xE0391201},
+ {0x4734, 0x00000020},
+ {0x4738, 0x8325C500},
+ {0x473C, 0x00000B7F},
+ {0x46C0, 0x00000000},
+ {0x46C4, 0x00000000},
+ {0x46C8, 0x00000219},
+ {0x4BDC, 0x00002020},
+ {0x46CC, 0x00000000},
+ {0x46D0, 0x00000000},
+ {0x4A3C, 0x00000002},
+ {0x46D4, 0x00000001},
+ {0x46D8, 0x00000001},
+ {0x46DC, 0x00000000},
+ {0x46E0, 0x00000000},
+ {0x46E4, 0x00000151},
+ {0x46E8, 0x00000498},
+ {0x46EC, 0x00000498},
+ {0x46F0, 0x00000000},
+ {0x46F4, 0x00000000},
+ {0x46F8, 0x00001146},
+ {0x46FC, 0x00000000},
+ {0x4700, 0x00000000},
+ {0x4704, 0x00C8CC00},
+ {0x4708, 0xC400B6B6},
+ {0x470C, 0xDC400FC0},
+ {0x4A90, 0x00000110},
+ {0x4B10, 0x00000000},
+ {0x4BE0, 0x00000001},
+ {0x4710, 0x08882550},
+ {0x4714, 0x08CC2660},
+ {0x4718, 0x09102660},
+ {0x471C, 0x00000154},
+ {0x4740, 0xC69F38E8},
+ {0x4744, 0x462709E9},
+ {0x4748, 0x6750DC67},
+ {0x474C, 0xF3F0F1ED},
+ {0x4750, 0x30141506},
+ {0x4754, 0x2C2B2B2B},
+ {0x4758, 0x2C2C2C2C},
+ {0x475C, 0xE0B738E8},
+ {0x4760, 0x52381BFE},
+ {0x4764, 0x5031DC6C},
+ {0x4768, 0xFBEBDA00},
+ {0x476C, 0x1A10FF04},
+ {0x4770, 0x282A3000},
+ {0x4774, 0x2A29292A},
+ {0x4778, 0x04FA2A2A},
+ {0x477C, 0xEE0F04D1},
+ {0x47C4, 0x00000000},
+ {0x47C8, 0xA32103FE},
+ {0x47CC, 0xB20A5328},
+ {0x47D0, 0xC686314F},
+ {0x47D4, 0x000004D7},
+ {0x4BFC, 0x00000000},
+ {0x4C00, 0x0C442416},
+ {0x4C04, 0x00000000},
+ {0x47D8, 0x009B902A},
+ {0x47DC, 0x009B902A},
+ {0x47E0, 0x98682C18},
+ {0x47E4, 0x6318C4C1},
+ {0x47E8, 0x6248C631},
+ {0x47EC, 0x922A8253},
+ {0x47F0, 0x00000005},
+ {0x47F4, 0x00001759},
+ {0x47F8, 0x4BB01800},
+ {0x47FC, 0x831408BE},
+ {0x4A84, 0x000000E9},
+ {0x4C08, 0x0F801404},
+ {0x4C0C, 0x00A2B404},
+ {0x4800, 0x9ABBCACB},
+ {0x4804, 0x56867578},
+ {0x4808, 0xBCCBBB13},
+ {0x480C, 0x7889989B},
+ {0x4810, 0xBBB0F455},
+ {0x4814, 0x777BBBBB},
+ {0x4818, 0x15277777},
+ {0x481C, 0x27039CE9},
+ {0x4820, 0x42424432},
+ {0x4824, 0x36058342},
+ {0x4828, 0x00000006},
+ {0x482C, 0x00000005},
+ {0x4830, 0x00000005},
+ {0x4834, 0xC7013016},
+ {0x4838, 0x84413016},
+ {0x483C, 0x84413016},
+ {0x4840, 0x8C413016},
+ {0x4844, 0x8C40B028},
+ {0x4848, 0x3140B028},
+ {0x484C, 0x2940B028},
+ {0x4850, 0x8440B028},
+ {0x4854, 0x2318C610},
+ {0x4858, 0x45344753},
+ {0x485C, 0x236A6A88},
+ {0x4860, 0xAC8DF814},
+ {0x4864, 0x08877ACB},
+ {0x4868, 0x000107AA},
+ {0x4A94, 0x00000000},
+ {0x486C, 0xBCEB4A14},
+ {0x4870, 0x000A3A4A},
+ {0x4874, 0xBCEB4A14},
+ {0x4878, 0x000A3A4A},
+ {0x487C, 0xBCBDBD85},
+ {0x4880, 0x0CABB99A},
+ {0x4884, 0x38384242},
+ {0x4888, 0x0086102E},
+ {0x488C, 0xCA24C82A},
+ {0x4AFC, 0x00000000},
+ {0x4C14, 0x0000349D},
+ {0x4CF8, 0x00000007},
+ {0x4890, 0x00008A62},
+ {0x4894, 0x00000008},
+ {0x4958, 0x80040000},
+ {0x495C, 0x80040000},
+ {0x4960, 0xFE800000},
+ {0x4964, 0x834C0000},
+ {0x4968, 0x00000000},
+ {0x496C, 0x00000000},
+ {0x4970, 0x00000000},
+ {0x4974, 0x00000000},
+ {0x4978, 0x00000000},
+ {0x497C, 0x00000000},
+ {0x4980, 0x40000000},
+ {0x4984, 0x00000000},
+ {0x4988, 0x00000000},
+ {0x498C, 0x00000000},
+ {0x4990, 0x00000000},
+ {0x4994, 0x04065800},
+ {0x4998, 0x02004080},
+ {0x499C, 0x0E1E3E05},
+ {0x49A0, 0x0A163068},
+ {0x49A4, 0x00206040},
+ {0x49A8, 0x02020202},
+ {0x49AC, 0x00002020},
+ {0x49B0, 0xF8F8F418},
+ {0x49B4, 0xF8E8F8F8},
+ {0x49B8, 0xF80808E8},
+ {0x4A00, 0xF8F8FA00},
+ {0x4A04, 0xFAFAFAF8},
+ {0x4A08, 0xFAFAFAFA},
+ {0x49BC, 0x00000000},
+ {0x49C0, 0x800C562D},
+ {0x49C4, 0x00000101},
+ {0x49C8, 0x00000000},
+ {0x49CC, 0x00000000},
+ {0x49D0, 0x00000000},
+ {0x49D4, 0x00000000},
+ {0x49D8, 0x00000000},
+ {0x49DC, 0x00000000},
+ {0x49E0, 0x00000000},
+ {0x49E4, 0x00000000},
+ {0x49E8, 0x00000000},
+ {0x49EC, 0x00000000},
+ {0x4C28, 0x00000000},
+ {0x4C2C, 0x00000000},
+ {0x4C30, 0x00000000},
+ {0x4C34, 0x00000000},
+ {0x4C38, 0x00000000},
+ {0x4C3C, 0x00000000},
+ {0x4C40, 0x00000000},
+ {0x4C44, 0x01C0C832},
+ {0x4C48, 0x03207032},
+ {0x4C4C, 0x0320701C},
+ {0x4C50, 0x03207032},
+ {0x4C54, 0x01C0C81C},
+ {0x4C58, 0x00A0281C},
+ {0x4C5C, 0x0320C80A},
+ {0x4C60, 0x00A0C832},
+ {0x4C64, 0x01C0C832},
+ {0x4C68, 0x03207032},
+ {0x4C6C, 0x0320701C},
+ {0x4C70, 0x03207032},
+ {0x4C74, 0x01C0C81C},
+ {0x4C78, 0x00A0281C},
+ {0x4C7C, 0x0321A80A},
+ {0x4C80, 0x0320C86A},
+ {0x4C84, 0x12B02832},
+ {0x4C88, 0x12B3292B},
+ {0x4C8C, 0x0CA4ACCA},
+ {0x4C90, 0x12B4AC6A},
+ {0x4C94, 0x0CA4ACCA},
+ {0x4C98, 0x06A3292B},
+ {0x4C9C, 0x06A0280A},
+ {0x4CA0, 0x0CA0286A},
+ {0x4CA4, 0x0CA1A8CA},
+ {0x4CA8, 0x06A3286A},
+ {0x4CAC, 0x0000000A},
+ {0x4CB0, 0x01209C27},
+ {0x4CB4, 0x02704800},
+ {0x4CB8, 0x02704812},
+ {0x4CBC, 0x00004827},
+ {0x4CC0, 0x01209C12},
+ {0x4CC4, 0x00000012},
+ {0x4CC8, 0x02718000},
+ {0x4CCC, 0x02709C60},
+ {0x4CD0, 0x00000027},
+ {0x4CD4, 0x00000000},
+ {0x4CD8, 0x0000014A},
+ {0x994, 0x00000010},
+ {0x904, 0x00000005},
+ {0x708, 0x00000000},
+ {0x884, 0x0043F01D},
+ {0x710, 0xEF810000},
+ {0x718, 0x1333233F},
+ {0x604, 0x041E1E1E},
+ {0x714, 0x00010000},
+ {0x586C, 0x000000F0},
+ {0x586C, 0x000000E0},
+ {0x586C, 0x000000D0},
+ {0x586C, 0x000000C0},
+ {0x586C, 0x000000B0},
+ {0x586C, 0x000000A0},
+ {0x586C, 0x00000090},
+ {0x586C, 0x00000080},
+ {0x586C, 0x00000070},
+ {0x586C, 0x00000060},
+ {0x586C, 0x00000050},
+ {0x586C, 0x00000040},
+ {0x586C, 0x00000030},
+ {0x586C, 0x00000020},
+ {0x586C, 0x00000010},
+ {0x586C, 0x00000000},
+ {0xC0D4, 0xABA41460},
+ {0xC0D8, 0xC43A7E87},
+ {0xC0DC, 0x30C194B8},
+ {0xC0E0, 0x75008138},
+ {0xC0E4, 0x0000272B},
+ {0xC0E8, 0x000A0C81},
+ {0xC0EC, 0x00030003},
+ {0xC0F0, 0x00000024},
+ {0xC0C4, 0x005E3A00},
+ {0xC004, 0x45800000},
+ {0xC024, 0x45800000},
+ {0x334, 0xFFFFFFFF},
+ {0x33C, 0x55000000},
+ {0x340, 0x00005555},
+ {0x724, 0x00111200},
+ {0x5868, 0xA9550000},
+ {0x5870, 0x33221100},
+ {0x5874, 0x77665544},
+ {0x5878, 0xBBAA9988},
+ {0x587C, 0xFFEEDDCC},
+ {0x5880, 0x76543210},
+ {0x5884, 0xFEDCBA98},
+ {0x5888, 0x00000000},
+ {0x588C, 0x00000000},
+ {0x5894, 0x00000008},
+ {0x650, 0x00200888},
+ {0x710, 0xF3810000},
+ {0x020, 0x0000F381},
+ {0x024, 0x0000F381},
+ {0x000, 0xC580801E},
+ {0x980, 0x10002250},
+ {0x988, 0x3C3C4107},
+ {0x994, 0x00000010},
+ {0x000, 0x0580801F},
+ {0x240C, 0x00000000},
+ {0x640, 0x210A141E},
+ {0x640, 0x2114141E},
+ {0x640, 0x2114141E},
+ {0x644, 0x3414283C},
+ {0x644, 0x3425283C},
+ {0x644, 0x3426283C},
+ {0x2640, 0x140A141E},
+ {0x2640, 0x1414141E},
+ {0x2640, 0x1414141E},
+ {0x2644, 0x3414283C},
+ {0x2644, 0x3425283C},
+ {0x2644, 0x3425183C},
+ {0x2300, 0x02748790},
+ {0x2304, 0x00558670},
+ {0x2308, 0x002883F0},
+ {0x230C, 0x00090120},
+ {0x2310, 0x00000000},
+ {0x2314, 0x06000000},
+ {0x2318, 0x00000000},
+ {0x231C, 0x00000000},
+ {0x2320, 0x03020100},
+ {0x2324, 0x07060504},
+ {0x2328, 0x0B0A0908},
+ {0x232C, 0x0F0E0D0C},
+ {0x2330, 0x13121110},
+ {0x2334, 0x17161514},
+ {0x2338, 0x0C700022},
+ {0x233C, 0x0A0529D0},
+ {0x2340, 0x000529D0},
+ {0x2344, 0x0006318A},
+ {0x2348, 0xB7E6318A},
+ {0x234C, 0x80039C00},
+ {0x2350, 0x80039C00},
+ {0x2354, 0x0005298F},
+ {0x2358, 0x0015296E},
+ {0x235C, 0x0C07FC31},
+ {0x2360, 0x0219AAAE},
+ {0x2364, 0xE4F624C3},
+ {0x2368, 0x53626F15},
+ {0x236C, 0x48000000},
+ {0x2370, 0x48000000},
+ {0x2374, 0x07540000},
+ {0x2378, 0x202401B9},
+ {0x237C, 0x00F7000E},
+ {0x2380, 0x0F0A1111},
+ {0x2384, 0x30D9000F},
+ {0x2388, 0x0200EA02},
+ {0x238C, 0x003CB061},
+ {0x2390, 0x69C00000},
+ {0x2394, 0x00000000},
+ {0x2398, 0x000000F0},
+ {0x239C, 0x0001FFFF},
+ {0x23A0, 0x00C80064},
+ {0x23A4, 0x0190012C},
+ {0x23A8, 0x001917BE},
+ {0x23AC, 0x0B30880C},
+ {0x23B0, 0x9281CE00},
+ {0x23B4, 0x7F027C00},
+ {0x704, 0x601E0502},
+ {0x5600, 0x00000000},
+ {0x5604, 0x802D2721},
+ {0x5610, 0x00201020},
+ {0x5618, 0x00801008},
+ {0x5624, 0x0808081E},
+ {0x562C, 0x0000081D},
+ {0x5634, 0x3D2EE000},
+ {0x5638, 0x0001AC42},
+ {0x5640, 0x3D6EF000},
+ {0x5644, 0x0001AC3E},
+ {0x566C, 0x00210005},
+ {0x5680, 0x20500010},
+ {0x5684, 0x00020001},
+ {0x56A0, 0x0034C000},
+ {0x56BC, 0x04000000},
+ {0x56C0, 0x00000688},
+ {0x56C4, 0x00000010},
+ {0x56C8, 0x0E800400},
+ {0x56CC, 0x01E400FF},
+ {0x5800, 0x003F807F},
+ {0x5810, 0x59008400},
+ {0x5814, 0x201AF000},
+ {0x5818, 0x182C18E8},
+ {0x581C, 0x3DD80280},
+ {0x5820, 0x80000080},
+ {0x5828, 0x023F8121},
+ {0x5830, 0x023F8121},
+ {0x5838, 0x003F8121},
+ {0x5840, 0x023F8121},
+ {0x5848, 0x023F8121},
+ {0x5850, 0x023F8121},
+ {0x5858, 0x003F7121},
+ {0x5860, 0x023F7121},
+ {0x5864, 0x1A1801FF},
+ {0x5868, 0xA9A90002},
+ {0x5880, 0x77777777},
+ {0x5884, 0x77777777},
+ {0x5894, 0x01080604},
+ {0x5898, 0x00000000},
+ {0x589C, 0x00000000},
+ {0x58A0, 0x000000FE},
+ {0x58B0, 0x00000800},
+ {0x58BC, 0x07A7807F},
+ {0x58C0, 0x007E0000},
+ {0x58C4, 0x0003FFFF},
+ {0x58D4, 0x7401FE00},
+ {0x58D8, 0x8008016C},
+ {0x58DC, 0xC000807F},
+ {0x58E4, 0x3000881F},
+ {0x58E8, 0x00000003},
+ {0x58F0, 0x400401FF},
+ {0x58F4, 0x80000000},
+ {0x58F8, 0xC0000000},
+ {0x58FC, 0x00000000},
+ {0x700, 0x40000030},
+ {0x704, 0x601E0502},
+ {0x704, 0x601E0500},
+ {0x704, 0x601E0502},
+ {0x20FC, 0x00000000},
+ {0x20F8, 0x00000000},
+ {0x20F0, 0x00000000},
+ {0x9C0, 0x00000001},
+ {0x9C0, 0x00000000},
+ {0x9C0, 0x00000001},
+ {0x9C0, 0x00000000},
+ {0x4AE8, 0x00000744},
+ {0x4AD4, 0x00000040},
+ {0x4AE4, 0x0079E99E},
+ {0x4BC8, 0xFBD5B89F},
+ {0x4BCC, 0x99563918},
+ {0x4BD0, 0x12EED5B8},
+ {0x4BD4, 0x6F7D542F},
+ {0x4BD8, 0x0000001D},
+ {0x300, 0xF30CE31C},
+ {0x304, 0x13EF1F19},
+ {0x308, 0x0C0CF3F3},
+ {0x30C, 0x0CE30C0C},
+ {0x310, 0x80496000},
+ {0x314, 0x0041E000},
+ {0x318, 0x20022042},
+ {0x31C, 0x20448009},
+ {0x320, 0x00010031},
+ {0x324, 0xE000E000},
+ {0x328, 0xE000E000},
+ {0x32C, 0xE0008049},
+ {0x12BC, 0x10104041},
+ {0x12C0, 0x13311111},
+ {0x12E4, 0x30D52A68},
+ {0x010, 0x0005FFFF},
+ {0x028, 0x0000F381},
+ {0x02C, 0x0000F381},
+ {0x620, 0x00141230},
+ {0x70C, 0x00000020},
+ {0x720, 0x20000000},
+ {0x730, 0x00000002},
+ {0x738, 0x004100C0},
+ {0x73C, 0x00000002},
+ {0x748, 0x01000002},
+ {0x74C, 0x00000001},
+ {0xA08, 0x00007800},
+ {0xC14, 0x25010000},
+ {0xC3C, 0x2840E1BF},
+ {0xC40, 0x00000000},
+ {0xC44, 0x00000007},
+ {0xC48, 0x410E4000},
+ {0xC54, 0x1EE14368},
+ {0xC58, 0x41000000},
+ {0xC5C, 0x80558000},
+ {0xC60, 0x017FFFF2},
+ {0xC64, 0x0010A130},
+ {0xC68, 0x90000050},
+ {0xC6C, 0x10201021},
+ {0xC70, 0x071B0660},
+ {0xC74, 0x00000000},
+ {0xC78, 0x80000000},
+ {0xC7C, 0x0020BFE0},
+ {0xC88, 0xC2AC8000},
+ {0xC8C, 0x02F2FC08},
+ {0xD00, 0x77777777},
+ {0xD04, 0xBBBBBBBB},
+ {0xD08, 0xBBBBBBBB},
+ {0xD0C, 0x000B2070},
+ {0xD10, 0x20110FFF},
+ {0xD18, 0x50009800},
+ {0xD20, 0x01900000},
+ {0xD30, 0x03FF8000},
+ {0xD40, 0xF64FA0F7},
+ {0xD44, 0x0401463F},
+ {0xD48, 0x0003FF7F},
+ {0xD4C, 0x00000000},
+ {0xD50, 0xF64FA0F7},
+ {0xD54, 0x04100437},
+ {0xD58, 0x0000FF7F},
+ {0xD5C, 0x00000000},
+ {0xD60, 0x00000000},
+ {0xD64, 0x00000000},
+ {0xD70, 0x00000015},
+ {0xD78, 0x00000001},
+ {0xD7C, 0x001D050E},
+ {0xD80, 0x00000100},
+ {0xD84, 0x00006607},
+ {0xD90, 0x000003FF},
+ {0xD94, 0x00000000},
+ {0xD98, 0x0000003F},
+ {0xD9C, 0x00000000},
+ {0xDA0, 0x000003FE},
+ {0xDA4, 0x00000000},
+ {0xDA8, 0x0000003F},
+ {0xDAC, 0x00000000},
+ {0xDD4, 0x00000000},
+ {0x1010, 0x00000000},
+ {0x2000, 0x50BBBF04},
+ {0x2008, 0x000FFFFF},
+ {0x5800, 0x03FF807F},
+ {0x5804, 0x04237040},
+ {0x5808, 0x04237040},
+ {0x5818, 0x082C1800},
+ {0x624, 0x0101030A},
+ {0x241C, 0x00000001},
+ {0xC0F8, 0x00000001},
+ {0x35C, 0x000004C4},
+ {0x1200, 0x00010142},
+ {0x120C, 0x00012233},
+ {0x1210, 0x8049E304},
+ {0x12A0, 0x49107056},
+ {0x12A8, 0x33337025},
+ {0x12AC, 0x12333121},
+ {0x12B8, 0x30020000},
+ {0x0F0, 0x00000001},
+ {0x0F4, 0x00000011},
+ {0x0F8, 0x20230307},
+};
+
+static const struct rtw89_reg2_def rtw89_8851b_phy_bb_reg_gain[] = {
+ {0xF00100FF, 0x00000000},
+ {0xF00200FF, 0x00000001},
+ {0xF00300FF, 0x00000002},
+ {0xF00400FF, 0x00000003},
+ {0xF00500FF, 0x00000004},
+ {0xF00600FF, 0x00000005},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x13F6D7B6},
+ {0x001, 0x00725132},
+ {0x002, 0x00005A38},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x13F6D7B6},
+ {0x001, 0x00725132},
+ {0x002, 0x00005A38},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x13F6D7B6},
+ {0x001, 0x00725132},
+ {0x002, 0x00005A38},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x19FADCBC},
+ {0x001, 0x007A5A3A},
+ {0x002, 0x00005838},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x19FADCBC},
+ {0x001, 0x007A5A3A},
+ {0x002, 0x00005838},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x000, 0x19FADCBC},
+ {0x001, 0x007A5A3A},
+ {0x002, 0x00005838},
+ {0xA0000000, 0x00000000},
+ {0x000, 0x13F6D7B6},
+ {0x001, 0x00725132},
+ {0x002, 0x00005A38},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0xA0000000, 0x00000000},
+ {0x100, 0x1BFEE0B7},
+ {0x101, 0x006C5238},
+ {0x102, 0x00005031},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x19F8D8C1},
+ {0x10001, 0x006F4F31},
+ {0x10002, 0x00006F58},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x19F8D8C1},
+ {0x10001, 0x006F4F31},
+ {0x10002, 0x00006F58},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x19F8D8C1},
+ {0x10001, 0x006F4F31},
+ {0x10002, 0x00006F58},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x1DF8DAC1},
+ {0x10001, 0x00755437},
+ {0x10002, 0x00007058},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x1DF8DAC1},
+ {0x10001, 0x00755437},
+ {0x10002, 0x00007058},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10000, 0x1DF8DAC1},
+ {0x10001, 0x00755437},
+ {0x10002, 0x00007058},
+ {0xA0000000, 0x00000000},
+ {0x10000, 0x19F8D8C1},
+ {0x10001, 0x006F4F31},
+ {0x10002, 0x00006F58},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0xA0000000, 0x00000000},
+ {0x10100, 0x09E9C69F},
+ {0x10101, 0x00674627},
+ {0x10102, 0x00006750},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1AF0D2B8},
+ {0x20001, 0x00755334},
+ {0x20002, 0x00006F58},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1AF0D2B8},
+ {0x20001, 0x00755334},
+ {0x20002, 0x00006F58},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1AF0D2B8},
+ {0x20001, 0x00755334},
+ {0x20002, 0x00006F58},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1D00E2C8},
+ {0x20001, 0x00775336},
+ {0x20002, 0x00006D58},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1D00E2C8},
+ {0x20001, 0x00775336},
+ {0x20002, 0x00006D58},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20000, 0x1D00E2C8},
+ {0x20001, 0x00775336},
+ {0x20002, 0x00006D58},
+ {0xA0000000, 0x00000000},
+ {0x20000, 0x1AF0D2B8},
+ {0x20001, 0x00755334},
+ {0x20002, 0x00006F58},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0xA0000000, 0x00000000},
+ {0x20100, 0x07E9C6A0},
+ {0x20101, 0x00674728},
+ {0x20102, 0x00006850},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x15EED2B6},
+ {0x30001, 0x006F4D2F},
+ {0x30002, 0x00006F58},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x15EED2B6},
+ {0x30001, 0x006F4D2F},
+ {0x30002, 0x00006F58},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x15EED2B6},
+ {0x30001, 0x006F4D2F},
+ {0x30002, 0x00006F58},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x1F00E2C6},
+ {0x30001, 0x00795739},
+ {0x30002, 0x00006F58},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x1F00E2C6},
+ {0x30001, 0x00795739},
+ {0x30002, 0x00006F58},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30000, 0x1F00E2C6},
+ {0x30001, 0x00795739},
+ {0x30002, 0x00006F58},
+ {0xA0000000, 0x00000000},
+ {0x30000, 0x15EED2B6},
+ {0x30001, 0x006F4D2F},
+ {0x30002, 0x00006F58},
+ {0xB0000000, 0x00000000},
+ {0x800100ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0x900200ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0x900300ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0x900400ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0x900500ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0x900600ff, 0x00000000}, {0x40000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0xA0000000, 0x00000000},
+ {0x30100, 0x06E9C69F},
+ {0x30101, 0x00654527},
+ {0x30102, 0x00006750},
+ {0xB0000000, 0x00000000},
+ {0x1000000, 0x000000F4},
+ {0x1000010, 0x000000F8},
+ {0x1000011, 0x0000F8F8},
+ {0x1000100, 0x000000F8},
+ {0x1000110, 0x00000000},
+ {0x1000111, 0x00000000},
+ {0x1010000, 0x000000F4},
+ {0x1010010, 0x000000F8},
+ {0x1010011, 0x0000F8F8},
+ {0x1010020, 0x000000F8},
+ {0x1010021, 0x0808E8E8},
+ {0x1010029, 0x0000F8F8},
+ {0x1010100, 0x000000F4},
+ {0x1010110, 0x000000F8},
+ {0x1010111, 0x0000F8F8},
+ {0x1010120, 0x000000F8},
+ {0x1010121, 0x0808E8E8},
+ {0x1010129, 0x0000F8F8},
+ {0x1020000, 0x000000F4},
+ {0x1020010, 0x000000F8},
+ {0x1020011, 0x0000F8F8},
+ {0x1020020, 0x000000F8},
+ {0x1020021, 0x0808E8E8},
+ {0x1020029, 0x0000F8F8},
+ {0x1020100, 0x000000F4},
+ {0x1020110, 0x000000F8},
+ {0x1020111, 0x0000F8F8},
+ {0x1020120, 0x000000F8},
+ {0x1020121, 0x0808E8E8},
+ {0x1020129, 0x0000F8F8},
+ {0x1030000, 0x000000F4},
+ {0x1030010, 0x000000F8},
+ {0x1030011, 0x0000F8F8},
+ {0x1030020, 0x000000F8},
+ {0x1030021, 0x0808E8E8},
+ {0x1030029, 0x0000F8F8},
+ {0x1030100, 0x000000F4},
+ {0x1030110, 0x000000F8},
+ {0x1030111, 0x0000F8F8},
+ {0x1030120, 0x000000F8},
+ {0x1030121, 0x0808E8E8},
+ {0x1030129, 0x0000F8F8},
+};
+
+static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
+ {0xF0010000, 0x00000000},
+ {0xF0020000, 0x00000001},
+ {0xF0030000, 0x00000002},
+ {0x000, 0x00030000},
+ {0x018, 0x00013124},
+ {0x0EF, 0x00080000},
+ {0x033, 0x00000008},
+ {0x03E, 0x00000110},
+ {0x03F, 0x0000D39C},
+ {0x033, 0x0000000C},
+ {0x03E, 0x00000110},
+ {0x03F, 0x0000F79E},
+ {0x0EF, 0x00000000},
+ {0x01B, 0x00003A40},
+ {0x08F, 0x000C170E},
+ {0x08E, 0x00005160},
+ {0x002, 0x00000600},
+ {0x0EE, 0x00000002},
+ {0x033, 0x00000002},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000003},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000004},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000005},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000006},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000007},
+ {0x03F, 0x0000003F},
+ {0x033, 0x00000008},
+ {0x03F, 0x0000003F},
+ {0x033, 0x0000000C},
+ {0x03F, 0x0000003F},
+ {0x033, 0x0000000D},
+ {0x03F, 0x0000003F},
+ {0x033, 0x0000000E},
+ {0x03F, 0x0000003F},
+ {0x0EE, 0x00000000},
+ {0x0EF, 0x00004000},
+ {0x033, 0x00000007},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00000707},
+ {0x033, 0x00000006},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00000704},
+ {0x033, 0x00000005},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00020500},
+ {0x033, 0x00000004},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00010404},
+ {0x033, 0x00000003},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00099B04},
+ {0x033, 0x00000002},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00092B04},
+ {0x033, 0x00000001},
+ {0x03E, 0x00000000},
+ {0x03F, 0x000B3204},
+ {0x033, 0x00000000},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00003000},
+ {0x033, 0x00000017},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00000787},
+ {0x033, 0x00000016},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00000784},
+ {0x033, 0x00000015},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00020580},
+ {0x033, 0x00000014},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00010484},
+ {0x033, 0x00000013},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00099B84},
+ {0x033, 0x00000012},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00092B84},
+ {0x033, 0x00000011},
+ {0x03E, 0x00000000},
+ {0x03F, 0x000B3284},
+ {0x033, 0x00000010},
+ {0x03E, 0x00000000},
+ {0x03F, 0x00003080},
+ {0x0EF, 0x00000000},
+ {0x0EE, 0x00000010},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000003},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000003},
+ {0x0EE, 0x00000000},
+ {0x0EF, 0x00001000},
+ {0x033, 0x00000000},
+ {0x03F, 0x00000034},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000037},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000034},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000024},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000037},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000027},
+ {0x0EF, 0x00000000},
+ {0x0EC, 0x00000400},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000022},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000022},
+ {0x033, 0x00000009},
+ {0x03F, 0x00000022},
+ {0x0EC, 0x00000000},
+ {0x0EC, 0x00000004},
+ {0x033, 0x00000000},
+ {0x03F, 0x000000AE},
+ {0x033, 0x00000001},
+ {0x03F, 0x0000008C},
+ {0x033, 0x00000002},
+ {0x03F, 0x0000006A},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000048},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000026},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000004},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000002},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000000},
+ {0x0EC, 0x00000000},
+ {0x0EF, 0x00008000},
+ {0x033, 0x00000007},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000006},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000005},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x00000004},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x00000003},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001BB0},
+ {0x033, 0x00000002},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001AB0},
+ {0x033, 0x00000001},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D9BC},
+ {0x033, 0x00000000},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D4BC},
+ {0x033, 0x00000017},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000016},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000015},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x00000014},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x00000013},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001BB0},
+ {0x033, 0x00000012},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001AB0},
+ {0x033, 0x00000011},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D9BC},
+ {0x033, 0x00000010},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D4BC},
+ {0x033, 0x00000027},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000026},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x00000025},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x00000024},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x00000023},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001BB0},
+ {0x033, 0x00000022},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001AB0},
+ {0x033, 0x00000021},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D9BC},
+ {0x033, 0x00000020},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D4BC},
+ {0x033, 0x0000000E},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x0000000D},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x0000000C},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x0000000B},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00091BB0},
+ {0x033, 0x0000000A},
+ {0x03E, 0x00000003},
+ {0x03F, 0x000A9AB0},
+ {0x033, 0x00000009},
+ {0x03E, 0x00000003},
+ {0x03F, 0x000BD9BC},
+ {0x033, 0x00000008},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0009D4BC},
+ {0x033, 0x0000001E},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x0000001D},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x0000001C},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x0000001B},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00091BB0},
+ {0x033, 0x0000001A},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00099AB0},
+ {0x033, 0x00000019},
+ {0x03E, 0x00000003},
+ {0x03F, 0x000AD9BC},
+ {0x033, 0x00000018},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0009D4BC},
+ {0x033, 0x0000002E},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001FB0},
+ {0x033, 0x0000002D},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001DB0},
+ {0x033, 0x0000002C},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001CB0},
+ {0x033, 0x0000002B},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00001BB0},
+ {0x033, 0x0000002A},
+ {0x03E, 0x00000003},
+ {0x03F, 0x00009AB0},
+ {0x033, 0x00000029},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0009D9BC},
+ {0x033, 0x00000028},
+ {0x03E, 0x00000003},
+ {0x03F, 0x0000D4BC},
+ {0x0EF, 0x00000000},
+ {0x0EF, 0x00002000},
+ {0x033, 0x00000000},
+ {0x03F, 0x00000005},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000004},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000004},
+ {0x033, 0x00000004},
+ {0x03F, 0x0000000C},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000003},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000003},
+ {0x0EF, 0x00000000},
+ {0x06C, 0x00038085},
+ {0x06D, 0x00000D6B},
+ {0x06E, 0x0001FB89},
+ {0x06F, 0x00097B99},
+ {0x069, 0x00008040},
+ {0x0EF, 0x00000200},
+ {0x033, 0x00000004},
+ {0x03F, 0x000008FF},
+ {0x033, 0x00000005},
+ {0x03F, 0x000004F2},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000217},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000131},
+ {0x0EF, 0x00000000},
+ {0x0EF, 0x00000400},
+ {0x033, 0x00000004},
+ {0x03F, 0x000004F7},
+ {0x033, 0x00000005},
+ {0x03F, 0x000004F7},
+ {0x033, 0x00000006},
+ {0x03F, 0x000004F2},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000117},
+ {0x0EF, 0x00000000},
+ {0x043, 0x00005000},
+ {0x036, 0x000147D0},
+ {0x0B0, 0x0008677C},
+ {0x0B1, 0x00012920},
+ {0x0BB, 0x000EF000},
+ {0x0CB, 0x000A9594},
+ {0x0CC, 0x000C36D2},
+ {0x0CD, 0x00024923},
+ {0x0CE, 0x00020180},
+ {0x0CF, 0x00000000},
+ {0x0D5, 0x0006E27A},
+ {0x0D8, 0x00000044},
+ {0x0D9, 0x00000007},
+ {0x0DD, 0x00000020},
+ {0x0E3, 0x0000002C},
+ {0x0B7, 0x0000000C},
+ {0x0E1, 0x000080C0},
+ {0x0E4, 0x00000380},
+ {0x0ED, 0x00002000},
+ {0x033, 0x00000001},
+ {0x03D, 0x000A6094},
+ {0x03E, 0x00003449},
+ {0x03F, 0x00000001},
+ {0x033, 0x00000003},
+ {0x03D, 0x000AA094},
+ {0x03E, 0x00003449},
+ {0x03F, 0x00000001},
+ {0x0ED, 0x00000000},
+ {0x0ED, 0x00000100},
+ {0x033, 0x00000000},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000001},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000002},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000003},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000004},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000005},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000007},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000008},
+ {0x03F, 0x0000007F},
+ {0x033, 0x00000009},
+ {0x03F, 0x0000007F},
+ {0x0ED, 0x00000000},
+ {0x0ED, 0x00000080},
+ {0x033, 0x00000000},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x033, 0x00000010},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x033, 0x00000030},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x033, 0x00000040},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x033, 0x00000050},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x033, 0x00000070},
+ {0x03E, 0x000007E1},
+ {0x03F, 0x0001F87F},
+ {0x0ED, 0x00000000},
+ {0x0ED, 0x00000004},
+ {0x033, 0x00000000},
+ {0x03F, 0x00008420},
+ {0x0ED, 0x00000000},
+ {0x018, 0x00011108},
+ {0x0B9, 0x00000000},
+ {0x0B9, 0x00000000},
+ {0x0B9, 0x00000200},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0FF, 0x00000000},
+ {0x0B9, 0x00000000},
+ {0x018, 0x00013124},
+ {0x05A, 0x0006808F},
+ {0x0ED, 0x00000008},
+ {0x033, 0x00000001},
+ {0x03F, 0x0000000F},
+ {0x0ED, 0x00000000},
+ {0x000, 0x00020000},
+ {0x018, 0x00010124},
+ {0x0EE, 0x00000800},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000002},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000003},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000006},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000007},
+ {0x0EE, 0x00000000},
+ {0x0EE, 0x00001000},
+ {0x033, 0x00000008},
+ {0x03F, 0x00000000},
+ {0x033, 0x00000009},
+ {0x03F, 0x00000001},
+ {0x033, 0x0000000A},
+ {0x03F, 0x00000003},
+ {0x033, 0x0000000B},
+ {0x03F, 0x00000103},
+ {0x033, 0x0000000C},
+ {0x03F, 0x00000107},
+ {0x033, 0x0000000D},
+ {0x03F, 0x00000207},
+ {0x033, 0x0000000E},
+ {0x03F, 0x00000307},
+ {0x033, 0x0000000F},
+ {0x03F, 0x00000307},
+ {0x0EE, 0x00000000},
+ {0x0EE, 0x00000200},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000000},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000001},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000002},
+ {0x033, 0x00000007},
+ {0x03F, 0x00000003},
+ {0x0EE, 0x00000000},
+ {0x011, 0x00014062},
+ {0x0EF, 0x00000010},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000DF3},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000DF3},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000A83},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000A83},
+ {0x033, 0x00000005},
+ {0x03F, 0x00000643},
+ {0x033, 0x00000006},
+ {0x03F, 0x00000643},
+ {0x0EF, 0x00000000},
+ {0x0EF, 0x00000100},
+ {0x033, 0x00000001},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000002},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000003},
+ {0x03F, 0x0001B5A9},
+ {0x033, 0x00000004},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000005},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000006},
+ {0x03F, 0x0001B589},
+ {0x033, 0x00000007},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000008},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000009},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000000A},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000000B},
+ {0x03F, 0x0001B5A9},
+ {0x033, 0x0000000C},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000000D},
+ {0x03F, 0x0001B5A9},
+ {0x033, 0x0000000E},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000000F},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000010},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000011},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000012},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000013},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000014},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000015},
+ {0x03F, 0x0001B589},
+ {0x033, 0x00000016},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000017},
+ {0x03F, 0x0001B5A9},
+ {0x033, 0x00000018},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000019},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001A},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001B},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001C},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001D},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001E},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x0000001F},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000020},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000021},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000022},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000023},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000024},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000025},
+ {0x03F, 0x0001B5A8},
+ {0x033, 0x00000022},
+ {0x03F, 0x0001B5A8},
+ {0x0EF, 0x00000000},
+ {0x0EF, 0x00000040},
+ {0x033, 0x00000001},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000002},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000003},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000004},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000005},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000006},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000007},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000008},
+ {0x03F, 0x000002C5},
+ {0x033, 0x00000009},
+ {0x03F, 0x000002C5},
+ {0x033, 0x0000000A},
+ {0x03F, 0x000002C5},
+ {0x033, 0x0000000B},
+ {0x03F, 0x000002C5},
+ {0x0EF, 0x00000000},
+ {0x059, 0x00050033},
+ {0x061, 0x0005F48A},
+ {0x062, 0x00077435},
+ {0x063, 0x000F80A2},
+ {0x065, 0x00018F22},
+ {0x067, 0x00008060},
+ {0x07E, 0x0009780B},
+ {0x0EE, 0x00000004},
+ {0x033, 0x0000000B},
+ {0x03F, 0x0000000B},
+ {0x033, 0x0000000C},
+ {0x03F, 0x00000012},
+ {0x033, 0x0000000D},
+ {0x03F, 0x00000019},
+ {0x033, 0x0000000F},
+ {0x03F, 0x0000000B},
+ {0x033, 0x00000010},
+ {0x03F, 0x00000012},
+ {0x033, 0x00000011},
+ {0x03F, 0x00000019},
+ {0x03F, 0x00000000},
+ {0x0EE, 0x00000000},
+ {0x0EE, 0x00000800},
+ {0x033, 0x00000000},
+ {0x03F, 0x00000001},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000002},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000003},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000007},
+ {0x0EE, 0x00000000},
+ {0x0EE, 0x00001000},
+ {0x033, 0x00000000},
+ {0x03F, 0x00003000},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000000},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000001},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000003},
+ {0x033, 0x00000004},
+ {0x03F, 0x00000007},
+ {0x033, 0x00000005},
+ {0x03F, 0x0000000F},
+ {0x033, 0x00000006},
+ {0x03F, 0x0000010F},
+ {0x033, 0x00000007},
+ {0x03F, 0x0000030F},
+ {0x0EE, 0x00000000},
+ {0x0EE, 0x00000200},
+ {0x033, 0x00000000},
+ {0x03F, 0x00000004},
+ {0x033, 0x00000001},
+ {0x03F, 0x00000005},
+ {0x033, 0x00000002},
+ {0x03F, 0x00000006},
+ {0x033, 0x00000003},
+ {0x03F, 0x00000007},
+ {0x0EE, 0x00000000},
+ {0x0EF, 0x00000080},
+ {0x033, 0x00000004},
+ {0x03E, 0x0000001D},
+ {0x03F, 0x0001A241},
+ {0x033, 0x00000005},
+ {0x03E, 0x0000001D},
+ {0x03F, 0x0001A241},
+ {0x033, 0x00000006},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000007},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000008},
+ {0x03E, 0x0000001D},
+ {0x03F, 0x0001A241},
+ {0x033, 0x00000009},
+ {0x03E, 0x0001A241},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000000A},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000000B},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000000C},
+ {0x03E, 0x0000001D},
+ {0x03F, 0x0001A241},
+ {0x033, 0x0000000D},
+ {0x03E, 0x0000001D},
+ {0x03F, 0x0001A241},
+ {0x033, 0x0000000E},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000000F},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000010},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000011},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000012},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000013},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000014},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000015},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000016},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000017},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000018},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000019},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x0000001A},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000001B},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000001C},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x0000001D},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x0000001E},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000001F},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000020},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000021},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x000199C1},
+ {0x033, 0x00000022},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000023},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000024},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000025},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000026},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000027},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000028},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000029},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x0000002A},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000002B},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000002C},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x0000002D},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x0000002E},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000002F},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000030},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000031},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000032},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000033},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000034},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000035},
+ {0x03E, 0x0000001C},
+ {0x03F, 0x0001E141},
+ {0x033, 0x00000036},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000037},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000038},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x00000039},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C1},
+ {0x033, 0x0000003A},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x033, 0x0000003B},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x033, 0x0000003C},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x033, 0x0000003D},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x033, 0x0000003E},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x033, 0x0000003F},
+ {0x03E, 0x0000001B},
+ {0x03F, 0x0001C3C3},
+ {0x0EF, 0x00000000},
+ {0x051, 0x0003D368},
+ {0x052, 0x000A3338},
+ {0x053, 0x000688AF},
+ {0x054, 0x00012C04},
+ {0x058, 0x00084221},
+ {0x05B, 0x000EB000},
+ {0x100EE, 0x00002000},
+ {0x10030, 0x000000F9},
+ {0x10030, 0x000004F6},
+ {0x10030, 0x000008F3},
+ {0x10030, 0x00000CF0},
+ {0x10030, 0x000010ED},
+ {0x10030, 0x000014EA},
+ {0x10030, 0x000018E7},
+ {0x10030, 0x00001CE4},
+ {0x10030, 0x000020E1},
+ {0x10030, 0x000024A4},
+ {0x10030, 0x000028A1},
+ {0x10030, 0x00002C9E},
+ {0x10030, 0x0000309B},
+ {0x10030, 0x0000341E},
+ {0x10030, 0x0000381B},
+ {0x10030, 0x00003C18},
+ {0x10030, 0x00004015},
+ {0x10030, 0x000200BC},
+ {0x10030, 0x000204B9},
+ {0x10030, 0x000208B6},
+ {0x10030, 0x00020CB3},
+ {0x10030, 0x000210B0},
+ {0x10030, 0x000214AD},
+ {0x10030, 0x0002186C},
+ {0x10030, 0x00021C69},
+ {0x10030, 0x00022066},
+ {0x10030, 0x00022426},
+ {0x10030, 0x00022823},
+ {0x10030, 0x00022C20},
+ {0x10030, 0x0002301D},
+ {0x10030, 0x0002341A},
+ {0x10030, 0x00023817},
+ {0x10030, 0x00023C14},
+ {0x10030, 0x00024011},
+ {0x10030, 0x000280BC},
+ {0x10030, 0x000284B9},
+ {0x10030, 0x000288B6},
+ {0x10030, 0x00028CB3},
+ {0x10030, 0x000290B0},
+ {0x10030, 0x000294AD},
+ {0x10030, 0x0002986C},
+ {0x10030, 0x00029C69},
+ {0x10030, 0x0002A066},
+ {0x10030, 0x0002A426},
+ {0x10030, 0x0002A823},
+ {0x10030, 0x0002AC20},
+ {0x10030, 0x0002B01D},
+ {0x10030, 0x0002B41A},
+ {0x10030, 0x0002B817},
+ {0x10030, 0x0002BC14},
+ {0x10030, 0x0002C011},
+ {0x10030, 0x000300BC},
+ {0x10030, 0x000304B9},
+ {0x10030, 0x000308B6},
+ {0x10030, 0x00030CB3},
+ {0x10030, 0x000310B0},
+ {0x10030, 0x000314AD},
+ {0x10030, 0x0003186C},
+ {0x10030, 0x00031C69},
+ {0x10030, 0x00032066},
+ {0x10030, 0x00032426},
+ {0x10030, 0x00032823},
+ {0x10030, 0x00032C20},
+ {0x10030, 0x0003301D},
+ {0x10030, 0x0003341A},
+ {0x10030, 0x00033817},
+ {0x10030, 0x00033C14},
+ {0x10030, 0x00034011},
+ {0x100EE, 0x00000000},
+ {0x100EE, 0x00004000},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DDD},
+ {0x10030, 0x000211D7},
+ {0x10030, 0x000215D1},
+ {0x10030, 0x00021919},
+ {0x10030, 0x00021D13},
+ {0x10030, 0x000220D9},
+ {0x10030, 0x000224D3},
+ {0x10030, 0x00022899},
+ {0x10030, 0x00022C93},
+ {0x10030, 0x00023059},
+ {0x10030, 0x00023453},
+ {0x10030, 0x00023819},
+ {0x10030, 0x00023C13},
+ {0x10030, 0x0002400D},
+ {0x10030, 0x00024407},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E9},
+ {0x10030, 0x000289E3},
+ {0x10030, 0x00028DDD},
+ {0x10030, 0x000291D7},
+ {0x10030, 0x000295D1},
+ {0x10030, 0x00029919},
+ {0x10030, 0x00029D13},
+ {0x10030, 0x0002A0D9},
+ {0x10030, 0x0002A4D3},
+ {0x10030, 0x0002A899},
+ {0x10030, 0x0002AC93},
+ {0x10030, 0x0002B059},
+ {0x10030, 0x0002B453},
+ {0x10030, 0x0002B819},
+ {0x10030, 0x0002BC13},
+ {0x10030, 0x0002C00D},
+ {0x10030, 0x0002C407},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E9},
+ {0x10030, 0x000309E3},
+ {0x10030, 0x00030DDD},
+ {0x10030, 0x000311D7},
+ {0x10030, 0x000315D1},
+ {0x10030, 0x00031919},
+ {0x10030, 0x00031D13},
+ {0x10030, 0x000320D9},
+ {0x10030, 0x000324D3},
+ {0x10030, 0x00032899},
+ {0x10030, 0x00032C93},
+ {0x10030, 0x00033059},
+ {0x10030, 0x00033453},
+ {0x10030, 0x00033819},
+ {0x10030, 0x00033C13},
+ {0x10030, 0x0003400D},
+ {0x10030, 0x00034407},
+ {0x100EE, 0x00000000},
+ {0x100EE, 0x00004000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011A5},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001965},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002125},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x000028E5},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030A5},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003865},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004025},
+ {0x10030, 0x0000441F},
+ {0x100EE, 0x00000000},
+ {0x0EF, 0x00000008},
+ {0x033, 0x00000000},
+ {0x03F, 0x00000004},
+ {0x0EF, 0x00000000},
+ {0x005, 0x00000001},
+ {0x10005, 0x00000001},
+ {0x0FE, 0x00000022},
+};
+
+static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = {
+ {0x8000, 0x00000008},
+ {0x8008, 0x00000000},
+ {0x8004, 0xe8862b66},
+ {0x800c, 0x78000000},
+ {0x8010, 0x88015000},
+ {0x8014, 0x80010100},
+ {0x8018, 0x10010100},
+ {0x801c, 0xa210bc00},
+ {0x8020, 0x000403e0},
+ {0x8024, 0x00072160},
+ {0x8028, 0x00180e00},
+ {0x8030, 0x400000c0},
+ {0x8034, 0x11000830},
+ {0x8038, 0x40000000},
+ {0x803c, 0x00000008},
+ {0x8040, 0x00000046},
+ {0x8044, 0x0010001f},
+ {0x8048, 0x00000003},
+ {0x804c, 0x420840e0},
+ {0x8050, 0xce08cce0},
+ {0x8054, 0x420840e0},
+ {0x8058, 0xce08cce0},
+ {0x805c, 0x150c0b02},
+ {0x8060, 0x150c0b02},
+ {0x8064, 0x2aa00047},
+ {0x8074, 0x80000000},
+ {0x807c, 0x000000ee},
+ {0x8088, 0x80000000},
+ {0x808c, 0x00000000},
+ {0x80b0, 0x00000000},
+ {0x80cc, 0x00000000},
+ {0x80d0, 0x00000000},
+ {0x80ec, 0x00000002},
+ {0x8098, 0x0000ff00},
+ {0x8070, 0x00e80000},
+ {0x80b0, 0xffe00fff},
+ {0x809c, 0x0000001f},
+ {0x80b8, 0x00002000},
+ {0x80bc, 0x00050033},
+ {0xa400, 0x00000000},
+ {0xa404, 0x00000180},
+ {0xa408, 0x000001af},
+ {0xa40c, 0x000001e3},
+ {0xa410, 0x00000220},
+ {0xa414, 0x00000262},
+ {0xa418, 0x000002ac},
+ {0xa41c, 0x0000035e},
+ {0xa420, 0x000003c7},
+ {0xa424, 0x0000043d},
+ {0xa428, 0x000004c1},
+ {0xa42c, 0x00000556},
+ {0xa430, 0x000005fc},
+ {0xa434, 0x000006b7},
+ {0xa438, 0x00000789},
+ {0xa43c, 0x00000875},
+ {0xa440, 0x0000011f},
+ {0x8104, 0x00000000},
+ {0x810c, 0x00000000},
+ {0x8110, 0x00000000},
+ {0x8114, 0x00000000},
+ {0x8120, 0x10010000},
+ {0x8124, 0x00000000},
+ {0x8128, 0x00000200},
+ {0x812c, 0x0000c000},
+ {0x8130, 0x40000000},
+ {0x8138, 0x40000000},
+ {0x813c, 0x40000000},
+ {0x8140, 0x00000000},
+ {0x8144, 0x0b040b03},
+ {0x8148, 0x07020b04},
+ {0x814c, 0x07020b04},
+ {0x8150, 0xe4e40000},
+ {0x8158, 0xffffffff},
+ {0x815c, 0xffffffff},
+ {0x8160, 0xffffffff},
+ {0x8164, 0xffffffff},
+ {0x8168, 0xffffffff},
+ {0x816c, 0x1fffffff},
+ {0x81cc, 0x00000000},
+ {0x81dc, 0x00000002},
+ {0x81e0, 0x00000000},
+ {0x81e4, 0x00000001},
+ {0x81a0, 0x00000000},
+ {0x81ac, 0x3fc20400},
+ {0x81b0, 0x3f914100},
+ {0x81bc, 0x0000005b},
+ {0x81c0, 0x0000005b},
+ {0x81b4, 0x01e0f078},
+ {0x81b8, 0x01e0f078},
+ {0x81f0, 0x0000f078},
+ {0x81d8, 0x00000001},
+ {0x9500, 0x00000000},
+ {0x9504, 0x00000000},
+ {0x9508, 0x00000000},
+ {0x950c, 0x00000000},
+ {0x9510, 0x00000000},
+ {0x9514, 0x00000000},
+ {0x9518, 0x00000000},
+ {0x951c, 0x00000000},
+ {0x9520, 0x00000000},
+ {0x9524, 0x00000000},
+ {0x9528, 0x00000000},
+ {0x952c, 0x00000000},
+ {0x9530, 0x00000000},
+ {0x9534, 0x00000000},
+ {0x9538, 0x00000000},
+ {0x953c, 0x00000000},
+ {0x9540, 0x04000000},
+ {0x9544, 0x00000000},
+ {0x9548, 0x00000000},
+ {0x954c, 0x00000000},
+ {0x9550, 0x00000000},
+ {0x9554, 0x00000000},
+ {0x9558, 0x00000000},
+ {0x955c, 0x00000000},
+ {0x9560, 0x00000000},
+ {0x9564, 0x00000000},
+ {0x9568, 0x00000000},
+ {0x956c, 0x00000000},
+ {0x9570, 0x00000000},
+ {0x9574, 0x00000000},
+ {0x9578, 0x00000000},
+ {0x957c, 0x00000000},
+ {0x9580, 0x00000000},
+ {0x9584, 0x04000000},
+ {0x9588, 0x00000000},
+ {0x958c, 0x00000000},
+ {0x9590, 0x00000000},
+ {0x9594, 0x00000000},
+ {0x9598, 0x00000000},
+ {0x959c, 0x00000000},
+ {0x95a0, 0x00000000},
+ {0x95a4, 0x00000000},
+ {0x95a8, 0x00000000},
+ {0x95ac, 0x00000000},
+ {0x95b0, 0x00000000},
+ {0x95b4, 0x00000000},
+ {0x95b8, 0x00000000},
+ {0x95bc, 0x00000000},
+ {0x95c0, 0x00000000},
+ {0x95c4, 0x00000000},
+ {0x95c8, 0x04000000},
+ {0x95cc, 0x00000000},
+ {0x95d0, 0x00000000},
+ {0x95d4, 0x00000000},
+ {0x95d8, 0x00000000},
+ {0x95dc, 0x00000000},
+ {0x95e0, 0x00000000},
+ {0x95e4, 0x00000000},
+ {0x95e8, 0x00000000},
+ {0x95ec, 0x00000000},
+ {0x95f0, 0x00000000},
+ {0x95f4, 0x00000000},
+ {0x95f8, 0x00000000},
+ {0x95fc, 0x00000000},
+ {0x9600, 0x00000000},
+ {0x9604, 0x00000000},
+ {0x9608, 0x00000000},
+ {0x960c, 0x04000000},
+ {0x9610, 0x00000000},
+ {0x9614, 0x00000000},
+ {0x9618, 0x00000000},
+ {0x961c, 0x00000000},
+ {0x9620, 0x00000000},
+ {0x9624, 0x00000000},
+ {0x9628, 0x00000000},
+ {0x962c, 0x00000000},
+ {0x9630, 0x00000000},
+ {0x9634, 0x00000000},
+ {0x9638, 0x00000000},
+ {0x963c, 0x00000000},
+ {0x9640, 0x00000000},
+ {0x9644, 0x00000000},
+ {0x9648, 0x00000000},
+ {0x964c, 0x00000000},
+ {0x9650, 0x04000000},
+ {0x9654, 0x00000000},
+ {0x9658, 0x00000000},
+ {0x965c, 0x00000000},
+ {0x9660, 0x00000000},
+ {0x9664, 0x00000000},
+ {0x9668, 0x00000000},
+ {0x966c, 0x00000000},
+ {0x9670, 0x00000000},
+ {0x9674, 0x00000000},
+ {0x9678, 0x00000000},
+ {0x967c, 0x00000000},
+ {0x9680, 0x00000000},
+ {0x9684, 0x00000000},
+ {0x9688, 0x00000000},
+ {0x968c, 0x00000000},
+ {0x9690, 0x00000000},
+ {0x9694, 0x04000000},
+ {0x9698, 0x00000000},
+ {0x969c, 0x00000000},
+ {0x96a0, 0x00000000},
+ {0x96a4, 0x00000000},
+ {0x96a8, 0x00000000},
+ {0x96ac, 0x00000000},
+ {0x96b0, 0x00000000},
+ {0x96b4, 0x00000000},
+ {0x96b8, 0x00000000},
+ {0x96bc, 0x00000000},
+ {0x96c0, 0x00000000},
+ {0x96c4, 0x00000000},
+ {0x96c8, 0x00000000},
+ {0x96cc, 0x00000000},
+ {0x96d0, 0x00000000},
+ {0x96d4, 0x00000000},
+ {0x96d8, 0x04000000},
+ {0x96dc, 0x00000000},
+ {0x96e0, 0x00000000},
+ {0x96e4, 0x00000000},
+ {0x96e8, 0x00000000},
+ {0x96ec, 0x00000000},
+ {0x96f0, 0x00000000},
+ {0x96f4, 0x00000000},
+ {0x96f8, 0x00000000},
+ {0x96fc, 0x00000000},
+ {0x9700, 0x00000000},
+ {0x9704, 0x00000000},
+ {0x9708, 0x00000000},
+ {0x970c, 0x00000000},
+ {0x9710, 0x00000000},
+ {0x9714, 0x00000000},
+ {0x9718, 0x00000000},
+ {0x971c, 0x04000000},
+ {0x9720, 0x00000000},
+ {0x9724, 0x00000000},
+ {0x9728, 0x00000000},
+ {0x972c, 0x00000000},
+ {0x9730, 0x00000000},
+ {0x9734, 0x00000000},
+ {0x9738, 0x00000000},
+ {0x973c, 0x00000000},
+ {0x9740, 0x00000000},
+ {0x9744, 0x00000000},
+ {0x9748, 0x00000000},
+ {0x974c, 0x00000000},
+ {0x9750, 0x00000000},
+ {0x9754, 0x00000000},
+ {0x9758, 0x00000000},
+ {0x975c, 0x00000000},
+ {0x9760, 0x04000000},
+ {0x9764, 0x00000000},
+ {0x9768, 0x00000000},
+ {0x976c, 0x00000000},
+ {0x9770, 0x00000000},
+ {0x9774, 0x00000000},
+ {0x9778, 0x00000000},
+ {0x977c, 0x00000000},
+ {0x9780, 0x00000000},
+ {0x9784, 0x00000000},
+ {0x9788, 0x00000000},
+ {0x978c, 0x00000000},
+ {0x9790, 0x00000000},
+ {0x9794, 0x00000000},
+ {0x9798, 0x00000000},
+ {0x979c, 0x00000000},
+ {0x97a0, 0x00000000},
+ {0x97a4, 0x04000000},
+ {0x97a8, 0x00000000},
+ {0x97ac, 0x00000000},
+ {0x97b0, 0x00000000},
+ {0x97b4, 0x00000000},
+ {0x97b8, 0x00000000},
+ {0x97bc, 0x00000000},
+ {0x97c0, 0x00000000},
+ {0x97c4, 0x00000000},
+ {0x97c8, 0x00000000},
+ {0x97cc, 0x00000000},
+ {0x97d0, 0x00000000},
+ {0x97d4, 0x00000000},
+ {0x97d8, 0x00000000},
+ {0x97dc, 0x00000000},
+ {0x97e0, 0x00000000},
+ {0x97e4, 0x00000000},
+ {0x97e8, 0x04000000},
+ {0x97ec, 0x00000000},
+ {0x97f0, 0x00000000},
+ {0x97f4, 0x00000000},
+ {0x97f8, 0x00000000},
+ {0x97fc, 0x00000000},
+ {0x9800, 0x00000000},
+ {0x9804, 0x00000000},
+ {0x9808, 0x00000000},
+ {0x980c, 0x00000000},
+ {0x9810, 0x00000000},
+ {0x9814, 0x00000000},
+ {0x9818, 0x00000000},
+ {0x981c, 0x00000000},
+ {0x9820, 0x00000000},
+ {0x9824, 0x00000000},
+ {0x9828, 0x00000000},
+ {0x982c, 0x04000000},
+ {0x81d8, 0x00000000},
+ {0xb104, 0x2b251f19},
+ {0xb108, 0x433d3731},
+ {0xb10c, 0x5b554f49},
+ {0xb110, 0x736d6761},
+ {0xb114, 0x7f7f7f79},
+ {0xb118, 0x120f7f7f},
+ {0xb11c, 0x1e1b1815},
+ {0xb120, 0x2a272421},
+ {0xb124, 0x3633302d},
+ {0xb128, 0x3f3f3c39},
+ {0xb12c, 0x3f3f3f3f},
+ {0x8088, 0x00000110},
+ {0x8000, 0x00000008},
+ {0x8080, 0x00000005},
+ {0x8500, 0x80000008},
+ {0x8504, 0x43000004},
+ {0x8508, 0x4b044a00},
+ {0x850c, 0x40098604},
+ {0x8510, 0x0004e01f},
+ {0x8514, 0x74104b00},
+ {0x8518, 0x000021e0},
+ {0x851c, 0x74301658},
+ {0x8520, 0x43800004},
+ {0x8524, 0x4c000007},
+ {0x8528, 0x43000004},
+ {0x852c, 0x56030007},
+ {0x8530, 0x57000004},
+ {0x8534, 0x400042fe},
+ {0x8538, 0x50554200},
+ {0x853c, 0xb4183000},
+ {0x8540, 0xe537a50f},
+ {0x8544, 0xf12bf02b},
+ {0x8548, 0xf32bf22b},
+ {0x854c, 0xf62bf42b},
+ {0x8550, 0xf82bf72b},
+ {0x8554, 0xfa2bf92b},
+ {0x8558, 0xfd2bfc2b},
+ {0x855c, 0xe537fe2b},
+ {0x8560, 0xf12af02a},
+ {0x8564, 0xf32af22a},
+ {0x8568, 0xf52af42a},
+ {0x856c, 0x000bf62a},
+ {0x8570, 0xf028a511},
+ {0x8574, 0xf228f128},
+ {0x8578, 0xf428f328},
+ {0x857c, 0xf628f528},
+ {0x8580, 0xf828f728},
+ {0x8584, 0xfa28f928},
+ {0x8588, 0xfc28fb28},
+ {0x858c, 0xfe28fd28},
+ {0x8590, 0xf028ff28},
+ {0x8594, 0xf228f128},
+ {0x8598, 0x30750001},
+ {0x859c, 0x30753075},
+ {0x85a0, 0x30b63097},
+ {0x85a4, 0x30be30bb},
+ {0x85a8, 0x30d930cc},
+ {0x85ac, 0x316d30e6},
+ {0x85b0, 0x3189317f},
+ {0x85b4, 0x31d23193},
+ {0x85b8, 0x31e43210},
+ {0x85bc, 0x31e831dd},
+ {0x85c0, 0x322831e1},
+ {0x85c4, 0x323c3232},
+ {0x85c8, 0x32503246},
+ {0x85cc, 0x3264325a},
+ {0x85d0, 0x3278326e},
+ {0x85d4, 0x32983285},
+ {0x85d8, 0x32aa32a6},
+ {0x85dc, 0x330b32f3},
+ {0x85e0, 0x333f330c},
+ {0x85e4, 0x334c3341},
+ {0x85e8, 0xe35e0001},
+ {0x85ec, 0x20887410},
+ {0x85f0, 0x140f0200},
+ {0x85f4, 0x02002098},
+ {0x85f8, 0x7430140f},
+ {0x85fc, 0x5b10e39c},
+ {0x8600, 0x20807410},
+ {0x8604, 0x140f0000},
+ {0x8608, 0x56015507},
+ {0x860c, 0x7410e382},
+ {0x8610, 0x02002088},
+ {0x8614, 0x5517140f},
+ {0x8618, 0xe34ee382},
+ {0x861c, 0x468e7508},
+ {0x8620, 0xe0ace38c},
+ {0x8624, 0x5500f0e2},
+ {0x8628, 0x5501e37e},
+ {0x862c, 0x5b10f1de},
+ {0x8630, 0x20907410},
+ {0x8634, 0x140f0000},
+ {0x8638, 0xe3825507},
+ {0x863c, 0x20987410},
+ {0x8640, 0x140f0200},
+ {0x8644, 0xe3825517},
+ {0x8648, 0x46967509},
+ {0x864c, 0xe0ace38c},
+ {0x8650, 0xe37e5500},
+ {0x8654, 0x00015501},
+ {0x8658, 0x4d000007},
+ {0x865c, 0x74200004},
+ {0x8660, 0x57005710},
+ {0x8664, 0x9700140f},
+ {0x8668, 0x00017430},
+ {0x866c, 0xe39ce35e},
+ {0x8670, 0xe52a0bbd},
+ {0x8674, 0xe36a0001},
+ {0x8678, 0x0001e3c4},
+ {0x867c, 0x55005b30},
+ {0x8680, 0x46500005},
+ {0x8684, 0x74000004},
+ {0x8688, 0x1658e37e},
+ {0x868c, 0x74305501},
+ {0x8690, 0x46100005},
+ {0x8694, 0x00010004},
+ {0x8698, 0x30f8e35e},
+ {0x869c, 0xe52a0023},
+ {0x86a0, 0x54ed0002},
+ {0x86a4, 0x00230baa},
+ {0x86a8, 0x0002e52a},
+ {0x86ac, 0xe356e3e4},
+ {0x86b0, 0xe35e0001},
+ {0x86b4, 0x002230f3},
+ {0x86b8, 0x0002e52a},
+ {0x86bc, 0x0baa54ec},
+ {0x86c0, 0xe52a0022},
+ {0x86c4, 0xe3e40002},
+ {0x86c8, 0x0001e356},
+ {0x86cc, 0x0baae35e},
+ {0x86d0, 0xe3e430ec},
+ {0x86d4, 0x0001e356},
+ {0x86d8, 0x6d0f6c67},
+ {0x86dc, 0xe52ae39c},
+ {0x86e0, 0xe39c6c8b},
+ {0x86e4, 0x0bace52a},
+ {0x86e8, 0x6d0f6cb3},
+ {0x86ec, 0xe52ae39c},
+ {0x86f0, 0x6cdb0bad},
+ {0x86f4, 0xe39c6d0f},
+ {0x86f8, 0x6cf5e52a},
+ {0x86fc, 0xe39c6d0f},
+ {0x8700, 0x6c0be52a},
+ {0x8704, 0xe39c6d00},
+ {0x8708, 0x6c25e52a},
+ {0x870c, 0xe52ae39c},
+ {0x8710, 0x6c4df8c6},
+ {0x8714, 0xe52ae39c},
+ {0x8718, 0x6c75f9cf},
+ {0x871c, 0xe52ae39c},
+ {0x8720, 0xe39c6c99},
+ {0x8724, 0xfad6e52a},
+ {0x8728, 0x21e87410},
+ {0x872c, 0x6e670009},
+ {0x8730, 0xe3c46f0f},
+ {0x8734, 0x7410e52f},
+ {0x8738, 0x000b21e8},
+ {0x873c, 0xe3c46e8b},
+ {0x8740, 0x7410e52f},
+ {0x8744, 0x000d21e8},
+ {0x8748, 0x6f0f6eb3},
+ {0x874c, 0xe52fe3c4},
+ {0x8750, 0xfe07ff08},
+ {0x8754, 0x21e87410},
+ {0x8758, 0x6ec7000e},
+ {0x875c, 0xe52fe3c4},
+ {0x8760, 0x21e87410},
+ {0x8764, 0x6edb000f},
+ {0x8768, 0xe3c46f0f},
+ {0x876c, 0x7410e52f},
+ {0x8770, 0x001021e8},
+ {0x8774, 0xe3c46eef},
+ {0x8778, 0xff03e52f},
+ {0x877c, 0xe52ffe02},
+ {0x8780, 0x21e87410},
+ {0x8784, 0x6e110013},
+ {0x8788, 0xe3c46f00},
+ {0x878c, 0xff03e52f},
+ {0x8790, 0xe52ffe02},
+ {0x8794, 0x21e87410},
+ {0x8798, 0x6e250014},
+ {0x879c, 0xe52fe3c4},
+ {0x87a0, 0xff08fc24},
+ {0x87a4, 0x7410fe07},
+ {0x87a8, 0x001521e8},
+ {0x87ac, 0xe3c46e39},
+ {0x87b0, 0x7410e52f},
+ {0x87b4, 0x001621e8},
+ {0x87b8, 0xe3c46e4d},
+ {0x87bc, 0xfd27e52f},
+ {0x87c0, 0x21e87410},
+ {0x87c4, 0x6e750018},
+ {0x87c8, 0xe52fe3c4},
+ {0x87cc, 0x21e87410},
+ {0x87d0, 0x6e99001a},
+ {0x87d4, 0xe52fe3c4},
+ {0x87d8, 0xe36afe24},
+ {0x87dc, 0x63404380},
+ {0x87e0, 0x43006880},
+ {0x87e4, 0x31300bac},
+ {0x87e8, 0xe52f0022},
+ {0x87ec, 0x54ec0002},
+ {0x87f0, 0x00220baa},
+ {0x87f4, 0x0002e52f},
+ {0x87f8, 0xe362e3e4},
+ {0x87fc, 0xe36a0001},
+ {0x8800, 0x63404380},
+ {0x8804, 0x43006881},
+ {0x8808, 0x31210baa},
+ {0x880c, 0xe362e3e4},
+ {0x8810, 0xe36a0001},
+ {0x8814, 0x63414380},
+ {0x8818, 0x43006882},
+ {0x881c, 0x31140baa},
+ {0x8820, 0xe362e3e4},
+ {0x8824, 0x00040001},
+ {0x8828, 0x000742fc},
+ {0x882c, 0x00046001},
+ {0x8830, 0x00074200},
+ {0x8834, 0x62006220},
+ {0x8838, 0x55010004},
+ {0x883c, 0x66055b40},
+ {0x8840, 0x62000007},
+ {0x8844, 0xe40e6300},
+ {0x8848, 0x09000004},
+ {0x884c, 0x0b400a01},
+ {0x8850, 0x0e010d00},
+ {0x8854, 0x00040032},
+ {0x8858, 0x42fb950b},
+ {0x885c, 0x4d040007},
+ {0x8860, 0x42000004},
+ {0x8864, 0x00074380},
+ {0x8868, 0x00044d01},
+ {0x886c, 0x00074300},
+ {0x8870, 0x05a30562},
+ {0x8874, 0xe40e961f},
+ {0x8878, 0xe37e0004},
+ {0x887c, 0x06a20007},
+ {0x8880, 0xe40e07a3},
+ {0x8884, 0xe37e0004},
+ {0x8888, 0x0002e3fe},
+ {0x888c, 0x4380e406},
+ {0x8890, 0x4d000007},
+ {0x8894, 0x43000004},
+ {0x8898, 0x000742fe},
+ {0x889c, 0x00044d00},
+ {0x88a0, 0x00014200},
+ {0x88a4, 0x42fc0004},
+ {0x88a8, 0x60030007},
+ {0x88ac, 0x42000004},
+ {0x88b0, 0x00073199},
+ {0x88b4, 0x07a306a2},
+ {0x88b8, 0xe1eb31c5},
+ {0x88bc, 0xe1fee1f9},
+ {0x88c0, 0xe1eb0001},
+ {0x88c4, 0x0001e1fe},
+ {0x88c8, 0xe1f9e1f2},
+ {0x88cc, 0x0001e1fe},
+ {0x88d0, 0xe1fee1f2},
+ {0x88d4, 0x00040001},
+ {0x88d8, 0x000742fc},
+ {0x88dc, 0x00046003},
+ {0x88e0, 0x00014200},
+ {0x88e4, 0x42fc0004},
+ {0x88e8, 0x60010007},
+ {0x88ec, 0x42000004},
+ {0x88f0, 0x00070001},
+ {0x88f4, 0x62006220},
+ {0x88f8, 0x0001e406},
+ {0x88fc, 0x63000007},
+ {0x8900, 0x09000004},
+ {0x8904, 0x0e010a00},
+ {0x8908, 0x00070032},
+ {0x890c, 0xe40e06a2},
+ {0x8910, 0x0002e41a},
+ {0x8914, 0x000742fe},
+ {0x8918, 0x00044d00},
+ {0x891c, 0x00014200},
+ {0x8920, 0x77000005},
+ {0x8924, 0x52000007},
+ {0x8928, 0x42fe0004},
+ {0x892c, 0x60000007},
+ {0x8930, 0x42000004},
+ {0x8934, 0x60004380},
+ {0x8938, 0x62016100},
+ {0x893c, 0x68046310},
+ {0x8940, 0x41000005},
+ {0x8944, 0x00075500},
+ {0x8948, 0x00045c02},
+ {0x894c, 0x00014300},
+ {0x8950, 0x6c060005},
+ {0x8954, 0xe2aae298},
+ {0x8958, 0xe42ae285},
+ {0x895c, 0xe432e2f3},
+ {0x8960, 0x0001e30c},
+ {0x8964, 0x0005e285},
+ {0x8968, 0xe2986c06},
+ {0x896c, 0xe42ae4a9},
+ {0x8970, 0xe432e2f3},
+ {0x8974, 0x0001e30c},
+ {0x8978, 0x6c000005},
+ {0x897c, 0xe2aae298},
+ {0x8980, 0xe445e285},
+ {0x8984, 0xe44de2f3},
+ {0x8988, 0x0001e30c},
+ {0x898c, 0x0005e285},
+ {0x8990, 0xe2986c00},
+ {0x8994, 0xe445e4a9},
+ {0x8998, 0xe44de2f3},
+ {0x899c, 0x0001e30c},
+ {0x89a0, 0x6c040005},
+ {0x89a4, 0xe2aae298},
+ {0x89a8, 0xe460e285},
+ {0x89ac, 0xe468e2f3},
+ {0x89b0, 0x0001e30c},
+ {0x89b4, 0x0005e285},
+ {0x89b8, 0xe2986c04},
+ {0x89bc, 0xe460e4a9},
+ {0x89c0, 0xe468e2f3},
+ {0x89c4, 0x0001e30c},
+ {0x89c8, 0x6c020005},
+ {0x89cc, 0xe2aae298},
+ {0x89d0, 0xe47be285},
+ {0x89d4, 0xe483e2f3},
+ {0x89d8, 0x0001e30c},
+ {0x89dc, 0x0005e285},
+ {0x89e0, 0xe2986c02},
+ {0x89e4, 0xe47be4a9},
+ {0x89e8, 0xe483e2f3},
+ {0x89ec, 0x0001e30c},
+ {0x89f0, 0x43800004},
+ {0x89f4, 0x610a6008},
+ {0x89f8, 0x63ce6200},
+ {0x89fc, 0x60800006},
+ {0x8a00, 0x00047f00},
+ {0x8a04, 0xe4e04300},
+ {0x8a08, 0x00070001},
+ {0x8a0c, 0x4d015500},
+ {0x8a10, 0x74200004},
+ {0x8a14, 0x57107711},
+ {0x8a18, 0x140f5700},
+ {0x8a1c, 0x00077430},
+ {0x8a20, 0x00044d00},
+ {0x8a24, 0x00074380},
+ {0x8a28, 0x00047200},
+ {0x8a2c, 0x00014300},
+ {0x8a30, 0x74200004},
+ {0x8a34, 0x77000005},
+ {0x8a38, 0x73887e07},
+ {0x8a3c, 0x8f007380},
+ {0x8a40, 0x0004140f},
+ {0x8a44, 0x00057430},
+ {0x8a48, 0x00017300},
+ {0x8a4c, 0x0005e496},
+ {0x8a50, 0x00017300},
+ {0x8a54, 0x43800004},
+ {0x8a58, 0x0006b103},
+ {0x8a5c, 0x91037cdb},
+ {0x8a60, 0x40db0007},
+ {0x8a64, 0x43000004},
+ {0x8a68, 0x0005e496},
+ {0x8a6c, 0x00067380},
+ {0x8a70, 0x60025d01},
+ {0x8a74, 0xe4ba6200},
+ {0x8a78, 0x73000005},
+ {0x8a7c, 0x76080007},
+ {0x8a80, 0x00047578},
+ {0x8a84, 0x00074380},
+ {0x8a88, 0x5e005e01},
+ {0x8a8c, 0x0006140a},
+ {0x8a90, 0x7f006380},
+ {0x8a94, 0x00076080},
+ {0x8a98, 0x4e204c3f},
+ {0x8a9c, 0x73047280},
+ {0x8aa0, 0x140a7300},
+ {0x8aa4, 0x00044d20},
+ {0x8aa8, 0x00064300},
+ {0x8aac, 0x00077402},
+ {0x8ab0, 0x40004001},
+ {0x8ab4, 0x0006ab00},
+ {0x8ab8, 0x00077404},
+ {0x8abc, 0x40004001},
+ {0x8ac0, 0x140aab00},
+ {0x8ac4, 0x43800004},
+ {0x8ac8, 0x52800007},
+ {0x8acc, 0x140a5200},
+ {0x8ad0, 0x4d004c00},
+ {0x8ad4, 0x00064e00},
+ {0x8ad8, 0x63006080},
+ {0x8adc, 0x43000004},
+ {0x8ae0, 0x76000007},
+ {0x8ae4, 0x00040001},
+ {0x8ae8, 0xb1034380},
+ {0x8aec, 0x7cdb0006},
+ {0x8af0, 0x00079103},
+ {0x8af4, 0x000440db},
+ {0x8af8, 0xe4964300},
+ {0x8afc, 0xe4ba7e03},
+ {0x8b00, 0x43800004},
+ {0x8b04, 0x0006b103},
+ {0x8b08, 0x91037c5b},
+ {0x8b0c, 0x405b0007},
+ {0x8b10, 0x43000004},
+ {0x8b14, 0x00010001},
+ {0x8b18, 0x43800004},
+ {0x8b1c, 0x4e200007},
+ {0x8b20, 0x63800006},
+ {0x8b24, 0x5f807cdb},
+ {0x8b28, 0x43000004},
+ {0x8b2c, 0x76080007},
+ {0x8b30, 0x00057560},
+ {0x8b34, 0x00047380},
+ {0x8b38, 0x0005420e},
+ {0x8b3c, 0x14c86c01},
+ {0x8b40, 0x6c001432},
+ {0x8b44, 0x42000004},
+ {0x8b48, 0x43800004},
+ {0x8b4c, 0x5f000006},
+ {0x8b50, 0x73010007},
+ {0x8b54, 0x00047300},
+ {0x8b58, 0x0007420f},
+ {0x8b5c, 0x52005280},
+ {0x8b60, 0x0004140a},
+ {0x8b64, 0x00064200},
+ {0x8b68, 0x7c5b6300},
+ {0x8b6c, 0x4e000007},
+ {0x8b70, 0x43000004},
+ {0x8b74, 0x73000005},
+ {0x8b78, 0x76000007},
+ {0x8b7c, 0xe4c30001},
+ {0x8b80, 0x00040001},
+ {0x8b84, 0x60004380},
+ {0x8b88, 0x62016100},
+ {0x8b8c, 0x00066310},
+ {0x8b90, 0x00046000},
+ {0x8b94, 0x00014300},
+ {0x8b98, 0x0001e4e0},
+ {0x8b9c, 0x4e004f02},
+ {0x8ba0, 0x52015302},
+ {0x8ba4, 0x140f0001},
+ {0x8ba8, 0x00019700},
+ {0x8bac, 0x65014380},
+ {0x8bb0, 0x79007800},
+ {0x8bb4, 0x7b407a00},
+ {0x8bb8, 0x00014300},
+ {0x8bbc, 0x65004380},
+ {0x8bc0, 0x00014300},
+ {0x8bc4, 0x64014380},
+ {0x8bc8, 0x7d007c00},
+ {0x8bcc, 0x7f407e00},
+ {0x8bd0, 0x00014300},
+ {0x8bd4, 0x64004380},
+ {0x8bd8, 0x00014300},
+ {0x8bdc, 0x7b004380},
+ {0x8be0, 0x79007a04},
+ {0x8be4, 0x43007802},
+ {0x8be8, 0x33825509},
+ {0x8bec, 0x43800001},
+ {0x8bf0, 0x7a007b40},
+ {0x8bf4, 0x55194300},
+ {0x8bf8, 0x00013382},
+ {0x8bfc, 0x74007401},
+ {0x8c00, 0x00018e00},
+ {0x8c04, 0x52300007},
+ {0x8c08, 0x74310004},
+ {0x8c0c, 0x8e007430},
+ {0x8c10, 0x52200007},
+ {0x8c14, 0x00010004},
+ {0x8c18, 0x57005702},
+ {0x8c1c, 0x00018e00},
+ {0x8c20, 0x57425740},
+ {0x8c24, 0x8e005740},
+ {0x8c28, 0x00015700},
+ {0x8c2c, 0x561042ef},
+ {0x8c30, 0x42005600},
+ {0x8c34, 0x00018c00},
+ {0x8c38, 0xe3a75b20},
+ {0x8c3c, 0x54005480},
+ {0x8c40, 0x54005481},
+ {0x8c44, 0x54005482},
+ {0x8c48, 0xbf1ae3ac},
+ {0x8c4c, 0xe36e300b},
+ {0x8c50, 0xe390e377},
+ {0x8c54, 0x0001e523},
+ {0x8c58, 0x54c054bf},
+ {0x8c5c, 0x54c154a3},
+ {0x8c60, 0x4c1854a4},
+ {0x8c64, 0xbf091402},
+ {0x8c68, 0x54a454c2},
+ {0x8c6c, 0xbf051402},
+ {0x8c70, 0x54a354c1},
+ {0x8c74, 0xbf011402},
+ {0x8c78, 0x54dfe534},
+ {0x8c7c, 0x54bf0001},
+ {0x8c80, 0x050a54e5},
+ {0x8c84, 0x000154df},
+ {0x8c88, 0x00071657},
+ {0x8c8c, 0x00044c80},
+ {0x8c90, 0x43807430},
+ {0x8c94, 0x7e007f40},
+ {0x8c98, 0x7c027d00},
+ {0x8c9c, 0x5b404300},
+ {0x8ca0, 0x5c015501},
+ {0x8ca4, 0x5480e396},
+ {0x8ca8, 0x54815400},
+ {0x8cac, 0x54825400},
+ {0x8cb0, 0x00075400},
+ {0x8cb4, 0x00044c00},
+ {0x8cb8, 0xe3ac7410},
+ {0x8cbc, 0x300bbfe1},
+ {0x8cc0, 0x56005610},
+ {0x8cc4, 0x00018c00},
+ {0x8cc8, 0x57005704},
+ {0x8ccc, 0xa7038e00},
+ {0x8cd0, 0x33f0aff7},
+ {0x8cd4, 0xaf034019},
+ {0x8cd8, 0x33f0402b},
+ {0x8cdc, 0x33df402b},
+ {0x8ce0, 0x57005708},
+ {0x8ce4, 0x57818e00},
+ {0x8ce8, 0x8e005780},
+ {0x8cec, 0x00074380},
+ {0x8cf0, 0x5c005c01},
+ {0x8cf4, 0x00041403},
+ {0x8cf8, 0x00014300},
+ {0x8cfc, 0x0007427f},
+ {0x8d00, 0x62006280},
+ {0x8d04, 0x00049200},
+ {0x8d08, 0x00014200},
+ {0x8d0c, 0x0007427f},
+ {0x8d10, 0x63146394},
+ {0x8d14, 0x00049200},
+ {0x8d18, 0x00014200},
+ {0x8d1c, 0x42fe0004},
+ {0x8d20, 0x4d010007},
+ {0x8d24, 0x42000004},
+ {0x8d28, 0x140f7420},
+ {0x8d2c, 0x57005710},
+ {0x8d30, 0x0001141f},
+ {0x8d34, 0x42fe0004},
+ {0x8d38, 0x4d010007},
+ {0x8d3c, 0x42000004},
+ {0x8d40, 0x140f7420},
+ {0x8d44, 0x000742bf},
+ {0x8d48, 0x62006240},
+ {0x8d4c, 0x0004141f},
+ {0x8d50, 0x00014200},
+ {0x8d54, 0x5d060006},
+ {0x8d58, 0x61046003},
+ {0x8d5c, 0x00056201},
+ {0x8d60, 0x00017310},
+ {0x8d64, 0x43800004},
+ {0x8d68, 0x5e010007},
+ {0x8d6c, 0x140a5e00},
+ {0x8d70, 0x0006b103},
+ {0x8d74, 0x91037f07},
+ {0x8d78, 0x43070007},
+ {0x8d7c, 0x5c000006},
+ {0x8d80, 0x5e035d02},
+ {0x8d84, 0x43000004},
+ {0x8d88, 0x00060001},
+ {0x8d8c, 0x60005d04},
+ {0x8d90, 0x62016104},
+ {0x8d94, 0x73100005},
+ {0x8d98, 0x00040001},
+ {0x8d9c, 0x00074380},
+ {0x8da0, 0x5e005e01},
+ {0x8da4, 0xb103140a},
+ {0x8da8, 0x7fc60006},
+ {0x8dac, 0x00079103},
+ {0x8db0, 0x000643c6},
+ {0x8db4, 0x5d025c00},
+ {0x8db8, 0x00045e03},
+ {0x8dbc, 0x00014300},
+ {0x8dc0, 0x5d040006},
+ {0x8dc4, 0x61046000},
+ {0x8dc8, 0x00056201},
+ {0x8dcc, 0x00017310},
+ {0x8dd0, 0x43800004},
+ {0x8dd4, 0x5e010007},
+ {0x8dd8, 0x140a5e00},
+ {0x8ddc, 0x0006b103},
+ {0x8de0, 0x91037fc6},
+ {0x8de4, 0x43c60007},
+ {0x8de8, 0x5c000006},
+ {0x8dec, 0x5e035d02},
+ {0x8df0, 0x43000004},
+ {0x8df4, 0x00060001},
+ {0x8df8, 0x60025d00},
+ {0x8dfc, 0x62016100},
+ {0x8e00, 0x73000005},
+ {0x8e04, 0x00040001},
+ {0x8e08, 0x00074380},
+ {0x8e0c, 0x5e005e01},
+ {0x8e10, 0xb103140a},
+ {0x8e14, 0x7fc00006},
+ {0x8e18, 0x00079103},
+ {0x8e1c, 0x000643c0},
+ {0x8e20, 0x5d025c00},
+ {0x8e24, 0x00045e03},
+ {0x8e28, 0x00014300},
+ {0x8e2c, 0x7e020005},
+ {0x8e30, 0x42f70004},
+ {0x8e34, 0x6c080005},
+ {0x8e38, 0x42700004},
+ {0x8e3c, 0x73810005},
+ {0x8e40, 0x93007380},
+ {0x8e44, 0x42f70004},
+ {0x8e48, 0x6c000005},
+ {0x8e4c, 0x42000004},
+ {0x8e50, 0x00040001},
+ {0x8e54, 0x00074380},
+ {0x8e58, 0x73007304},
+ {0x8e5c, 0x72401405},
+ {0x8e60, 0x43000004},
+ {0x8e64, 0x74040006},
+ {0x8e68, 0x40010007},
+ {0x8e6c, 0xab004000},
+ {0x8e70, 0x0001140f},
+ {0x8e74, 0x140ae517},
+ {0x8e78, 0x140ae4c3},
+ {0x8e7c, 0x0001e51e},
+ {0x8e80, 0xe4c3e517},
+ {0x8e84, 0x00040001},
+ {0x8e88, 0x00047410},
+ {0x8e8c, 0x42f04380},
+ {0x8e90, 0x62080007},
+ {0x8e94, 0x24206301},
+ {0x8e98, 0x14c80000},
+ {0x8e9c, 0x00002428},
+ {0x8ea0, 0x1a4215f4},
+ {0x8ea4, 0x6300000b},
+ {0x8ea8, 0x42000004},
+ {0x8eac, 0x74304300},
+ {0x8eb0, 0x4380140f},
+ {0x8eb4, 0x73080007},
+ {0x8eb8, 0x00047300},
+ {0x8ebc, 0x00014300},
+ {0x8ec0, 0x4bf00007},
+ {0x8ec4, 0x490b4a8f},
+ {0x8ec8, 0x4a8e48f1},
+ {0x8ecc, 0x48a5490a},
+ {0x8ed0, 0x49094a8d},
+ {0x8ed4, 0x4a8c487d},
+ {0x8ed8, 0x48754908},
+ {0x8edc, 0x49074a8b},
+ {0x8ee0, 0x4a8a4889},
+ {0x8ee4, 0x48b74906},
+ {0x8ee8, 0x49054a89},
+ {0x8eec, 0x4a8848fc},
+ {0x8ef0, 0x48564905},
+ {0x8ef4, 0x49044a87},
+ {0x8ef8, 0x4a8648c1},
+ {0x8efc, 0x483d4904},
+ {0x8f00, 0x49034a85},
+ {0x8f04, 0x4a8448c7},
+ {0x8f08, 0x485e4903},
+ {0x8f0c, 0x49024a83},
+ {0x8f10, 0x4a8248ac},
+ {0x8f14, 0x48624902},
+ {0x8f18, 0x49024a81},
+ {0x8f1c, 0x4a804820},
+ {0x8f20, 0x48004900},
+ {0x8f24, 0x49014a90},
+ {0x8f28, 0x4a10481f},
+ {0x8f2c, 0x00060001},
+ {0x8f30, 0x5f005f80},
+ {0x8f34, 0x00059900},
+ {0x8f38, 0x00017300},
+ {0x8f3c, 0x63800006},
+ {0x8f40, 0x98006300},
+ {0x8f44, 0x549f0001},
+ {0x8f48, 0x5c015400},
+ {0x8f4c, 0x540054df},
+ {0x8f50, 0x00015c02},
+ {0x8f54, 0x07145c01},
+ {0x8f58, 0x5c025400},
+ {0x8f5c, 0x5c020001},
+ {0x8f60, 0x54000714},
+ {0x8f64, 0x00015c01},
+ {0x8f68, 0x4c184c98},
+ {0x8f6c, 0x00080001},
+ {0x8f70, 0x5c020004},
+ {0x8f74, 0x09017430},
+ {0x8f78, 0x0ba60c01},
+ {0x8f7c, 0x77800005},
+ {0x8f80, 0x52200007},
+ {0x8f84, 0x43800004},
+ {0x8f88, 0x610a6008},
+ {0x8f8c, 0x63c26200},
+ {0x8f90, 0x5c000007},
+ {0x8f94, 0x43000004},
+ {0x8f98, 0x00000001},
+ {0x8080, 0x00000004},
+ {0x8080, 0x00000000},
+ {0x8088, 0x00000000},
+};
+
+static const struct rtw89_txpwr_byrate_cfg rtw89_8851b_txpwr_byrate[] = {
+ { 0, 0, 0, 0, 4, 0x50505050, },
+ { 0, 0, 1, 0, 4, 0x54585858, },
+ { 0, 0, 1, 4, 4, 0x44484c50, },
+ { 0, 0, 2, 0, 4, 0x50545858, },
+ { 0, 0, 2, 4, 4, 0x4044484c, },
+ { 0, 0, 2, 8, 4, 0x3034383c, },
+ { 0, 0, 3, 0, 4, 0x50505050, },
+ { 0, 1, 2, 0, 4, 0x50545858, },
+ { 0, 1, 2, 4, 4, 0x4044484c, },
+ { 0, 1, 2, 8, 4, 0x3034383c, },
+ { 0, 1, 3, 0, 4, 0x50505050, },
+ { 0, 0, 4, 1, 4, 0x00000000, },
+ { 0, 0, 4, 0, 1, 0x00000000, },
+ { 1, 0, 1, 0, 4, 0x58585858, },
+ { 1, 0, 1, 4, 4, 0x484c5054, },
+ { 1, 0, 2, 0, 4, 0x54585858, },
+ { 1, 0, 2, 4, 4, 0x44484c50, },
+ { 1, 0, 2, 8, 4, 0x34383c40, },
+ { 1, 0, 3, 0, 4, 0x40404040, },
+ { 1, 1, 2, 0, 4, 0x54585858, },
+ { 1, 1, 2, 4, 4, 0x44484c50, },
+ { 1, 1, 2, 8, 4, 0x34383c40, },
+ { 1, 1, 3, 0, 4, 0x48484848, },
+ { 1, 0, 4, 0, 4, 0x00000000, },
+ { 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, },
+};
+
+static const s8 _txpwr_track_delta_swingidx_5ga_n[][DELTA_SWINGIDX_SIZE] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4},
+};
+
+static const s8 _txpwr_track_delta_swingidx_5ga_p[][DELTA_SWINGIDX_SIZE] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+};
+
+static const s8 _txpwr_track_delta_swingidx_2ga_n[] = {
+ 0, 0, 0, 0, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3,
+ -4, -4, -4, -4, -4, -5, -5, -5, -5, -5, -5, -6, -6, -6
+};
+
+static const s8 _txpwr_track_delta_swingidx_2ga_p[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4
+};
+
+static const s8 _txpwr_track_delta_swingidx_2g_cck_a_n[] = {
+ 0, 0, 0, 0, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3,
+ -4, -4, -4, -4, -4, -5, -5, -5, -5, -5, -5, -6, -6, -6
+};
+
+static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4
+};
+
+const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+ [RTW89_REGD_NUM] = {
+ [0][0][RTW89_ACMA] = 0,
+ [0][0][RTW89_CN] = 0,
+ [0][0][RTW89_ETSI] = 0,
+ [0][0][RTW89_FCC] = 1,
+ [0][0][RTW89_IC] = 1,
+ [0][0][RTW89_KCC] = 0,
+ [0][0][RTW89_MKK] = 0,
+ [0][0][RTW89_UK] = 0,
+ [0][1][RTW89_ACMA] = 0,
+ [0][1][RTW89_CN] = 0,
+ [0][1][RTW89_ETSI] = 0,
+ [0][1][RTW89_FCC] = 3,
+ [0][1][RTW89_IC] = 3,
+ [0][1][RTW89_KCC] = 0,
+ [0][1][RTW89_MKK] = 0,
+ [0][1][RTW89_UK] = 0,
+ [1][1][RTW89_ACMA] = 0,
+ [1][1][RTW89_CN] = 0,
+ [1][1][RTW89_ETSI] = 0,
+ [1][1][RTW89_FCC] = 3,
+ [1][1][RTW89_IC] = 3,
+ [1][1][RTW89_KCC] = 0,
+ [1][1][RTW89_MKK] = 0,
+ [1][1][RTW89_UK] = 0,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
+ [0][0][0][0][RTW89_WW][0] = 58,
+ [0][0][0][0][RTW89_WW][1] = 58,
+ [0][0][0][0][RTW89_WW][2] = 58,
+ [0][0][0][0][RTW89_WW][3] = 58,
+ [0][0][0][0][RTW89_WW][4] = 58,
+ [0][0][0][0][RTW89_WW][5] = 58,
+ [0][0][0][0][RTW89_WW][6] = 58,
+ [0][0][0][0][RTW89_WW][7] = 58,
+ [0][0][0][0][RTW89_WW][8] = 58,
+ [0][0][0][0][RTW89_WW][9] = 58,
+ [0][0][0][0][RTW89_WW][10] = 58,
+ [0][0][0][0][RTW89_WW][11] = 58,
+ [0][0][0][0][RTW89_WW][12] = 52,
+ [0][0][0][0][RTW89_WW][13] = 76,
+ [0][1][0][0][RTW89_WW][0] = 0,
+ [0][1][0][0][RTW89_WW][1] = 0,
+ [0][1][0][0][RTW89_WW][2] = 0,
+ [0][1][0][0][RTW89_WW][3] = 0,
+ [0][1][0][0][RTW89_WW][4] = 0,
+ [0][1][0][0][RTW89_WW][5] = 0,
+ [0][1][0][0][RTW89_WW][6] = 0,
+ [0][1][0][0][RTW89_WW][7] = 0,
+ [0][1][0][0][RTW89_WW][8] = 0,
+ [0][1][0][0][RTW89_WW][9] = 0,
+ [0][1][0][0][RTW89_WW][10] = 0,
+ [0][1][0][0][RTW89_WW][11] = 0,
+ [0][1][0][0][RTW89_WW][12] = 0,
+ [0][1][0][0][RTW89_WW][13] = 0,
+ [1][0][0][0][RTW89_WW][0] = 0,
+ [1][0][0][0][RTW89_WW][1] = 0,
+ [1][0][0][0][RTW89_WW][2] = 58,
+ [1][0][0][0][RTW89_WW][3] = 58,
+ [1][0][0][0][RTW89_WW][4] = 58,
+ [1][0][0][0][RTW89_WW][5] = 58,
+ [1][0][0][0][RTW89_WW][6] = 58,
+ [1][0][0][0][RTW89_WW][7] = 58,
+ [1][0][0][0][RTW89_WW][8] = 58,
+ [1][0][0][0][RTW89_WW][9] = 58,
+ [1][0][0][0][RTW89_WW][10] = 58,
+ [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] = 0,
+ [1][1][0][0][RTW89_WW][3] = 0,
+ [1][1][0][0][RTW89_WW][4] = 0,
+ [1][1][0][0][RTW89_WW][5] = 0,
+ [1][1][0][0][RTW89_WW][6] = 0,
+ [1][1][0][0][RTW89_WW][7] = 0,
+ [1][1][0][0][RTW89_WW][8] = 0,
+ [1][1][0][0][RTW89_WW][9] = 0,
+ [1][1][0][0][RTW89_WW][10] = 0,
+ [1][1][0][0][RTW89_WW][11] = 0,
+ [1][1][0][0][RTW89_WW][12] = 0,
+ [1][1][0][0][RTW89_WW][13] = 0,
+ [0][0][1][0][RTW89_WW][0] = 58,
+ [0][0][1][0][RTW89_WW][1] = 60,
+ [0][0][1][0][RTW89_WW][2] = 60,
+ [0][0][1][0][RTW89_WW][3] = 60,
+ [0][0][1][0][RTW89_WW][4] = 60,
+ [0][0][1][0][RTW89_WW][5] = 60,
+ [0][0][1][0][RTW89_WW][6] = 60,
+ [0][0][1][0][RTW89_WW][7] = 60,
+ [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] = 60,
+ [0][0][1][0][RTW89_WW][12] = 58,
+ [0][0][1][0][RTW89_WW][13] = 0,
+ [0][1][1][0][RTW89_WW][0] = 0,
+ [0][1][1][0][RTW89_WW][1] = 0,
+ [0][1][1][0][RTW89_WW][2] = 0,
+ [0][1][1][0][RTW89_WW][3] = 0,
+ [0][1][1][0][RTW89_WW][4] = 0,
+ [0][1][1][0][RTW89_WW][5] = 0,
+ [0][1][1][0][RTW89_WW][6] = 0,
+ [0][1][1][0][RTW89_WW][7] = 0,
+ [0][1][1][0][RTW89_WW][8] = 0,
+ [0][1][1][0][RTW89_WW][9] = 0,
+ [0][1][1][0][RTW89_WW][10] = 0,
+ [0][1][1][0][RTW89_WW][11] = 0,
+ [0][1][1][0][RTW89_WW][12] = 0,
+ [0][1][1][0][RTW89_WW][13] = 0,
+ [0][0][2][0][RTW89_WW][0] = 60,
+ [0][0][2][0][RTW89_WW][1] = 60,
+ [0][0][2][0][RTW89_WW][2] = 60,
+ [0][0][2][0][RTW89_WW][3] = 60,
+ [0][0][2][0][RTW89_WW][4] = 60,
+ [0][0][2][0][RTW89_WW][5] = 60,
+ [0][0][2][0][RTW89_WW][6] = 60,
+ [0][0][2][0][RTW89_WW][7] = 60,
+ [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] = 60,
+ [0][0][2][0][RTW89_WW][12] = 60,
+ [0][0][2][0][RTW89_WW][13] = 0,
+ [0][1][2][0][RTW89_WW][0] = 0,
+ [0][1][2][0][RTW89_WW][1] = 0,
+ [0][1][2][0][RTW89_WW][2] = 0,
+ [0][1][2][0][RTW89_WW][3] = 0,
+ [0][1][2][0][RTW89_WW][4] = 0,
+ [0][1][2][0][RTW89_WW][5] = 0,
+ [0][1][2][0][RTW89_WW][6] = 0,
+ [0][1][2][0][RTW89_WW][7] = 0,
+ [0][1][2][0][RTW89_WW][8] = 0,
+ [0][1][2][0][RTW89_WW][9] = 0,
+ [0][1][2][0][RTW89_WW][10] = 0,
+ [0][1][2][0][RTW89_WW][11] = 0,
+ [0][1][2][0][RTW89_WW][12] = 0,
+ [0][1][2][0][RTW89_WW][13] = 0,
+ [0][1][2][1][RTW89_WW][0] = 0,
+ [0][1][2][1][RTW89_WW][1] = 0,
+ [0][1][2][1][RTW89_WW][2] = 0,
+ [0][1][2][1][RTW89_WW][3] = 0,
+ [0][1][2][1][RTW89_WW][4] = 0,
+ [0][1][2][1][RTW89_WW][5] = 0,
+ [0][1][2][1][RTW89_WW][6] = 0,
+ [0][1][2][1][RTW89_WW][7] = 0,
+ [0][1][2][1][RTW89_WW][8] = 0,
+ [0][1][2][1][RTW89_WW][9] = 0,
+ [0][1][2][1][RTW89_WW][10] = 0,
+ [0][1][2][1][RTW89_WW][11] = 0,
+ [0][1][2][1][RTW89_WW][12] = 0,
+ [0][1][2][1][RTW89_WW][13] = 0,
+ [1][0][2][0][RTW89_WW][0] = 0,
+ [1][0][2][0][RTW89_WW][1] = 0,
+ [1][0][2][0][RTW89_WW][2] = 58,
+ [1][0][2][0][RTW89_WW][3] = 58,
+ [1][0][2][0][RTW89_WW][4] = 58,
+ [1][0][2][0][RTW89_WW][5] = 58,
+ [1][0][2][0][RTW89_WW][6] = 58,
+ [1][0][2][0][RTW89_WW][7] = 58,
+ [1][0][2][0][RTW89_WW][8] = 58,
+ [1][0][2][0][RTW89_WW][9] = 58,
+ [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] = 0,
+ [1][1][2][0][RTW89_WW][3] = 0,
+ [1][1][2][0][RTW89_WW][4] = 0,
+ [1][1][2][0][RTW89_WW][5] = 0,
+ [1][1][2][0][RTW89_WW][6] = 0,
+ [1][1][2][0][RTW89_WW][7] = 0,
+ [1][1][2][0][RTW89_WW][8] = 0,
+ [1][1][2][0][RTW89_WW][9] = 0,
+ [1][1][2][0][RTW89_WW][10] = 0,
+ [1][1][2][0][RTW89_WW][11] = 0,
+ [1][1][2][0][RTW89_WW][12] = 0,
+ [1][1][2][0][RTW89_WW][13] = 0,
+ [1][1][2][1][RTW89_WW][0] = 0,
+ [1][1][2][1][RTW89_WW][1] = 0,
+ [1][1][2][1][RTW89_WW][2] = 0,
+ [1][1][2][1][RTW89_WW][3] = 0,
+ [1][1][2][1][RTW89_WW][4] = 0,
+ [1][1][2][1][RTW89_WW][5] = 0,
+ [1][1][2][1][RTW89_WW][6] = 0,
+ [1][1][2][1][RTW89_WW][7] = 0,
+ [1][1][2][1][RTW89_WW][8] = 0,
+ [1][1][2][1][RTW89_WW][9] = 0,
+ [1][1][2][1][RTW89_WW][10] = 0,
+ [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] = 84,
+ [0][0][0][0][RTW89_ETSI][0] = 58,
+ [0][0][0][0][RTW89_MKK][0] = 68,
+ [0][0][0][0][RTW89_IC][0] = 84,
+ [0][0][0][0][RTW89_KCC][0] = 68,
+ [0][0][0][0][RTW89_ACMA][0] = 58,
+ [0][0][0][0][RTW89_CN][0] = 60,
+ [0][0][0][0][RTW89_UK][0] = 58,
+ [0][0][0][0][RTW89_FCC][1] = 84,
+ [0][0][0][0][RTW89_ETSI][1] = 58,
+ [0][0][0][0][RTW89_MKK][1] = 68,
+ [0][0][0][0][RTW89_IC][1] = 84,
+ [0][0][0][0][RTW89_KCC][1] = 68,
+ [0][0][0][0][RTW89_ACMA][1] = 58,
+ [0][0][0][0][RTW89_CN][1] = 60,
+ [0][0][0][0][RTW89_UK][1] = 58,
+ [0][0][0][0][RTW89_FCC][2] = 84,
+ [0][0][0][0][RTW89_ETSI][2] = 58,
+ [0][0][0][0][RTW89_MKK][2] = 68,
+ [0][0][0][0][RTW89_IC][2] = 84,
+ [0][0][0][0][RTW89_KCC][2] = 68,
+ [0][0][0][0][RTW89_ACMA][2] = 58,
+ [0][0][0][0][RTW89_CN][2] = 60,
+ [0][0][0][0][RTW89_UK][2] = 58,
+ [0][0][0][0][RTW89_FCC][3] = 84,
+ [0][0][0][0][RTW89_ETSI][3] = 58,
+ [0][0][0][0][RTW89_MKK][3] = 68,
+ [0][0][0][0][RTW89_IC][3] = 84,
+ [0][0][0][0][RTW89_KCC][3] = 68,
+ [0][0][0][0][RTW89_ACMA][3] = 58,
+ [0][0][0][0][RTW89_CN][3] = 60,
+ [0][0][0][0][RTW89_UK][3] = 58,
+ [0][0][0][0][RTW89_FCC][4] = 84,
+ [0][0][0][0][RTW89_ETSI][4] = 58,
+ [0][0][0][0][RTW89_MKK][4] = 68,
+ [0][0][0][0][RTW89_IC][4] = 84,
+ [0][0][0][0][RTW89_KCC][4] = 68,
+ [0][0][0][0][RTW89_ACMA][4] = 58,
+ [0][0][0][0][RTW89_CN][4] = 60,
+ [0][0][0][0][RTW89_UK][4] = 58,
+ [0][0][0][0][RTW89_FCC][5] = 84,
+ [0][0][0][0][RTW89_ETSI][5] = 58,
+ [0][0][0][0][RTW89_MKK][5] = 68,
+ [0][0][0][0][RTW89_IC][5] = 84,
+ [0][0][0][0][RTW89_KCC][5] = 68,
+ [0][0][0][0][RTW89_ACMA][5] = 58,
+ [0][0][0][0][RTW89_CN][5] = 60,
+ [0][0][0][0][RTW89_UK][5] = 58,
+ [0][0][0][0][RTW89_FCC][6] = 84,
+ [0][0][0][0][RTW89_ETSI][6] = 58,
+ [0][0][0][0][RTW89_MKK][6] = 68,
+ [0][0][0][0][RTW89_IC][6] = 84,
+ [0][0][0][0][RTW89_KCC][6] = 68,
+ [0][0][0][0][RTW89_ACMA][6] = 58,
+ [0][0][0][0][RTW89_CN][6] = 60,
+ [0][0][0][0][RTW89_UK][6] = 58,
+ [0][0][0][0][RTW89_FCC][7] = 84,
+ [0][0][0][0][RTW89_ETSI][7] = 58,
+ [0][0][0][0][RTW89_MKK][7] = 68,
+ [0][0][0][0][RTW89_IC][7] = 84,
+ [0][0][0][0][RTW89_KCC][7] = 68,
+ [0][0][0][0][RTW89_ACMA][7] = 58,
+ [0][0][0][0][RTW89_CN][7] = 60,
+ [0][0][0][0][RTW89_UK][7] = 58,
+ [0][0][0][0][RTW89_FCC][8] = 84,
+ [0][0][0][0][RTW89_ETSI][8] = 58,
+ [0][0][0][0][RTW89_MKK][8] = 68,
+ [0][0][0][0][RTW89_IC][8] = 84,
+ [0][0][0][0][RTW89_KCC][8] = 68,
+ [0][0][0][0][RTW89_ACMA][8] = 58,
+ [0][0][0][0][RTW89_CN][8] = 60,
+ [0][0][0][0][RTW89_UK][8] = 58,
+ [0][0][0][0][RTW89_FCC][9] = 84,
+ [0][0][0][0][RTW89_ETSI][9] = 58,
+ [0][0][0][0][RTW89_MKK][9] = 68,
+ [0][0][0][0][RTW89_IC][9] = 84,
+ [0][0][0][0][RTW89_KCC][9] = 68,
+ [0][0][0][0][RTW89_ACMA][9] = 58,
+ [0][0][0][0][RTW89_CN][9] = 60,
+ [0][0][0][0][RTW89_UK][9] = 58,
+ [0][0][0][0][RTW89_FCC][10] = 82,
+ [0][0][0][0][RTW89_ETSI][10] = 58,
+ [0][0][0][0][RTW89_MKK][10] = 68,
+ [0][0][0][0][RTW89_IC][10] = 82,
+ [0][0][0][0][RTW89_KCC][10] = 68,
+ [0][0][0][0][RTW89_ACMA][10] = 58,
+ [0][0][0][0][RTW89_CN][10] = 60,
+ [0][0][0][0][RTW89_UK][10] = 58,
+ [0][0][0][0][RTW89_FCC][11] = 62,
+ [0][0][0][0][RTW89_ETSI][11] = 58,
+ [0][0][0][0][RTW89_MKK][11] = 68,
+ [0][0][0][0][RTW89_IC][11] = 62,
+ [0][0][0][0][RTW89_KCC][11] = 68,
+ [0][0][0][0][RTW89_ACMA][11] = 58,
+ [0][0][0][0][RTW89_CN][11] = 60,
+ [0][0][0][0][RTW89_UK][11] = 58,
+ [0][0][0][0][RTW89_FCC][12] = 52,
+ [0][0][0][0][RTW89_ETSI][12] = 58,
+ [0][0][0][0][RTW89_MKK][12] = 68,
+ [0][0][0][0][RTW89_IC][12] = 52,
+ [0][0][0][0][RTW89_KCC][12] = 68,
+ [0][0][0][0][RTW89_ACMA][12] = 58,
+ [0][0][0][0][RTW89_CN][12] = 60,
+ [0][0][0][0][RTW89_UK][12] = 58,
+ [0][0][0][0][RTW89_FCC][13] = 127,
+ [0][0][0][0][RTW89_ETSI][13] = 127,
+ [0][0][0][0][RTW89_MKK][13] = 76,
+ [0][0][0][0][RTW89_IC][13] = 127,
+ [0][0][0][0][RTW89_KCC][13] = 127,
+ [0][0][0][0][RTW89_ACMA][13] = 127,
+ [0][0][0][0][RTW89_CN][13] = 127,
+ [0][0][0][0][RTW89_UK][13] = 127,
+ [0][1][0][0][RTW89_FCC][0] = 127,
+ [0][1][0][0][RTW89_ETSI][0] = 127,
+ [0][1][0][0][RTW89_MKK][0] = 127,
+ [0][1][0][0][RTW89_IC][0] = 127,
+ [0][1][0][0][RTW89_KCC][0] = 127,
+ [0][1][0][0][RTW89_ACMA][0] = 127,
+ [0][1][0][0][RTW89_CN][0] = 127,
+ [0][1][0][0][RTW89_UK][0] = 127,
+ [0][1][0][0][RTW89_FCC][1] = 127,
+ [0][1][0][0][RTW89_ETSI][1] = 127,
+ [0][1][0][0][RTW89_MKK][1] = 127,
+ [0][1][0][0][RTW89_IC][1] = 127,
+ [0][1][0][0][RTW89_KCC][1] = 127,
+ [0][1][0][0][RTW89_ACMA][1] = 127,
+ [0][1][0][0][RTW89_CN][1] = 127,
+ [0][1][0][0][RTW89_UK][1] = 127,
+ [0][1][0][0][RTW89_FCC][2] = 127,
+ [0][1][0][0][RTW89_ETSI][2] = 127,
+ [0][1][0][0][RTW89_MKK][2] = 127,
+ [0][1][0][0][RTW89_IC][2] = 127,
+ [0][1][0][0][RTW89_KCC][2] = 127,
+ [0][1][0][0][RTW89_ACMA][2] = 127,
+ [0][1][0][0][RTW89_CN][2] = 127,
+ [0][1][0][0][RTW89_UK][2] = 127,
+ [0][1][0][0][RTW89_FCC][3] = 127,
+ [0][1][0][0][RTW89_ETSI][3] = 127,
+ [0][1][0][0][RTW89_MKK][3] = 127,
+ [0][1][0][0][RTW89_IC][3] = 127,
+ [0][1][0][0][RTW89_KCC][3] = 127,
+ [0][1][0][0][RTW89_ACMA][3] = 127,
+ [0][1][0][0][RTW89_CN][3] = 127,
+ [0][1][0][0][RTW89_UK][3] = 127,
+ [0][1][0][0][RTW89_FCC][4] = 127,
+ [0][1][0][0][RTW89_ETSI][4] = 127,
+ [0][1][0][0][RTW89_MKK][4] = 127,
+ [0][1][0][0][RTW89_IC][4] = 127,
+ [0][1][0][0][RTW89_KCC][4] = 127,
+ [0][1][0][0][RTW89_ACMA][4] = 127,
+ [0][1][0][0][RTW89_CN][4] = 127,
+ [0][1][0][0][RTW89_UK][4] = 127,
+ [0][1][0][0][RTW89_FCC][5] = 127,
+ [0][1][0][0][RTW89_ETSI][5] = 127,
+ [0][1][0][0][RTW89_MKK][5] = 127,
+ [0][1][0][0][RTW89_IC][5] = 127,
+ [0][1][0][0][RTW89_KCC][5] = 127,
+ [0][1][0][0][RTW89_ACMA][5] = 127,
+ [0][1][0][0][RTW89_CN][5] = 127,
+ [0][1][0][0][RTW89_UK][5] = 127,
+ [0][1][0][0][RTW89_FCC][6] = 127,
+ [0][1][0][0][RTW89_ETSI][6] = 127,
+ [0][1][0][0][RTW89_MKK][6] = 127,
+ [0][1][0][0][RTW89_IC][6] = 127,
+ [0][1][0][0][RTW89_KCC][6] = 127,
+ [0][1][0][0][RTW89_ACMA][6] = 127,
+ [0][1][0][0][RTW89_CN][6] = 127,
+ [0][1][0][0][RTW89_UK][6] = 127,
+ [0][1][0][0][RTW89_FCC][7] = 127,
+ [0][1][0][0][RTW89_ETSI][7] = 127,
+ [0][1][0][0][RTW89_MKK][7] = 127,
+ [0][1][0][0][RTW89_IC][7] = 127,
+ [0][1][0][0][RTW89_KCC][7] = 127,
+ [0][1][0][0][RTW89_ACMA][7] = 127,
+ [0][1][0][0][RTW89_CN][7] = 127,
+ [0][1][0][0][RTW89_UK][7] = 127,
+ [0][1][0][0][RTW89_FCC][8] = 127,
+ [0][1][0][0][RTW89_ETSI][8] = 127,
+ [0][1][0][0][RTW89_MKK][8] = 127,
+ [0][1][0][0][RTW89_IC][8] = 127,
+ [0][1][0][0][RTW89_KCC][8] = 127,
+ [0][1][0][0][RTW89_ACMA][8] = 127,
+ [0][1][0][0][RTW89_CN][8] = 127,
+ [0][1][0][0][RTW89_UK][8] = 127,
+ [0][1][0][0][RTW89_FCC][9] = 127,
+ [0][1][0][0][RTW89_ETSI][9] = 127,
+ [0][1][0][0][RTW89_MKK][9] = 127,
+ [0][1][0][0][RTW89_IC][9] = 127,
+ [0][1][0][0][RTW89_KCC][9] = 127,
+ [0][1][0][0][RTW89_ACMA][9] = 127,
+ [0][1][0][0][RTW89_CN][9] = 127,
+ [0][1][0][0][RTW89_UK][9] = 127,
+ [0][1][0][0][RTW89_FCC][10] = 127,
+ [0][1][0][0][RTW89_ETSI][10] = 127,
+ [0][1][0][0][RTW89_MKK][10] = 127,
+ [0][1][0][0][RTW89_IC][10] = 127,
+ [0][1][0][0][RTW89_KCC][10] = 127,
+ [0][1][0][0][RTW89_ACMA][10] = 127,
+ [0][1][0][0][RTW89_CN][10] = 127,
+ [0][1][0][0][RTW89_UK][10] = 127,
+ [0][1][0][0][RTW89_FCC][11] = 127,
+ [0][1][0][0][RTW89_ETSI][11] = 127,
+ [0][1][0][0][RTW89_MKK][11] = 127,
+ [0][1][0][0][RTW89_IC][11] = 127,
+ [0][1][0][0][RTW89_KCC][11] = 127,
+ [0][1][0][0][RTW89_ACMA][11] = 127,
+ [0][1][0][0][RTW89_CN][11] = 127,
+ [0][1][0][0][RTW89_UK][11] = 127,
+ [0][1][0][0][RTW89_FCC][12] = 127,
+ [0][1][0][0][RTW89_ETSI][12] = 127,
+ [0][1][0][0][RTW89_MKK][12] = 127,
+ [0][1][0][0][RTW89_IC][12] = 127,
+ [0][1][0][0][RTW89_KCC][12] = 127,
+ [0][1][0][0][RTW89_ACMA][12] = 127,
+ [0][1][0][0][RTW89_CN][12] = 127,
+ [0][1][0][0][RTW89_UK][12] = 127,
+ [0][1][0][0][RTW89_FCC][13] = 127,
+ [0][1][0][0][RTW89_ETSI][13] = 127,
+ [0][1][0][0][RTW89_MKK][13] = 127,
+ [0][1][0][0][RTW89_IC][13] = 127,
+ [0][1][0][0][RTW89_KCC][13] = 127,
+ [0][1][0][0][RTW89_ACMA][13] = 127,
+ [0][1][0][0][RTW89_CN][13] = 127,
+ [0][1][0][0][RTW89_UK][13] = 127,
+ [1][0][0][0][RTW89_FCC][0] = 127,
+ [1][0][0][0][RTW89_ETSI][0] = 127,
+ [1][0][0][0][RTW89_MKK][0] = 127,
+ [1][0][0][0][RTW89_IC][0] = 127,
+ [1][0][0][0][RTW89_KCC][0] = 127,
+ [1][0][0][0][RTW89_ACMA][0] = 127,
+ [1][0][0][0][RTW89_CN][0] = 127,
+ [1][0][0][0][RTW89_UK][0] = 127,
+ [1][0][0][0][RTW89_FCC][1] = 127,
+ [1][0][0][0][RTW89_ETSI][1] = 127,
+ [1][0][0][0][RTW89_MKK][1] = 127,
+ [1][0][0][0][RTW89_IC][1] = 127,
+ [1][0][0][0][RTW89_KCC][1] = 127,
+ [1][0][0][0][RTW89_ACMA][1] = 127,
+ [1][0][0][0][RTW89_CN][1] = 127,
+ [1][0][0][0][RTW89_UK][1] = 127,
+ [1][0][0][0][RTW89_FCC][2] = 127,
+ [1][0][0][0][RTW89_ETSI][2] = 58,
+ [1][0][0][0][RTW89_MKK][2] = 70,
+ [1][0][0][0][RTW89_IC][2] = 127,
+ [1][0][0][0][RTW89_KCC][2] = 68,
+ [1][0][0][0][RTW89_ACMA][2] = 58,
+ [1][0][0][0][RTW89_CN][2] = 60,
+ [1][0][0][0][RTW89_UK][2] = 58,
+ [1][0][0][0][RTW89_FCC][3] = 127,
+ [1][0][0][0][RTW89_ETSI][3] = 58,
+ [1][0][0][0][RTW89_MKK][3] = 76,
+ [1][0][0][0][RTW89_IC][3] = 127,
+ [1][0][0][0][RTW89_KCC][3] = 68,
+ [1][0][0][0][RTW89_ACMA][3] = 58,
+ [1][0][0][0][RTW89_CN][3] = 60,
+ [1][0][0][0][RTW89_UK][3] = 58,
+ [1][0][0][0][RTW89_FCC][4] = 127,
+ [1][0][0][0][RTW89_ETSI][4] = 58,
+ [1][0][0][0][RTW89_MKK][4] = 76,
+ [1][0][0][0][RTW89_IC][4] = 127,
+ [1][0][0][0][RTW89_KCC][4] = 68,
+ [1][0][0][0][RTW89_ACMA][4] = 58,
+ [1][0][0][0][RTW89_CN][4] = 60,
+ [1][0][0][0][RTW89_UK][4] = 58,
+ [1][0][0][0][RTW89_FCC][5] = 127,
+ [1][0][0][0][RTW89_ETSI][5] = 58,
+ [1][0][0][0][RTW89_MKK][5] = 76,
+ [1][0][0][0][RTW89_IC][5] = 127,
+ [1][0][0][0][RTW89_KCC][5] = 68,
+ [1][0][0][0][RTW89_ACMA][5] = 58,
+ [1][0][0][0][RTW89_CN][5] = 60,
+ [1][0][0][0][RTW89_UK][5] = 58,
+ [1][0][0][0][RTW89_FCC][6] = 127,
+ [1][0][0][0][RTW89_ETSI][6] = 58,
+ [1][0][0][0][RTW89_MKK][6] = 76,
+ [1][0][0][0][RTW89_IC][6] = 127,
+ [1][0][0][0][RTW89_KCC][6] = 68,
+ [1][0][0][0][RTW89_ACMA][6] = 58,
+ [1][0][0][0][RTW89_CN][6] = 60,
+ [1][0][0][0][RTW89_UK][6] = 58,
+ [1][0][0][0][RTW89_FCC][7] = 127,
+ [1][0][0][0][RTW89_ETSI][7] = 58,
+ [1][0][0][0][RTW89_MKK][7] = 76,
+ [1][0][0][0][RTW89_IC][7] = 127,
+ [1][0][0][0][RTW89_KCC][7] = 68,
+ [1][0][0][0][RTW89_ACMA][7] = 58,
+ [1][0][0][0][RTW89_CN][7] = 60,
+ [1][0][0][0][RTW89_UK][7] = 58,
+ [1][0][0][0][RTW89_FCC][8] = 127,
+ [1][0][0][0][RTW89_ETSI][8] = 58,
+ [1][0][0][0][RTW89_MKK][8] = 76,
+ [1][0][0][0][RTW89_IC][8] = 127,
+ [1][0][0][0][RTW89_KCC][8] = 68,
+ [1][0][0][0][RTW89_ACMA][8] = 58,
+ [1][0][0][0][RTW89_CN][8] = 60,
+ [1][0][0][0][RTW89_UK][8] = 58,
+ [1][0][0][0][RTW89_FCC][9] = 127,
+ [1][0][0][0][RTW89_ETSI][9] = 58,
+ [1][0][0][0][RTW89_MKK][9] = 76,
+ [1][0][0][0][RTW89_IC][9] = 127,
+ [1][0][0][0][RTW89_KCC][9] = 68,
+ [1][0][0][0][RTW89_ACMA][9] = 58,
+ [1][0][0][0][RTW89_CN][9] = 60,
+ [1][0][0][0][RTW89_UK][9] = 58,
+ [1][0][0][0][RTW89_FCC][10] = 127,
+ [1][0][0][0][RTW89_ETSI][10] = 58,
+ [1][0][0][0][RTW89_MKK][10] = 66,
+ [1][0][0][0][RTW89_IC][10] = 127,
+ [1][0][0][0][RTW89_KCC][10] = 68,
+ [1][0][0][0][RTW89_ACMA][10] = 58,
+ [1][0][0][0][RTW89_CN][10] = 60,
+ [1][0][0][0][RTW89_UK][10] = 58,
+ [1][0][0][0][RTW89_FCC][11] = 127,
+ [1][0][0][0][RTW89_ETSI][11] = 127,
+ [1][0][0][0][RTW89_MKK][11] = 127,
+ [1][0][0][0][RTW89_IC][11] = 127,
+ [1][0][0][0][RTW89_KCC][11] = 127,
+ [1][0][0][0][RTW89_ACMA][11] = 127,
+ [1][0][0][0][RTW89_CN][11] = 127,
+ [1][0][0][0][RTW89_UK][11] = 127,
+ [1][0][0][0][RTW89_FCC][12] = 127,
+ [1][0][0][0][RTW89_ETSI][12] = 127,
+ [1][0][0][0][RTW89_MKK][12] = 127,
+ [1][0][0][0][RTW89_IC][12] = 127,
+ [1][0][0][0][RTW89_KCC][12] = 127,
+ [1][0][0][0][RTW89_ACMA][12] = 127,
+ [1][0][0][0][RTW89_CN][12] = 127,
+ [1][0][0][0][RTW89_UK][12] = 127,
+ [1][0][0][0][RTW89_FCC][13] = 127,
+ [1][0][0][0][RTW89_ETSI][13] = 127,
+ [1][0][0][0][RTW89_MKK][13] = 127,
+ [1][0][0][0][RTW89_IC][13] = 127,
+ [1][0][0][0][RTW89_KCC][13] = 127,
+ [1][0][0][0][RTW89_ACMA][13] = 127,
+ [1][0][0][0][RTW89_CN][13] = 127,
+ [1][0][0][0][RTW89_UK][13] = 127,
+ [1][1][0][0][RTW89_FCC][0] = 127,
+ [1][1][0][0][RTW89_ETSI][0] = 127,
+ [1][1][0][0][RTW89_MKK][0] = 127,
+ [1][1][0][0][RTW89_IC][0] = 127,
+ [1][1][0][0][RTW89_KCC][0] = 127,
+ [1][1][0][0][RTW89_ACMA][0] = 127,
+ [1][1][0][0][RTW89_CN][0] = 127,
+ [1][1][0][0][RTW89_UK][0] = 127,
+ [1][1][0][0][RTW89_FCC][1] = 127,
+ [1][1][0][0][RTW89_ETSI][1] = 127,
+ [1][1][0][0][RTW89_MKK][1] = 127,
+ [1][1][0][0][RTW89_IC][1] = 127,
+ [1][1][0][0][RTW89_KCC][1] = 127,
+ [1][1][0][0][RTW89_ACMA][1] = 127,
+ [1][1][0][0][RTW89_CN][1] = 127,
+ [1][1][0][0][RTW89_UK][1] = 127,
+ [1][1][0][0][RTW89_FCC][2] = 127,
+ [1][1][0][0][RTW89_ETSI][2] = 127,
+ [1][1][0][0][RTW89_MKK][2] = 127,
+ [1][1][0][0][RTW89_IC][2] = 127,
+ [1][1][0][0][RTW89_KCC][2] = 127,
+ [1][1][0][0][RTW89_ACMA][2] = 127,
+ [1][1][0][0][RTW89_CN][2] = 127,
+ [1][1][0][0][RTW89_UK][2] = 127,
+ [1][1][0][0][RTW89_FCC][3] = 127,
+ [1][1][0][0][RTW89_ETSI][3] = 127,
+ [1][1][0][0][RTW89_MKK][3] = 127,
+ [1][1][0][0][RTW89_IC][3] = 127,
+ [1][1][0][0][RTW89_KCC][3] = 127,
+ [1][1][0][0][RTW89_ACMA][3] = 127,
+ [1][1][0][0][RTW89_CN][3] = 127,
+ [1][1][0][0][RTW89_UK][3] = 127,
+ [1][1][0][0][RTW89_FCC][4] = 127,
+ [1][1][0][0][RTW89_ETSI][4] = 127,
+ [1][1][0][0][RTW89_MKK][4] = 127,
+ [1][1][0][0][RTW89_IC][4] = 127,
+ [1][1][0][0][RTW89_KCC][4] = 127,
+ [1][1][0][0][RTW89_ACMA][4] = 127,
+ [1][1][0][0][RTW89_CN][4] = 127,
+ [1][1][0][0][RTW89_UK][4] = 127,
+ [1][1][0][0][RTW89_FCC][5] = 127,
+ [1][1][0][0][RTW89_ETSI][5] = 127,
+ [1][1][0][0][RTW89_MKK][5] = 127,
+ [1][1][0][0][RTW89_IC][5] = 127,
+ [1][1][0][0][RTW89_KCC][5] = 127,
+ [1][1][0][0][RTW89_ACMA][5] = 127,
+ [1][1][0][0][RTW89_CN][5] = 127,
+ [1][1][0][0][RTW89_UK][5] = 127,
+ [1][1][0][0][RTW89_FCC][6] = 127,
+ [1][1][0][0][RTW89_ETSI][6] = 127,
+ [1][1][0][0][RTW89_MKK][6] = 127,
+ [1][1][0][0][RTW89_IC][6] = 127,
+ [1][1][0][0][RTW89_KCC][6] = 127,
+ [1][1][0][0][RTW89_ACMA][6] = 127,
+ [1][1][0][0][RTW89_CN][6] = 127,
+ [1][1][0][0][RTW89_UK][6] = 127,
+ [1][1][0][0][RTW89_FCC][7] = 127,
+ [1][1][0][0][RTW89_ETSI][7] = 127,
+ [1][1][0][0][RTW89_MKK][7] = 127,
+ [1][1][0][0][RTW89_IC][7] = 127,
+ [1][1][0][0][RTW89_KCC][7] = 127,
+ [1][1][0][0][RTW89_ACMA][7] = 127,
+ [1][1][0][0][RTW89_CN][7] = 127,
+ [1][1][0][0][RTW89_UK][7] = 127,
+ [1][1][0][0][RTW89_FCC][8] = 127,
+ [1][1][0][0][RTW89_ETSI][8] = 127,
+ [1][1][0][0][RTW89_MKK][8] = 127,
+ [1][1][0][0][RTW89_IC][8] = 127,
+ [1][1][0][0][RTW89_KCC][8] = 127,
+ [1][1][0][0][RTW89_ACMA][8] = 127,
+ [1][1][0][0][RTW89_CN][8] = 127,
+ [1][1][0][0][RTW89_UK][8] = 127,
+ [1][1][0][0][RTW89_FCC][9] = 127,
+ [1][1][0][0][RTW89_ETSI][9] = 127,
+ [1][1][0][0][RTW89_MKK][9] = 127,
+ [1][1][0][0][RTW89_IC][9] = 127,
+ [1][1][0][0][RTW89_KCC][9] = 127,
+ [1][1][0][0][RTW89_ACMA][9] = 127,
+ [1][1][0][0][RTW89_CN][9] = 127,
+ [1][1][0][0][RTW89_UK][9] = 127,
+ [1][1][0][0][RTW89_FCC][10] = 127,
+ [1][1][0][0][RTW89_ETSI][10] = 127,
+ [1][1][0][0][RTW89_MKK][10] = 127,
+ [1][1][0][0][RTW89_IC][10] = 127,
+ [1][1][0][0][RTW89_KCC][10] = 127,
+ [1][1][0][0][RTW89_ACMA][10] = 127,
+ [1][1][0][0][RTW89_CN][10] = 127,
+ [1][1][0][0][RTW89_UK][10] = 127,
+ [1][1][0][0][RTW89_FCC][11] = 127,
+ [1][1][0][0][RTW89_ETSI][11] = 127,
+ [1][1][0][0][RTW89_MKK][11] = 127,
+ [1][1][0][0][RTW89_IC][11] = 127,
+ [1][1][0][0][RTW89_KCC][11] = 127,
+ [1][1][0][0][RTW89_ACMA][11] = 127,
+ [1][1][0][0][RTW89_CN][11] = 127,
+ [1][1][0][0][RTW89_UK][11] = 127,
+ [1][1][0][0][RTW89_FCC][12] = 127,
+ [1][1][0][0][RTW89_ETSI][12] = 127,
+ [1][1][0][0][RTW89_MKK][12] = 127,
+ [1][1][0][0][RTW89_IC][12] = 127,
+ [1][1][0][0][RTW89_KCC][12] = 127,
+ [1][1][0][0][RTW89_ACMA][12] = 127,
+ [1][1][0][0][RTW89_CN][12] = 127,
+ [1][1][0][0][RTW89_UK][12] = 127,
+ [1][1][0][0][RTW89_FCC][13] = 127,
+ [1][1][0][0][RTW89_ETSI][13] = 127,
+ [1][1][0][0][RTW89_MKK][13] = 127,
+ [1][1][0][0][RTW89_IC][13] = 127,
+ [1][1][0][0][RTW89_KCC][13] = 127,
+ [1][1][0][0][RTW89_ACMA][13] = 127,
+ [1][1][0][0][RTW89_CN][13] = 127,
+ [1][1][0][0][RTW89_UK][13] = 127,
+ [0][0][1][0][RTW89_FCC][0] = 80,
+ [0][0][1][0][RTW89_ETSI][0] = 58,
+ [0][0][1][0][RTW89_MKK][0] = 72,
+ [0][0][1][0][RTW89_IC][0] = 80,
+ [0][0][1][0][RTW89_KCC][0] = 78,
+ [0][0][1][0][RTW89_ACMA][0] = 58,
+ [0][0][1][0][RTW89_CN][0] = 60,
+ [0][0][1][0][RTW89_UK][0] = 58,
+ [0][0][1][0][RTW89_FCC][1] = 80,
+ [0][0][1][0][RTW89_ETSI][1] = 60,
+ [0][0][1][0][RTW89_MKK][1] = 74,
+ [0][0][1][0][RTW89_IC][1] = 80,
+ [0][0][1][0][RTW89_KCC][1] = 78,
+ [0][0][1][0][RTW89_ACMA][1] = 60,
+ [0][0][1][0][RTW89_CN][1] = 60,
+ [0][0][1][0][RTW89_UK][1] = 60,
+ [0][0][1][0][RTW89_FCC][2] = 84,
+ [0][0][1][0][RTW89_ETSI][2] = 60,
+ [0][0][1][0][RTW89_MKK][2] = 74,
+ [0][0][1][0][RTW89_IC][2] = 84,
+ [0][0][1][0][RTW89_KCC][2] = 78,
+ [0][0][1][0][RTW89_ACMA][2] = 60,
+ [0][0][1][0][RTW89_CN][2] = 60,
+ [0][0][1][0][RTW89_UK][2] = 60,
+ [0][0][1][0][RTW89_FCC][3] = 84,
+ [0][0][1][0][RTW89_ETSI][3] = 60,
+ [0][0][1][0][RTW89_MKK][3] = 74,
+ [0][0][1][0][RTW89_IC][3] = 84,
+ [0][0][1][0][RTW89_KCC][3] = 78,
+ [0][0][1][0][RTW89_ACMA][3] = 60,
+ [0][0][1][0][RTW89_CN][3] = 60,
+ [0][0][1][0][RTW89_UK][3] = 60,
+ [0][0][1][0][RTW89_FCC][4] = 84,
+ [0][0][1][0][RTW89_ETSI][4] = 60,
+ [0][0][1][0][RTW89_MKK][4] = 74,
+ [0][0][1][0][RTW89_IC][4] = 84,
+ [0][0][1][0][RTW89_KCC][4] = 76,
+ [0][0][1][0][RTW89_ACMA][4] = 60,
+ [0][0][1][0][RTW89_CN][4] = 60,
+ [0][0][1][0][RTW89_UK][4] = 60,
+ [0][0][1][0][RTW89_FCC][5] = 84,
+ [0][0][1][0][RTW89_ETSI][5] = 60,
+ [0][0][1][0][RTW89_MKK][5] = 74,
+ [0][0][1][0][RTW89_IC][5] = 84,
+ [0][0][1][0][RTW89_KCC][5] = 76,
+ [0][0][1][0][RTW89_ACMA][5] = 60,
+ [0][0][1][0][RTW89_CN][5] = 60,
+ [0][0][1][0][RTW89_UK][5] = 60,
+ [0][0][1][0][RTW89_FCC][6] = 84,
+ [0][0][1][0][RTW89_ETSI][6] = 60,
+ [0][0][1][0][RTW89_MKK][6] = 74,
+ [0][0][1][0][RTW89_IC][6] = 84,
+ [0][0][1][0][RTW89_KCC][6] = 76,
+ [0][0][1][0][RTW89_ACMA][6] = 60,
+ [0][0][1][0][RTW89_CN][6] = 60,
+ [0][0][1][0][RTW89_UK][6] = 60,
+ [0][0][1][0][RTW89_FCC][7] = 84,
+ [0][0][1][0][RTW89_ETSI][7] = 60,
+ [0][0][1][0][RTW89_MKK][7] = 74,
+ [0][0][1][0][RTW89_IC][7] = 84,
+ [0][0][1][0][RTW89_KCC][7] = 76,
+ [0][0][1][0][RTW89_ACMA][7] = 60,
+ [0][0][1][0][RTW89_CN][7] = 60,
+ [0][0][1][0][RTW89_UK][7] = 60,
+ [0][0][1][0][RTW89_FCC][8] = 80,
+ [0][0][1][0][RTW89_ETSI][8] = 60,
+ [0][0][1][0][RTW89_MKK][8] = 74,
+ [0][0][1][0][RTW89_IC][8] = 80,
+ [0][0][1][0][RTW89_KCC][8] = 76,
+ [0][0][1][0][RTW89_ACMA][8] = 60,
+ [0][0][1][0][RTW89_CN][8] = 60,
+ [0][0][1][0][RTW89_UK][8] = 60,
+ [0][0][1][0][RTW89_FCC][9] = 76,
+ [0][0][1][0][RTW89_ETSI][9] = 60,
+ [0][0][1][0][RTW89_MKK][9] = 74,
+ [0][0][1][0][RTW89_IC][9] = 76,
+ [0][0][1][0][RTW89_KCC][9] = 74,
+ [0][0][1][0][RTW89_ACMA][9] = 60,
+ [0][0][1][0][RTW89_CN][9] = 60,
+ [0][0][1][0][RTW89_UK][9] = 60,
+ [0][0][1][0][RTW89_FCC][10] = 76,
+ [0][0][1][0][RTW89_ETSI][10] = 60,
+ [0][0][1][0][RTW89_MKK][10] = 74,
+ [0][0][1][0][RTW89_IC][10] = 76,
+ [0][0][1][0][RTW89_KCC][10] = 74,
+ [0][0][1][0][RTW89_ACMA][10] = 60,
+ [0][0][1][0][RTW89_CN][10] = 60,
+ [0][0][1][0][RTW89_UK][10] = 60,
+ [0][0][1][0][RTW89_FCC][11] = 68,
+ [0][0][1][0][RTW89_ETSI][11] = 60,
+ [0][0][1][0][RTW89_MKK][11] = 74,
+ [0][0][1][0][RTW89_IC][11] = 68,
+ [0][0][1][0][RTW89_KCC][11] = 74,
+ [0][0][1][0][RTW89_ACMA][11] = 60,
+ [0][0][1][0][RTW89_CN][11] = 60,
+ [0][0][1][0][RTW89_UK][11] = 60,
+ [0][0][1][0][RTW89_FCC][12] = 64,
+ [0][0][1][0][RTW89_ETSI][12] = 58,
+ [0][0][1][0][RTW89_MKK][12] = 70,
+ [0][0][1][0][RTW89_IC][12] = 64,
+ [0][0][1][0][RTW89_KCC][12] = 74,
+ [0][0][1][0][RTW89_ACMA][12] = 58,
+ [0][0][1][0][RTW89_CN][12] = 60,
+ [0][0][1][0][RTW89_UK][12] = 58,
+ [0][0][1][0][RTW89_FCC][13] = 127,
+ [0][0][1][0][RTW89_ETSI][13] = 127,
+ [0][0][1][0][RTW89_MKK][13] = 127,
+ [0][0][1][0][RTW89_IC][13] = 127,
+ [0][0][1][0][RTW89_KCC][13] = 127,
+ [0][0][1][0][RTW89_ACMA][13] = 127,
+ [0][0][1][0][RTW89_CN][13] = 127,
+ [0][0][1][0][RTW89_UK][13] = 127,
+ [0][1][1][0][RTW89_FCC][0] = 127,
+ [0][1][1][0][RTW89_ETSI][0] = 127,
+ [0][1][1][0][RTW89_MKK][0] = 127,
+ [0][1][1][0][RTW89_IC][0] = 127,
+ [0][1][1][0][RTW89_KCC][0] = 127,
+ [0][1][1][0][RTW89_ACMA][0] = 127,
+ [0][1][1][0][RTW89_CN][0] = 127,
+ [0][1][1][0][RTW89_UK][0] = 127,
+ [0][1][1][0][RTW89_FCC][1] = 127,
+ [0][1][1][0][RTW89_ETSI][1] = 127,
+ [0][1][1][0][RTW89_MKK][1] = 127,
+ [0][1][1][0][RTW89_IC][1] = 127,
+ [0][1][1][0][RTW89_KCC][1] = 127,
+ [0][1][1][0][RTW89_ACMA][1] = 127,
+ [0][1][1][0][RTW89_CN][1] = 127,
+ [0][1][1][0][RTW89_UK][1] = 127,
+ [0][1][1][0][RTW89_FCC][2] = 127,
+ [0][1][1][0][RTW89_ETSI][2] = 127,
+ [0][1][1][0][RTW89_MKK][2] = 127,
+ [0][1][1][0][RTW89_IC][2] = 127,
+ [0][1][1][0][RTW89_KCC][2] = 127,
+ [0][1][1][0][RTW89_ACMA][2] = 127,
+ [0][1][1][0][RTW89_CN][2] = 127,
+ [0][1][1][0][RTW89_UK][2] = 127,
+ [0][1][1][0][RTW89_FCC][3] = 127,
+ [0][1][1][0][RTW89_ETSI][3] = 127,
+ [0][1][1][0][RTW89_MKK][3] = 127,
+ [0][1][1][0][RTW89_IC][3] = 127,
+ [0][1][1][0][RTW89_KCC][3] = 127,
+ [0][1][1][0][RTW89_ACMA][3] = 127,
+ [0][1][1][0][RTW89_CN][3] = 127,
+ [0][1][1][0][RTW89_UK][3] = 127,
+ [0][1][1][0][RTW89_FCC][4] = 127,
+ [0][1][1][0][RTW89_ETSI][4] = 127,
+ [0][1][1][0][RTW89_MKK][4] = 127,
+ [0][1][1][0][RTW89_IC][4] = 127,
+ [0][1][1][0][RTW89_KCC][4] = 127,
+ [0][1][1][0][RTW89_ACMA][4] = 127,
+ [0][1][1][0][RTW89_CN][4] = 127,
+ [0][1][1][0][RTW89_UK][4] = 127,
+ [0][1][1][0][RTW89_FCC][5] = 127,
+ [0][1][1][0][RTW89_ETSI][5] = 127,
+ [0][1][1][0][RTW89_MKK][5] = 127,
+ [0][1][1][0][RTW89_IC][5] = 127,
+ [0][1][1][0][RTW89_KCC][5] = 127,
+ [0][1][1][0][RTW89_ACMA][5] = 127,
+ [0][1][1][0][RTW89_CN][5] = 127,
+ [0][1][1][0][RTW89_UK][5] = 127,
+ [0][1][1][0][RTW89_FCC][6] = 127,
+ [0][1][1][0][RTW89_ETSI][6] = 127,
+ [0][1][1][0][RTW89_MKK][6] = 127,
+ [0][1][1][0][RTW89_IC][6] = 127,
+ [0][1][1][0][RTW89_KCC][6] = 127,
+ [0][1][1][0][RTW89_ACMA][6] = 127,
+ [0][1][1][0][RTW89_CN][6] = 127,
+ [0][1][1][0][RTW89_UK][6] = 127,
+ [0][1][1][0][RTW89_FCC][7] = 127,
+ [0][1][1][0][RTW89_ETSI][7] = 127,
+ [0][1][1][0][RTW89_MKK][7] = 127,
+ [0][1][1][0][RTW89_IC][7] = 127,
+ [0][1][1][0][RTW89_KCC][7] = 127,
+ [0][1][1][0][RTW89_ACMA][7] = 127,
+ [0][1][1][0][RTW89_CN][7] = 127,
+ [0][1][1][0][RTW89_UK][7] = 127,
+ [0][1][1][0][RTW89_FCC][8] = 127,
+ [0][1][1][0][RTW89_ETSI][8] = 127,
+ [0][1][1][0][RTW89_MKK][8] = 127,
+ [0][1][1][0][RTW89_IC][8] = 127,
+ [0][1][1][0][RTW89_KCC][8] = 127,
+ [0][1][1][0][RTW89_ACMA][8] = 127,
+ [0][1][1][0][RTW89_CN][8] = 127,
+ [0][1][1][0][RTW89_UK][8] = 127,
+ [0][1][1][0][RTW89_FCC][9] = 127,
+ [0][1][1][0][RTW89_ETSI][9] = 127,
+ [0][1][1][0][RTW89_MKK][9] = 127,
+ [0][1][1][0][RTW89_IC][9] = 127,
+ [0][1][1][0][RTW89_KCC][9] = 127,
+ [0][1][1][0][RTW89_ACMA][9] = 127,
+ [0][1][1][0][RTW89_CN][9] = 127,
+ [0][1][1][0][RTW89_UK][9] = 127,
+ [0][1][1][0][RTW89_FCC][10] = 127,
+ [0][1][1][0][RTW89_ETSI][10] = 127,
+ [0][1][1][0][RTW89_MKK][10] = 127,
+ [0][1][1][0][RTW89_IC][10] = 127,
+ [0][1][1][0][RTW89_KCC][10] = 127,
+ [0][1][1][0][RTW89_ACMA][10] = 127,
+ [0][1][1][0][RTW89_CN][10] = 127,
+ [0][1][1][0][RTW89_UK][10] = 127,
+ [0][1][1][0][RTW89_FCC][11] = 127,
+ [0][1][1][0][RTW89_ETSI][11] = 127,
+ [0][1][1][0][RTW89_MKK][11] = 127,
+ [0][1][1][0][RTW89_IC][11] = 127,
+ [0][1][1][0][RTW89_KCC][11] = 127,
+ [0][1][1][0][RTW89_ACMA][11] = 127,
+ [0][1][1][0][RTW89_CN][11] = 127,
+ [0][1][1][0][RTW89_UK][11] = 127,
+ [0][1][1][0][RTW89_FCC][12] = 127,
+ [0][1][1][0][RTW89_ETSI][12] = 127,
+ [0][1][1][0][RTW89_MKK][12] = 127,
+ [0][1][1][0][RTW89_IC][12] = 127,
+ [0][1][1][0][RTW89_KCC][12] = 127,
+ [0][1][1][0][RTW89_ACMA][12] = 127,
+ [0][1][1][0][RTW89_CN][12] = 127,
+ [0][1][1][0][RTW89_UK][12] = 127,
+ [0][1][1][0][RTW89_FCC][13] = 127,
+ [0][1][1][0][RTW89_ETSI][13] = 127,
+ [0][1][1][0][RTW89_MKK][13] = 127,
+ [0][1][1][0][RTW89_IC][13] = 127,
+ [0][1][1][0][RTW89_KCC][13] = 127,
+ [0][1][1][0][RTW89_ACMA][13] = 127,
+ [0][1][1][0][RTW89_CN][13] = 127,
+ [0][1][1][0][RTW89_UK][13] = 127,
+ [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_ETSI][0] = 60,
+ [0][0][2][0][RTW89_MKK][0] = 72,
+ [0][0][2][0][RTW89_IC][0] = 78,
+ [0][0][2][0][RTW89_KCC][0] = 78,
+ [0][0][2][0][RTW89_ACMA][0] = 60,
+ [0][0][2][0][RTW89_CN][0] = 60,
+ [0][0][2][0][RTW89_UK][0] = 60,
+ [0][0][2][0][RTW89_FCC][1] = 78,
+ [0][0][2][0][RTW89_ETSI][1] = 60,
+ [0][0][2][0][RTW89_MKK][1] = 78,
+ [0][0][2][0][RTW89_IC][1] = 78,
+ [0][0][2][0][RTW89_KCC][1] = 78,
+ [0][0][2][0][RTW89_ACMA][1] = 60,
+ [0][0][2][0][RTW89_CN][1] = 60,
+ [0][0][2][0][RTW89_UK][1] = 60,
+ [0][0][2][0][RTW89_FCC][2] = 82,
+ [0][0][2][0][RTW89_ETSI][2] = 60,
+ [0][0][2][0][RTW89_MKK][2] = 78,
+ [0][0][2][0][RTW89_IC][2] = 82,
+ [0][0][2][0][RTW89_KCC][2] = 78,
+ [0][0][2][0][RTW89_ACMA][2] = 60,
+ [0][0][2][0][RTW89_CN][2] = 60,
+ [0][0][2][0][RTW89_UK][2] = 60,
+ [0][0][2][0][RTW89_FCC][3] = 82,
+ [0][0][2][0][RTW89_ETSI][3] = 60,
+ [0][0][2][0][RTW89_MKK][3] = 78,
+ [0][0][2][0][RTW89_IC][3] = 82,
+ [0][0][2][0][RTW89_KCC][3] = 78,
+ [0][0][2][0][RTW89_ACMA][3] = 60,
+ [0][0][2][0][RTW89_CN][3] = 60,
+ [0][0][2][0][RTW89_UK][3] = 60,
+ [0][0][2][0][RTW89_FCC][4] = 82,
+ [0][0][2][0][RTW89_ETSI][4] = 60,
+ [0][0][2][0][RTW89_MKK][4] = 78,
+ [0][0][2][0][RTW89_IC][4] = 82,
+ [0][0][2][0][RTW89_KCC][4] = 78,
+ [0][0][2][0][RTW89_ACMA][4] = 60,
+ [0][0][2][0][RTW89_CN][4] = 60,
+ [0][0][2][0][RTW89_UK][4] = 60,
+ [0][0][2][0][RTW89_FCC][5] = 82,
+ [0][0][2][0][RTW89_ETSI][5] = 60,
+ [0][0][2][0][RTW89_MKK][5] = 78,
+ [0][0][2][0][RTW89_IC][5] = 82,
+ [0][0][2][0][RTW89_KCC][5] = 78,
+ [0][0][2][0][RTW89_ACMA][5] = 60,
+ [0][0][2][0][RTW89_CN][5] = 60,
+ [0][0][2][0][RTW89_UK][5] = 60,
+ [0][0][2][0][RTW89_FCC][6] = 82,
+ [0][0][2][0][RTW89_ETSI][6] = 60,
+ [0][0][2][0][RTW89_MKK][6] = 78,
+ [0][0][2][0][RTW89_IC][6] = 82,
+ [0][0][2][0][RTW89_KCC][6] = 78,
+ [0][0][2][0][RTW89_ACMA][6] = 60,
+ [0][0][2][0][RTW89_CN][6] = 60,
+ [0][0][2][0][RTW89_UK][6] = 60,
+ [0][0][2][0][RTW89_FCC][7] = 82,
+ [0][0][2][0][RTW89_ETSI][7] = 60,
+ [0][0][2][0][RTW89_MKK][7] = 78,
+ [0][0][2][0][RTW89_IC][7] = 82,
+ [0][0][2][0][RTW89_KCC][7] = 78,
+ [0][0][2][0][RTW89_ACMA][7] = 60,
+ [0][0][2][0][RTW89_CN][7] = 60,
+ [0][0][2][0][RTW89_UK][7] = 60,
+ [0][0][2][0][RTW89_FCC][8] = 80,
+ [0][0][2][0][RTW89_ETSI][8] = 60,
+ [0][0][2][0][RTW89_MKK][8] = 78,
+ [0][0][2][0][RTW89_IC][8] = 80,
+ [0][0][2][0][RTW89_KCC][8] = 78,
+ [0][0][2][0][RTW89_ACMA][8] = 60,
+ [0][0][2][0][RTW89_CN][8] = 60,
+ [0][0][2][0][RTW89_UK][8] = 60,
+ [0][0][2][0][RTW89_FCC][9] = 76,
+ [0][0][2][0][RTW89_ETSI][9] = 60,
+ [0][0][2][0][RTW89_MKK][9] = 78,
+ [0][0][2][0][RTW89_IC][9] = 76,
+ [0][0][2][0][RTW89_KCC][9] = 78,
+ [0][0][2][0][RTW89_ACMA][9] = 60,
+ [0][0][2][0][RTW89_CN][9] = 60,
+ [0][0][2][0][RTW89_UK][9] = 60,
+ [0][0][2][0][RTW89_FCC][10] = 76,
+ [0][0][2][0][RTW89_ETSI][10] = 60,
+ [0][0][2][0][RTW89_MKK][10] = 78,
+ [0][0][2][0][RTW89_IC][10] = 76,
+ [0][0][2][0][RTW89_KCC][10] = 78,
+ [0][0][2][0][RTW89_ACMA][10] = 60,
+ [0][0][2][0][RTW89_CN][10] = 60,
+ [0][0][2][0][RTW89_UK][10] = 60,
+ [0][0][2][0][RTW89_FCC][11] = 70,
+ [0][0][2][0][RTW89_ETSI][11] = 60,
+ [0][0][2][0][RTW89_MKK][11] = 78,
+ [0][0][2][0][RTW89_IC][11] = 70,
+ [0][0][2][0][RTW89_KCC][11] = 78,
+ [0][0][2][0][RTW89_ACMA][11] = 60,
+ [0][0][2][0][RTW89_CN][11] = 60,
+ [0][0][2][0][RTW89_UK][11] = 60,
+ [0][0][2][0][RTW89_FCC][12] = 70,
+ [0][0][2][0][RTW89_ETSI][12] = 60,
+ [0][0][2][0][RTW89_MKK][12] = 70,
+ [0][0][2][0][RTW89_IC][12] = 70,
+ [0][0][2][0][RTW89_KCC][12] = 78,
+ [0][0][2][0][RTW89_ACMA][12] = 60,
+ [0][0][2][0][RTW89_CN][12] = 60,
+ [0][0][2][0][RTW89_UK][12] = 60,
+ [0][0][2][0][RTW89_FCC][13] = 127,
+ [0][0][2][0][RTW89_ETSI][13] = 127,
+ [0][0][2][0][RTW89_MKK][13] = 127,
+ [0][0][2][0][RTW89_IC][13] = 127,
+ [0][0][2][0][RTW89_KCC][13] = 127,
+ [0][0][2][0][RTW89_ACMA][13] = 127,
+ [0][0][2][0][RTW89_CN][13] = 127,
+ [0][0][2][0][RTW89_UK][13] = 127,
+ [0][1][2][0][RTW89_FCC][0] = 127,
+ [0][1][2][0][RTW89_ETSI][0] = 127,
+ [0][1][2][0][RTW89_MKK][0] = 127,
+ [0][1][2][0][RTW89_IC][0] = 127,
+ [0][1][2][0][RTW89_KCC][0] = 127,
+ [0][1][2][0][RTW89_ACMA][0] = 127,
+ [0][1][2][0][RTW89_CN][0] = 127,
+ [0][1][2][0][RTW89_UK][0] = 127,
+ [0][1][2][0][RTW89_FCC][1] = 127,
+ [0][1][2][0][RTW89_ETSI][1] = 127,
+ [0][1][2][0][RTW89_MKK][1] = 127,
+ [0][1][2][0][RTW89_IC][1] = 127,
+ [0][1][2][0][RTW89_KCC][1] = 127,
+ [0][1][2][0][RTW89_ACMA][1] = 127,
+ [0][1][2][0][RTW89_CN][1] = 127,
+ [0][1][2][0][RTW89_UK][1] = 127,
+ [0][1][2][0][RTW89_FCC][2] = 127,
+ [0][1][2][0][RTW89_ETSI][2] = 127,
+ [0][1][2][0][RTW89_MKK][2] = 127,
+ [0][1][2][0][RTW89_IC][2] = 127,
+ [0][1][2][0][RTW89_KCC][2] = 127,
+ [0][1][2][0][RTW89_ACMA][2] = 127,
+ [0][1][2][0][RTW89_CN][2] = 127,
+ [0][1][2][0][RTW89_UK][2] = 127,
+ [0][1][2][0][RTW89_FCC][3] = 127,
+ [0][1][2][0][RTW89_ETSI][3] = 127,
+ [0][1][2][0][RTW89_MKK][3] = 127,
+ [0][1][2][0][RTW89_IC][3] = 127,
+ [0][1][2][0][RTW89_KCC][3] = 127,
+ [0][1][2][0][RTW89_ACMA][3] = 127,
+ [0][1][2][0][RTW89_CN][3] = 127,
+ [0][1][2][0][RTW89_UK][3] = 127,
+ [0][1][2][0][RTW89_FCC][4] = 127,
+ [0][1][2][0][RTW89_ETSI][4] = 127,
+ [0][1][2][0][RTW89_MKK][4] = 127,
+ [0][1][2][0][RTW89_IC][4] = 127,
+ [0][1][2][0][RTW89_KCC][4] = 127,
+ [0][1][2][0][RTW89_ACMA][4] = 127,
+ [0][1][2][0][RTW89_CN][4] = 127,
+ [0][1][2][0][RTW89_UK][4] = 127,
+ [0][1][2][0][RTW89_FCC][5] = 127,
+ [0][1][2][0][RTW89_ETSI][5] = 127,
+ [0][1][2][0][RTW89_MKK][5] = 127,
+ [0][1][2][0][RTW89_IC][5] = 127,
+ [0][1][2][0][RTW89_KCC][5] = 127,
+ [0][1][2][0][RTW89_ACMA][5] = 127,
+ [0][1][2][0][RTW89_CN][5] = 127,
+ [0][1][2][0][RTW89_UK][5] = 127,
+ [0][1][2][0][RTW89_FCC][6] = 127,
+ [0][1][2][0][RTW89_ETSI][6] = 127,
+ [0][1][2][0][RTW89_MKK][6] = 127,
+ [0][1][2][0][RTW89_IC][6] = 127,
+ [0][1][2][0][RTW89_KCC][6] = 127,
+ [0][1][2][0][RTW89_ACMA][6] = 127,
+ [0][1][2][0][RTW89_CN][6] = 127,
+ [0][1][2][0][RTW89_UK][6] = 127,
+ [0][1][2][0][RTW89_FCC][7] = 127,
+ [0][1][2][0][RTW89_ETSI][7] = 127,
+ [0][1][2][0][RTW89_MKK][7] = 127,
+ [0][1][2][0][RTW89_IC][7] = 127,
+ [0][1][2][0][RTW89_KCC][7] = 127,
+ [0][1][2][0][RTW89_ACMA][7] = 127,
+ [0][1][2][0][RTW89_CN][7] = 127,
+ [0][1][2][0][RTW89_UK][7] = 127,
+ [0][1][2][0][RTW89_FCC][8] = 127,
+ [0][1][2][0][RTW89_ETSI][8] = 127,
+ [0][1][2][0][RTW89_MKK][8] = 127,
+ [0][1][2][0][RTW89_IC][8] = 127,
+ [0][1][2][0][RTW89_KCC][8] = 127,
+ [0][1][2][0][RTW89_ACMA][8] = 127,
+ [0][1][2][0][RTW89_CN][8] = 127,
+ [0][1][2][0][RTW89_UK][8] = 127,
+ [0][1][2][0][RTW89_FCC][9] = 127,
+ [0][1][2][0][RTW89_ETSI][9] = 127,
+ [0][1][2][0][RTW89_MKK][9] = 127,
+ [0][1][2][0][RTW89_IC][9] = 127,
+ [0][1][2][0][RTW89_KCC][9] = 127,
+ [0][1][2][0][RTW89_ACMA][9] = 127,
+ [0][1][2][0][RTW89_CN][9] = 127,
+ [0][1][2][0][RTW89_UK][9] = 127,
+ [0][1][2][0][RTW89_FCC][10] = 127,
+ [0][1][2][0][RTW89_ETSI][10] = 127,
+ [0][1][2][0][RTW89_MKK][10] = 127,
+ [0][1][2][0][RTW89_IC][10] = 127,
+ [0][1][2][0][RTW89_KCC][10] = 127,
+ [0][1][2][0][RTW89_ACMA][10] = 127,
+ [0][1][2][0][RTW89_CN][10] = 127,
+ [0][1][2][0][RTW89_UK][10] = 127,
+ [0][1][2][0][RTW89_FCC][11] = 127,
+ [0][1][2][0][RTW89_ETSI][11] = 127,
+ [0][1][2][0][RTW89_MKK][11] = 127,
+ [0][1][2][0][RTW89_IC][11] = 127,
+ [0][1][2][0][RTW89_KCC][11] = 127,
+ [0][1][2][0][RTW89_ACMA][11] = 127,
+ [0][1][2][0][RTW89_CN][11] = 127,
+ [0][1][2][0][RTW89_UK][11] = 127,
+ [0][1][2][0][RTW89_FCC][12] = 127,
+ [0][1][2][0][RTW89_ETSI][12] = 127,
+ [0][1][2][0][RTW89_MKK][12] = 127,
+ [0][1][2][0][RTW89_IC][12] = 127,
+ [0][1][2][0][RTW89_KCC][12] = 127,
+ [0][1][2][0][RTW89_ACMA][12] = 127,
+ [0][1][2][0][RTW89_CN][12] = 127,
+ [0][1][2][0][RTW89_UK][12] = 127,
+ [0][1][2][0][RTW89_FCC][13] = 127,
+ [0][1][2][0][RTW89_ETSI][13] = 127,
+ [0][1][2][0][RTW89_MKK][13] = 127,
+ [0][1][2][0][RTW89_IC][13] = 127,
+ [0][1][2][0][RTW89_KCC][13] = 127,
+ [0][1][2][0][RTW89_ACMA][13] = 127,
+ [0][1][2][0][RTW89_CN][13] = 127,
+ [0][1][2][0][RTW89_UK][13] = 127,
+ [0][1][2][1][RTW89_FCC][0] = 127,
+ [0][1][2][1][RTW89_ETSI][0] = 127,
+ [0][1][2][1][RTW89_MKK][0] = 127,
+ [0][1][2][1][RTW89_IC][0] = 127,
+ [0][1][2][1][RTW89_KCC][0] = 127,
+ [0][1][2][1][RTW89_ACMA][0] = 127,
+ [0][1][2][1][RTW89_CN][0] = 127,
+ [0][1][2][1][RTW89_UK][0] = 127,
+ [0][1][2][1][RTW89_FCC][1] = 127,
+ [0][1][2][1][RTW89_ETSI][1] = 127,
+ [0][1][2][1][RTW89_MKK][1] = 127,
+ [0][1][2][1][RTW89_IC][1] = 127,
+ [0][1][2][1][RTW89_KCC][1] = 127,
+ [0][1][2][1][RTW89_ACMA][1] = 127,
+ [0][1][2][1][RTW89_CN][1] = 127,
+ [0][1][2][1][RTW89_UK][1] = 127,
+ [0][1][2][1][RTW89_FCC][2] = 127,
+ [0][1][2][1][RTW89_ETSI][2] = 127,
+ [0][1][2][1][RTW89_MKK][2] = 127,
+ [0][1][2][1][RTW89_IC][2] = 127,
+ [0][1][2][1][RTW89_KCC][2] = 127,
+ [0][1][2][1][RTW89_ACMA][2] = 127,
+ [0][1][2][1][RTW89_CN][2] = 127,
+ [0][1][2][1][RTW89_UK][2] = 127,
+ [0][1][2][1][RTW89_FCC][3] = 127,
+ [0][1][2][1][RTW89_ETSI][3] = 127,
+ [0][1][2][1][RTW89_MKK][3] = 127,
+ [0][1][2][1][RTW89_IC][3] = 127,
+ [0][1][2][1][RTW89_KCC][3] = 127,
+ [0][1][2][1][RTW89_ACMA][3] = 127,
+ [0][1][2][1][RTW89_CN][3] = 127,
+ [0][1][2][1][RTW89_UK][3] = 127,
+ [0][1][2][1][RTW89_FCC][4] = 127,
+ [0][1][2][1][RTW89_ETSI][4] = 127,
+ [0][1][2][1][RTW89_MKK][4] = 127,
+ [0][1][2][1][RTW89_IC][4] = 127,
+ [0][1][2][1][RTW89_KCC][4] = 127,
+ [0][1][2][1][RTW89_ACMA][4] = 127,
+ [0][1][2][1][RTW89_CN][4] = 127,
+ [0][1][2][1][RTW89_UK][4] = 127,
+ [0][1][2][1][RTW89_FCC][5] = 127,
+ [0][1][2][1][RTW89_ETSI][5] = 127,
+ [0][1][2][1][RTW89_MKK][5] = 127,
+ [0][1][2][1][RTW89_IC][5] = 127,
+ [0][1][2][1][RTW89_KCC][5] = 127,
+ [0][1][2][1][RTW89_ACMA][5] = 127,
+ [0][1][2][1][RTW89_CN][5] = 127,
+ [0][1][2][1][RTW89_UK][5] = 127,
+ [0][1][2][1][RTW89_FCC][6] = 127,
+ [0][1][2][1][RTW89_ETSI][6] = 127,
+ [0][1][2][1][RTW89_MKK][6] = 127,
+ [0][1][2][1][RTW89_IC][6] = 127,
+ [0][1][2][1][RTW89_KCC][6] = 127,
+ [0][1][2][1][RTW89_ACMA][6] = 127,
+ [0][1][2][1][RTW89_CN][6] = 127,
+ [0][1][2][1][RTW89_UK][6] = 127,
+ [0][1][2][1][RTW89_FCC][7] = 127,
+ [0][1][2][1][RTW89_ETSI][7] = 127,
+ [0][1][2][1][RTW89_MKK][7] = 127,
+ [0][1][2][1][RTW89_IC][7] = 127,
+ [0][1][2][1][RTW89_KCC][7] = 127,
+ [0][1][2][1][RTW89_ACMA][7] = 127,
+ [0][1][2][1][RTW89_CN][7] = 127,
+ [0][1][2][1][RTW89_UK][7] = 127,
+ [0][1][2][1][RTW89_FCC][8] = 127,
+ [0][1][2][1][RTW89_ETSI][8] = 127,
+ [0][1][2][1][RTW89_MKK][8] = 127,
+ [0][1][2][1][RTW89_IC][8] = 127,
+ [0][1][2][1][RTW89_KCC][8] = 127,
+ [0][1][2][1][RTW89_ACMA][8] = 127,
+ [0][1][2][1][RTW89_CN][8] = 127,
+ [0][1][2][1][RTW89_UK][8] = 127,
+ [0][1][2][1][RTW89_FCC][9] = 127,
+ [0][1][2][1][RTW89_ETSI][9] = 127,
+ [0][1][2][1][RTW89_MKK][9] = 127,
+ [0][1][2][1][RTW89_IC][9] = 127,
+ [0][1][2][1][RTW89_KCC][9] = 127,
+ [0][1][2][1][RTW89_ACMA][9] = 127,
+ [0][1][2][1][RTW89_CN][9] = 127,
+ [0][1][2][1][RTW89_UK][9] = 127,
+ [0][1][2][1][RTW89_FCC][10] = 127,
+ [0][1][2][1][RTW89_ETSI][10] = 127,
+ [0][1][2][1][RTW89_MKK][10] = 127,
+ [0][1][2][1][RTW89_IC][10] = 127,
+ [0][1][2][1][RTW89_KCC][10] = 127,
+ [0][1][2][1][RTW89_ACMA][10] = 127,
+ [0][1][2][1][RTW89_CN][10] = 127,
+ [0][1][2][1][RTW89_UK][10] = 127,
+ [0][1][2][1][RTW89_FCC][11] = 127,
+ [0][1][2][1][RTW89_ETSI][11] = 127,
+ [0][1][2][1][RTW89_MKK][11] = 127,
+ [0][1][2][1][RTW89_IC][11] = 127,
+ [0][1][2][1][RTW89_KCC][11] = 127,
+ [0][1][2][1][RTW89_ACMA][11] = 127,
+ [0][1][2][1][RTW89_CN][11] = 127,
+ [0][1][2][1][RTW89_UK][11] = 127,
+ [0][1][2][1][RTW89_FCC][12] = 127,
+ [0][1][2][1][RTW89_ETSI][12] = 127,
+ [0][1][2][1][RTW89_MKK][12] = 127,
+ [0][1][2][1][RTW89_IC][12] = 127,
+ [0][1][2][1][RTW89_KCC][12] = 127,
+ [0][1][2][1][RTW89_ACMA][12] = 127,
+ [0][1][2][1][RTW89_CN][12] = 127,
+ [0][1][2][1][RTW89_UK][12] = 127,
+ [0][1][2][1][RTW89_FCC][13] = 127,
+ [0][1][2][1][RTW89_ETSI][13] = 127,
+ [0][1][2][1][RTW89_MKK][13] = 127,
+ [0][1][2][1][RTW89_IC][13] = 127,
+ [0][1][2][1][RTW89_KCC][13] = 127,
+ [0][1][2][1][RTW89_ACMA][13] = 127,
+ [0][1][2][1][RTW89_CN][13] = 127,
+ [0][1][2][1][RTW89_UK][13] = 127,
+ [1][0][2][0][RTW89_FCC][0] = 127,
+ [1][0][2][0][RTW89_ETSI][0] = 127,
+ [1][0][2][0][RTW89_MKK][0] = 127,
+ [1][0][2][0][RTW89_IC][0] = 127,
+ [1][0][2][0][RTW89_KCC][0] = 127,
+ [1][0][2][0][RTW89_ACMA][0] = 127,
+ [1][0][2][0][RTW89_CN][0] = 127,
+ [1][0][2][0][RTW89_UK][0] = 127,
+ [1][0][2][0][RTW89_FCC][1] = 127,
+ [1][0][2][0][RTW89_ETSI][1] = 127,
+ [1][0][2][0][RTW89_MKK][1] = 127,
+ [1][0][2][0][RTW89_IC][1] = 127,
+ [1][0][2][0][RTW89_KCC][1] = 127,
+ [1][0][2][0][RTW89_ACMA][1] = 127,
+ [1][0][2][0][RTW89_CN][1] = 127,
+ [1][0][2][0][RTW89_UK][1] = 127,
+ [1][0][2][0][RTW89_FCC][2] = 72,
+ [1][0][2][0][RTW89_ETSI][2] = 58,
+ [1][0][2][0][RTW89_MKK][2] = 80,
+ [1][0][2][0][RTW89_IC][2] = 72,
+ [1][0][2][0][RTW89_KCC][2] = 80,
+ [1][0][2][0][RTW89_ACMA][2] = 58,
+ [1][0][2][0][RTW89_CN][2] = 60,
+ [1][0][2][0][RTW89_UK][2] = 58,
+ [1][0][2][0][RTW89_FCC][3] = 72,
+ [1][0][2][0][RTW89_ETSI][3] = 58,
+ [1][0][2][0][RTW89_MKK][3] = 80,
+ [1][0][2][0][RTW89_IC][3] = 72,
+ [1][0][2][0][RTW89_KCC][3] = 80,
+ [1][0][2][0][RTW89_ACMA][3] = 58,
+ [1][0][2][0][RTW89_CN][3] = 60,
+ [1][0][2][0][RTW89_UK][3] = 58,
+ [1][0][2][0][RTW89_FCC][4] = 76,
+ [1][0][2][0][RTW89_ETSI][4] = 58,
+ [1][0][2][0][RTW89_MKK][4] = 80,
+ [1][0][2][0][RTW89_IC][4] = 76,
+ [1][0][2][0][RTW89_KCC][4] = 80,
+ [1][0][2][0][RTW89_ACMA][4] = 58,
+ [1][0][2][0][RTW89_CN][4] = 60,
+ [1][0][2][0][RTW89_UK][4] = 58,
+ [1][0][2][0][RTW89_FCC][5] = 78,
+ [1][0][2][0][RTW89_ETSI][5] = 58,
+ [1][0][2][0][RTW89_MKK][5] = 80,
+ [1][0][2][0][RTW89_IC][5] = 78,
+ [1][0][2][0][RTW89_KCC][5] = 80,
+ [1][0][2][0][RTW89_ACMA][5] = 58,
+ [1][0][2][0][RTW89_CN][5] = 60,
+ [1][0][2][0][RTW89_UK][5] = 58,
+ [1][0][2][0][RTW89_FCC][6] = 78,
+ [1][0][2][0][RTW89_ETSI][6] = 58,
+ [1][0][2][0][RTW89_MKK][6] = 78,
+ [1][0][2][0][RTW89_IC][6] = 78,
+ [1][0][2][0][RTW89_KCC][6] = 80,
+ [1][0][2][0][RTW89_ACMA][6] = 58,
+ [1][0][2][0][RTW89_CN][6] = 60,
+ [1][0][2][0][RTW89_UK][6] = 58,
+ [1][0][2][0][RTW89_FCC][7] = 78,
+ [1][0][2][0][RTW89_ETSI][7] = 58,
+ [1][0][2][0][RTW89_MKK][7] = 80,
+ [1][0][2][0][RTW89_IC][7] = 78,
+ [1][0][2][0][RTW89_KCC][7] = 80,
+ [1][0][2][0][RTW89_ACMA][7] = 58,
+ [1][0][2][0][RTW89_CN][7] = 60,
+ [1][0][2][0][RTW89_UK][7] = 58,
+ [1][0][2][0][RTW89_FCC][8] = 78,
+ [1][0][2][0][RTW89_ETSI][8] = 58,
+ [1][0][2][0][RTW89_MKK][8] = 80,
+ [1][0][2][0][RTW89_IC][8] = 78,
+ [1][0][2][0][RTW89_KCC][8] = 78,
+ [1][0][2][0][RTW89_ACMA][8] = 58,
+ [1][0][2][0][RTW89_CN][8] = 60,
+ [1][0][2][0][RTW89_UK][8] = 58,
+ [1][0][2][0][RTW89_FCC][9] = 76,
+ [1][0][2][0][RTW89_ETSI][9] = 58,
+ [1][0][2][0][RTW89_MKK][9] = 80,
+ [1][0][2][0][RTW89_IC][9] = 76,
+ [1][0][2][0][RTW89_KCC][9] = 78,
+ [1][0][2][0][RTW89_ACMA][9] = 58,
+ [1][0][2][0][RTW89_CN][9] = 60,
+ [1][0][2][0][RTW89_UK][9] = 58,
+ [1][0][2][0][RTW89_FCC][10] = 70,
+ [1][0][2][0][RTW89_ETSI][10] = 58,
+ [1][0][2][0][RTW89_MKK][10] = 78,
+ [1][0][2][0][RTW89_IC][10] = 70,
+ [1][0][2][0][RTW89_KCC][10] = 78,
+ [1][0][2][0][RTW89_ACMA][10] = 58,
+ [1][0][2][0][RTW89_CN][10] = 60,
+ [1][0][2][0][RTW89_UK][10] = 58,
+ [1][0][2][0][RTW89_FCC][11] = 127,
+ [1][0][2][0][RTW89_ETSI][11] = 127,
+ [1][0][2][0][RTW89_MKK][11] = 127,
+ [1][0][2][0][RTW89_IC][11] = 127,
+ [1][0][2][0][RTW89_KCC][11] = 127,
+ [1][0][2][0][RTW89_ACMA][11] = 127,
+ [1][0][2][0][RTW89_CN][11] = 127,
+ [1][0][2][0][RTW89_UK][11] = 127,
+ [1][0][2][0][RTW89_FCC][12] = 127,
+ [1][0][2][0][RTW89_ETSI][12] = 127,
+ [1][0][2][0][RTW89_MKK][12] = 127,
+ [1][0][2][0][RTW89_IC][12] = 127,
+ [1][0][2][0][RTW89_KCC][12] = 127,
+ [1][0][2][0][RTW89_ACMA][12] = 127,
+ [1][0][2][0][RTW89_CN][12] = 127,
+ [1][0][2][0][RTW89_UK][12] = 127,
+ [1][0][2][0][RTW89_FCC][13] = 127,
+ [1][0][2][0][RTW89_ETSI][13] = 127,
+ [1][0][2][0][RTW89_MKK][13] = 127,
+ [1][0][2][0][RTW89_IC][13] = 127,
+ [1][0][2][0][RTW89_KCC][13] = 127,
+ [1][0][2][0][RTW89_ACMA][13] = 127,
+ [1][0][2][0][RTW89_CN][13] = 127,
+ [1][0][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_FCC][0] = 127,
+ [1][1][2][0][RTW89_ETSI][0] = 127,
+ [1][1][2][0][RTW89_MKK][0] = 127,
+ [1][1][2][0][RTW89_IC][0] = 127,
+ [1][1][2][0][RTW89_KCC][0] = 127,
+ [1][1][2][0][RTW89_ACMA][0] = 127,
+ [1][1][2][0][RTW89_CN][0] = 127,
+ [1][1][2][0][RTW89_UK][0] = 127,
+ [1][1][2][0][RTW89_FCC][1] = 127,
+ [1][1][2][0][RTW89_ETSI][1] = 127,
+ [1][1][2][0][RTW89_MKK][1] = 127,
+ [1][1][2][0][RTW89_IC][1] = 127,
+ [1][1][2][0][RTW89_KCC][1] = 127,
+ [1][1][2][0][RTW89_ACMA][1] = 127,
+ [1][1][2][0][RTW89_CN][1] = 127,
+ [1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_FCC][2] = 127,
+ [1][1][2][0][RTW89_ETSI][2] = 127,
+ [1][1][2][0][RTW89_MKK][2] = 127,
+ [1][1][2][0][RTW89_IC][2] = 127,
+ [1][1][2][0][RTW89_KCC][2] = 127,
+ [1][1][2][0][RTW89_ACMA][2] = 127,
+ [1][1][2][0][RTW89_CN][2] = 127,
+ [1][1][2][0][RTW89_UK][2] = 127,
+ [1][1][2][0][RTW89_FCC][3] = 127,
+ [1][1][2][0][RTW89_ETSI][3] = 127,
+ [1][1][2][0][RTW89_MKK][3] = 127,
+ [1][1][2][0][RTW89_IC][3] = 127,
+ [1][1][2][0][RTW89_KCC][3] = 127,
+ [1][1][2][0][RTW89_ACMA][3] = 127,
+ [1][1][2][0][RTW89_CN][3] = 127,
+ [1][1][2][0][RTW89_UK][3] = 127,
+ [1][1][2][0][RTW89_FCC][4] = 127,
+ [1][1][2][0][RTW89_ETSI][4] = 127,
+ [1][1][2][0][RTW89_MKK][4] = 127,
+ [1][1][2][0][RTW89_IC][4] = 127,
+ [1][1][2][0][RTW89_KCC][4] = 127,
+ [1][1][2][0][RTW89_ACMA][4] = 127,
+ [1][1][2][0][RTW89_CN][4] = 127,
+ [1][1][2][0][RTW89_UK][4] = 127,
+ [1][1][2][0][RTW89_FCC][5] = 127,
+ [1][1][2][0][RTW89_ETSI][5] = 127,
+ [1][1][2][0][RTW89_MKK][5] = 127,
+ [1][1][2][0][RTW89_IC][5] = 127,
+ [1][1][2][0][RTW89_KCC][5] = 127,
+ [1][1][2][0][RTW89_ACMA][5] = 127,
+ [1][1][2][0][RTW89_CN][5] = 127,
+ [1][1][2][0][RTW89_UK][5] = 127,
+ [1][1][2][0][RTW89_FCC][6] = 127,
+ [1][1][2][0][RTW89_ETSI][6] = 127,
+ [1][1][2][0][RTW89_MKK][6] = 127,
+ [1][1][2][0][RTW89_IC][6] = 127,
+ [1][1][2][0][RTW89_KCC][6] = 127,
+ [1][1][2][0][RTW89_ACMA][6] = 127,
+ [1][1][2][0][RTW89_CN][6] = 127,
+ [1][1][2][0][RTW89_UK][6] = 127,
+ [1][1][2][0][RTW89_FCC][7] = 127,
+ [1][1][2][0][RTW89_ETSI][7] = 127,
+ [1][1][2][0][RTW89_MKK][7] = 127,
+ [1][1][2][0][RTW89_IC][7] = 127,
+ [1][1][2][0][RTW89_KCC][7] = 127,
+ [1][1][2][0][RTW89_ACMA][7] = 127,
+ [1][1][2][0][RTW89_CN][7] = 127,
+ [1][1][2][0][RTW89_UK][7] = 127,
+ [1][1][2][0][RTW89_FCC][8] = 127,
+ [1][1][2][0][RTW89_ETSI][8] = 127,
+ [1][1][2][0][RTW89_MKK][8] = 127,
+ [1][1][2][0][RTW89_IC][8] = 127,
+ [1][1][2][0][RTW89_KCC][8] = 127,
+ [1][1][2][0][RTW89_ACMA][8] = 127,
+ [1][1][2][0][RTW89_CN][8] = 127,
+ [1][1][2][0][RTW89_UK][8] = 127,
+ [1][1][2][0][RTW89_FCC][9] = 127,
+ [1][1][2][0][RTW89_ETSI][9] = 127,
+ [1][1][2][0][RTW89_MKK][9] = 127,
+ [1][1][2][0][RTW89_IC][9] = 127,
+ [1][1][2][0][RTW89_KCC][9] = 127,
+ [1][1][2][0][RTW89_ACMA][9] = 127,
+ [1][1][2][0][RTW89_CN][9] = 127,
+ [1][1][2][0][RTW89_UK][9] = 127,
+ [1][1][2][0][RTW89_FCC][10] = 127,
+ [1][1][2][0][RTW89_ETSI][10] = 127,
+ [1][1][2][0][RTW89_MKK][10] = 127,
+ [1][1][2][0][RTW89_IC][10] = 127,
+ [1][1][2][0][RTW89_KCC][10] = 127,
+ [1][1][2][0][RTW89_ACMA][10] = 127,
+ [1][1][2][0][RTW89_CN][10] = 127,
+ [1][1][2][0][RTW89_UK][10] = 127,
+ [1][1][2][0][RTW89_FCC][11] = 127,
+ [1][1][2][0][RTW89_ETSI][11] = 127,
+ [1][1][2][0][RTW89_MKK][11] = 127,
+ [1][1][2][0][RTW89_IC][11] = 127,
+ [1][1][2][0][RTW89_KCC][11] = 127,
+ [1][1][2][0][RTW89_ACMA][11] = 127,
+ [1][1][2][0][RTW89_CN][11] = 127,
+ [1][1][2][0][RTW89_UK][11] = 127,
+ [1][1][2][0][RTW89_FCC][12] = 127,
+ [1][1][2][0][RTW89_ETSI][12] = 127,
+ [1][1][2][0][RTW89_MKK][12] = 127,
+ [1][1][2][0][RTW89_IC][12] = 127,
+ [1][1][2][0][RTW89_KCC][12] = 127,
+ [1][1][2][0][RTW89_ACMA][12] = 127,
+ [1][1][2][0][RTW89_CN][12] = 127,
+ [1][1][2][0][RTW89_UK][12] = 127,
+ [1][1][2][0][RTW89_FCC][13] = 127,
+ [1][1][2][0][RTW89_ETSI][13] = 127,
+ [1][1][2][0][RTW89_MKK][13] = 127,
+ [1][1][2][0][RTW89_IC][13] = 127,
+ [1][1][2][0][RTW89_KCC][13] = 127,
+ [1][1][2][0][RTW89_ACMA][13] = 127,
+ [1][1][2][0][RTW89_CN][13] = 127,
+ [1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_FCC][0] = 127,
+ [1][1][2][1][RTW89_ETSI][0] = 127,
+ [1][1][2][1][RTW89_MKK][0] = 127,
+ [1][1][2][1][RTW89_IC][0] = 127,
+ [1][1][2][1][RTW89_KCC][0] = 127,
+ [1][1][2][1][RTW89_ACMA][0] = 127,
+ [1][1][2][1][RTW89_CN][0] = 127,
+ [1][1][2][1][RTW89_UK][0] = 127,
+ [1][1][2][1][RTW89_FCC][1] = 127,
+ [1][1][2][1][RTW89_ETSI][1] = 127,
+ [1][1][2][1][RTW89_MKK][1] = 127,
+ [1][1][2][1][RTW89_IC][1] = 127,
+ [1][1][2][1][RTW89_KCC][1] = 127,
+ [1][1][2][1][RTW89_ACMA][1] = 127,
+ [1][1][2][1][RTW89_CN][1] = 127,
+ [1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_FCC][2] = 127,
+ [1][1][2][1][RTW89_ETSI][2] = 127,
+ [1][1][2][1][RTW89_MKK][2] = 127,
+ [1][1][2][1][RTW89_IC][2] = 127,
+ [1][1][2][1][RTW89_KCC][2] = 127,
+ [1][1][2][1][RTW89_ACMA][2] = 127,
+ [1][1][2][1][RTW89_CN][2] = 127,
+ [1][1][2][1][RTW89_UK][2] = 127,
+ [1][1][2][1][RTW89_FCC][3] = 127,
+ [1][1][2][1][RTW89_ETSI][3] = 127,
+ [1][1][2][1][RTW89_MKK][3] = 127,
+ [1][1][2][1][RTW89_IC][3] = 127,
+ [1][1][2][1][RTW89_KCC][3] = 127,
+ [1][1][2][1][RTW89_ACMA][3] = 127,
+ [1][1][2][1][RTW89_CN][3] = 127,
+ [1][1][2][1][RTW89_UK][3] = 127,
+ [1][1][2][1][RTW89_FCC][4] = 127,
+ [1][1][2][1][RTW89_ETSI][4] = 127,
+ [1][1][2][1][RTW89_MKK][4] = 127,
+ [1][1][2][1][RTW89_IC][4] = 127,
+ [1][1][2][1][RTW89_KCC][4] = 127,
+ [1][1][2][1][RTW89_ACMA][4] = 127,
+ [1][1][2][1][RTW89_CN][4] = 127,
+ [1][1][2][1][RTW89_UK][4] = 127,
+ [1][1][2][1][RTW89_FCC][5] = 127,
+ [1][1][2][1][RTW89_ETSI][5] = 127,
+ [1][1][2][1][RTW89_MKK][5] = 127,
+ [1][1][2][1][RTW89_IC][5] = 127,
+ [1][1][2][1][RTW89_KCC][5] = 127,
+ [1][1][2][1][RTW89_ACMA][5] = 127,
+ [1][1][2][1][RTW89_CN][5] = 127,
+ [1][1][2][1][RTW89_UK][5] = 127,
+ [1][1][2][1][RTW89_FCC][6] = 127,
+ [1][1][2][1][RTW89_ETSI][6] = 127,
+ [1][1][2][1][RTW89_MKK][6] = 127,
+ [1][1][2][1][RTW89_IC][6] = 127,
+ [1][1][2][1][RTW89_KCC][6] = 127,
+ [1][1][2][1][RTW89_ACMA][6] = 127,
+ [1][1][2][1][RTW89_CN][6] = 127,
+ [1][1][2][1][RTW89_UK][6] = 127,
+ [1][1][2][1][RTW89_FCC][7] = 127,
+ [1][1][2][1][RTW89_ETSI][7] = 127,
+ [1][1][2][1][RTW89_MKK][7] = 127,
+ [1][1][2][1][RTW89_IC][7] = 127,
+ [1][1][2][1][RTW89_KCC][7] = 127,
+ [1][1][2][1][RTW89_ACMA][7] = 127,
+ [1][1][2][1][RTW89_CN][7] = 127,
+ [1][1][2][1][RTW89_UK][7] = 127,
+ [1][1][2][1][RTW89_FCC][8] = 127,
+ [1][1][2][1][RTW89_ETSI][8] = 127,
+ [1][1][2][1][RTW89_MKK][8] = 127,
+ [1][1][2][1][RTW89_IC][8] = 127,
+ [1][1][2][1][RTW89_KCC][8] = 127,
+ [1][1][2][1][RTW89_ACMA][8] = 127,
+ [1][1][2][1][RTW89_CN][8] = 127,
+ [1][1][2][1][RTW89_UK][8] = 127,
+ [1][1][2][1][RTW89_FCC][9] = 127,
+ [1][1][2][1][RTW89_ETSI][9] = 127,
+ [1][1][2][1][RTW89_MKK][9] = 127,
+ [1][1][2][1][RTW89_IC][9] = 127,
+ [1][1][2][1][RTW89_KCC][9] = 127,
+ [1][1][2][1][RTW89_ACMA][9] = 127,
+ [1][1][2][1][RTW89_CN][9] = 127,
+ [1][1][2][1][RTW89_UK][9] = 127,
+ [1][1][2][1][RTW89_FCC][10] = 127,
+ [1][1][2][1][RTW89_ETSI][10] = 127,
+ [1][1][2][1][RTW89_MKK][10] = 127,
+ [1][1][2][1][RTW89_IC][10] = 127,
+ [1][1][2][1][RTW89_KCC][10] = 127,
+ [1][1][2][1][RTW89_ACMA][10] = 127,
+ [1][1][2][1][RTW89_CN][10] = 127,
+ [1][1][2][1][RTW89_UK][10] = 127,
+ [1][1][2][1][RTW89_FCC][11] = 127,
+ [1][1][2][1][RTW89_ETSI][11] = 127,
+ [1][1][2][1][RTW89_MKK][11] = 127,
+ [1][1][2][1][RTW89_IC][11] = 127,
+ [1][1][2][1][RTW89_KCC][11] = 127,
+ [1][1][2][1][RTW89_ACMA][11] = 127,
+ [1][1][2][1][RTW89_CN][11] = 127,
+ [1][1][2][1][RTW89_UK][11] = 127,
+ [1][1][2][1][RTW89_FCC][12] = 127,
+ [1][1][2][1][RTW89_ETSI][12] = 127,
+ [1][1][2][1][RTW89_MKK][12] = 127,
+ [1][1][2][1][RTW89_IC][12] = 127,
+ [1][1][2][1][RTW89_KCC][12] = 127,
+ [1][1][2][1][RTW89_ACMA][12] = 127,
+ [1][1][2][1][RTW89_CN][12] = 127,
+ [1][1][2][1][RTW89_UK][12] = 127,
+ [1][1][2][1][RTW89_FCC][13] = 127,
+ [1][1][2][1][RTW89_ETSI][13] = 127,
+ [1][1][2][1][RTW89_MKK][13] = 127,
+ [1][1][2][1][RTW89_IC][13] = 127,
+ [1][1][2][1][RTW89_KCC][13] = 127,
+ [1][1][2][1][RTW89_ACMA][13] = 127,
+ [1][1][2][1][RTW89_CN][13] = 127,
+ [1][1][2][1][RTW89_UK][13] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
+ [0][0][1][0][RTW89_WW][0] = 58,
+ [0][0][1][0][RTW89_WW][2] = 58,
+ [0][0][1][0][RTW89_WW][4] = 58,
+ [0][0][1][0][RTW89_WW][6] = 50,
+ [0][0][1][0][RTW89_WW][8] = 58,
+ [0][0][1][0][RTW89_WW][10] = 58,
+ [0][0][1][0][RTW89_WW][12] = 58,
+ [0][0][1][0][RTW89_WW][14] = 58,
+ [0][0][1][0][RTW89_WW][15] = 58,
+ [0][0][1][0][RTW89_WW][17] = 60,
+ [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][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] = 74,
+ [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] = 72,
+ [0][0][1][0][RTW89_WW][50] = 72,
+ [0][0][1][0][RTW89_WW][52] = 72,
+ [0][1][1][0][RTW89_WW][0] = 0,
+ [0][1][1][0][RTW89_WW][2] = 0,
+ [0][1][1][0][RTW89_WW][4] = 0,
+ [0][1][1][0][RTW89_WW][6] = 0,
+ [0][1][1][0][RTW89_WW][8] = 0,
+ [0][1][1][0][RTW89_WW][10] = 0,
+ [0][1][1][0][RTW89_WW][12] = 0,
+ [0][1][1][0][RTW89_WW][14] = 0,
+ [0][1][1][0][RTW89_WW][15] = 0,
+ [0][1][1][0][RTW89_WW][17] = 0,
+ [0][1][1][0][RTW89_WW][19] = 0,
+ [0][1][1][0][RTW89_WW][21] = 0,
+ [0][1][1][0][RTW89_WW][23] = 0,
+ [0][1][1][0][RTW89_WW][25] = 0,
+ [0][1][1][0][RTW89_WW][27] = 0,
+ [0][1][1][0][RTW89_WW][29] = 0,
+ [0][1][1][0][RTW89_WW][31] = 0,
+ [0][1][1][0][RTW89_WW][33] = 0,
+ [0][1][1][0][RTW89_WW][35] = 0,
+ [0][1][1][0][RTW89_WW][37] = 0,
+ [0][1][1][0][RTW89_WW][38] = 0,
+ [0][1][1][0][RTW89_WW][40] = 0,
+ [0][1][1][0][RTW89_WW][42] = 0,
+ [0][1][1][0][RTW89_WW][44] = 0,
+ [0][1][1][0][RTW89_WW][46] = 0,
+ [0][1][1][0][RTW89_WW][48] = 0,
+ [0][1][1][0][RTW89_WW][50] = 0,
+ [0][1][1][0][RTW89_WW][52] = 0,
+ [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] = 54,
+ [0][0][2][0][RTW89_WW][8] = 62,
+ [0][0][2][0][RTW89_WW][10] = 62,
+ [0][0][2][0][RTW89_WW][12] = 62,
+ [0][0][2][0][RTW89_WW][14] = 62,
+ [0][0][2][0][RTW89_WW][15] = 60,
+ [0][0][2][0][RTW89_WW][17] = 62,
+ [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][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] = 76,
+ [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] = 74,
+ [0][0][2][0][RTW89_WW][50] = 76,
+ [0][0][2][0][RTW89_WW][52] = 76,
+ [0][1][2][0][RTW89_WW][0] = 0,
+ [0][1][2][0][RTW89_WW][2] = 0,
+ [0][1][2][0][RTW89_WW][4] = 0,
+ [0][1][2][0][RTW89_WW][6] = 0,
+ [0][1][2][0][RTW89_WW][8] = 0,
+ [0][1][2][0][RTW89_WW][10] = 0,
+ [0][1][2][0][RTW89_WW][12] = 0,
+ [0][1][2][0][RTW89_WW][14] = 0,
+ [0][1][2][0][RTW89_WW][15] = 0,
+ [0][1][2][0][RTW89_WW][17] = 0,
+ [0][1][2][0][RTW89_WW][19] = 0,
+ [0][1][2][0][RTW89_WW][21] = 0,
+ [0][1][2][0][RTW89_WW][23] = 0,
+ [0][1][2][0][RTW89_WW][25] = 0,
+ [0][1][2][0][RTW89_WW][27] = 0,
+ [0][1][2][0][RTW89_WW][29] = 0,
+ [0][1][2][0][RTW89_WW][31] = 0,
+ [0][1][2][0][RTW89_WW][33] = 0,
+ [0][1][2][0][RTW89_WW][35] = 0,
+ [0][1][2][0][RTW89_WW][37] = 0,
+ [0][1][2][0][RTW89_WW][38] = 0,
+ [0][1][2][0][RTW89_WW][40] = 0,
+ [0][1][2][0][RTW89_WW][42] = 0,
+ [0][1][2][0][RTW89_WW][44] = 0,
+ [0][1][2][0][RTW89_WW][46] = 0,
+ [0][1][2][0][RTW89_WW][48] = 0,
+ [0][1][2][0][RTW89_WW][50] = 0,
+ [0][1][2][0][RTW89_WW][52] = 0,
+ [0][1][2][1][RTW89_WW][0] = 0,
+ [0][1][2][1][RTW89_WW][2] = 0,
+ [0][1][2][1][RTW89_WW][4] = 0,
+ [0][1][2][1][RTW89_WW][6] = 0,
+ [0][1][2][1][RTW89_WW][8] = 0,
+ [0][1][2][1][RTW89_WW][10] = 0,
+ [0][1][2][1][RTW89_WW][12] = 0,
+ [0][1][2][1][RTW89_WW][14] = 0,
+ [0][1][2][1][RTW89_WW][15] = 0,
+ [0][1][2][1][RTW89_WW][17] = 0,
+ [0][1][2][1][RTW89_WW][19] = 0,
+ [0][1][2][1][RTW89_WW][21] = 0,
+ [0][1][2][1][RTW89_WW][23] = 0,
+ [0][1][2][1][RTW89_WW][25] = 0,
+ [0][1][2][1][RTW89_WW][27] = 0,
+ [0][1][2][1][RTW89_WW][29] = 0,
+ [0][1][2][1][RTW89_WW][31] = 0,
+ [0][1][2][1][RTW89_WW][33] = 0,
+ [0][1][2][1][RTW89_WW][35] = 0,
+ [0][1][2][1][RTW89_WW][37] = 0,
+ [0][1][2][1][RTW89_WW][38] = 0,
+ [0][1][2][1][RTW89_WW][40] = 0,
+ [0][1][2][1][RTW89_WW][42] = 0,
+ [0][1][2][1][RTW89_WW][44] = 0,
+ [0][1][2][1][RTW89_WW][46] = 0,
+ [0][1][2][1][RTW89_WW][48] = 0,
+ [0][1][2][1][RTW89_WW][50] = 0,
+ [0][1][2][1][RTW89_WW][52] = 0,
+ [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][5] = 62,
+ [1][0][2][0][RTW89_WW][9] = 64,
+ [1][0][2][0][RTW89_WW][13] = 64,
+ [1][0][2][0][RTW89_WW][16] = 66,
+ [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][39] = 30,
+ [1][0][2][0][RTW89_WW][43] = 30,
+ [1][0][2][0][RTW89_WW][47] = 84,
+ [1][0][2][0][RTW89_WW][51] = 84,
+ [1][1][2][0][RTW89_WW][1] = 0,
+ [1][1][2][0][RTW89_WW][5] = 0,
+ [1][1][2][0][RTW89_WW][9] = 0,
+ [1][1][2][0][RTW89_WW][13] = 0,
+ [1][1][2][0][RTW89_WW][16] = 0,
+ [1][1][2][0][RTW89_WW][20] = 0,
+ [1][1][2][0][RTW89_WW][24] = 0,
+ [1][1][2][0][RTW89_WW][28] = 0,
+ [1][1][2][0][RTW89_WW][32] = 0,
+ [1][1][2][0][RTW89_WW][36] = 0,
+ [1][1][2][0][RTW89_WW][39] = 0,
+ [1][1][2][0][RTW89_WW][43] = 0,
+ [1][1][2][0][RTW89_WW][47] = 0,
+ [1][1][2][0][RTW89_WW][51] = 0,
+ [1][1][2][1][RTW89_WW][1] = 0,
+ [1][1][2][1][RTW89_WW][5] = 0,
+ [1][1][2][1][RTW89_WW][9] = 0,
+ [1][1][2][1][RTW89_WW][13] = 0,
+ [1][1][2][1][RTW89_WW][16] = 0,
+ [1][1][2][1][RTW89_WW][20] = 0,
+ [1][1][2][1][RTW89_WW][24] = 0,
+ [1][1][2][1][RTW89_WW][28] = 0,
+ [1][1][2][1][RTW89_WW][32] = 0,
+ [1][1][2][1][RTW89_WW][36] = 0,
+ [1][1][2][1][RTW89_WW][39] = 0,
+ [1][1][2][1][RTW89_WW][43] = 0,
+ [1][1][2][1][RTW89_WW][47] = 0,
+ [1][1][2][1][RTW89_WW][51] = 0,
+ [2][0][2][0][RTW89_WW][3] = 62,
+ [2][0][2][0][RTW89_WW][11] = 62,
+ [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][26] = 64,
+ [2][0][2][0][RTW89_WW][34] = 72,
+ [2][0][2][0][RTW89_WW][41] = 30,
+ [2][0][2][0][RTW89_WW][49] = 74,
+ [2][1][2][0][RTW89_WW][3] = 0,
+ [2][1][2][0][RTW89_WW][11] = 0,
+ [2][1][2][0][RTW89_WW][18] = 0,
+ [2][1][2][0][RTW89_WW][26] = 0,
+ [2][1][2][0][RTW89_WW][34] = 0,
+ [2][1][2][0][RTW89_WW][41] = 0,
+ [2][1][2][0][RTW89_WW][49] = 0,
+ [2][1][2][1][RTW89_WW][3] = 0,
+ [2][1][2][1][RTW89_WW][11] = 0,
+ [2][1][2][1][RTW89_WW][18] = 0,
+ [2][1][2][1][RTW89_WW][26] = 0,
+ [2][1][2][1][RTW89_WW][34] = 0,
+ [2][1][2][1][RTW89_WW][41] = 0,
+ [2][1][2][1][RTW89_WW][49] = 0,
+ [3][0][2][0][RTW89_WW][7] = 58,
+ [3][0][2][0][RTW89_WW][22] = 58,
+ [3][0][2][0][RTW89_WW][45] = 0,
+ [3][1][2][0][RTW89_WW][7] = 0,
+ [3][1][2][0][RTW89_WW][22] = 0,
+ [3][1][2][0][RTW89_WW][45] = 0,
+ [3][1][2][1][RTW89_WW][7] = 0,
+ [3][1][2][1][RTW89_WW][22] = 0,
+ [3][1][2][1][RTW89_WW][45] = 0,
+ [0][0][1][0][RTW89_FCC][0] = 80,
+ [0][0][1][0][RTW89_ETSI][0] = 58,
+ [0][0][1][0][RTW89_MKK][0] = 60,
+ [0][0][1][0][RTW89_IC][0] = 62,
+ [0][0][1][0][RTW89_KCC][0] = 74,
+ [0][0][1][0][RTW89_ACMA][0] = 58,
+ [0][0][1][0][RTW89_CN][0] = 60,
+ [0][0][1][0][RTW89_UK][0] = 58,
+ [0][0][1][0][RTW89_FCC][2] = 82,
+ [0][0][1][0][RTW89_ETSI][2] = 58,
+ [0][0][1][0][RTW89_MKK][2] = 60,
+ [0][0][1][0][RTW89_IC][2] = 62,
+ [0][0][1][0][RTW89_KCC][2] = 74,
+ [0][0][1][0][RTW89_ACMA][2] = 58,
+ [0][0][1][0][RTW89_CN][2] = 60,
+ [0][0][1][0][RTW89_UK][2] = 58,
+ [0][0][1][0][RTW89_FCC][4] = 82,
+ [0][0][1][0][RTW89_ETSI][4] = 58,
+ [0][0][1][0][RTW89_MKK][4] = 60,
+ [0][0][1][0][RTW89_IC][4] = 62,
+ [0][0][1][0][RTW89_KCC][4] = 74,
+ [0][0][1][0][RTW89_ACMA][4] = 58,
+ [0][0][1][0][RTW89_CN][4] = 60,
+ [0][0][1][0][RTW89_UK][4] = 58,
+ [0][0][1][0][RTW89_FCC][6] = 82,
+ [0][0][1][0][RTW89_ETSI][6] = 58,
+ [0][0][1][0][RTW89_MKK][6] = 60,
+ [0][0][1][0][RTW89_IC][6] = 62,
+ [0][0][1][0][RTW89_KCC][6] = 50,
+ [0][0][1][0][RTW89_ACMA][6] = 58,
+ [0][0][1][0][RTW89_CN][6] = 60,
+ [0][0][1][0][RTW89_UK][6] = 58,
+ [0][0][1][0][RTW89_FCC][8] = 82,
+ [0][0][1][0][RTW89_ETSI][8] = 58,
+ [0][0][1][0][RTW89_MKK][8] = 60,
+ [0][0][1][0][RTW89_IC][8] = 64,
+ [0][0][1][0][RTW89_KCC][8] = 74,
+ [0][0][1][0][RTW89_ACMA][8] = 58,
+ [0][0][1][0][RTW89_CN][8] = 60,
+ [0][0][1][0][RTW89_UK][8] = 58,
+ [0][0][1][0][RTW89_FCC][10] = 82,
+ [0][0][1][0][RTW89_ETSI][10] = 58,
+ [0][0][1][0][RTW89_MKK][10] = 60,
+ [0][0][1][0][RTW89_IC][10] = 64,
+ [0][0][1][0][RTW89_KCC][10] = 74,
+ [0][0][1][0][RTW89_ACMA][10] = 58,
+ [0][0][1][0][RTW89_CN][10] = 60,
+ [0][0][1][0][RTW89_UK][10] = 58,
+ [0][0][1][0][RTW89_FCC][12] = 82,
+ [0][0][1][0][RTW89_ETSI][12] = 58,
+ [0][0][1][0][RTW89_MKK][12] = 60,
+ [0][0][1][0][RTW89_IC][12] = 64,
+ [0][0][1][0][RTW89_KCC][12] = 76,
+ [0][0][1][0][RTW89_ACMA][12] = 58,
+ [0][0][1][0][RTW89_CN][12] = 60,
+ [0][0][1][0][RTW89_UK][12] = 58,
+ [0][0][1][0][RTW89_FCC][14] = 78,
+ [0][0][1][0][RTW89_ETSI][14] = 58,
+ [0][0][1][0][RTW89_MKK][14] = 60,
+ [0][0][1][0][RTW89_IC][14] = 64,
+ [0][0][1][0][RTW89_KCC][14] = 76,
+ [0][0][1][0][RTW89_ACMA][14] = 58,
+ [0][0][1][0][RTW89_CN][14] = 60,
+ [0][0][1][0][RTW89_UK][14] = 58,
+ [0][0][1][0][RTW89_FCC][15] = 78,
+ [0][0][1][0][RTW89_ETSI][15] = 58,
+ [0][0][1][0][RTW89_MKK][15] = 78,
+ [0][0][1][0][RTW89_IC][15] = 78,
+ [0][0][1][0][RTW89_KCC][15] = 78,
+ [0][0][1][0][RTW89_ACMA][15] = 58,
+ [0][0][1][0][RTW89_CN][15] = 127,
+ [0][0][1][0][RTW89_UK][15] = 58,
+ [0][0][1][0][RTW89_FCC][17] = 82,
+ [0][0][1][0][RTW89_ETSI][17] = 60,
+ [0][0][1][0][RTW89_MKK][17] = 78,
+ [0][0][1][0][RTW89_IC][17] = 82,
+ [0][0][1][0][RTW89_KCC][17] = 78,
+ [0][0][1][0][RTW89_ACMA][17] = 60,
+ [0][0][1][0][RTW89_CN][17] = 127,
+ [0][0][1][0][RTW89_UK][17] = 60,
+ [0][0][1][0][RTW89_FCC][19] = 82,
+ [0][0][1][0][RTW89_ETSI][19] = 60,
+ [0][0][1][0][RTW89_MKK][19] = 78,
+ [0][0][1][0][RTW89_IC][19] = 82,
+ [0][0][1][0][RTW89_KCC][19] = 78,
+ [0][0][1][0][RTW89_ACMA][19] = 60,
+ [0][0][1][0][RTW89_CN][19] = 127,
+ [0][0][1][0][RTW89_UK][19] = 60,
+ [0][0][1][0][RTW89_FCC][21] = 82,
+ [0][0][1][0][RTW89_ETSI][21] = 60,
+ [0][0][1][0][RTW89_MKK][21] = 78,
+ [0][0][1][0][RTW89_IC][21] = 82,
+ [0][0][1][0][RTW89_KCC][21] = 78,
+ [0][0][1][0][RTW89_ACMA][21] = 60,
+ [0][0][1][0][RTW89_CN][21] = 127,
+ [0][0][1][0][RTW89_UK][21] = 60,
+ [0][0][1][0][RTW89_FCC][23] = 82,
+ [0][0][1][0][RTW89_ETSI][23] = 60,
+ [0][0][1][0][RTW89_MKK][23] = 78,
+ [0][0][1][0][RTW89_IC][23] = 82,
+ [0][0][1][0][RTW89_KCC][23] = 78,
+ [0][0][1][0][RTW89_ACMA][23] = 60,
+ [0][0][1][0][RTW89_CN][23] = 127,
+ [0][0][1][0][RTW89_UK][23] = 60,
+ [0][0][1][0][RTW89_FCC][25] = 82,
+ [0][0][1][0][RTW89_ETSI][25] = 60,
+ [0][0][1][0][RTW89_MKK][25] = 78,
+ [0][0][1][0][RTW89_IC][25] = 127,
+ [0][0][1][0][RTW89_KCC][25] = 78,
+ [0][0][1][0][RTW89_ACMA][25] = 127,
+ [0][0][1][0][RTW89_CN][25] = 127,
+ [0][0][1][0][RTW89_UK][25] = 60,
+ [0][0][1][0][RTW89_FCC][27] = 82,
+ [0][0][1][0][RTW89_ETSI][27] = 60,
+ [0][0][1][0][RTW89_MKK][27] = 78,
+ [0][0][1][0][RTW89_IC][27] = 127,
+ [0][0][1][0][RTW89_KCC][27] = 78,
+ [0][0][1][0][RTW89_ACMA][27] = 127,
+ [0][0][1][0][RTW89_CN][27] = 127,
+ [0][0][1][0][RTW89_UK][27] = 60,
+ [0][0][1][0][RTW89_FCC][29] = 82,
+ [0][0][1][0][RTW89_ETSI][29] = 60,
+ [0][0][1][0][RTW89_MKK][29] = 78,
+ [0][0][1][0][RTW89_IC][29] = 127,
+ [0][0][1][0][RTW89_KCC][29] = 78,
+ [0][0][1][0][RTW89_ACMA][29] = 127,
+ [0][0][1][0][RTW89_CN][29] = 127,
+ [0][0][1][0][RTW89_UK][29] = 60,
+ [0][0][1][0][RTW89_FCC][31] = 82,
+ [0][0][1][0][RTW89_ETSI][31] = 60,
+ [0][0][1][0][RTW89_MKK][31] = 78,
+ [0][0][1][0][RTW89_IC][31] = 82,
+ [0][0][1][0][RTW89_KCC][31] = 74,
+ [0][0][1][0][RTW89_ACMA][31] = 60,
+ [0][0][1][0][RTW89_CN][31] = 127,
+ [0][0][1][0][RTW89_UK][31] = 60,
+ [0][0][1][0][RTW89_FCC][33] = 82,
+ [0][0][1][0][RTW89_ETSI][33] = 60,
+ [0][0][1][0][RTW89_MKK][33] = 78,
+ [0][0][1][0][RTW89_IC][33] = 82,
+ [0][0][1][0][RTW89_KCC][33] = 74,
+ [0][0][1][0][RTW89_ACMA][33] = 60,
+ [0][0][1][0][RTW89_CN][33] = 127,
+ [0][0][1][0][RTW89_UK][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_KCC][35] = 74,
+ [0][0][1][0][RTW89_ACMA][35] = 60,
+ [0][0][1][0][RTW89_CN][35] = 127,
+ [0][0][1][0][RTW89_UK][35] = 60,
+ [0][0][1][0][RTW89_FCC][37] = 82,
+ [0][0][1][0][RTW89_ETSI][37] = 127,
+ [0][0][1][0][RTW89_MKK][37] = 78,
+ [0][0][1][0][RTW89_IC][37] = 82,
+ [0][0][1][0][RTW89_KCC][37] = 74,
+ [0][0][1][0][RTW89_ACMA][37] = 78,
+ [0][0][1][0][RTW89_CN][37] = 127,
+ [0][0][1][0][RTW89_UK][37] = 78,
+ [0][0][1][0][RTW89_FCC][38] = 82,
+ [0][0][1][0][RTW89_ETSI][38] = 30,
+ [0][0][1][0][RTW89_MKK][38] = 127,
+ [0][0][1][0][RTW89_IC][38] = 82,
+ [0][0][1][0][RTW89_KCC][38] = 70,
+ [0][0][1][0][RTW89_ACMA][38] = 78,
+ [0][0][1][0][RTW89_CN][38] = 78,
+ [0][0][1][0][RTW89_UK][38] = 58,
+ [0][0][1][0][RTW89_FCC][40] = 82,
+ [0][0][1][0][RTW89_ETSI][40] = 30,
+ [0][0][1][0][RTW89_MKK][40] = 127,
+ [0][0][1][0][RTW89_IC][40] = 82,
+ [0][0][1][0][RTW89_KCC][40] = 76,
+ [0][0][1][0][RTW89_ACMA][40] = 78,
+ [0][0][1][0][RTW89_CN][40] = 78,
+ [0][0][1][0][RTW89_UK][40] = 58,
+ [0][0][1][0][RTW89_FCC][42] = 82,
+ [0][0][1][0][RTW89_ETSI][42] = 30,
+ [0][0][1][0][RTW89_MKK][42] = 127,
+ [0][0][1][0][RTW89_IC][42] = 82,
+ [0][0][1][0][RTW89_KCC][42] = 76,
+ [0][0][1][0][RTW89_ACMA][42] = 78,
+ [0][0][1][0][RTW89_CN][42] = 78,
+ [0][0][1][0][RTW89_UK][42] = 58,
+ [0][0][1][0][RTW89_FCC][44] = 82,
+ [0][0][1][0][RTW89_ETSI][44] = 30,
+ [0][0][1][0][RTW89_MKK][44] = 127,
+ [0][0][1][0][RTW89_IC][44] = 82,
+ [0][0][1][0][RTW89_KCC][44] = 76,
+ [0][0][1][0][RTW89_ACMA][44] = 78,
+ [0][0][1][0][RTW89_CN][44] = 78,
+ [0][0][1][0][RTW89_UK][44] = 58,
+ [0][0][1][0][RTW89_FCC][46] = 82,
+ [0][0][1][0][RTW89_ETSI][46] = 30,
+ [0][0][1][0][RTW89_MKK][46] = 127,
+ [0][0][1][0][RTW89_IC][46] = 82,
+ [0][0][1][0][RTW89_KCC][46] = 76,
+ [0][0][1][0][RTW89_ACMA][46] = 78,
+ [0][0][1][0][RTW89_CN][46] = 78,
+ [0][0][1][0][RTW89_UK][46] = 58,
+ [0][0][1][0][RTW89_FCC][48] = 72,
+ [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_KCC][48] = 127,
+ [0][0][1][0][RTW89_ACMA][48] = 127,
+ [0][0][1][0][RTW89_CN][48] = 127,
+ [0][0][1][0][RTW89_UK][48] = 127,
+ [0][0][1][0][RTW89_FCC][50] = 72,
+ [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_KCC][50] = 127,
+ [0][0][1][0][RTW89_ACMA][50] = 127,
+ [0][0][1][0][RTW89_CN][50] = 127,
+ [0][0][1][0][RTW89_UK][50] = 127,
+ [0][0][1][0][RTW89_FCC][52] = 72,
+ [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_KCC][52] = 127,
+ [0][0][1][0][RTW89_ACMA][52] = 127,
+ [0][0][1][0][RTW89_CN][52] = 127,
+ [0][0][1][0][RTW89_UK][52] = 127,
+ [0][1][1][0][RTW89_FCC][0] = 127,
+ [0][1][1][0][RTW89_ETSI][0] = 127,
+ [0][1][1][0][RTW89_MKK][0] = 127,
+ [0][1][1][0][RTW89_IC][0] = 127,
+ [0][1][1][0][RTW89_KCC][0] = 127,
+ [0][1][1][0][RTW89_ACMA][0] = 127,
+ [0][1][1][0][RTW89_CN][0] = 127,
+ [0][1][1][0][RTW89_UK][0] = 127,
+ [0][1][1][0][RTW89_FCC][2] = 127,
+ [0][1][1][0][RTW89_ETSI][2] = 127,
+ [0][1][1][0][RTW89_MKK][2] = 127,
+ [0][1][1][0][RTW89_IC][2] = 127,
+ [0][1][1][0][RTW89_KCC][2] = 127,
+ [0][1][1][0][RTW89_ACMA][2] = 127,
+ [0][1][1][0][RTW89_CN][2] = 127,
+ [0][1][1][0][RTW89_UK][2] = 127,
+ [0][1][1][0][RTW89_FCC][4] = 127,
+ [0][1][1][0][RTW89_ETSI][4] = 127,
+ [0][1][1][0][RTW89_MKK][4] = 127,
+ [0][1][1][0][RTW89_IC][4] = 127,
+ [0][1][1][0][RTW89_KCC][4] = 127,
+ [0][1][1][0][RTW89_ACMA][4] = 127,
+ [0][1][1][0][RTW89_CN][4] = 127,
+ [0][1][1][0][RTW89_UK][4] = 127,
+ [0][1][1][0][RTW89_FCC][6] = 127,
+ [0][1][1][0][RTW89_ETSI][6] = 127,
+ [0][1][1][0][RTW89_MKK][6] = 127,
+ [0][1][1][0][RTW89_IC][6] = 127,
+ [0][1][1][0][RTW89_KCC][6] = 127,
+ [0][1][1][0][RTW89_ACMA][6] = 127,
+ [0][1][1][0][RTW89_CN][6] = 127,
+ [0][1][1][0][RTW89_UK][6] = 127,
+ [0][1][1][0][RTW89_FCC][8] = 127,
+ [0][1][1][0][RTW89_ETSI][8] = 127,
+ [0][1][1][0][RTW89_MKK][8] = 127,
+ [0][1][1][0][RTW89_IC][8] = 127,
+ [0][1][1][0][RTW89_KCC][8] = 127,
+ [0][1][1][0][RTW89_ACMA][8] = 127,
+ [0][1][1][0][RTW89_CN][8] = 127,
+ [0][1][1][0][RTW89_UK][8] = 127,
+ [0][1][1][0][RTW89_FCC][10] = 127,
+ [0][1][1][0][RTW89_ETSI][10] = 127,
+ [0][1][1][0][RTW89_MKK][10] = 127,
+ [0][1][1][0][RTW89_IC][10] = 127,
+ [0][1][1][0][RTW89_KCC][10] = 127,
+ [0][1][1][0][RTW89_ACMA][10] = 127,
+ [0][1][1][0][RTW89_CN][10] = 127,
+ [0][1][1][0][RTW89_UK][10] = 127,
+ [0][1][1][0][RTW89_FCC][12] = 127,
+ [0][1][1][0][RTW89_ETSI][12] = 127,
+ [0][1][1][0][RTW89_MKK][12] = 127,
+ [0][1][1][0][RTW89_IC][12] = 127,
+ [0][1][1][0][RTW89_KCC][12] = 127,
+ [0][1][1][0][RTW89_ACMA][12] = 127,
+ [0][1][1][0][RTW89_CN][12] = 127,
+ [0][1][1][0][RTW89_UK][12] = 127,
+ [0][1][1][0][RTW89_FCC][14] = 127,
+ [0][1][1][0][RTW89_ETSI][14] = 127,
+ [0][1][1][0][RTW89_MKK][14] = 127,
+ [0][1][1][0][RTW89_IC][14] = 127,
+ [0][1][1][0][RTW89_KCC][14] = 127,
+ [0][1][1][0][RTW89_ACMA][14] = 127,
+ [0][1][1][0][RTW89_CN][14] = 127,
+ [0][1][1][0][RTW89_UK][14] = 127,
+ [0][1][1][0][RTW89_FCC][15] = 127,
+ [0][1][1][0][RTW89_ETSI][15] = 127,
+ [0][1][1][0][RTW89_MKK][15] = 127,
+ [0][1][1][0][RTW89_IC][15] = 127,
+ [0][1][1][0][RTW89_KCC][15] = 127,
+ [0][1][1][0][RTW89_ACMA][15] = 127,
+ [0][1][1][0][RTW89_CN][15] = 127,
+ [0][1][1][0][RTW89_UK][15] = 127,
+ [0][1][1][0][RTW89_FCC][17] = 127,
+ [0][1][1][0][RTW89_ETSI][17] = 127,
+ [0][1][1][0][RTW89_MKK][17] = 127,
+ [0][1][1][0][RTW89_IC][17] = 127,
+ [0][1][1][0][RTW89_KCC][17] = 127,
+ [0][1][1][0][RTW89_ACMA][17] = 127,
+ [0][1][1][0][RTW89_CN][17] = 127,
+ [0][1][1][0][RTW89_UK][17] = 127,
+ [0][1][1][0][RTW89_FCC][19] = 127,
+ [0][1][1][0][RTW89_ETSI][19] = 127,
+ [0][1][1][0][RTW89_MKK][19] = 127,
+ [0][1][1][0][RTW89_IC][19] = 127,
+ [0][1][1][0][RTW89_KCC][19] = 127,
+ [0][1][1][0][RTW89_ACMA][19] = 127,
+ [0][1][1][0][RTW89_CN][19] = 127,
+ [0][1][1][0][RTW89_UK][19] = 127,
+ [0][1][1][0][RTW89_FCC][21] = 127,
+ [0][1][1][0][RTW89_ETSI][21] = 127,
+ [0][1][1][0][RTW89_MKK][21] = 127,
+ [0][1][1][0][RTW89_IC][21] = 127,
+ [0][1][1][0][RTW89_KCC][21] = 127,
+ [0][1][1][0][RTW89_ACMA][21] = 127,
+ [0][1][1][0][RTW89_CN][21] = 127,
+ [0][1][1][0][RTW89_UK][21] = 127,
+ [0][1][1][0][RTW89_FCC][23] = 127,
+ [0][1][1][0][RTW89_ETSI][23] = 127,
+ [0][1][1][0][RTW89_MKK][23] = 127,
+ [0][1][1][0][RTW89_IC][23] = 127,
+ [0][1][1][0][RTW89_KCC][23] = 127,
+ [0][1][1][0][RTW89_ACMA][23] = 127,
+ [0][1][1][0][RTW89_CN][23] = 127,
+ [0][1][1][0][RTW89_UK][23] = 127,
+ [0][1][1][0][RTW89_FCC][25] = 127,
+ [0][1][1][0][RTW89_ETSI][25] = 127,
+ [0][1][1][0][RTW89_MKK][25] = 127,
+ [0][1][1][0][RTW89_IC][25] = 127,
+ [0][1][1][0][RTW89_KCC][25] = 127,
+ [0][1][1][0][RTW89_ACMA][25] = 127,
+ [0][1][1][0][RTW89_CN][25] = 127,
+ [0][1][1][0][RTW89_UK][25] = 127,
+ [0][1][1][0][RTW89_FCC][27] = 127,
+ [0][1][1][0][RTW89_ETSI][27] = 127,
+ [0][1][1][0][RTW89_MKK][27] = 127,
+ [0][1][1][0][RTW89_IC][27] = 127,
+ [0][1][1][0][RTW89_KCC][27] = 127,
+ [0][1][1][0][RTW89_ACMA][27] = 127,
+ [0][1][1][0][RTW89_CN][27] = 127,
+ [0][1][1][0][RTW89_UK][27] = 127,
+ [0][1][1][0][RTW89_FCC][29] = 127,
+ [0][1][1][0][RTW89_ETSI][29] = 127,
+ [0][1][1][0][RTW89_MKK][29] = 127,
+ [0][1][1][0][RTW89_IC][29] = 127,
+ [0][1][1][0][RTW89_KCC][29] = 127,
+ [0][1][1][0][RTW89_ACMA][29] = 127,
+ [0][1][1][0][RTW89_CN][29] = 127,
+ [0][1][1][0][RTW89_UK][29] = 127,
+ [0][1][1][0][RTW89_FCC][31] = 127,
+ [0][1][1][0][RTW89_ETSI][31] = 127,
+ [0][1][1][0][RTW89_MKK][31] = 127,
+ [0][1][1][0][RTW89_IC][31] = 127,
+ [0][1][1][0][RTW89_KCC][31] = 127,
+ [0][1][1][0][RTW89_ACMA][31] = 127,
+ [0][1][1][0][RTW89_CN][31] = 127,
+ [0][1][1][0][RTW89_UK][31] = 127,
+ [0][1][1][0][RTW89_FCC][33] = 127,
+ [0][1][1][0][RTW89_ETSI][33] = 127,
+ [0][1][1][0][RTW89_MKK][33] = 127,
+ [0][1][1][0][RTW89_IC][33] = 127,
+ [0][1][1][0][RTW89_KCC][33] = 127,
+ [0][1][1][0][RTW89_ACMA][33] = 127,
+ [0][1][1][0][RTW89_CN][33] = 127,
+ [0][1][1][0][RTW89_UK][33] = 127,
+ [0][1][1][0][RTW89_FCC][35] = 127,
+ [0][1][1][0][RTW89_ETSI][35] = 127,
+ [0][1][1][0][RTW89_MKK][35] = 127,
+ [0][1][1][0][RTW89_IC][35] = 127,
+ [0][1][1][0][RTW89_KCC][35] = 127,
+ [0][1][1][0][RTW89_ACMA][35] = 127,
+ [0][1][1][0][RTW89_CN][35] = 127,
+ [0][1][1][0][RTW89_UK][35] = 127,
+ [0][1][1][0][RTW89_FCC][37] = 127,
+ [0][1][1][0][RTW89_ETSI][37] = 127,
+ [0][1][1][0][RTW89_MKK][37] = 127,
+ [0][1][1][0][RTW89_IC][37] = 127,
+ [0][1][1][0][RTW89_KCC][37] = 127,
+ [0][1][1][0][RTW89_ACMA][37] = 127,
+ [0][1][1][0][RTW89_CN][37] = 127,
+ [0][1][1][0][RTW89_UK][37] = 127,
+ [0][1][1][0][RTW89_FCC][38] = 127,
+ [0][1][1][0][RTW89_ETSI][38] = 127,
+ [0][1][1][0][RTW89_MKK][38] = 127,
+ [0][1][1][0][RTW89_IC][38] = 127,
+ [0][1][1][0][RTW89_KCC][38] = 127,
+ [0][1][1][0][RTW89_ACMA][38] = 127,
+ [0][1][1][0][RTW89_CN][38] = 127,
+ [0][1][1][0][RTW89_UK][38] = 127,
+ [0][1][1][0][RTW89_FCC][40] = 127,
+ [0][1][1][0][RTW89_ETSI][40] = 127,
+ [0][1][1][0][RTW89_MKK][40] = 127,
+ [0][1][1][0][RTW89_IC][40] = 127,
+ [0][1][1][0][RTW89_KCC][40] = 127,
+ [0][1][1][0][RTW89_ACMA][40] = 127,
+ [0][1][1][0][RTW89_CN][40] = 127,
+ [0][1][1][0][RTW89_UK][40] = 127,
+ [0][1][1][0][RTW89_FCC][42] = 127,
+ [0][1][1][0][RTW89_ETSI][42] = 127,
+ [0][1][1][0][RTW89_MKK][42] = 127,
+ [0][1][1][0][RTW89_IC][42] = 127,
+ [0][1][1][0][RTW89_KCC][42] = 127,
+ [0][1][1][0][RTW89_ACMA][42] = 127,
+ [0][1][1][0][RTW89_CN][42] = 127,
+ [0][1][1][0][RTW89_UK][42] = 127,
+ [0][1][1][0][RTW89_FCC][44] = 127,
+ [0][1][1][0][RTW89_ETSI][44] = 127,
+ [0][1][1][0][RTW89_MKK][44] = 127,
+ [0][1][1][0][RTW89_IC][44] = 127,
+ [0][1][1][0][RTW89_KCC][44] = 127,
+ [0][1][1][0][RTW89_ACMA][44] = 127,
+ [0][1][1][0][RTW89_CN][44] = 127,
+ [0][1][1][0][RTW89_UK][44] = 127,
+ [0][1][1][0][RTW89_FCC][46] = 127,
+ [0][1][1][0][RTW89_ETSI][46] = 127,
+ [0][1][1][0][RTW89_MKK][46] = 127,
+ [0][1][1][0][RTW89_IC][46] = 127,
+ [0][1][1][0][RTW89_KCC][46] = 127,
+ [0][1][1][0][RTW89_ACMA][46] = 127,
+ [0][1][1][0][RTW89_CN][46] = 127,
+ [0][1][1][0][RTW89_UK][46] = 127,
+ [0][1][1][0][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][1][0][RTW89_ACMA][48] = 127,
+ [0][1][1][0][RTW89_CN][48] = 127,
+ [0][1][1][0][RTW89_UK][48] = 127,
+ [0][1][1][0][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][1][0][RTW89_ACMA][50] = 127,
+ [0][1][1][0][RTW89_CN][50] = 127,
+ [0][1][1][0][RTW89_UK][50] = 127,
+ [0][1][1][0][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][1][0][RTW89_ACMA][52] = 127,
+ [0][1][1][0][RTW89_CN][52] = 127,
+ [0][1][1][0][RTW89_UK][52] = 127,
+ [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_ETSI][0] = 62,
+ [0][0][2][0][RTW89_MKK][0] = 62,
+ [0][0][2][0][RTW89_IC][0] = 64,
+ [0][0][2][0][RTW89_KCC][0] = 76,
+ [0][0][2][0][RTW89_ACMA][0] = 62,
+ [0][0][2][0][RTW89_CN][0] = 62,
+ [0][0][2][0][RTW89_UK][0] = 62,
+ [0][0][2][0][RTW89_FCC][2] = 82,
+ [0][0][2][0][RTW89_ETSI][2] = 62,
+ [0][0][2][0][RTW89_MKK][2] = 62,
+ [0][0][2][0][RTW89_IC][2] = 64,
+ [0][0][2][0][RTW89_KCC][2] = 76,
+ [0][0][2][0][RTW89_ACMA][2] = 62,
+ [0][0][2][0][RTW89_CN][2] = 62,
+ [0][0][2][0][RTW89_UK][2] = 62,
+ [0][0][2][0][RTW89_FCC][4] = 82,
+ [0][0][2][0][RTW89_ETSI][4] = 62,
+ [0][0][2][0][RTW89_MKK][4] = 62,
+ [0][0][2][0][RTW89_IC][4] = 64,
+ [0][0][2][0][RTW89_KCC][4] = 76,
+ [0][0][2][0][RTW89_ACMA][4] = 62,
+ [0][0][2][0][RTW89_CN][4] = 62,
+ [0][0][2][0][RTW89_UK][4] = 62,
+ [0][0][2][0][RTW89_FCC][6] = 82,
+ [0][0][2][0][RTW89_ETSI][6] = 62,
+ [0][0][2][0][RTW89_MKK][6] = 62,
+ [0][0][2][0][RTW89_IC][6] = 64,
+ [0][0][2][0][RTW89_KCC][6] = 54,
+ [0][0][2][0][RTW89_ACMA][6] = 62,
+ [0][0][2][0][RTW89_CN][6] = 62,
+ [0][0][2][0][RTW89_UK][6] = 62,
+ [0][0][2][0][RTW89_FCC][8] = 82,
+ [0][0][2][0][RTW89_ETSI][8] = 62,
+ [0][0][2][0][RTW89_MKK][8] = 62,
+ [0][0][2][0][RTW89_IC][8] = 64,
+ [0][0][2][0][RTW89_KCC][8] = 76,
+ [0][0][2][0][RTW89_ACMA][8] = 62,
+ [0][0][2][0][RTW89_CN][8] = 62,
+ [0][0][2][0][RTW89_UK][8] = 62,
+ [0][0][2][0][RTW89_FCC][10] = 82,
+ [0][0][2][0][RTW89_ETSI][10] = 62,
+ [0][0][2][0][RTW89_MKK][10] = 62,
+ [0][0][2][0][RTW89_IC][10] = 64,
+ [0][0][2][0][RTW89_KCC][10] = 76,
+ [0][0][2][0][RTW89_ACMA][10] = 62,
+ [0][0][2][0][RTW89_CN][10] = 62,
+ [0][0][2][0][RTW89_UK][10] = 62,
+ [0][0][2][0][RTW89_FCC][12] = 82,
+ [0][0][2][0][RTW89_ETSI][12] = 62,
+ [0][0][2][0][RTW89_MKK][12] = 62,
+ [0][0][2][0][RTW89_IC][12] = 64,
+ [0][0][2][0][RTW89_KCC][12] = 78,
+ [0][0][2][0][RTW89_ACMA][12] = 62,
+ [0][0][2][0][RTW89_CN][12] = 62,
+ [0][0][2][0][RTW89_UK][12] = 62,
+ [0][0][2][0][RTW89_FCC][14] = 76,
+ [0][0][2][0][RTW89_ETSI][14] = 62,
+ [0][0][2][0][RTW89_MKK][14] = 62,
+ [0][0][2][0][RTW89_IC][14] = 64,
+ [0][0][2][0][RTW89_KCC][14] = 78,
+ [0][0][2][0][RTW89_ACMA][14] = 62,
+ [0][0][2][0][RTW89_CN][14] = 62,
+ [0][0][2][0][RTW89_UK][14] = 62,
+ [0][0][2][0][RTW89_FCC][15] = 76,
+ [0][0][2][0][RTW89_ETSI][15] = 60,
+ [0][0][2][0][RTW89_MKK][15] = 78,
+ [0][0][2][0][RTW89_IC][15] = 76,
+ [0][0][2][0][RTW89_KCC][15] = 78,
+ [0][0][2][0][RTW89_ACMA][15] = 60,
+ [0][0][2][0][RTW89_CN][15] = 127,
+ [0][0][2][0][RTW89_UK][15] = 60,
+ [0][0][2][0][RTW89_FCC][17] = 82,
+ [0][0][2][0][RTW89_ETSI][17] = 62,
+ [0][0][2][0][RTW89_MKK][17] = 78,
+ [0][0][2][0][RTW89_IC][17] = 82,
+ [0][0][2][0][RTW89_KCC][17] = 78,
+ [0][0][2][0][RTW89_ACMA][17] = 62,
+ [0][0][2][0][RTW89_CN][17] = 127,
+ [0][0][2][0][RTW89_UK][17] = 62,
+ [0][0][2][0][RTW89_FCC][19] = 82,
+ [0][0][2][0][RTW89_ETSI][19] = 62,
+ [0][0][2][0][RTW89_MKK][19] = 78,
+ [0][0][2][0][RTW89_IC][19] = 82,
+ [0][0][2][0][RTW89_KCC][19] = 78,
+ [0][0][2][0][RTW89_ACMA][19] = 62,
+ [0][0][2][0][RTW89_CN][19] = 127,
+ [0][0][2][0][RTW89_UK][19] = 62,
+ [0][0][2][0][RTW89_FCC][21] = 82,
+ [0][0][2][0][RTW89_ETSI][21] = 62,
+ [0][0][2][0][RTW89_MKK][21] = 78,
+ [0][0][2][0][RTW89_IC][21] = 82,
+ [0][0][2][0][RTW89_KCC][21] = 78,
+ [0][0][2][0][RTW89_ACMA][21] = 62,
+ [0][0][2][0][RTW89_CN][21] = 127,
+ [0][0][2][0][RTW89_UK][21] = 62,
+ [0][0][2][0][RTW89_FCC][23] = 82,
+ [0][0][2][0][RTW89_ETSI][23] = 62,
+ [0][0][2][0][RTW89_MKK][23] = 78,
+ [0][0][2][0][RTW89_IC][23] = 82,
+ [0][0][2][0][RTW89_KCC][23] = 78,
+ [0][0][2][0][RTW89_ACMA][23] = 62,
+ [0][0][2][0][RTW89_CN][23] = 127,
+ [0][0][2][0][RTW89_UK][23] = 62,
+ [0][0][2][0][RTW89_FCC][25] = 82,
+ [0][0][2][0][RTW89_ETSI][25] = 62,
+ [0][0][2][0][RTW89_MKK][25] = 78,
+ [0][0][2][0][RTW89_IC][25] = 127,
+ [0][0][2][0][RTW89_KCC][25] = 78,
+ [0][0][2][0][RTW89_ACMA][25] = 127,
+ [0][0][2][0][RTW89_CN][25] = 127,
+ [0][0][2][0][RTW89_UK][25] = 62,
+ [0][0][2][0][RTW89_FCC][27] = 82,
+ [0][0][2][0][RTW89_ETSI][27] = 62,
+ [0][0][2][0][RTW89_MKK][27] = 78,
+ [0][0][2][0][RTW89_IC][27] = 127,
+ [0][0][2][0][RTW89_KCC][27] = 78,
+ [0][0][2][0][RTW89_ACMA][27] = 127,
+ [0][0][2][0][RTW89_CN][27] = 127,
+ [0][0][2][0][RTW89_UK][27] = 62,
+ [0][0][2][0][RTW89_FCC][29] = 82,
+ [0][0][2][0][RTW89_ETSI][29] = 62,
+ [0][0][2][0][RTW89_MKK][29] = 78,
+ [0][0][2][0][RTW89_IC][29] = 127,
+ [0][0][2][0][RTW89_KCC][29] = 78,
+ [0][0][2][0][RTW89_ACMA][29] = 127,
+ [0][0][2][0][RTW89_CN][29] = 127,
+ [0][0][2][0][RTW89_UK][29] = 62,
+ [0][0][2][0][RTW89_FCC][31] = 82,
+ [0][0][2][0][RTW89_ETSI][31] = 62,
+ [0][0][2][0][RTW89_MKK][31] = 78,
+ [0][0][2][0][RTW89_IC][31] = 82,
+ [0][0][2][0][RTW89_KCC][31] = 74,
+ [0][0][2][0][RTW89_ACMA][31] = 62,
+ [0][0][2][0][RTW89_CN][31] = 127,
+ [0][0][2][0][RTW89_UK][31] = 62,
+ [0][0][2][0][RTW89_FCC][33] = 82,
+ [0][0][2][0][RTW89_ETSI][33] = 62,
+ [0][0][2][0][RTW89_MKK][33] = 78,
+ [0][0][2][0][RTW89_IC][33] = 82,
+ [0][0][2][0][RTW89_KCC][33] = 74,
+ [0][0][2][0][RTW89_ACMA][33] = 62,
+ [0][0][2][0][RTW89_CN][33] = 127,
+ [0][0][2][0][RTW89_UK][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_KCC][35] = 74,
+ [0][0][2][0][RTW89_ACMA][35] = 62,
+ [0][0][2][0][RTW89_CN][35] = 127,
+ [0][0][2][0][RTW89_UK][35] = 62,
+ [0][0][2][0][RTW89_FCC][37] = 82,
+ [0][0][2][0][RTW89_ETSI][37] = 127,
+ [0][0][2][0][RTW89_MKK][37] = 78,
+ [0][0][2][0][RTW89_IC][37] = 82,
+ [0][0][2][0][RTW89_KCC][37] = 76,
+ [0][0][2][0][RTW89_ACMA][37] = 78,
+ [0][0][2][0][RTW89_CN][37] = 127,
+ [0][0][2][0][RTW89_UK][37] = 78,
+ [0][0][2][0][RTW89_FCC][38] = 82,
+ [0][0][2][0][RTW89_ETSI][38] = 30,
+ [0][0][2][0][RTW89_MKK][38] = 127,
+ [0][0][2][0][RTW89_IC][38] = 82,
+ [0][0][2][0][RTW89_KCC][38] = 66,
+ [0][0][2][0][RTW89_ACMA][38] = 78,
+ [0][0][2][0][RTW89_CN][38] = 78,
+ [0][0][2][0][RTW89_UK][38] = 60,
+ [0][0][2][0][RTW89_FCC][40] = 82,
+ [0][0][2][0][RTW89_ETSI][40] = 30,
+ [0][0][2][0][RTW89_MKK][40] = 127,
+ [0][0][2][0][RTW89_IC][40] = 82,
+ [0][0][2][0][RTW89_KCC][40] = 74,
+ [0][0][2][0][RTW89_ACMA][40] = 78,
+ [0][0][2][0][RTW89_CN][40] = 78,
+ [0][0][2][0][RTW89_UK][40] = 60,
+ [0][0][2][0][RTW89_FCC][42] = 82,
+ [0][0][2][0][RTW89_ETSI][42] = 30,
+ [0][0][2][0][RTW89_MKK][42] = 127,
+ [0][0][2][0][RTW89_IC][42] = 82,
+ [0][0][2][0][RTW89_KCC][42] = 74,
+ [0][0][2][0][RTW89_ACMA][42] = 78,
+ [0][0][2][0][RTW89_CN][42] = 78,
+ [0][0][2][0][RTW89_UK][42] = 60,
+ [0][0][2][0][RTW89_FCC][44] = 82,
+ [0][0][2][0][RTW89_ETSI][44] = 30,
+ [0][0][2][0][RTW89_MKK][44] = 127,
+ [0][0][2][0][RTW89_IC][44] = 82,
+ [0][0][2][0][RTW89_KCC][44] = 74,
+ [0][0][2][0][RTW89_ACMA][44] = 78,
+ [0][0][2][0][RTW89_CN][44] = 78,
+ [0][0][2][0][RTW89_UK][44] = 60,
+ [0][0][2][0][RTW89_FCC][46] = 82,
+ [0][0][2][0][RTW89_ETSI][46] = 30,
+ [0][0][2][0][RTW89_MKK][46] = 127,
+ [0][0][2][0][RTW89_IC][46] = 82,
+ [0][0][2][0][RTW89_KCC][46] = 74,
+ [0][0][2][0][RTW89_ACMA][46] = 78,
+ [0][0][2][0][RTW89_CN][46] = 78,
+ [0][0][2][0][RTW89_UK][46] = 60,
+ [0][0][2][0][RTW89_FCC][48] = 74,
+ [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_KCC][48] = 127,
+ [0][0][2][0][RTW89_ACMA][48] = 127,
+ [0][0][2][0][RTW89_CN][48] = 127,
+ [0][0][2][0][RTW89_UK][48] = 127,
+ [0][0][2][0][RTW89_FCC][50] = 76,
+ [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_KCC][50] = 127,
+ [0][0][2][0][RTW89_ACMA][50] = 127,
+ [0][0][2][0][RTW89_CN][50] = 127,
+ [0][0][2][0][RTW89_UK][50] = 127,
+ [0][0][2][0][RTW89_FCC][52] = 76,
+ [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_KCC][52] = 127,
+ [0][0][2][0][RTW89_ACMA][52] = 127,
+ [0][0][2][0][RTW89_CN][52] = 127,
+ [0][0][2][0][RTW89_UK][52] = 127,
+ [0][1][2][0][RTW89_FCC][0] = 127,
+ [0][1][2][0][RTW89_ETSI][0] = 127,
+ [0][1][2][0][RTW89_MKK][0] = 127,
+ [0][1][2][0][RTW89_IC][0] = 127,
+ [0][1][2][0][RTW89_KCC][0] = 127,
+ [0][1][2][0][RTW89_ACMA][0] = 127,
+ [0][1][2][0][RTW89_CN][0] = 127,
+ [0][1][2][0][RTW89_UK][0] = 127,
+ [0][1][2][0][RTW89_FCC][2] = 127,
+ [0][1][2][0][RTW89_ETSI][2] = 127,
+ [0][1][2][0][RTW89_MKK][2] = 127,
+ [0][1][2][0][RTW89_IC][2] = 127,
+ [0][1][2][0][RTW89_KCC][2] = 127,
+ [0][1][2][0][RTW89_ACMA][2] = 127,
+ [0][1][2][0][RTW89_CN][2] = 127,
+ [0][1][2][0][RTW89_UK][2] = 127,
+ [0][1][2][0][RTW89_FCC][4] = 127,
+ [0][1][2][0][RTW89_ETSI][4] = 127,
+ [0][1][2][0][RTW89_MKK][4] = 127,
+ [0][1][2][0][RTW89_IC][4] = 127,
+ [0][1][2][0][RTW89_KCC][4] = 127,
+ [0][1][2][0][RTW89_ACMA][4] = 127,
+ [0][1][2][0][RTW89_CN][4] = 127,
+ [0][1][2][0][RTW89_UK][4] = 127,
+ [0][1][2][0][RTW89_FCC][6] = 127,
+ [0][1][2][0][RTW89_ETSI][6] = 127,
+ [0][1][2][0][RTW89_MKK][6] = 127,
+ [0][1][2][0][RTW89_IC][6] = 127,
+ [0][1][2][0][RTW89_KCC][6] = 127,
+ [0][1][2][0][RTW89_ACMA][6] = 127,
+ [0][1][2][0][RTW89_CN][6] = 127,
+ [0][1][2][0][RTW89_UK][6] = 127,
+ [0][1][2][0][RTW89_FCC][8] = 127,
+ [0][1][2][0][RTW89_ETSI][8] = 127,
+ [0][1][2][0][RTW89_MKK][8] = 127,
+ [0][1][2][0][RTW89_IC][8] = 127,
+ [0][1][2][0][RTW89_KCC][8] = 127,
+ [0][1][2][0][RTW89_ACMA][8] = 127,
+ [0][1][2][0][RTW89_CN][8] = 127,
+ [0][1][2][0][RTW89_UK][8] = 127,
+ [0][1][2][0][RTW89_FCC][10] = 127,
+ [0][1][2][0][RTW89_ETSI][10] = 127,
+ [0][1][2][0][RTW89_MKK][10] = 127,
+ [0][1][2][0][RTW89_IC][10] = 127,
+ [0][1][2][0][RTW89_KCC][10] = 127,
+ [0][1][2][0][RTW89_ACMA][10] = 127,
+ [0][1][2][0][RTW89_CN][10] = 127,
+ [0][1][2][0][RTW89_UK][10] = 127,
+ [0][1][2][0][RTW89_FCC][12] = 127,
+ [0][1][2][0][RTW89_ETSI][12] = 127,
+ [0][1][2][0][RTW89_MKK][12] = 127,
+ [0][1][2][0][RTW89_IC][12] = 127,
+ [0][1][2][0][RTW89_KCC][12] = 127,
+ [0][1][2][0][RTW89_ACMA][12] = 127,
+ [0][1][2][0][RTW89_CN][12] = 127,
+ [0][1][2][0][RTW89_UK][12] = 127,
+ [0][1][2][0][RTW89_FCC][14] = 127,
+ [0][1][2][0][RTW89_ETSI][14] = 127,
+ [0][1][2][0][RTW89_MKK][14] = 127,
+ [0][1][2][0][RTW89_IC][14] = 127,
+ [0][1][2][0][RTW89_KCC][14] = 127,
+ [0][1][2][0][RTW89_ACMA][14] = 127,
+ [0][1][2][0][RTW89_CN][14] = 127,
+ [0][1][2][0][RTW89_UK][14] = 127,
+ [0][1][2][0][RTW89_FCC][15] = 127,
+ [0][1][2][0][RTW89_ETSI][15] = 127,
+ [0][1][2][0][RTW89_MKK][15] = 127,
+ [0][1][2][0][RTW89_IC][15] = 127,
+ [0][1][2][0][RTW89_KCC][15] = 127,
+ [0][1][2][0][RTW89_ACMA][15] = 127,
+ [0][1][2][0][RTW89_CN][15] = 127,
+ [0][1][2][0][RTW89_UK][15] = 127,
+ [0][1][2][0][RTW89_FCC][17] = 127,
+ [0][1][2][0][RTW89_ETSI][17] = 127,
+ [0][1][2][0][RTW89_MKK][17] = 127,
+ [0][1][2][0][RTW89_IC][17] = 127,
+ [0][1][2][0][RTW89_KCC][17] = 127,
+ [0][1][2][0][RTW89_ACMA][17] = 127,
+ [0][1][2][0][RTW89_CN][17] = 127,
+ [0][1][2][0][RTW89_UK][17] = 127,
+ [0][1][2][0][RTW89_FCC][19] = 127,
+ [0][1][2][0][RTW89_ETSI][19] = 127,
+ [0][1][2][0][RTW89_MKK][19] = 127,
+ [0][1][2][0][RTW89_IC][19] = 127,
+ [0][1][2][0][RTW89_KCC][19] = 127,
+ [0][1][2][0][RTW89_ACMA][19] = 127,
+ [0][1][2][0][RTW89_CN][19] = 127,
+ [0][1][2][0][RTW89_UK][19] = 127,
+ [0][1][2][0][RTW89_FCC][21] = 127,
+ [0][1][2][0][RTW89_ETSI][21] = 127,
+ [0][1][2][0][RTW89_MKK][21] = 127,
+ [0][1][2][0][RTW89_IC][21] = 127,
+ [0][1][2][0][RTW89_KCC][21] = 127,
+ [0][1][2][0][RTW89_ACMA][21] = 127,
+ [0][1][2][0][RTW89_CN][21] = 127,
+ [0][1][2][0][RTW89_UK][21] = 127,
+ [0][1][2][0][RTW89_FCC][23] = 127,
+ [0][1][2][0][RTW89_ETSI][23] = 127,
+ [0][1][2][0][RTW89_MKK][23] = 127,
+ [0][1][2][0][RTW89_IC][23] = 127,
+ [0][1][2][0][RTW89_KCC][23] = 127,
+ [0][1][2][0][RTW89_ACMA][23] = 127,
+ [0][1][2][0][RTW89_CN][23] = 127,
+ [0][1][2][0][RTW89_UK][23] = 127,
+ [0][1][2][0][RTW89_FCC][25] = 127,
+ [0][1][2][0][RTW89_ETSI][25] = 127,
+ [0][1][2][0][RTW89_MKK][25] = 127,
+ [0][1][2][0][RTW89_IC][25] = 127,
+ [0][1][2][0][RTW89_KCC][25] = 127,
+ [0][1][2][0][RTW89_ACMA][25] = 127,
+ [0][1][2][0][RTW89_CN][25] = 127,
+ [0][1][2][0][RTW89_UK][25] = 127,
+ [0][1][2][0][RTW89_FCC][27] = 127,
+ [0][1][2][0][RTW89_ETSI][27] = 127,
+ [0][1][2][0][RTW89_MKK][27] = 127,
+ [0][1][2][0][RTW89_IC][27] = 127,
+ [0][1][2][0][RTW89_KCC][27] = 127,
+ [0][1][2][0][RTW89_ACMA][27] = 127,
+ [0][1][2][0][RTW89_CN][27] = 127,
+ [0][1][2][0][RTW89_UK][27] = 127,
+ [0][1][2][0][RTW89_FCC][29] = 127,
+ [0][1][2][0][RTW89_ETSI][29] = 127,
+ [0][1][2][0][RTW89_MKK][29] = 127,
+ [0][1][2][0][RTW89_IC][29] = 127,
+ [0][1][2][0][RTW89_KCC][29] = 127,
+ [0][1][2][0][RTW89_ACMA][29] = 127,
+ [0][1][2][0][RTW89_CN][29] = 127,
+ [0][1][2][0][RTW89_UK][29] = 127,
+ [0][1][2][0][RTW89_FCC][31] = 127,
+ [0][1][2][0][RTW89_ETSI][31] = 127,
+ [0][1][2][0][RTW89_MKK][31] = 127,
+ [0][1][2][0][RTW89_IC][31] = 127,
+ [0][1][2][0][RTW89_KCC][31] = 127,
+ [0][1][2][0][RTW89_ACMA][31] = 127,
+ [0][1][2][0][RTW89_CN][31] = 127,
+ [0][1][2][0][RTW89_UK][31] = 127,
+ [0][1][2][0][RTW89_FCC][33] = 127,
+ [0][1][2][0][RTW89_ETSI][33] = 127,
+ [0][1][2][0][RTW89_MKK][33] = 127,
+ [0][1][2][0][RTW89_IC][33] = 127,
+ [0][1][2][0][RTW89_KCC][33] = 127,
+ [0][1][2][0][RTW89_ACMA][33] = 127,
+ [0][1][2][0][RTW89_CN][33] = 127,
+ [0][1][2][0][RTW89_UK][33] = 127,
+ [0][1][2][0][RTW89_FCC][35] = 127,
+ [0][1][2][0][RTW89_ETSI][35] = 127,
+ [0][1][2][0][RTW89_MKK][35] = 127,
+ [0][1][2][0][RTW89_IC][35] = 127,
+ [0][1][2][0][RTW89_KCC][35] = 127,
+ [0][1][2][0][RTW89_ACMA][35] = 127,
+ [0][1][2][0][RTW89_CN][35] = 127,
+ [0][1][2][0][RTW89_UK][35] = 127,
+ [0][1][2][0][RTW89_FCC][37] = 127,
+ [0][1][2][0][RTW89_ETSI][37] = 127,
+ [0][1][2][0][RTW89_MKK][37] = 127,
+ [0][1][2][0][RTW89_IC][37] = 127,
+ [0][1][2][0][RTW89_KCC][37] = 127,
+ [0][1][2][0][RTW89_ACMA][37] = 127,
+ [0][1][2][0][RTW89_CN][37] = 127,
+ [0][1][2][0][RTW89_UK][37] = 127,
+ [0][1][2][0][RTW89_FCC][38] = 127,
+ [0][1][2][0][RTW89_ETSI][38] = 127,
+ [0][1][2][0][RTW89_MKK][38] = 127,
+ [0][1][2][0][RTW89_IC][38] = 127,
+ [0][1][2][0][RTW89_KCC][38] = 127,
+ [0][1][2][0][RTW89_ACMA][38] = 127,
+ [0][1][2][0][RTW89_CN][38] = 127,
+ [0][1][2][0][RTW89_UK][38] = 127,
+ [0][1][2][0][RTW89_FCC][40] = 127,
+ [0][1][2][0][RTW89_ETSI][40] = 127,
+ [0][1][2][0][RTW89_MKK][40] = 127,
+ [0][1][2][0][RTW89_IC][40] = 127,
+ [0][1][2][0][RTW89_KCC][40] = 127,
+ [0][1][2][0][RTW89_ACMA][40] = 127,
+ [0][1][2][0][RTW89_CN][40] = 127,
+ [0][1][2][0][RTW89_UK][40] = 127,
+ [0][1][2][0][RTW89_FCC][42] = 127,
+ [0][1][2][0][RTW89_ETSI][42] = 127,
+ [0][1][2][0][RTW89_MKK][42] = 127,
+ [0][1][2][0][RTW89_IC][42] = 127,
+ [0][1][2][0][RTW89_KCC][42] = 127,
+ [0][1][2][0][RTW89_ACMA][42] = 127,
+ [0][1][2][0][RTW89_CN][42] = 127,
+ [0][1][2][0][RTW89_UK][42] = 127,
+ [0][1][2][0][RTW89_FCC][44] = 127,
+ [0][1][2][0][RTW89_ETSI][44] = 127,
+ [0][1][2][0][RTW89_MKK][44] = 127,
+ [0][1][2][0][RTW89_IC][44] = 127,
+ [0][1][2][0][RTW89_KCC][44] = 127,
+ [0][1][2][0][RTW89_ACMA][44] = 127,
+ [0][1][2][0][RTW89_CN][44] = 127,
+ [0][1][2][0][RTW89_UK][44] = 127,
+ [0][1][2][0][RTW89_FCC][46] = 127,
+ [0][1][2][0][RTW89_ETSI][46] = 127,
+ [0][1][2][0][RTW89_MKK][46] = 127,
+ [0][1][2][0][RTW89_IC][46] = 127,
+ [0][1][2][0][RTW89_KCC][46] = 127,
+ [0][1][2][0][RTW89_ACMA][46] = 127,
+ [0][1][2][0][RTW89_CN][46] = 127,
+ [0][1][2][0][RTW89_UK][46] = 127,
+ [0][1][2][0][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][2][0][RTW89_ACMA][48] = 127,
+ [0][1][2][0][RTW89_CN][48] = 127,
+ [0][1][2][0][RTW89_UK][48] = 127,
+ [0][1][2][0][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][2][0][RTW89_ACMA][50] = 127,
+ [0][1][2][0][RTW89_CN][50] = 127,
+ [0][1][2][0][RTW89_UK][50] = 127,
+ [0][1][2][0][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][2][0][RTW89_ACMA][52] = 127,
+ [0][1][2][0][RTW89_CN][52] = 127,
+ [0][1][2][0][RTW89_UK][52] = 127,
+ [0][1][2][1][RTW89_FCC][0] = 127,
+ [0][1][2][1][RTW89_ETSI][0] = 127,
+ [0][1][2][1][RTW89_MKK][0] = 127,
+ [0][1][2][1][RTW89_IC][0] = 127,
+ [0][1][2][1][RTW89_KCC][0] = 127,
+ [0][1][2][1][RTW89_ACMA][0] = 127,
+ [0][1][2][1][RTW89_CN][0] = 127,
+ [0][1][2][1][RTW89_UK][0] = 127,
+ [0][1][2][1][RTW89_FCC][2] = 127,
+ [0][1][2][1][RTW89_ETSI][2] = 127,
+ [0][1][2][1][RTW89_MKK][2] = 127,
+ [0][1][2][1][RTW89_IC][2] = 127,
+ [0][1][2][1][RTW89_KCC][2] = 127,
+ [0][1][2][1][RTW89_ACMA][2] = 127,
+ [0][1][2][1][RTW89_CN][2] = 127,
+ [0][1][2][1][RTW89_UK][2] = 127,
+ [0][1][2][1][RTW89_FCC][4] = 127,
+ [0][1][2][1][RTW89_ETSI][4] = 127,
+ [0][1][2][1][RTW89_MKK][4] = 127,
+ [0][1][2][1][RTW89_IC][4] = 127,
+ [0][1][2][1][RTW89_KCC][4] = 127,
+ [0][1][2][1][RTW89_ACMA][4] = 127,
+ [0][1][2][1][RTW89_CN][4] = 127,
+ [0][1][2][1][RTW89_UK][4] = 127,
+ [0][1][2][1][RTW89_FCC][6] = 127,
+ [0][1][2][1][RTW89_ETSI][6] = 127,
+ [0][1][2][1][RTW89_MKK][6] = 127,
+ [0][1][2][1][RTW89_IC][6] = 127,
+ [0][1][2][1][RTW89_KCC][6] = 127,
+ [0][1][2][1][RTW89_ACMA][6] = 127,
+ [0][1][2][1][RTW89_CN][6] = 127,
+ [0][1][2][1][RTW89_UK][6] = 127,
+ [0][1][2][1][RTW89_FCC][8] = 127,
+ [0][1][2][1][RTW89_ETSI][8] = 127,
+ [0][1][2][1][RTW89_MKK][8] = 127,
+ [0][1][2][1][RTW89_IC][8] = 127,
+ [0][1][2][1][RTW89_KCC][8] = 127,
+ [0][1][2][1][RTW89_ACMA][8] = 127,
+ [0][1][2][1][RTW89_CN][8] = 127,
+ [0][1][2][1][RTW89_UK][8] = 127,
+ [0][1][2][1][RTW89_FCC][10] = 127,
+ [0][1][2][1][RTW89_ETSI][10] = 127,
+ [0][1][2][1][RTW89_MKK][10] = 127,
+ [0][1][2][1][RTW89_IC][10] = 127,
+ [0][1][2][1][RTW89_KCC][10] = 127,
+ [0][1][2][1][RTW89_ACMA][10] = 127,
+ [0][1][2][1][RTW89_CN][10] = 127,
+ [0][1][2][1][RTW89_UK][10] = 127,
+ [0][1][2][1][RTW89_FCC][12] = 127,
+ [0][1][2][1][RTW89_ETSI][12] = 127,
+ [0][1][2][1][RTW89_MKK][12] = 127,
+ [0][1][2][1][RTW89_IC][12] = 127,
+ [0][1][2][1][RTW89_KCC][12] = 127,
+ [0][1][2][1][RTW89_ACMA][12] = 127,
+ [0][1][2][1][RTW89_CN][12] = 127,
+ [0][1][2][1][RTW89_UK][12] = 127,
+ [0][1][2][1][RTW89_FCC][14] = 127,
+ [0][1][2][1][RTW89_ETSI][14] = 127,
+ [0][1][2][1][RTW89_MKK][14] = 127,
+ [0][1][2][1][RTW89_IC][14] = 127,
+ [0][1][2][1][RTW89_KCC][14] = 127,
+ [0][1][2][1][RTW89_ACMA][14] = 127,
+ [0][1][2][1][RTW89_CN][14] = 127,
+ [0][1][2][1][RTW89_UK][14] = 127,
+ [0][1][2][1][RTW89_FCC][15] = 127,
+ [0][1][2][1][RTW89_ETSI][15] = 127,
+ [0][1][2][1][RTW89_MKK][15] = 127,
+ [0][1][2][1][RTW89_IC][15] = 127,
+ [0][1][2][1][RTW89_KCC][15] = 127,
+ [0][1][2][1][RTW89_ACMA][15] = 127,
+ [0][1][2][1][RTW89_CN][15] = 127,
+ [0][1][2][1][RTW89_UK][15] = 127,
+ [0][1][2][1][RTW89_FCC][17] = 127,
+ [0][1][2][1][RTW89_ETSI][17] = 127,
+ [0][1][2][1][RTW89_MKK][17] = 127,
+ [0][1][2][1][RTW89_IC][17] = 127,
+ [0][1][2][1][RTW89_KCC][17] = 127,
+ [0][1][2][1][RTW89_ACMA][17] = 127,
+ [0][1][2][1][RTW89_CN][17] = 127,
+ [0][1][2][1][RTW89_UK][17] = 127,
+ [0][1][2][1][RTW89_FCC][19] = 127,
+ [0][1][2][1][RTW89_ETSI][19] = 127,
+ [0][1][2][1][RTW89_MKK][19] = 127,
+ [0][1][2][1][RTW89_IC][19] = 127,
+ [0][1][2][1][RTW89_KCC][19] = 127,
+ [0][1][2][1][RTW89_ACMA][19] = 127,
+ [0][1][2][1][RTW89_CN][19] = 127,
+ [0][1][2][1][RTW89_UK][19] = 127,
+ [0][1][2][1][RTW89_FCC][21] = 127,
+ [0][1][2][1][RTW89_ETSI][21] = 127,
+ [0][1][2][1][RTW89_MKK][21] = 127,
+ [0][1][2][1][RTW89_IC][21] = 127,
+ [0][1][2][1][RTW89_KCC][21] = 127,
+ [0][1][2][1][RTW89_ACMA][21] = 127,
+ [0][1][2][1][RTW89_CN][21] = 127,
+ [0][1][2][1][RTW89_UK][21] = 127,
+ [0][1][2][1][RTW89_FCC][23] = 127,
+ [0][1][2][1][RTW89_ETSI][23] = 127,
+ [0][1][2][1][RTW89_MKK][23] = 127,
+ [0][1][2][1][RTW89_IC][23] = 127,
+ [0][1][2][1][RTW89_KCC][23] = 127,
+ [0][1][2][1][RTW89_ACMA][23] = 127,
+ [0][1][2][1][RTW89_CN][23] = 127,
+ [0][1][2][1][RTW89_UK][23] = 127,
+ [0][1][2][1][RTW89_FCC][25] = 127,
+ [0][1][2][1][RTW89_ETSI][25] = 127,
+ [0][1][2][1][RTW89_MKK][25] = 127,
+ [0][1][2][1][RTW89_IC][25] = 127,
+ [0][1][2][1][RTW89_KCC][25] = 127,
+ [0][1][2][1][RTW89_ACMA][25] = 127,
+ [0][1][2][1][RTW89_CN][25] = 127,
+ [0][1][2][1][RTW89_UK][25] = 127,
+ [0][1][2][1][RTW89_FCC][27] = 127,
+ [0][1][2][1][RTW89_ETSI][27] = 127,
+ [0][1][2][1][RTW89_MKK][27] = 127,
+ [0][1][2][1][RTW89_IC][27] = 127,
+ [0][1][2][1][RTW89_KCC][27] = 127,
+ [0][1][2][1][RTW89_ACMA][27] = 127,
+ [0][1][2][1][RTW89_CN][27] = 127,
+ [0][1][2][1][RTW89_UK][27] = 127,
+ [0][1][2][1][RTW89_FCC][29] = 127,
+ [0][1][2][1][RTW89_ETSI][29] = 127,
+ [0][1][2][1][RTW89_MKK][29] = 127,
+ [0][1][2][1][RTW89_IC][29] = 127,
+ [0][1][2][1][RTW89_KCC][29] = 127,
+ [0][1][2][1][RTW89_ACMA][29] = 127,
+ [0][1][2][1][RTW89_CN][29] = 127,
+ [0][1][2][1][RTW89_UK][29] = 127,
+ [0][1][2][1][RTW89_FCC][31] = 127,
+ [0][1][2][1][RTW89_ETSI][31] = 127,
+ [0][1][2][1][RTW89_MKK][31] = 127,
+ [0][1][2][1][RTW89_IC][31] = 127,
+ [0][1][2][1][RTW89_KCC][31] = 127,
+ [0][1][2][1][RTW89_ACMA][31] = 127,
+ [0][1][2][1][RTW89_CN][31] = 127,
+ [0][1][2][1][RTW89_UK][31] = 127,
+ [0][1][2][1][RTW89_FCC][33] = 127,
+ [0][1][2][1][RTW89_ETSI][33] = 127,
+ [0][1][2][1][RTW89_MKK][33] = 127,
+ [0][1][2][1][RTW89_IC][33] = 127,
+ [0][1][2][1][RTW89_KCC][33] = 127,
+ [0][1][2][1][RTW89_ACMA][33] = 127,
+ [0][1][2][1][RTW89_CN][33] = 127,
+ [0][1][2][1][RTW89_UK][33] = 127,
+ [0][1][2][1][RTW89_FCC][35] = 127,
+ [0][1][2][1][RTW89_ETSI][35] = 127,
+ [0][1][2][1][RTW89_MKK][35] = 127,
+ [0][1][2][1][RTW89_IC][35] = 127,
+ [0][1][2][1][RTW89_KCC][35] = 127,
+ [0][1][2][1][RTW89_ACMA][35] = 127,
+ [0][1][2][1][RTW89_CN][35] = 127,
+ [0][1][2][1][RTW89_UK][35] = 127,
+ [0][1][2][1][RTW89_FCC][37] = 127,
+ [0][1][2][1][RTW89_ETSI][37] = 127,
+ [0][1][2][1][RTW89_MKK][37] = 127,
+ [0][1][2][1][RTW89_IC][37] = 127,
+ [0][1][2][1][RTW89_KCC][37] = 127,
+ [0][1][2][1][RTW89_ACMA][37] = 127,
+ [0][1][2][1][RTW89_CN][37] = 127,
+ [0][1][2][1][RTW89_UK][37] = 127,
+ [0][1][2][1][RTW89_FCC][38] = 127,
+ [0][1][2][1][RTW89_ETSI][38] = 127,
+ [0][1][2][1][RTW89_MKK][38] = 127,
+ [0][1][2][1][RTW89_IC][38] = 127,
+ [0][1][2][1][RTW89_KCC][38] = 127,
+ [0][1][2][1][RTW89_ACMA][38] = 127,
+ [0][1][2][1][RTW89_CN][38] = 127,
+ [0][1][2][1][RTW89_UK][38] = 127,
+ [0][1][2][1][RTW89_FCC][40] = 127,
+ [0][1][2][1][RTW89_ETSI][40] = 127,
+ [0][1][2][1][RTW89_MKK][40] = 127,
+ [0][1][2][1][RTW89_IC][40] = 127,
+ [0][1][2][1][RTW89_KCC][40] = 127,
+ [0][1][2][1][RTW89_ACMA][40] = 127,
+ [0][1][2][1][RTW89_CN][40] = 127,
+ [0][1][2][1][RTW89_UK][40] = 127,
+ [0][1][2][1][RTW89_FCC][42] = 127,
+ [0][1][2][1][RTW89_ETSI][42] = 127,
+ [0][1][2][1][RTW89_MKK][42] = 127,
+ [0][1][2][1][RTW89_IC][42] = 127,
+ [0][1][2][1][RTW89_KCC][42] = 127,
+ [0][1][2][1][RTW89_ACMA][42] = 127,
+ [0][1][2][1][RTW89_CN][42] = 127,
+ [0][1][2][1][RTW89_UK][42] = 127,
+ [0][1][2][1][RTW89_FCC][44] = 127,
+ [0][1][2][1][RTW89_ETSI][44] = 127,
+ [0][1][2][1][RTW89_MKK][44] = 127,
+ [0][1][2][1][RTW89_IC][44] = 127,
+ [0][1][2][1][RTW89_KCC][44] = 127,
+ [0][1][2][1][RTW89_ACMA][44] = 127,
+ [0][1][2][1][RTW89_CN][44] = 127,
+ [0][1][2][1][RTW89_UK][44] = 127,
+ [0][1][2][1][RTW89_FCC][46] = 127,
+ [0][1][2][1][RTW89_ETSI][46] = 127,
+ [0][1][2][1][RTW89_MKK][46] = 127,
+ [0][1][2][1][RTW89_IC][46] = 127,
+ [0][1][2][1][RTW89_KCC][46] = 127,
+ [0][1][2][1][RTW89_ACMA][46] = 127,
+ [0][1][2][1][RTW89_CN][46] = 127,
+ [0][1][2][1][RTW89_UK][46] = 127,
+ [0][1][2][1][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][2][1][RTW89_ACMA][48] = 127,
+ [0][1][2][1][RTW89_CN][48] = 127,
+ [0][1][2][1][RTW89_UK][48] = 127,
+ [0][1][2][1][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][2][1][RTW89_ACMA][50] = 127,
+ [0][1][2][1][RTW89_CN][50] = 127,
+ [0][1][2][1][RTW89_UK][50] = 127,
+ [0][1][2][1][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][2][1][RTW89_ACMA][52] = 127,
+ [0][1][2][1][RTW89_CN][52] = 127,
+ [0][1][2][1][RTW89_UK][52] = 127,
+ [1][0][2][0][RTW89_FCC][1] = 68,
+ [1][0][2][0][RTW89_ETSI][1] = 64,
+ [1][0][2][0][RTW89_MKK][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_KCC][1] = 74,
+ [1][0][2][0][RTW89_ACMA][1] = 64,
+ [1][0][2][0][RTW89_CN][1] = 64,
+ [1][0][2][0][RTW89_UK][1] = 64,
+ [1][0][2][0][RTW89_FCC][5] = 82,
+ [1][0][2][0][RTW89_ETSI][5] = 64,
+ [1][0][2][0][RTW89_MKK][5] = 62,
+ [1][0][2][0][RTW89_IC][5] = 64,
+ [1][0][2][0][RTW89_KCC][5] = 66,
+ [1][0][2][0][RTW89_ACMA][5] = 64,
+ [1][0][2][0][RTW89_CN][5] = 64,
+ [1][0][2][0][RTW89_UK][5] = 64,
+ [1][0][2][0][RTW89_FCC][9] = 82,
+ [1][0][2][0][RTW89_ETSI][9] = 64,
+ [1][0][2][0][RTW89_MKK][9] = 64,
+ [1][0][2][0][RTW89_IC][9] = 64,
+ [1][0][2][0][RTW89_KCC][9] = 78,
+ [1][0][2][0][RTW89_ACMA][9] = 64,
+ [1][0][2][0][RTW89_CN][9] = 64,
+ [1][0][2][0][RTW89_UK][9] = 64,
+ [1][0][2][0][RTW89_FCC][13] = 66,
+ [1][0][2][0][RTW89_ETSI][13] = 64,
+ [1][0][2][0][RTW89_MKK][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_KCC][13] = 72,
+ [1][0][2][0][RTW89_ACMA][13] = 64,
+ [1][0][2][0][RTW89_CN][13] = 64,
+ [1][0][2][0][RTW89_UK][13] = 64,
+ [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_ETSI][16] = 66,
+ [1][0][2][0][RTW89_MKK][16] = 80,
+ [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_KCC][16] = 74,
+ [1][0][2][0][RTW89_ACMA][16] = 66,
+ [1][0][2][0][RTW89_CN][16] = 127,
+ [1][0][2][0][RTW89_UK][16] = 66,
+ [1][0][2][0][RTW89_FCC][20] = 80,
+ [1][0][2][0][RTW89_ETSI][20] = 66,
+ [1][0][2][0][RTW89_MKK][20] = 80,
+ [1][0][2][0][RTW89_IC][20] = 80,
+ [1][0][2][0][RTW89_KCC][20] = 74,
+ [1][0][2][0][RTW89_ACMA][20] = 66,
+ [1][0][2][0][RTW89_CN][20] = 127,
+ [1][0][2][0][RTW89_UK][20] = 66,
+ [1][0][2][0][RTW89_FCC][24] = 80,
+ [1][0][2][0][RTW89_ETSI][24] = 66,
+ [1][0][2][0][RTW89_MKK][24] = 80,
+ [1][0][2][0][RTW89_IC][24] = 127,
+ [1][0][2][0][RTW89_KCC][24] = 74,
+ [1][0][2][0][RTW89_ACMA][24] = 127,
+ [1][0][2][0][RTW89_CN][24] = 127,
+ [1][0][2][0][RTW89_UK][24] = 66,
+ [1][0][2][0][RTW89_FCC][28] = 80,
+ [1][0][2][0][RTW89_ETSI][28] = 66,
+ [1][0][2][0][RTW89_MKK][28] = 80,
+ [1][0][2][0][RTW89_IC][28] = 127,
+ [1][0][2][0][RTW89_KCC][28] = 74,
+ [1][0][2][0][RTW89_ACMA][28] = 127,
+ [1][0][2][0][RTW89_CN][28] = 127,
+ [1][0][2][0][RTW89_UK][28] = 66,
+ [1][0][2][0][RTW89_FCC][32] = 76,
+ [1][0][2][0][RTW89_ETSI][32] = 66,
+ [1][0][2][0][RTW89_MKK][32] = 80,
+ [1][0][2][0][RTW89_IC][32] = 76,
+ [1][0][2][0][RTW89_KCC][32] = 78,
+ [1][0][2][0][RTW89_ACMA][32] = 66,
+ [1][0][2][0][RTW89_CN][32] = 127,
+ [1][0][2][0][RTW89_UK][32] = 66,
+ [1][0][2][0][RTW89_FCC][36] = 80,
+ [1][0][2][0][RTW89_ETSI][36] = 127,
+ [1][0][2][0][RTW89_MKK][36] = 80,
+ [1][0][2][0][RTW89_IC][36] = 80,
+ [1][0][2][0][RTW89_KCC][36] = 76,
+ [1][0][2][0][RTW89_ACMA][36] = 78,
+ [1][0][2][0][RTW89_CN][36] = 127,
+ [1][0][2][0][RTW89_UK][36] = 80,
+ [1][0][2][0][RTW89_FCC][39] = 84,
+ [1][0][2][0][RTW89_ETSI][39] = 30,
+ [1][0][2][0][RTW89_MKK][39] = 127,
+ [1][0][2][0][RTW89_IC][39] = 84,
+ [1][0][2][0][RTW89_KCC][39] = 68,
+ [1][0][2][0][RTW89_ACMA][39] = 80,
+ [1][0][2][0][RTW89_CN][39] = 70,
+ [1][0][2][0][RTW89_UK][39] = 64,
+ [1][0][2][0][RTW89_FCC][43] = 84,
+ [1][0][2][0][RTW89_ETSI][43] = 30,
+ [1][0][2][0][RTW89_MKK][43] = 127,
+ [1][0][2][0][RTW89_IC][43] = 84,
+ [1][0][2][0][RTW89_KCC][43] = 78,
+ [1][0][2][0][RTW89_ACMA][43] = 80,
+ [1][0][2][0][RTW89_CN][43] = 80,
+ [1][0][2][0][RTW89_UK][43] = 64,
+ [1][0][2][0][RTW89_FCC][47] = 84,
+ [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_KCC][47] = 127,
+ [1][0][2][0][RTW89_ACMA][47] = 127,
+ [1][0][2][0][RTW89_CN][47] = 127,
+ [1][0][2][0][RTW89_UK][47] = 127,
+ [1][0][2][0][RTW89_FCC][51] = 84,
+ [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_KCC][51] = 127,
+ [1][0][2][0][RTW89_ACMA][51] = 127,
+ [1][0][2][0][RTW89_CN][51] = 127,
+ [1][0][2][0][RTW89_UK][51] = 127,
+ [1][1][2][0][RTW89_FCC][1] = 127,
+ [1][1][2][0][RTW89_ETSI][1] = 127,
+ [1][1][2][0][RTW89_MKK][1] = 127,
+ [1][1][2][0][RTW89_IC][1] = 127,
+ [1][1][2][0][RTW89_KCC][1] = 127,
+ [1][1][2][0][RTW89_ACMA][1] = 127,
+ [1][1][2][0][RTW89_CN][1] = 127,
+ [1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_FCC][5] = 127,
+ [1][1][2][0][RTW89_ETSI][5] = 127,
+ [1][1][2][0][RTW89_MKK][5] = 127,
+ [1][1][2][0][RTW89_IC][5] = 127,
+ [1][1][2][0][RTW89_KCC][5] = 127,
+ [1][1][2][0][RTW89_ACMA][5] = 127,
+ [1][1][2][0][RTW89_CN][5] = 127,
+ [1][1][2][0][RTW89_UK][5] = 127,
+ [1][1][2][0][RTW89_FCC][9] = 127,
+ [1][1][2][0][RTW89_ETSI][9] = 127,
+ [1][1][2][0][RTW89_MKK][9] = 127,
+ [1][1][2][0][RTW89_IC][9] = 127,
+ [1][1][2][0][RTW89_KCC][9] = 127,
+ [1][1][2][0][RTW89_ACMA][9] = 127,
+ [1][1][2][0][RTW89_CN][9] = 127,
+ [1][1][2][0][RTW89_UK][9] = 127,
+ [1][1][2][0][RTW89_FCC][13] = 127,
+ [1][1][2][0][RTW89_ETSI][13] = 127,
+ [1][1][2][0][RTW89_MKK][13] = 127,
+ [1][1][2][0][RTW89_IC][13] = 127,
+ [1][1][2][0][RTW89_KCC][13] = 127,
+ [1][1][2][0][RTW89_ACMA][13] = 127,
+ [1][1][2][0][RTW89_CN][13] = 127,
+ [1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_FCC][16] = 127,
+ [1][1][2][0][RTW89_ETSI][16] = 127,
+ [1][1][2][0][RTW89_MKK][16] = 127,
+ [1][1][2][0][RTW89_IC][16] = 127,
+ [1][1][2][0][RTW89_KCC][16] = 127,
+ [1][1][2][0][RTW89_ACMA][16] = 127,
+ [1][1][2][0][RTW89_CN][16] = 127,
+ [1][1][2][0][RTW89_UK][16] = 127,
+ [1][1][2][0][RTW89_FCC][20] = 127,
+ [1][1][2][0][RTW89_ETSI][20] = 127,
+ [1][1][2][0][RTW89_MKK][20] = 127,
+ [1][1][2][0][RTW89_IC][20] = 127,
+ [1][1][2][0][RTW89_KCC][20] = 127,
+ [1][1][2][0][RTW89_ACMA][20] = 127,
+ [1][1][2][0][RTW89_CN][20] = 127,
+ [1][1][2][0][RTW89_UK][20] = 127,
+ [1][1][2][0][RTW89_FCC][24] = 127,
+ [1][1][2][0][RTW89_ETSI][24] = 127,
+ [1][1][2][0][RTW89_MKK][24] = 127,
+ [1][1][2][0][RTW89_IC][24] = 127,
+ [1][1][2][0][RTW89_KCC][24] = 127,
+ [1][1][2][0][RTW89_ACMA][24] = 127,
+ [1][1][2][0][RTW89_CN][24] = 127,
+ [1][1][2][0][RTW89_UK][24] = 127,
+ [1][1][2][0][RTW89_FCC][28] = 127,
+ [1][1][2][0][RTW89_ETSI][28] = 127,
+ [1][1][2][0][RTW89_MKK][28] = 127,
+ [1][1][2][0][RTW89_IC][28] = 127,
+ [1][1][2][0][RTW89_KCC][28] = 127,
+ [1][1][2][0][RTW89_ACMA][28] = 127,
+ [1][1][2][0][RTW89_CN][28] = 127,
+ [1][1][2][0][RTW89_UK][28] = 127,
+ [1][1][2][0][RTW89_FCC][32] = 127,
+ [1][1][2][0][RTW89_ETSI][32] = 127,
+ [1][1][2][0][RTW89_MKK][32] = 127,
+ [1][1][2][0][RTW89_IC][32] = 127,
+ [1][1][2][0][RTW89_KCC][32] = 127,
+ [1][1][2][0][RTW89_ACMA][32] = 127,
+ [1][1][2][0][RTW89_CN][32] = 127,
+ [1][1][2][0][RTW89_UK][32] = 127,
+ [1][1][2][0][RTW89_FCC][36] = 127,
+ [1][1][2][0][RTW89_ETSI][36] = 127,
+ [1][1][2][0][RTW89_MKK][36] = 127,
+ [1][1][2][0][RTW89_IC][36] = 127,
+ [1][1][2][0][RTW89_KCC][36] = 127,
+ [1][1][2][0][RTW89_ACMA][36] = 127,
+ [1][1][2][0][RTW89_CN][36] = 127,
+ [1][1][2][0][RTW89_UK][36] = 127,
+ [1][1][2][0][RTW89_FCC][39] = 127,
+ [1][1][2][0][RTW89_ETSI][39] = 127,
+ [1][1][2][0][RTW89_MKK][39] = 127,
+ [1][1][2][0][RTW89_IC][39] = 127,
+ [1][1][2][0][RTW89_KCC][39] = 127,
+ [1][1][2][0][RTW89_ACMA][39] = 127,
+ [1][1][2][0][RTW89_CN][39] = 127,
+ [1][1][2][0][RTW89_UK][39] = 127,
+ [1][1][2][0][RTW89_FCC][43] = 127,
+ [1][1][2][0][RTW89_ETSI][43] = 127,
+ [1][1][2][0][RTW89_MKK][43] = 127,
+ [1][1][2][0][RTW89_IC][43] = 127,
+ [1][1][2][0][RTW89_KCC][43] = 127,
+ [1][1][2][0][RTW89_ACMA][43] = 127,
+ [1][1][2][0][RTW89_CN][43] = 127,
+ [1][1][2][0][RTW89_UK][43] = 127,
+ [1][1][2][0][RTW89_FCC][47] = 127,
+ [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_KCC][47] = 127,
+ [1][1][2][0][RTW89_ACMA][47] = 127,
+ [1][1][2][0][RTW89_CN][47] = 127,
+ [1][1][2][0][RTW89_UK][47] = 127,
+ [1][1][2][0][RTW89_FCC][51] = 127,
+ [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_KCC][51] = 127,
+ [1][1][2][0][RTW89_ACMA][51] = 127,
+ [1][1][2][0][RTW89_CN][51] = 127,
+ [1][1][2][0][RTW89_UK][51] = 127,
+ [1][1][2][1][RTW89_FCC][1] = 127,
+ [1][1][2][1][RTW89_ETSI][1] = 127,
+ [1][1][2][1][RTW89_MKK][1] = 127,
+ [1][1][2][1][RTW89_IC][1] = 127,
+ [1][1][2][1][RTW89_KCC][1] = 127,
+ [1][1][2][1][RTW89_ACMA][1] = 127,
+ [1][1][2][1][RTW89_CN][1] = 127,
+ [1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_FCC][5] = 127,
+ [1][1][2][1][RTW89_ETSI][5] = 127,
+ [1][1][2][1][RTW89_MKK][5] = 127,
+ [1][1][2][1][RTW89_IC][5] = 127,
+ [1][1][2][1][RTW89_KCC][5] = 127,
+ [1][1][2][1][RTW89_ACMA][5] = 127,
+ [1][1][2][1][RTW89_CN][5] = 127,
+ [1][1][2][1][RTW89_UK][5] = 127,
+ [1][1][2][1][RTW89_FCC][9] = 127,
+ [1][1][2][1][RTW89_ETSI][9] = 127,
+ [1][1][2][1][RTW89_MKK][9] = 127,
+ [1][1][2][1][RTW89_IC][9] = 127,
+ [1][1][2][1][RTW89_KCC][9] = 127,
+ [1][1][2][1][RTW89_ACMA][9] = 127,
+ [1][1][2][1][RTW89_CN][9] = 127,
+ [1][1][2][1][RTW89_UK][9] = 127,
+ [1][1][2][1][RTW89_FCC][13] = 127,
+ [1][1][2][1][RTW89_ETSI][13] = 127,
+ [1][1][2][1][RTW89_MKK][13] = 127,
+ [1][1][2][1][RTW89_IC][13] = 127,
+ [1][1][2][1][RTW89_KCC][13] = 127,
+ [1][1][2][1][RTW89_ACMA][13] = 127,
+ [1][1][2][1][RTW89_CN][13] = 127,
+ [1][1][2][1][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_FCC][16] = 127,
+ [1][1][2][1][RTW89_ETSI][16] = 127,
+ [1][1][2][1][RTW89_MKK][16] = 127,
+ [1][1][2][1][RTW89_IC][16] = 127,
+ [1][1][2][1][RTW89_KCC][16] = 127,
+ [1][1][2][1][RTW89_ACMA][16] = 127,
+ [1][1][2][1][RTW89_CN][16] = 127,
+ [1][1][2][1][RTW89_UK][16] = 127,
+ [1][1][2][1][RTW89_FCC][20] = 127,
+ [1][1][2][1][RTW89_ETSI][20] = 127,
+ [1][1][2][1][RTW89_MKK][20] = 127,
+ [1][1][2][1][RTW89_IC][20] = 127,
+ [1][1][2][1][RTW89_KCC][20] = 127,
+ [1][1][2][1][RTW89_ACMA][20] = 127,
+ [1][1][2][1][RTW89_CN][20] = 127,
+ [1][1][2][1][RTW89_UK][20] = 127,
+ [1][1][2][1][RTW89_FCC][24] = 127,
+ [1][1][2][1][RTW89_ETSI][24] = 127,
+ [1][1][2][1][RTW89_MKK][24] = 127,
+ [1][1][2][1][RTW89_IC][24] = 127,
+ [1][1][2][1][RTW89_KCC][24] = 127,
+ [1][1][2][1][RTW89_ACMA][24] = 127,
+ [1][1][2][1][RTW89_CN][24] = 127,
+ [1][1][2][1][RTW89_UK][24] = 127,
+ [1][1][2][1][RTW89_FCC][28] = 127,
+ [1][1][2][1][RTW89_ETSI][28] = 127,
+ [1][1][2][1][RTW89_MKK][28] = 127,
+ [1][1][2][1][RTW89_IC][28] = 127,
+ [1][1][2][1][RTW89_KCC][28] = 127,
+ [1][1][2][1][RTW89_ACMA][28] = 127,
+ [1][1][2][1][RTW89_CN][28] = 127,
+ [1][1][2][1][RTW89_UK][28] = 127,
+ [1][1][2][1][RTW89_FCC][32] = 127,
+ [1][1][2][1][RTW89_ETSI][32] = 127,
+ [1][1][2][1][RTW89_MKK][32] = 127,
+ [1][1][2][1][RTW89_IC][32] = 127,
+ [1][1][2][1][RTW89_KCC][32] = 127,
+ [1][1][2][1][RTW89_ACMA][32] = 127,
+ [1][1][2][1][RTW89_CN][32] = 127,
+ [1][1][2][1][RTW89_UK][32] = 127,
+ [1][1][2][1][RTW89_FCC][36] = 127,
+ [1][1][2][1][RTW89_ETSI][36] = 127,
+ [1][1][2][1][RTW89_MKK][36] = 127,
+ [1][1][2][1][RTW89_IC][36] = 127,
+ [1][1][2][1][RTW89_KCC][36] = 127,
+ [1][1][2][1][RTW89_ACMA][36] = 127,
+ [1][1][2][1][RTW89_CN][36] = 127,
+ [1][1][2][1][RTW89_UK][36] = 127,
+ [1][1][2][1][RTW89_FCC][39] = 127,
+ [1][1][2][1][RTW89_ETSI][39] = 127,
+ [1][1][2][1][RTW89_MKK][39] = 127,
+ [1][1][2][1][RTW89_IC][39] = 127,
+ [1][1][2][1][RTW89_KCC][39] = 127,
+ [1][1][2][1][RTW89_ACMA][39] = 127,
+ [1][1][2][1][RTW89_CN][39] = 127,
+ [1][1][2][1][RTW89_UK][39] = 127,
+ [1][1][2][1][RTW89_FCC][43] = 127,
+ [1][1][2][1][RTW89_ETSI][43] = 127,
+ [1][1][2][1][RTW89_MKK][43] = 127,
+ [1][1][2][1][RTW89_IC][43] = 127,
+ [1][1][2][1][RTW89_KCC][43] = 127,
+ [1][1][2][1][RTW89_ACMA][43] = 127,
+ [1][1][2][1][RTW89_CN][43] = 127,
+ [1][1][2][1][RTW89_UK][43] = 127,
+ [1][1][2][1][RTW89_FCC][47] = 127,
+ [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_KCC][47] = 127,
+ [1][1][2][1][RTW89_ACMA][47] = 127,
+ [1][1][2][1][RTW89_CN][47] = 127,
+ [1][1][2][1][RTW89_UK][47] = 127,
+ [1][1][2][1][RTW89_FCC][51] = 127,
+ [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_KCC][51] = 127,
+ [1][1][2][1][RTW89_ACMA][51] = 127,
+ [1][1][2][1][RTW89_CN][51] = 127,
+ [1][1][2][1][RTW89_UK][51] = 127,
+ [2][0][2][0][RTW89_FCC][3] = 76,
+ [2][0][2][0][RTW89_ETSI][3] = 64,
+ [2][0][2][0][RTW89_MKK][3] = 62,
+ [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_KCC][3] = 72,
+ [2][0][2][0][RTW89_ACMA][3] = 64,
+ [2][0][2][0][RTW89_CN][3] = 64,
+ [2][0][2][0][RTW89_UK][3] = 64,
+ [2][0][2][0][RTW89_FCC][11] = 64,
+ [2][0][2][0][RTW89_ETSI][11] = 64,
+ [2][0][2][0][RTW89_MKK][11] = 64,
+ [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_KCC][11] = 72,
+ [2][0][2][0][RTW89_ACMA][11] = 64,
+ [2][0][2][0][RTW89_CN][11] = 64,
+ [2][0][2][0][RTW89_UK][11] = 64,
+ [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_ETSI][18] = 64,
+ [2][0][2][0][RTW89_MKK][18] = 72,
+ [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_KCC][18] = 72,
+ [2][0][2][0][RTW89_ACMA][18] = 64,
+ [2][0][2][0][RTW89_CN][18] = 127,
+ [2][0][2][0][RTW89_UK][18] = 64,
+ [2][0][2][0][RTW89_FCC][26] = 76,
+ [2][0][2][0][RTW89_ETSI][26] = 64,
+ [2][0][2][0][RTW89_MKK][26] = 72,
+ [2][0][2][0][RTW89_IC][26] = 127,
+ [2][0][2][0][RTW89_KCC][26] = 72,
+ [2][0][2][0][RTW89_ACMA][26] = 127,
+ [2][0][2][0][RTW89_CN][26] = 127,
+ [2][0][2][0][RTW89_UK][26] = 64,
+ [2][0][2][0][RTW89_FCC][34] = 76,
+ [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_KCC][34] = 72,
+ [2][0][2][0][RTW89_ACMA][34] = 72,
+ [2][0][2][0][RTW89_CN][34] = 127,
+ [2][0][2][0][RTW89_UK][34] = 72,
+ [2][0][2][0][RTW89_FCC][41] = 76,
+ [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_KCC][41] = 64,
+ [2][0][2][0][RTW89_ACMA][41] = 72,
+ [2][0][2][0][RTW89_CN][41] = 72,
+ [2][0][2][0][RTW89_UK][41] = 64,
+ [2][0][2][0][RTW89_FCC][49] = 74,
+ [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_KCC][49] = 127,
+ [2][0][2][0][RTW89_ACMA][49] = 127,
+ [2][0][2][0][RTW89_CN][49] = 127,
+ [2][0][2][0][RTW89_UK][49] = 127,
+ [2][1][2][0][RTW89_FCC][3] = 127,
+ [2][1][2][0][RTW89_ETSI][3] = 127,
+ [2][1][2][0][RTW89_MKK][3] = 127,
+ [2][1][2][0][RTW89_IC][3] = 127,
+ [2][1][2][0][RTW89_KCC][3] = 127,
+ [2][1][2][0][RTW89_ACMA][3] = 127,
+ [2][1][2][0][RTW89_CN][3] = 127,
+ [2][1][2][0][RTW89_UK][3] = 127,
+ [2][1][2][0][RTW89_FCC][11] = 127,
+ [2][1][2][0][RTW89_ETSI][11] = 127,
+ [2][1][2][0][RTW89_MKK][11] = 127,
+ [2][1][2][0][RTW89_IC][11] = 127,
+ [2][1][2][0][RTW89_KCC][11] = 127,
+ [2][1][2][0][RTW89_ACMA][11] = 127,
+ [2][1][2][0][RTW89_CN][11] = 127,
+ [2][1][2][0][RTW89_UK][11] = 127,
+ [2][1][2][0][RTW89_FCC][18] = 127,
+ [2][1][2][0][RTW89_ETSI][18] = 127,
+ [2][1][2][0][RTW89_MKK][18] = 127,
+ [2][1][2][0][RTW89_IC][18] = 127,
+ [2][1][2][0][RTW89_KCC][18] = 127,
+ [2][1][2][0][RTW89_ACMA][18] = 127,
+ [2][1][2][0][RTW89_CN][18] = 127,
+ [2][1][2][0][RTW89_UK][18] = 127,
+ [2][1][2][0][RTW89_FCC][26] = 127,
+ [2][1][2][0][RTW89_ETSI][26] = 127,
+ [2][1][2][0][RTW89_MKK][26] = 127,
+ [2][1][2][0][RTW89_IC][26] = 127,
+ [2][1][2][0][RTW89_KCC][26] = 127,
+ [2][1][2][0][RTW89_ACMA][26] = 127,
+ [2][1][2][0][RTW89_CN][26] = 127,
+ [2][1][2][0][RTW89_UK][26] = 127,
+ [2][1][2][0][RTW89_FCC][34] = 127,
+ [2][1][2][0][RTW89_ETSI][34] = 127,
+ [2][1][2][0][RTW89_MKK][34] = 127,
+ [2][1][2][0][RTW89_IC][34] = 127,
+ [2][1][2][0][RTW89_KCC][34] = 127,
+ [2][1][2][0][RTW89_ACMA][34] = 127,
+ [2][1][2][0][RTW89_CN][34] = 127,
+ [2][1][2][0][RTW89_UK][34] = 127,
+ [2][1][2][0][RTW89_FCC][41] = 127,
+ [2][1][2][0][RTW89_ETSI][41] = 127,
+ [2][1][2][0][RTW89_MKK][41] = 127,
+ [2][1][2][0][RTW89_IC][41] = 127,
+ [2][1][2][0][RTW89_KCC][41] = 127,
+ [2][1][2][0][RTW89_ACMA][41] = 127,
+ [2][1][2][0][RTW89_CN][41] = 127,
+ [2][1][2][0][RTW89_UK][41] = 127,
+ [2][1][2][0][RTW89_FCC][49] = 127,
+ [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_KCC][49] = 127,
+ [2][1][2][0][RTW89_ACMA][49] = 127,
+ [2][1][2][0][RTW89_CN][49] = 127,
+ [2][1][2][0][RTW89_UK][49] = 127,
+ [2][1][2][1][RTW89_FCC][3] = 127,
+ [2][1][2][1][RTW89_ETSI][3] = 127,
+ [2][1][2][1][RTW89_MKK][3] = 127,
+ [2][1][2][1][RTW89_IC][3] = 127,
+ [2][1][2][1][RTW89_KCC][3] = 127,
+ [2][1][2][1][RTW89_ACMA][3] = 127,
+ [2][1][2][1][RTW89_CN][3] = 127,
+ [2][1][2][1][RTW89_UK][3] = 127,
+ [2][1][2][1][RTW89_FCC][11] = 127,
+ [2][1][2][1][RTW89_ETSI][11] = 127,
+ [2][1][2][1][RTW89_MKK][11] = 127,
+ [2][1][2][1][RTW89_IC][11] = 127,
+ [2][1][2][1][RTW89_KCC][11] = 127,
+ [2][1][2][1][RTW89_ACMA][11] = 127,
+ [2][1][2][1][RTW89_CN][11] = 127,
+ [2][1][2][1][RTW89_UK][11] = 127,
+ [2][1][2][1][RTW89_FCC][18] = 127,
+ [2][1][2][1][RTW89_ETSI][18] = 127,
+ [2][1][2][1][RTW89_MKK][18] = 127,
+ [2][1][2][1][RTW89_IC][18] = 127,
+ [2][1][2][1][RTW89_KCC][18] = 127,
+ [2][1][2][1][RTW89_ACMA][18] = 127,
+ [2][1][2][1][RTW89_CN][18] = 127,
+ [2][1][2][1][RTW89_UK][18] = 127,
+ [2][1][2][1][RTW89_FCC][26] = 127,
+ [2][1][2][1][RTW89_ETSI][26] = 127,
+ [2][1][2][1][RTW89_MKK][26] = 127,
+ [2][1][2][1][RTW89_IC][26] = 127,
+ [2][1][2][1][RTW89_KCC][26] = 127,
+ [2][1][2][1][RTW89_ACMA][26] = 127,
+ [2][1][2][1][RTW89_CN][26] = 127,
+ [2][1][2][1][RTW89_UK][26] = 127,
+ [2][1][2][1][RTW89_FCC][34] = 127,
+ [2][1][2][1][RTW89_ETSI][34] = 127,
+ [2][1][2][1][RTW89_MKK][34] = 127,
+ [2][1][2][1][RTW89_IC][34] = 127,
+ [2][1][2][1][RTW89_KCC][34] = 127,
+ [2][1][2][1][RTW89_ACMA][34] = 127,
+ [2][1][2][1][RTW89_CN][34] = 127,
+ [2][1][2][1][RTW89_UK][34] = 127,
+ [2][1][2][1][RTW89_FCC][41] = 127,
+ [2][1][2][1][RTW89_ETSI][41] = 127,
+ [2][1][2][1][RTW89_MKK][41] = 127,
+ [2][1][2][1][RTW89_IC][41] = 127,
+ [2][1][2][1][RTW89_KCC][41] = 127,
+ [2][1][2][1][RTW89_ACMA][41] = 127,
+ [2][1][2][1][RTW89_CN][41] = 127,
+ [2][1][2][1][RTW89_UK][41] = 127,
+ [2][1][2][1][RTW89_FCC][49] = 127,
+ [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_KCC][49] = 127,
+ [2][1][2][1][RTW89_ACMA][49] = 127,
+ [2][1][2][1][RTW89_CN][49] = 127,
+ [2][1][2][1][RTW89_UK][49] = 127,
+ [3][0][2][0][RTW89_FCC][7] = 127,
+ [3][0][2][0][RTW89_ETSI][7] = 127,
+ [3][0][2][0][RTW89_MKK][7] = 127,
+ [3][0][2][0][RTW89_IC][7] = 127,
+ [3][0][2][0][RTW89_KCC][7] = 127,
+ [3][0][2][0][RTW89_ACMA][7] = 127,
+ [3][0][2][0][RTW89_CN][7] = 58,
+ [3][0][2][0][RTW89_UK][7] = 127,
+ [3][0][2][0][RTW89_FCC][22] = 127,
+ [3][0][2][0][RTW89_ETSI][22] = 127,
+ [3][0][2][0][RTW89_MKK][22] = 127,
+ [3][0][2][0][RTW89_IC][22] = 127,
+ [3][0][2][0][RTW89_KCC][22] = 127,
+ [3][0][2][0][RTW89_ACMA][22] = 127,
+ [3][0][2][0][RTW89_CN][22] = 58,
+ [3][0][2][0][RTW89_UK][22] = 127,
+ [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_KCC][45] = 127,
+ [3][0][2][0][RTW89_ACMA][45] = 127,
+ [3][0][2][0][RTW89_CN][45] = 127,
+ [3][0][2][0][RTW89_UK][45] = 127,
+ [3][1][2][0][RTW89_FCC][7] = 127,
+ [3][1][2][0][RTW89_ETSI][7] = 127,
+ [3][1][2][0][RTW89_MKK][7] = 127,
+ [3][1][2][0][RTW89_IC][7] = 127,
+ [3][1][2][0][RTW89_KCC][7] = 127,
+ [3][1][2][0][RTW89_ACMA][7] = 127,
+ [3][1][2][0][RTW89_CN][7] = 127,
+ [3][1][2][0][RTW89_UK][7] = 127,
+ [3][1][2][0][RTW89_FCC][22] = 127,
+ [3][1][2][0][RTW89_ETSI][22] = 127,
+ [3][1][2][0][RTW89_MKK][22] = 127,
+ [3][1][2][0][RTW89_IC][22] = 127,
+ [3][1][2][0][RTW89_KCC][22] = 127,
+ [3][1][2][0][RTW89_ACMA][22] = 127,
+ [3][1][2][0][RTW89_CN][22] = 127,
+ [3][1][2][0][RTW89_UK][22] = 127,
+ [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_KCC][45] = 127,
+ [3][1][2][0][RTW89_ACMA][45] = 127,
+ [3][1][2][0][RTW89_CN][45] = 127,
+ [3][1][2][0][RTW89_UK][45] = 127,
+ [3][1][2][1][RTW89_FCC][7] = 127,
+ [3][1][2][1][RTW89_ETSI][7] = 127,
+ [3][1][2][1][RTW89_MKK][7] = 127,
+ [3][1][2][1][RTW89_IC][7] = 127,
+ [3][1][2][1][RTW89_KCC][7] = 127,
+ [3][1][2][1][RTW89_ACMA][7] = 127,
+ [3][1][2][1][RTW89_CN][7] = 127,
+ [3][1][2][1][RTW89_UK][7] = 127,
+ [3][1][2][1][RTW89_FCC][22] = 127,
+ [3][1][2][1][RTW89_ETSI][22] = 127,
+ [3][1][2][1][RTW89_MKK][22] = 127,
+ [3][1][2][1][RTW89_IC][22] = 127,
+ [3][1][2][1][RTW89_KCC][22] = 127,
+ [3][1][2][1][RTW89_ACMA][22] = 127,
+ [3][1][2][1][RTW89_CN][22] = 127,
+ [3][1][2][1][RTW89_UK][22] = 127,
+ [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,
+ [3][1][2][1][RTW89_KCC][45] = 127,
+ [3][1][2][1][RTW89_ACMA][45] = 127,
+ [3][1][2][1][RTW89_CN][45] = 127,
+ [3][1][2][1][RTW89_UK][45] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
+ [0][0][RTW89_WW][0] = 30,
+ [0][0][RTW89_WW][1] = 30,
+ [0][0][RTW89_WW][2] = 30,
+ [0][0][RTW89_WW][3] = 30,
+ [0][0][RTW89_WW][4] = 30,
+ [0][0][RTW89_WW][5] = 30,
+ [0][0][RTW89_WW][6] = 30,
+ [0][0][RTW89_WW][7] = 30,
+ [0][0][RTW89_WW][8] = 30,
+ [0][0][RTW89_WW][9] = 30,
+ [0][0][RTW89_WW][10] = 30,
+ [0][0][RTW89_WW][11] = 30,
+ [0][0][RTW89_WW][12] = 30,
+ [0][0][RTW89_WW][13] = 0,
+ [0][1][RTW89_WW][0] = 20,
+ [0][1][RTW89_WW][1] = 22,
+ [0][1][RTW89_WW][2] = 22,
+ [0][1][RTW89_WW][3] = 22,
+ [0][1][RTW89_WW][4] = 22,
+ [0][1][RTW89_WW][5] = 22,
+ [0][1][RTW89_WW][6] = 22,
+ [0][1][RTW89_WW][7] = 22,
+ [0][1][RTW89_WW][8] = 22,
+ [0][1][RTW89_WW][9] = 22,
+ [0][1][RTW89_WW][10] = 22,
+ [0][1][RTW89_WW][11] = 22,
+ [0][1][RTW89_WW][12] = 20,
+ [0][1][RTW89_WW][13] = 0,
+ [1][0][RTW89_WW][0] = 42,
+ [1][0][RTW89_WW][1] = 42,
+ [1][0][RTW89_WW][2] = 42,
+ [1][0][RTW89_WW][3] = 42,
+ [1][0][RTW89_WW][4] = 42,
+ [1][0][RTW89_WW][5] = 42,
+ [1][0][RTW89_WW][6] = 42,
+ [1][0][RTW89_WW][7] = 42,
+ [1][0][RTW89_WW][8] = 42,
+ [1][0][RTW89_WW][9] = 42,
+ [1][0][RTW89_WW][10] = 42,
+ [1][0][RTW89_WW][11] = 42,
+ [1][0][RTW89_WW][12] = 34,
+ [1][0][RTW89_WW][13] = 0,
+ [1][1][RTW89_WW][0] = 32,
+ [1][1][RTW89_WW][1] = 32,
+ [1][1][RTW89_WW][2] = 32,
+ [1][1][RTW89_WW][3] = 32,
+ [1][1][RTW89_WW][4] = 32,
+ [1][1][RTW89_WW][5] = 32,
+ [1][1][RTW89_WW][6] = 32,
+ [1][1][RTW89_WW][7] = 32,
+ [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][13] = 0,
+ [2][0][RTW89_WW][0] = 54,
+ [2][0][RTW89_WW][1] = 54,
+ [2][0][RTW89_WW][2] = 54,
+ [2][0][RTW89_WW][3] = 54,
+ [2][0][RTW89_WW][4] = 54,
+ [2][0][RTW89_WW][5] = 54,
+ [2][0][RTW89_WW][6] = 54,
+ [2][0][RTW89_WW][7] = 54,
+ [2][0][RTW89_WW][8] = 54,
+ [2][0][RTW89_WW][9] = 54,
+ [2][0][RTW89_WW][10] = 54,
+ [2][0][RTW89_WW][11] = 54,
+ [2][0][RTW89_WW][12] = 34,
+ [2][0][RTW89_WW][13] = 0,
+ [2][1][RTW89_WW][0] = 44,
+ [2][1][RTW89_WW][1] = 44,
+ [2][1][RTW89_WW][2] = 44,
+ [2][1][RTW89_WW][3] = 44,
+ [2][1][RTW89_WW][4] = 44,
+ [2][1][RTW89_WW][5] = 44,
+ [2][1][RTW89_WW][6] = 44,
+ [2][1][RTW89_WW][7] = 44,
+ [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][13] = 0,
+ [0][0][RTW89_FCC][0] = 62,
+ [0][0][RTW89_ETSI][0] = 30,
+ [0][0][RTW89_MKK][0] = 40,
+ [0][0][RTW89_IC][0] = 62,
+ [0][0][RTW89_KCC][0] = 46,
+ [0][0][RTW89_ACMA][0] = 30,
+ [0][0][RTW89_CN][0] = 32,
+ [0][0][RTW89_UK][0] = 30,
+ [0][0][RTW89_FCC][1] = 62,
+ [0][0][RTW89_ETSI][1] = 30,
+ [0][0][RTW89_MKK][1] = 44,
+ [0][0][RTW89_IC][1] = 62,
+ [0][0][RTW89_KCC][1] = 46,
+ [0][0][RTW89_ACMA][1] = 30,
+ [0][0][RTW89_CN][1] = 32,
+ [0][0][RTW89_UK][1] = 30,
+ [0][0][RTW89_FCC][2] = 66,
+ [0][0][RTW89_ETSI][2] = 30,
+ [0][0][RTW89_MKK][2] = 44,
+ [0][0][RTW89_IC][2] = 66,
+ [0][0][RTW89_KCC][2] = 46,
+ [0][0][RTW89_ACMA][2] = 30,
+ [0][0][RTW89_CN][2] = 32,
+ [0][0][RTW89_UK][2] = 30,
+ [0][0][RTW89_FCC][3] = 70,
+ [0][0][RTW89_ETSI][3] = 30,
+ [0][0][RTW89_MKK][3] = 44,
+ [0][0][RTW89_IC][3] = 70,
+ [0][0][RTW89_KCC][3] = 46,
+ [0][0][RTW89_ACMA][3] = 30,
+ [0][0][RTW89_CN][3] = 32,
+ [0][0][RTW89_UK][3] = 30,
+ [0][0][RTW89_FCC][4] = 70,
+ [0][0][RTW89_ETSI][4] = 30,
+ [0][0][RTW89_MKK][4] = 44,
+ [0][0][RTW89_IC][4] = 70,
+ [0][0][RTW89_KCC][4] = 48,
+ [0][0][RTW89_ACMA][4] = 30,
+ [0][0][RTW89_CN][4] = 32,
+ [0][0][RTW89_UK][4] = 30,
+ [0][0][RTW89_FCC][5] = 84,
+ [0][0][RTW89_ETSI][5] = 30,
+ [0][0][RTW89_MKK][5] = 44,
+ [0][0][RTW89_IC][5] = 84,
+ [0][0][RTW89_KCC][5] = 48,
+ [0][0][RTW89_ACMA][5] = 30,
+ [0][0][RTW89_CN][5] = 32,
+ [0][0][RTW89_UK][5] = 30,
+ [0][0][RTW89_FCC][6] = 66,
+ [0][0][RTW89_ETSI][6] = 30,
+ [0][0][RTW89_MKK][6] = 44,
+ [0][0][RTW89_IC][6] = 66,
+ [0][0][RTW89_KCC][6] = 48,
+ [0][0][RTW89_ACMA][6] = 30,
+ [0][0][RTW89_CN][6] = 32,
+ [0][0][RTW89_UK][6] = 30,
+ [0][0][RTW89_FCC][7] = 66,
+ [0][0][RTW89_ETSI][7] = 30,
+ [0][0][RTW89_MKK][7] = 44,
+ [0][0][RTW89_IC][7] = 66,
+ [0][0][RTW89_KCC][7] = 48,
+ [0][0][RTW89_ACMA][7] = 30,
+ [0][0][RTW89_CN][7] = 32,
+ [0][0][RTW89_UK][7] = 30,
+ [0][0][RTW89_FCC][8] = 62,
+ [0][0][RTW89_ETSI][8] = 30,
+ [0][0][RTW89_MKK][8] = 44,
+ [0][0][RTW89_IC][8] = 62,
+ [0][0][RTW89_KCC][8] = 48,
+ [0][0][RTW89_ACMA][8] = 30,
+ [0][0][RTW89_CN][8] = 32,
+ [0][0][RTW89_UK][8] = 30,
+ [0][0][RTW89_FCC][9] = 58,
+ [0][0][RTW89_ETSI][9] = 30,
+ [0][0][RTW89_MKK][9] = 44,
+ [0][0][RTW89_IC][9] = 58,
+ [0][0][RTW89_KCC][9] = 44,
+ [0][0][RTW89_ACMA][9] = 30,
+ [0][0][RTW89_CN][9] = 32,
+ [0][0][RTW89_UK][9] = 30,
+ [0][0][RTW89_FCC][10] = 58,
+ [0][0][RTW89_ETSI][10] = 30,
+ [0][0][RTW89_MKK][10] = 44,
+ [0][0][RTW89_IC][10] = 58,
+ [0][0][RTW89_KCC][10] = 44,
+ [0][0][RTW89_ACMA][10] = 30,
+ [0][0][RTW89_CN][10] = 32,
+ [0][0][RTW89_UK][10] = 30,
+ [0][0][RTW89_FCC][11] = 54,
+ [0][0][RTW89_ETSI][11] = 30,
+ [0][0][RTW89_MKK][11] = 44,
+ [0][0][RTW89_IC][11] = 54,
+ [0][0][RTW89_KCC][11] = 44,
+ [0][0][RTW89_ACMA][11] = 30,
+ [0][0][RTW89_CN][11] = 32,
+ [0][0][RTW89_UK][11] = 30,
+ [0][0][RTW89_FCC][12] = 36,
+ [0][0][RTW89_ETSI][12] = 30,
+ [0][0][RTW89_MKK][12] = 40,
+ [0][0][RTW89_IC][12] = 36,
+ [0][0][RTW89_KCC][12] = 44,
+ [0][0][RTW89_ACMA][12] = 30,
+ [0][0][RTW89_CN][12] = 32,
+ [0][0][RTW89_UK][12] = 30,
+ [0][0][RTW89_FCC][13] = 127,
+ [0][0][RTW89_ETSI][13] = 127,
+ [0][0][RTW89_MKK][13] = 127,
+ [0][0][RTW89_IC][13] = 127,
+ [0][0][RTW89_KCC][13] = 127,
+ [0][0][RTW89_ACMA][13] = 127,
+ [0][0][RTW89_CN][13] = 127,
+ [0][0][RTW89_UK][13] = 127,
+ [0][1][RTW89_FCC][0] = 127,
+ [0][1][RTW89_ETSI][0] = 127,
+ [0][1][RTW89_MKK][0] = 127,
+ [0][1][RTW89_IC][0] = 127,
+ [0][1][RTW89_KCC][0] = 127,
+ [0][1][RTW89_ACMA][0] = 127,
+ [0][1][RTW89_CN][0] = 20,
+ [0][1][RTW89_UK][0] = 127,
+ [0][1][RTW89_FCC][1] = 127,
+ [0][1][RTW89_ETSI][1] = 127,
+ [0][1][RTW89_MKK][1] = 127,
+ [0][1][RTW89_IC][1] = 127,
+ [0][1][RTW89_KCC][1] = 127,
+ [0][1][RTW89_ACMA][1] = 127,
+ [0][1][RTW89_CN][1] = 22,
+ [0][1][RTW89_UK][1] = 127,
+ [0][1][RTW89_FCC][2] = 127,
+ [0][1][RTW89_ETSI][2] = 127,
+ [0][1][RTW89_MKK][2] = 127,
+ [0][1][RTW89_IC][2] = 127,
+ [0][1][RTW89_KCC][2] = 127,
+ [0][1][RTW89_ACMA][2] = 127,
+ [0][1][RTW89_CN][2] = 22,
+ [0][1][RTW89_UK][2] = 127,
+ [0][1][RTW89_FCC][3] = 127,
+ [0][1][RTW89_ETSI][3] = 127,
+ [0][1][RTW89_MKK][3] = 127,
+ [0][1][RTW89_IC][3] = 127,
+ [0][1][RTW89_KCC][3] = 127,
+ [0][1][RTW89_ACMA][3] = 127,
+ [0][1][RTW89_CN][3] = 22,
+ [0][1][RTW89_UK][3] = 127,
+ [0][1][RTW89_FCC][4] = 127,
+ [0][1][RTW89_ETSI][4] = 127,
+ [0][1][RTW89_MKK][4] = 127,
+ [0][1][RTW89_IC][4] = 127,
+ [0][1][RTW89_KCC][4] = 127,
+ [0][1][RTW89_ACMA][4] = 127,
+ [0][1][RTW89_CN][4] = 22,
+ [0][1][RTW89_UK][4] = 127,
+ [0][1][RTW89_FCC][5] = 127,
+ [0][1][RTW89_ETSI][5] = 127,
+ [0][1][RTW89_MKK][5] = 127,
+ [0][1][RTW89_IC][5] = 127,
+ [0][1][RTW89_KCC][5] = 127,
+ [0][1][RTW89_ACMA][5] = 127,
+ [0][1][RTW89_CN][5] = 22,
+ [0][1][RTW89_UK][5] = 127,
+ [0][1][RTW89_FCC][6] = 127,
+ [0][1][RTW89_ETSI][6] = 127,
+ [0][1][RTW89_MKK][6] = 127,
+ [0][1][RTW89_IC][6] = 127,
+ [0][1][RTW89_KCC][6] = 127,
+ [0][1][RTW89_ACMA][6] = 127,
+ [0][1][RTW89_CN][6] = 22,
+ [0][1][RTW89_UK][6] = 127,
+ [0][1][RTW89_FCC][7] = 127,
+ [0][1][RTW89_ETSI][7] = 127,
+ [0][1][RTW89_MKK][7] = 127,
+ [0][1][RTW89_IC][7] = 127,
+ [0][1][RTW89_KCC][7] = 127,
+ [0][1][RTW89_ACMA][7] = 127,
+ [0][1][RTW89_CN][7] = 22,
+ [0][1][RTW89_UK][7] = 127,
+ [0][1][RTW89_FCC][8] = 127,
+ [0][1][RTW89_ETSI][8] = 127,
+ [0][1][RTW89_MKK][8] = 127,
+ [0][1][RTW89_IC][8] = 127,
+ [0][1][RTW89_KCC][8] = 127,
+ [0][1][RTW89_ACMA][8] = 127,
+ [0][1][RTW89_CN][8] = 22,
+ [0][1][RTW89_UK][8] = 127,
+ [0][1][RTW89_FCC][9] = 127,
+ [0][1][RTW89_ETSI][9] = 127,
+ [0][1][RTW89_MKK][9] = 127,
+ [0][1][RTW89_IC][9] = 127,
+ [0][1][RTW89_KCC][9] = 127,
+ [0][1][RTW89_ACMA][9] = 127,
+ [0][1][RTW89_CN][9] = 22,
+ [0][1][RTW89_UK][9] = 127,
+ [0][1][RTW89_FCC][10] = 127,
+ [0][1][RTW89_ETSI][10] = 127,
+ [0][1][RTW89_MKK][10] = 127,
+ [0][1][RTW89_IC][10] = 127,
+ [0][1][RTW89_KCC][10] = 127,
+ [0][1][RTW89_ACMA][10] = 127,
+ [0][1][RTW89_CN][10] = 22,
+ [0][1][RTW89_UK][10] = 127,
+ [0][1][RTW89_FCC][11] = 127,
+ [0][1][RTW89_ETSI][11] = 127,
+ [0][1][RTW89_MKK][11] = 127,
+ [0][1][RTW89_IC][11] = 127,
+ [0][1][RTW89_KCC][11] = 127,
+ [0][1][RTW89_ACMA][11] = 127,
+ [0][1][RTW89_CN][11] = 22,
+ [0][1][RTW89_UK][11] = 127,
+ [0][1][RTW89_FCC][12] = 127,
+ [0][1][RTW89_ETSI][12] = 127,
+ [0][1][RTW89_MKK][12] = 127,
+ [0][1][RTW89_IC][12] = 127,
+ [0][1][RTW89_KCC][12] = 127,
+ [0][1][RTW89_ACMA][12] = 127,
+ [0][1][RTW89_CN][12] = 20,
+ [0][1][RTW89_UK][12] = 127,
+ [0][1][RTW89_FCC][13] = 127,
+ [0][1][RTW89_ETSI][13] = 127,
+ [0][1][RTW89_MKK][13] = 127,
+ [0][1][RTW89_IC][13] = 127,
+ [0][1][RTW89_KCC][13] = 127,
+ [0][1][RTW89_ACMA][13] = 127,
+ [0][1][RTW89_CN][13] = 127,
+ [0][1][RTW89_UK][13] = 127,
+ [1][0][RTW89_FCC][0] = 70,
+ [1][0][RTW89_ETSI][0] = 42,
+ [1][0][RTW89_MKK][0] = 52,
+ [1][0][RTW89_IC][0] = 70,
+ [1][0][RTW89_KCC][0] = 56,
+ [1][0][RTW89_ACMA][0] = 42,
+ [1][0][RTW89_CN][0] = 42,
+ [1][0][RTW89_UK][0] = 42,
+ [1][0][RTW89_FCC][1] = 70,
+ [1][0][RTW89_ETSI][1] = 42,
+ [1][0][RTW89_MKK][1] = 52,
+ [1][0][RTW89_IC][1] = 70,
+ [1][0][RTW89_KCC][1] = 56,
+ [1][0][RTW89_ACMA][1] = 42,
+ [1][0][RTW89_CN][1] = 44,
+ [1][0][RTW89_UK][1] = 42,
+ [1][0][RTW89_FCC][2] = 74,
+ [1][0][RTW89_ETSI][2] = 42,
+ [1][0][RTW89_MKK][2] = 52,
+ [1][0][RTW89_IC][2] = 74,
+ [1][0][RTW89_KCC][2] = 56,
+ [1][0][RTW89_ACMA][2] = 42,
+ [1][0][RTW89_CN][2] = 44,
+ [1][0][RTW89_UK][2] = 42,
+ [1][0][RTW89_FCC][3] = 76,
+ [1][0][RTW89_ETSI][3] = 42,
+ [1][0][RTW89_MKK][3] = 52,
+ [1][0][RTW89_IC][3] = 76,
+ [1][0][RTW89_KCC][3] = 56,
+ [1][0][RTW89_ACMA][3] = 42,
+ [1][0][RTW89_CN][3] = 44,
+ [1][0][RTW89_UK][3] = 42,
+ [1][0][RTW89_FCC][4] = 76,
+ [1][0][RTW89_ETSI][4] = 42,
+ [1][0][RTW89_MKK][4] = 52,
+ [1][0][RTW89_IC][4] = 76,
+ [1][0][RTW89_KCC][4] = 56,
+ [1][0][RTW89_ACMA][4] = 42,
+ [1][0][RTW89_CN][4] = 44,
+ [1][0][RTW89_UK][4] = 42,
+ [1][0][RTW89_FCC][5] = 82,
+ [1][0][RTW89_ETSI][5] = 42,
+ [1][0][RTW89_MKK][5] = 52,
+ [1][0][RTW89_IC][5] = 82,
+ [1][0][RTW89_KCC][5] = 56,
+ [1][0][RTW89_ACMA][5] = 42,
+ [1][0][RTW89_CN][5] = 44,
+ [1][0][RTW89_UK][5] = 42,
+ [1][0][RTW89_FCC][6] = 74,
+ [1][0][RTW89_ETSI][6] = 42,
+ [1][0][RTW89_MKK][6] = 52,
+ [1][0][RTW89_IC][6] = 74,
+ [1][0][RTW89_KCC][6] = 56,
+ [1][0][RTW89_ACMA][6] = 42,
+ [1][0][RTW89_CN][6] = 44,
+ [1][0][RTW89_UK][6] = 42,
+ [1][0][RTW89_FCC][7] = 74,
+ [1][0][RTW89_ETSI][7] = 42,
+ [1][0][RTW89_MKK][7] = 52,
+ [1][0][RTW89_IC][7] = 74,
+ [1][0][RTW89_KCC][7] = 56,
+ [1][0][RTW89_ACMA][7] = 42,
+ [1][0][RTW89_CN][7] = 44,
+ [1][0][RTW89_UK][7] = 42,
+ [1][0][RTW89_FCC][8] = 74,
+ [1][0][RTW89_ETSI][8] = 42,
+ [1][0][RTW89_MKK][8] = 52,
+ [1][0][RTW89_IC][8] = 74,
+ [1][0][RTW89_KCC][8] = 56,
+ [1][0][RTW89_ACMA][8] = 42,
+ [1][0][RTW89_CN][8] = 44,
+ [1][0][RTW89_UK][8] = 42,
+ [1][0][RTW89_FCC][9] = 70,
+ [1][0][RTW89_ETSI][9] = 42,
+ [1][0][RTW89_MKK][9] = 52,
+ [1][0][RTW89_IC][9] = 70,
+ [1][0][RTW89_KCC][9] = 58,
+ [1][0][RTW89_ACMA][9] = 42,
+ [1][0][RTW89_CN][9] = 44,
+ [1][0][RTW89_UK][9] = 42,
+ [1][0][RTW89_FCC][10] = 70,
+ [1][0][RTW89_ETSI][10] = 42,
+ [1][0][RTW89_MKK][10] = 52,
+ [1][0][RTW89_IC][10] = 70,
+ [1][0][RTW89_KCC][10] = 58,
+ [1][0][RTW89_ACMA][10] = 42,
+ [1][0][RTW89_CN][10] = 44,
+ [1][0][RTW89_UK][10] = 42,
+ [1][0][RTW89_FCC][11] = 66,
+ [1][0][RTW89_ETSI][11] = 42,
+ [1][0][RTW89_MKK][11] = 52,
+ [1][0][RTW89_IC][11] = 66,
+ [1][0][RTW89_KCC][11] = 58,
+ [1][0][RTW89_ACMA][11] = 42,
+ [1][0][RTW89_CN][11] = 44,
+ [1][0][RTW89_UK][11] = 42,
+ [1][0][RTW89_FCC][12] = 34,
+ [1][0][RTW89_ETSI][12] = 42,
+ [1][0][RTW89_MKK][12] = 52,
+ [1][0][RTW89_IC][12] = 34,
+ [1][0][RTW89_KCC][12] = 58,
+ [1][0][RTW89_ACMA][12] = 42,
+ [1][0][RTW89_CN][12] = 42,
+ [1][0][RTW89_UK][12] = 42,
+ [1][0][RTW89_FCC][13] = 127,
+ [1][0][RTW89_ETSI][13] = 127,
+ [1][0][RTW89_MKK][13] = 127,
+ [1][0][RTW89_IC][13] = 127,
+ [1][0][RTW89_KCC][13] = 127,
+ [1][0][RTW89_ACMA][13] = 127,
+ [1][0][RTW89_CN][13] = 127,
+ [1][0][RTW89_UK][13] = 127,
+ [1][1][RTW89_FCC][0] = 127,
+ [1][1][RTW89_ETSI][0] = 127,
+ [1][1][RTW89_MKK][0] = 127,
+ [1][1][RTW89_IC][0] = 127,
+ [1][1][RTW89_KCC][0] = 127,
+ [1][1][RTW89_ACMA][0] = 127,
+ [1][1][RTW89_CN][0] = 32,
+ [1][1][RTW89_UK][0] = 127,
+ [1][1][RTW89_FCC][1] = 127,
+ [1][1][RTW89_ETSI][1] = 127,
+ [1][1][RTW89_MKK][1] = 127,
+ [1][1][RTW89_IC][1] = 127,
+ [1][1][RTW89_KCC][1] = 127,
+ [1][1][RTW89_ACMA][1] = 127,
+ [1][1][RTW89_CN][1] = 32,
+ [1][1][RTW89_UK][1] = 127,
+ [1][1][RTW89_FCC][2] = 127,
+ [1][1][RTW89_ETSI][2] = 127,
+ [1][1][RTW89_MKK][2] = 127,
+ [1][1][RTW89_IC][2] = 127,
+ [1][1][RTW89_KCC][2] = 127,
+ [1][1][RTW89_ACMA][2] = 127,
+ [1][1][RTW89_CN][2] = 32,
+ [1][1][RTW89_UK][2] = 127,
+ [1][1][RTW89_FCC][3] = 127,
+ [1][1][RTW89_ETSI][3] = 127,
+ [1][1][RTW89_MKK][3] = 127,
+ [1][1][RTW89_IC][3] = 127,
+ [1][1][RTW89_KCC][3] = 127,
+ [1][1][RTW89_ACMA][3] = 127,
+ [1][1][RTW89_CN][3] = 32,
+ [1][1][RTW89_UK][3] = 127,
+ [1][1][RTW89_FCC][4] = 127,
+ [1][1][RTW89_ETSI][4] = 127,
+ [1][1][RTW89_MKK][4] = 127,
+ [1][1][RTW89_IC][4] = 127,
+ [1][1][RTW89_KCC][4] = 127,
+ [1][1][RTW89_ACMA][4] = 127,
+ [1][1][RTW89_CN][4] = 32,
+ [1][1][RTW89_UK][4] = 127,
+ [1][1][RTW89_FCC][5] = 127,
+ [1][1][RTW89_ETSI][5] = 127,
+ [1][1][RTW89_MKK][5] = 127,
+ [1][1][RTW89_IC][5] = 127,
+ [1][1][RTW89_KCC][5] = 127,
+ [1][1][RTW89_ACMA][5] = 127,
+ [1][1][RTW89_CN][5] = 32,
+ [1][1][RTW89_UK][5] = 127,
+ [1][1][RTW89_FCC][6] = 127,
+ [1][1][RTW89_ETSI][6] = 127,
+ [1][1][RTW89_MKK][6] = 127,
+ [1][1][RTW89_IC][6] = 127,
+ [1][1][RTW89_KCC][6] = 127,
+ [1][1][RTW89_ACMA][6] = 127,
+ [1][1][RTW89_CN][6] = 32,
+ [1][1][RTW89_UK][6] = 127,
+ [1][1][RTW89_FCC][7] = 127,
+ [1][1][RTW89_ETSI][7] = 127,
+ [1][1][RTW89_MKK][7] = 127,
+ [1][1][RTW89_IC][7] = 127,
+ [1][1][RTW89_KCC][7] = 127,
+ [1][1][RTW89_ACMA][7] = 127,
+ [1][1][RTW89_CN][7] = 32,
+ [1][1][RTW89_UK][7] = 127,
+ [1][1][RTW89_FCC][8] = 127,
+ [1][1][RTW89_ETSI][8] = 127,
+ [1][1][RTW89_MKK][8] = 127,
+ [1][1][RTW89_IC][8] = 127,
+ [1][1][RTW89_KCC][8] = 127,
+ [1][1][RTW89_ACMA][8] = 127,
+ [1][1][RTW89_CN][8] = 32,
+ [1][1][RTW89_UK][8] = 127,
+ [1][1][RTW89_FCC][9] = 127,
+ [1][1][RTW89_ETSI][9] = 127,
+ [1][1][RTW89_MKK][9] = 127,
+ [1][1][RTW89_IC][9] = 127,
+ [1][1][RTW89_KCC][9] = 127,
+ [1][1][RTW89_ACMA][9] = 127,
+ [1][1][RTW89_CN][9] = 32,
+ [1][1][RTW89_UK][9] = 127,
+ [1][1][RTW89_FCC][10] = 127,
+ [1][1][RTW89_ETSI][10] = 127,
+ [1][1][RTW89_MKK][10] = 127,
+ [1][1][RTW89_IC][10] = 127,
+ [1][1][RTW89_KCC][10] = 127,
+ [1][1][RTW89_ACMA][10] = 127,
+ [1][1][RTW89_CN][10] = 32,
+ [1][1][RTW89_UK][10] = 127,
+ [1][1][RTW89_FCC][11] = 127,
+ [1][1][RTW89_ETSI][11] = 127,
+ [1][1][RTW89_MKK][11] = 127,
+ [1][1][RTW89_IC][11] = 127,
+ [1][1][RTW89_KCC][11] = 127,
+ [1][1][RTW89_ACMA][11] = 127,
+ [1][1][RTW89_CN][11] = 32,
+ [1][1][RTW89_UK][11] = 127,
+ [1][1][RTW89_FCC][12] = 127,
+ [1][1][RTW89_ETSI][12] = 127,
+ [1][1][RTW89_MKK][12] = 127,
+ [1][1][RTW89_IC][12] = 127,
+ [1][1][RTW89_KCC][12] = 127,
+ [1][1][RTW89_ACMA][12] = 127,
+ [1][1][RTW89_CN][12] = 32,
+ [1][1][RTW89_UK][12] = 127,
+ [1][1][RTW89_FCC][13] = 127,
+ [1][1][RTW89_ETSI][13] = 127,
+ [1][1][RTW89_MKK][13] = 127,
+ [1][1][RTW89_IC][13] = 127,
+ [1][1][RTW89_KCC][13] = 127,
+ [1][1][RTW89_ACMA][13] = 127,
+ [1][1][RTW89_CN][13] = 127,
+ [1][1][RTW89_UK][13] = 127,
+ [2][0][RTW89_FCC][0] = 76,
+ [2][0][RTW89_ETSI][0] = 54,
+ [2][0][RTW89_MKK][0] = 64,
+ [2][0][RTW89_IC][0] = 76,
+ [2][0][RTW89_KCC][0] = 68,
+ [2][0][RTW89_ACMA][0] = 54,
+ [2][0][RTW89_CN][0] = 56,
+ [2][0][RTW89_UK][0] = 54,
+ [2][0][RTW89_FCC][1] = 76,
+ [2][0][RTW89_ETSI][1] = 54,
+ [2][0][RTW89_MKK][1] = 64,
+ [2][0][RTW89_IC][1] = 76,
+ [2][0][RTW89_KCC][1] = 68,
+ [2][0][RTW89_ACMA][1] = 54,
+ [2][0][RTW89_CN][1] = 56,
+ [2][0][RTW89_UK][1] = 54,
+ [2][0][RTW89_FCC][2] = 78,
+ [2][0][RTW89_ETSI][2] = 54,
+ [2][0][RTW89_MKK][2] = 64,
+ [2][0][RTW89_IC][2] = 78,
+ [2][0][RTW89_KCC][2] = 68,
+ [2][0][RTW89_ACMA][2] = 54,
+ [2][0][RTW89_CN][2] = 56,
+ [2][0][RTW89_UK][2] = 54,
+ [2][0][RTW89_FCC][3] = 78,
+ [2][0][RTW89_ETSI][3] = 54,
+ [2][0][RTW89_MKK][3] = 64,
+ [2][0][RTW89_IC][3] = 78,
+ [2][0][RTW89_KCC][3] = 68,
+ [2][0][RTW89_ACMA][3] = 54,
+ [2][0][RTW89_CN][3] = 56,
+ [2][0][RTW89_UK][3] = 54,
+ [2][0][RTW89_FCC][4] = 78,
+ [2][0][RTW89_ETSI][4] = 54,
+ [2][0][RTW89_MKK][4] = 64,
+ [2][0][RTW89_IC][4] = 78,
+ [2][0][RTW89_KCC][4] = 68,
+ [2][0][RTW89_ACMA][4] = 54,
+ [2][0][RTW89_CN][4] = 56,
+ [2][0][RTW89_UK][4] = 54,
+ [2][0][RTW89_FCC][5] = 82,
+ [2][0][RTW89_ETSI][5] = 54,
+ [2][0][RTW89_MKK][5] = 64,
+ [2][0][RTW89_IC][5] = 82,
+ [2][0][RTW89_KCC][5] = 68,
+ [2][0][RTW89_ACMA][5] = 54,
+ [2][0][RTW89_CN][5] = 56,
+ [2][0][RTW89_UK][5] = 54,
+ [2][0][RTW89_FCC][6] = 74,
+ [2][0][RTW89_ETSI][6] = 54,
+ [2][0][RTW89_MKK][6] = 64,
+ [2][0][RTW89_IC][6] = 74,
+ [2][0][RTW89_KCC][6] = 68,
+ [2][0][RTW89_ACMA][6] = 54,
+ [2][0][RTW89_CN][6] = 56,
+ [2][0][RTW89_UK][6] = 54,
+ [2][0][RTW89_FCC][7] = 74,
+ [2][0][RTW89_ETSI][7] = 54,
+ [2][0][RTW89_MKK][7] = 64,
+ [2][0][RTW89_IC][7] = 74,
+ [2][0][RTW89_KCC][7] = 68,
+ [2][0][RTW89_ACMA][7] = 54,
+ [2][0][RTW89_CN][7] = 56,
+ [2][0][RTW89_UK][7] = 54,
+ [2][0][RTW89_FCC][8] = 74,
+ [2][0][RTW89_ETSI][8] = 54,
+ [2][0][RTW89_MKK][8] = 64,
+ [2][0][RTW89_IC][8] = 74,
+ [2][0][RTW89_KCC][8] = 68,
+ [2][0][RTW89_ACMA][8] = 54,
+ [2][0][RTW89_CN][8] = 56,
+ [2][0][RTW89_UK][8] = 54,
+ [2][0][RTW89_FCC][9] = 72,
+ [2][0][RTW89_ETSI][9] = 54,
+ [2][0][RTW89_MKK][9] = 64,
+ [2][0][RTW89_IC][9] = 72,
+ [2][0][RTW89_KCC][9] = 68,
+ [2][0][RTW89_ACMA][9] = 54,
+ [2][0][RTW89_CN][9] = 56,
+ [2][0][RTW89_UK][9] = 54,
+ [2][0][RTW89_FCC][10] = 72,
+ [2][0][RTW89_ETSI][10] = 54,
+ [2][0][RTW89_MKK][10] = 64,
+ [2][0][RTW89_IC][10] = 72,
+ [2][0][RTW89_KCC][10] = 68,
+ [2][0][RTW89_ACMA][10] = 54,
+ [2][0][RTW89_CN][10] = 56,
+ [2][0][RTW89_UK][10] = 54,
+ [2][0][RTW89_FCC][11] = 64,
+ [2][0][RTW89_ETSI][11] = 54,
+ [2][0][RTW89_MKK][11] = 64,
+ [2][0][RTW89_IC][11] = 64,
+ [2][0][RTW89_KCC][11] = 68,
+ [2][0][RTW89_ACMA][11] = 54,
+ [2][0][RTW89_CN][11] = 56,
+ [2][0][RTW89_UK][11] = 54,
+ [2][0][RTW89_FCC][12] = 34,
+ [2][0][RTW89_ETSI][12] = 54,
+ [2][0][RTW89_MKK][12] = 64,
+ [2][0][RTW89_IC][12] = 34,
+ [2][0][RTW89_KCC][12] = 68,
+ [2][0][RTW89_ACMA][12] = 54,
+ [2][0][RTW89_CN][12] = 56,
+ [2][0][RTW89_UK][12] = 54,
+ [2][0][RTW89_FCC][13] = 127,
+ [2][0][RTW89_ETSI][13] = 127,
+ [2][0][RTW89_MKK][13] = 127,
+ [2][0][RTW89_IC][13] = 127,
+ [2][0][RTW89_KCC][13] = 127,
+ [2][0][RTW89_ACMA][13] = 127,
+ [2][0][RTW89_CN][13] = 127,
+ [2][0][RTW89_UK][13] = 127,
+ [2][1][RTW89_FCC][0] = 127,
+ [2][1][RTW89_ETSI][0] = 127,
+ [2][1][RTW89_MKK][0] = 127,
+ [2][1][RTW89_IC][0] = 127,
+ [2][1][RTW89_KCC][0] = 127,
+ [2][1][RTW89_ACMA][0] = 127,
+ [2][1][RTW89_CN][0] = 44,
+ [2][1][RTW89_UK][0] = 127,
+ [2][1][RTW89_FCC][1] = 127,
+ [2][1][RTW89_ETSI][1] = 127,
+ [2][1][RTW89_MKK][1] = 127,
+ [2][1][RTW89_IC][1] = 127,
+ [2][1][RTW89_KCC][1] = 127,
+ [2][1][RTW89_ACMA][1] = 127,
+ [2][1][RTW89_CN][1] = 44,
+ [2][1][RTW89_UK][1] = 127,
+ [2][1][RTW89_FCC][2] = 127,
+ [2][1][RTW89_ETSI][2] = 127,
+ [2][1][RTW89_MKK][2] = 127,
+ [2][1][RTW89_IC][2] = 127,
+ [2][1][RTW89_KCC][2] = 127,
+ [2][1][RTW89_ACMA][2] = 127,
+ [2][1][RTW89_CN][2] = 44,
+ [2][1][RTW89_UK][2] = 127,
+ [2][1][RTW89_FCC][3] = 127,
+ [2][1][RTW89_ETSI][3] = 127,
+ [2][1][RTW89_MKK][3] = 127,
+ [2][1][RTW89_IC][3] = 127,
+ [2][1][RTW89_KCC][3] = 127,
+ [2][1][RTW89_ACMA][3] = 127,
+ [2][1][RTW89_CN][3] = 44,
+ [2][1][RTW89_UK][3] = 127,
+ [2][1][RTW89_FCC][4] = 127,
+ [2][1][RTW89_ETSI][4] = 127,
+ [2][1][RTW89_MKK][4] = 127,
+ [2][1][RTW89_IC][4] = 127,
+ [2][1][RTW89_KCC][4] = 127,
+ [2][1][RTW89_ACMA][4] = 127,
+ [2][1][RTW89_CN][4] = 44,
+ [2][1][RTW89_UK][4] = 127,
+ [2][1][RTW89_FCC][5] = 127,
+ [2][1][RTW89_ETSI][5] = 127,
+ [2][1][RTW89_MKK][5] = 127,
+ [2][1][RTW89_IC][5] = 127,
+ [2][1][RTW89_KCC][5] = 127,
+ [2][1][RTW89_ACMA][5] = 127,
+ [2][1][RTW89_CN][5] = 44,
+ [2][1][RTW89_UK][5] = 127,
+ [2][1][RTW89_FCC][6] = 127,
+ [2][1][RTW89_ETSI][6] = 127,
+ [2][1][RTW89_MKK][6] = 127,
+ [2][1][RTW89_IC][6] = 127,
+ [2][1][RTW89_KCC][6] = 127,
+ [2][1][RTW89_ACMA][6] = 127,
+ [2][1][RTW89_CN][6] = 44,
+ [2][1][RTW89_UK][6] = 127,
+ [2][1][RTW89_FCC][7] = 127,
+ [2][1][RTW89_ETSI][7] = 127,
+ [2][1][RTW89_MKK][7] = 127,
+ [2][1][RTW89_IC][7] = 127,
+ [2][1][RTW89_KCC][7] = 127,
+ [2][1][RTW89_ACMA][7] = 127,
+ [2][1][RTW89_CN][7] = 44,
+ [2][1][RTW89_UK][7] = 127,
+ [2][1][RTW89_FCC][8] = 127,
+ [2][1][RTW89_ETSI][8] = 127,
+ [2][1][RTW89_MKK][8] = 127,
+ [2][1][RTW89_IC][8] = 127,
+ [2][1][RTW89_KCC][8] = 127,
+ [2][1][RTW89_ACMA][8] = 127,
+ [2][1][RTW89_CN][8] = 44,
+ [2][1][RTW89_UK][8] = 127,
+ [2][1][RTW89_FCC][9] = 127,
+ [2][1][RTW89_ETSI][9] = 127,
+ [2][1][RTW89_MKK][9] = 127,
+ [2][1][RTW89_IC][9] = 127,
+ [2][1][RTW89_KCC][9] = 127,
+ [2][1][RTW89_ACMA][9] = 127,
+ [2][1][RTW89_CN][9] = 44,
+ [2][1][RTW89_UK][9] = 127,
+ [2][1][RTW89_FCC][10] = 127,
+ [2][1][RTW89_ETSI][10] = 127,
+ [2][1][RTW89_MKK][10] = 127,
+ [2][1][RTW89_IC][10] = 127,
+ [2][1][RTW89_KCC][10] = 127,
+ [2][1][RTW89_ACMA][10] = 127,
+ [2][1][RTW89_CN][10] = 44,
+ [2][1][RTW89_UK][10] = 127,
+ [2][1][RTW89_FCC][11] = 127,
+ [2][1][RTW89_ETSI][11] = 127,
+ [2][1][RTW89_MKK][11] = 127,
+ [2][1][RTW89_IC][11] = 127,
+ [2][1][RTW89_KCC][11] = 127,
+ [2][1][RTW89_ACMA][11] = 127,
+ [2][1][RTW89_CN][11] = 44,
+ [2][1][RTW89_UK][11] = 127,
+ [2][1][RTW89_FCC][12] = 127,
+ [2][1][RTW89_ETSI][12] = 127,
+ [2][1][RTW89_MKK][12] = 127,
+ [2][1][RTW89_IC][12] = 127,
+ [2][1][RTW89_KCC][12] = 127,
+ [2][1][RTW89_ACMA][12] = 127,
+ [2][1][RTW89_CN][12] = 42,
+ [2][1][RTW89_UK][12] = 127,
+ [2][1][RTW89_FCC][13] = 127,
+ [2][1][RTW89_ETSI][13] = 127,
+ [2][1][RTW89_MKK][13] = 127,
+ [2][1][RTW89_IC][13] = 127,
+ [2][1][RTW89_KCC][13] = 127,
+ [2][1][RTW89_ACMA][13] = 127,
+ [2][1][RTW89_CN][13] = 127,
+ [2][1][RTW89_UK][13] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
+ [0][0][RTW89_WW][0] = 16,
+ [0][0][RTW89_WW][2] = 16,
+ [0][0][RTW89_WW][4] = 16,
+ [0][0][RTW89_WW][6] = 16,
+ [0][0][RTW89_WW][8] = 16,
+ [0][0][RTW89_WW][10] = 16,
+ [0][0][RTW89_WW][12] = 16,
+ [0][0][RTW89_WW][14] = 16,
+ [0][0][RTW89_WW][15] = 24,
+ [0][0][RTW89_WW][17] = 24,
+ [0][0][RTW89_WW][19] = 24,
+ [0][0][RTW89_WW][21] = 24,
+ [0][0][RTW89_WW][23] = 24,
+ [0][0][RTW89_WW][25] = 24,
+ [0][0][RTW89_WW][27] = 24,
+ [0][0][RTW89_WW][29] = 24,
+ [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] = 24,
+ [0][0][RTW89_WW][40] = 24,
+ [0][0][RTW89_WW][42] = 24,
+ [0][0][RTW89_WW][44] = 24,
+ [0][0][RTW89_WW][46] = 24,
+ [0][0][RTW89_WW][48] = 42,
+ [0][0][RTW89_WW][50] = 42,
+ [0][0][RTW89_WW][52] = 40,
+ [0][1][RTW89_WW][0] = 4,
+ [0][1][RTW89_WW][2] = 4,
+ [0][1][RTW89_WW][4] = 4,
+ [0][1][RTW89_WW][6] = 4,
+ [0][1][RTW89_WW][8] = 4,
+ [0][1][RTW89_WW][10] = 4,
+ [0][1][RTW89_WW][12] = 4,
+ [0][1][RTW89_WW][14] = 4,
+ [0][1][RTW89_WW][15] = 0,
+ [0][1][RTW89_WW][17] = 0,
+ [0][1][RTW89_WW][19] = 0,
+ [0][1][RTW89_WW][21] = 0,
+ [0][1][RTW89_WW][23] = 0,
+ [0][1][RTW89_WW][25] = 0,
+ [0][1][RTW89_WW][27] = 0,
+ [0][1][RTW89_WW][29] = 0,
+ [0][1][RTW89_WW][31] = 0,
+ [0][1][RTW89_WW][33] = 0,
+ [0][1][RTW89_WW][35] = 0,
+ [0][1][RTW89_WW][37] = 0,
+ [0][1][RTW89_WW][38] = 42,
+ [0][1][RTW89_WW][40] = 42,
+ [0][1][RTW89_WW][42] = 42,
+ [0][1][RTW89_WW][44] = 42,
+ [0][1][RTW89_WW][46] = 42,
+ [0][1][RTW89_WW][48] = 0,
+ [0][1][RTW89_WW][50] = 0,
+ [0][1][RTW89_WW][52] = 0,
+ [1][0][RTW89_WW][0] = 26,
+ [1][0][RTW89_WW][2] = 26,
+ [1][0][RTW89_WW][4] = 26,
+ [1][0][RTW89_WW][6] = 26,
+ [1][0][RTW89_WW][8] = 26,
+ [1][0][RTW89_WW][10] = 26,
+ [1][0][RTW89_WW][12] = 26,
+ [1][0][RTW89_WW][14] = 26,
+ [1][0][RTW89_WW][15] = 34,
+ [1][0][RTW89_WW][17] = 34,
+ [1][0][RTW89_WW][19] = 34,
+ [1][0][RTW89_WW][21] = 34,
+ [1][0][RTW89_WW][23] = 34,
+ [1][0][RTW89_WW][25] = 34,
+ [1][0][RTW89_WW][27] = 34,
+ [1][0][RTW89_WW][29] = 34,
+ [1][0][RTW89_WW][31] = 34,
+ [1][0][RTW89_WW][33] = 34,
+ [1][0][RTW89_WW][35] = 34,
+ [1][0][RTW89_WW][37] = 54,
+ [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] = 52,
+ [1][0][RTW89_WW][50] = 52,
+ [1][0][RTW89_WW][52] = 52,
+ [1][1][RTW89_WW][0] = 14,
+ [1][1][RTW89_WW][2] = 14,
+ [1][1][RTW89_WW][4] = 14,
+ [1][1][RTW89_WW][6] = 14,
+ [1][1][RTW89_WW][8] = 14,
+ [1][1][RTW89_WW][10] = 14,
+ [1][1][RTW89_WW][12] = 14,
+ [1][1][RTW89_WW][14] = 14,
+ [1][1][RTW89_WW][15] = 0,
+ [1][1][RTW89_WW][17] = 0,
+ [1][1][RTW89_WW][19] = 0,
+ [1][1][RTW89_WW][21] = 0,
+ [1][1][RTW89_WW][23] = 0,
+ [1][1][RTW89_WW][25] = 0,
+ [1][1][RTW89_WW][27] = 0,
+ [1][1][RTW89_WW][29] = 0,
+ [1][1][RTW89_WW][31] = 0,
+ [1][1][RTW89_WW][33] = 0,
+ [1][1][RTW89_WW][35] = 0,
+ [1][1][RTW89_WW][37] = 0,
+ [1][1][RTW89_WW][38] = 54,
+ [1][1][RTW89_WW][40] = 54,
+ [1][1][RTW89_WW][42] = 54,
+ [1][1][RTW89_WW][44] = 54,
+ [1][1][RTW89_WW][46] = 54,
+ [1][1][RTW89_WW][48] = 0,
+ [1][1][RTW89_WW][50] = 0,
+ [1][1][RTW89_WW][52] = 0,
+ [2][0][RTW89_WW][0] = 40,
+ [2][0][RTW89_WW][2] = 40,
+ [2][0][RTW89_WW][4] = 40,
+ [2][0][RTW89_WW][6] = 40,
+ [2][0][RTW89_WW][8] = 40,
+ [2][0][RTW89_WW][10] = 40,
+ [2][0][RTW89_WW][12] = 40,
+ [2][0][RTW89_WW][14] = 40,
+ [2][0][RTW89_WW][15] = 46,
+ [2][0][RTW89_WW][17] = 46,
+ [2][0][RTW89_WW][19] = 46,
+ [2][0][RTW89_WW][21] = 46,
+ [2][0][RTW89_WW][23] = 46,
+ [2][0][RTW89_WW][25] = 46,
+ [2][0][RTW89_WW][27] = 46,
+ [2][0][RTW89_WW][29] = 46,
+ [2][0][RTW89_WW][31] = 46,
+ [2][0][RTW89_WW][33] = 46,
+ [2][0][RTW89_WW][35] = 46,
+ [2][0][RTW89_WW][37] = 66,
+ [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] = 64,
+ [2][0][RTW89_WW][50] = 64,
+ [2][0][RTW89_WW][52] = 60,
+ [2][1][RTW89_WW][0] = 28,
+ [2][1][RTW89_WW][2] = 28,
+ [2][1][RTW89_WW][4] = 28,
+ [2][1][RTW89_WW][6] = 28,
+ [2][1][RTW89_WW][8] = 28,
+ [2][1][RTW89_WW][10] = 28,
+ [2][1][RTW89_WW][12] = 28,
+ [2][1][RTW89_WW][14] = 28,
+ [2][1][RTW89_WW][15] = 0,
+ [2][1][RTW89_WW][17] = 0,
+ [2][1][RTW89_WW][19] = 0,
+ [2][1][RTW89_WW][21] = 0,
+ [2][1][RTW89_WW][23] = 0,
+ [2][1][RTW89_WW][25] = 0,
+ [2][1][RTW89_WW][27] = 0,
+ [2][1][RTW89_WW][29] = 0,
+ [2][1][RTW89_WW][31] = 0,
+ [2][1][RTW89_WW][33] = 0,
+ [2][1][RTW89_WW][35] = 0,
+ [2][1][RTW89_WW][37] = 0,
+ [2][1][RTW89_WW][38] = 56,
+ [2][1][RTW89_WW][40] = 56,
+ [2][1][RTW89_WW][42] = 56,
+ [2][1][RTW89_WW][44] = 56,
+ [2][1][RTW89_WW][46] = 56,
+ [2][1][RTW89_WW][48] = 0,
+ [2][1][RTW89_WW][50] = 0,
+ [2][1][RTW89_WW][52] = 0,
+ [0][0][RTW89_FCC][0] = 52,
+ [0][0][RTW89_ETSI][0] = 24,
+ [0][0][RTW89_MKK][0] = 26,
+ [0][0][RTW89_IC][0] = 28,
+ [0][0][RTW89_KCC][0] = 42,
+ [0][0][RTW89_ACMA][0] = 24,
+ [0][0][RTW89_CN][0] = 16,
+ [0][0][RTW89_UK][0] = 24,
+ [0][0][RTW89_FCC][2] = 54,
+ [0][0][RTW89_ETSI][2] = 24,
+ [0][0][RTW89_MKK][2] = 26,
+ [0][0][RTW89_IC][2] = 28,
+ [0][0][RTW89_KCC][2] = 42,
+ [0][0][RTW89_ACMA][2] = 24,
+ [0][0][RTW89_CN][2] = 16,
+ [0][0][RTW89_UK][2] = 24,
+ [0][0][RTW89_FCC][4] = 52,
+ [0][0][RTW89_ETSI][4] = 24,
+ [0][0][RTW89_MKK][4] = 26,
+ [0][0][RTW89_IC][4] = 28,
+ [0][0][RTW89_KCC][4] = 42,
+ [0][0][RTW89_ACMA][4] = 24,
+ [0][0][RTW89_CN][4] = 16,
+ [0][0][RTW89_UK][4] = 24,
+ [0][0][RTW89_FCC][6] = 52,
+ [0][0][RTW89_ETSI][6] = 24,
+ [0][0][RTW89_MKK][6] = 26,
+ [0][0][RTW89_IC][6] = 28,
+ [0][0][RTW89_KCC][6] = 18,
+ [0][0][RTW89_ACMA][6] = 24,
+ [0][0][RTW89_CN][6] = 16,
+ [0][0][RTW89_UK][6] = 24,
+ [0][0][RTW89_FCC][8] = 52,
+ [0][0][RTW89_ETSI][8] = 24,
+ [0][0][RTW89_MKK][8] = 26,
+ [0][0][RTW89_IC][8] = 52,
+ [0][0][RTW89_KCC][8] = 42,
+ [0][0][RTW89_ACMA][8] = 24,
+ [0][0][RTW89_CN][8] = 16,
+ [0][0][RTW89_UK][8] = 24,
+ [0][0][RTW89_FCC][10] = 52,
+ [0][0][RTW89_ETSI][10] = 24,
+ [0][0][RTW89_MKK][10] = 26,
+ [0][0][RTW89_IC][10] = 52,
+ [0][0][RTW89_KCC][10] = 42,
+ [0][0][RTW89_ACMA][10] = 24,
+ [0][0][RTW89_CN][10] = 16,
+ [0][0][RTW89_UK][10] = 24,
+ [0][0][RTW89_FCC][12] = 56,
+ [0][0][RTW89_ETSI][12] = 24,
+ [0][0][RTW89_MKK][12] = 26,
+ [0][0][RTW89_IC][12] = 56,
+ [0][0][RTW89_KCC][12] = 44,
+ [0][0][RTW89_ACMA][12] = 24,
+ [0][0][RTW89_CN][12] = 16,
+ [0][0][RTW89_UK][12] = 24,
+ [0][0][RTW89_FCC][14] = 56,
+ [0][0][RTW89_ETSI][14] = 24,
+ [0][0][RTW89_MKK][14] = 26,
+ [0][0][RTW89_IC][14] = 56,
+ [0][0][RTW89_KCC][14] = 44,
+ [0][0][RTW89_ACMA][14] = 24,
+ [0][0][RTW89_CN][14] = 16,
+ [0][0][RTW89_UK][14] = 24,
+ [0][0][RTW89_FCC][15] = 54,
+ [0][0][RTW89_ETSI][15] = 24,
+ [0][0][RTW89_MKK][15] = 46,
+ [0][0][RTW89_IC][15] = 54,
+ [0][0][RTW89_KCC][15] = 44,
+ [0][0][RTW89_ACMA][15] = 24,
+ [0][0][RTW89_CN][15] = 127,
+ [0][0][RTW89_UK][15] = 24,
+ [0][0][RTW89_FCC][17] = 54,
+ [0][0][RTW89_ETSI][17] = 24,
+ [0][0][RTW89_MKK][17] = 50,
+ [0][0][RTW89_IC][17] = 54,
+ [0][0][RTW89_KCC][17] = 44,
+ [0][0][RTW89_ACMA][17] = 24,
+ [0][0][RTW89_CN][17] = 127,
+ [0][0][RTW89_UK][17] = 24,
+ [0][0][RTW89_FCC][19] = 54,
+ [0][0][RTW89_ETSI][19] = 24,
+ [0][0][RTW89_MKK][19] = 50,
+ [0][0][RTW89_IC][19] = 54,
+ [0][0][RTW89_KCC][19] = 44,
+ [0][0][RTW89_ACMA][19] = 24,
+ [0][0][RTW89_CN][19] = 127,
+ [0][0][RTW89_UK][19] = 24,
+ [0][0][RTW89_FCC][21] = 54,
+ [0][0][RTW89_ETSI][21] = 24,
+ [0][0][RTW89_MKK][21] = 50,
+ [0][0][RTW89_IC][21] = 54,
+ [0][0][RTW89_KCC][21] = 44,
+ [0][0][RTW89_ACMA][21] = 24,
+ [0][0][RTW89_CN][21] = 127,
+ [0][0][RTW89_UK][21] = 24,
+ [0][0][RTW89_FCC][23] = 54,
+ [0][0][RTW89_ETSI][23] = 24,
+ [0][0][RTW89_MKK][23] = 50,
+ [0][0][RTW89_IC][23] = 54,
+ [0][0][RTW89_KCC][23] = 44,
+ [0][0][RTW89_ACMA][23] = 24,
+ [0][0][RTW89_CN][23] = 127,
+ [0][0][RTW89_UK][23] = 24,
+ [0][0][RTW89_FCC][25] = 54,
+ [0][0][RTW89_ETSI][25] = 24,
+ [0][0][RTW89_MKK][25] = 50,
+ [0][0][RTW89_IC][25] = 127,
+ [0][0][RTW89_KCC][25] = 44,
+ [0][0][RTW89_ACMA][25] = 127,
+ [0][0][RTW89_CN][25] = 127,
+ [0][0][RTW89_UK][25] = 24,
+ [0][0][RTW89_FCC][27] = 54,
+ [0][0][RTW89_ETSI][27] = 24,
+ [0][0][RTW89_MKK][27] = 50,
+ [0][0][RTW89_IC][27] = 127,
+ [0][0][RTW89_KCC][27] = 42,
+ [0][0][RTW89_ACMA][27] = 127,
+ [0][0][RTW89_CN][27] = 127,
+ [0][0][RTW89_UK][27] = 24,
+ [0][0][RTW89_FCC][29] = 54,
+ [0][0][RTW89_ETSI][29] = 24,
+ [0][0][RTW89_MKK][29] = 50,
+ [0][0][RTW89_IC][29] = 127,
+ [0][0][RTW89_KCC][29] = 42,
+ [0][0][RTW89_ACMA][29] = 127,
+ [0][0][RTW89_CN][29] = 127,
+ [0][0][RTW89_UK][29] = 24,
+ [0][0][RTW89_FCC][31] = 54,
+ [0][0][RTW89_ETSI][31] = 24,
+ [0][0][RTW89_MKK][31] = 50,
+ [0][0][RTW89_IC][31] = 56,
+ [0][0][RTW89_KCC][31] = 42,
+ [0][0][RTW89_ACMA][31] = 24,
+ [0][0][RTW89_CN][31] = 127,
+ [0][0][RTW89_UK][31] = 24,
+ [0][0][RTW89_FCC][33] = 56,
+ [0][0][RTW89_ETSI][33] = 24,
+ [0][0][RTW89_MKK][33] = 50,
+ [0][0][RTW89_IC][33] = 56,
+ [0][0][RTW89_KCC][33] = 42,
+ [0][0][RTW89_ACMA][33] = 24,
+ [0][0][RTW89_CN][33] = 127,
+ [0][0][RTW89_UK][33] = 24,
+ [0][0][RTW89_FCC][35] = 56,
+ [0][0][RTW89_ETSI][35] = 24,
+ [0][0][RTW89_MKK][35] = 50,
+ [0][0][RTW89_IC][35] = 56,
+ [0][0][RTW89_KCC][35] = 42,
+ [0][0][RTW89_ACMA][35] = 24,
+ [0][0][RTW89_CN][35] = 127,
+ [0][0][RTW89_UK][35] = 24,
+ [0][0][RTW89_FCC][37] = 86,
+ [0][0][RTW89_ETSI][37] = 127,
+ [0][0][RTW89_MKK][37] = 46,
+ [0][0][RTW89_IC][37] = 86,
+ [0][0][RTW89_KCC][37] = 44,
+ [0][0][RTW89_ACMA][37] = 50,
+ [0][0][RTW89_CN][37] = 127,
+ [0][0][RTW89_UK][37] = 52,
+ [0][0][RTW89_FCC][38] = 68,
+ [0][0][RTW89_ETSI][38] = 28,
+ [0][0][RTW89_MKK][38] = 127,
+ [0][0][RTW89_IC][38] = 68,
+ [0][0][RTW89_KCC][38] = 44,
+ [0][0][RTW89_ACMA][38] = 84,
+ [0][0][RTW89_CN][38] = 54,
+ [0][0][RTW89_UK][38] = 24,
+ [0][0][RTW89_FCC][40] = 68,
+ [0][0][RTW89_ETSI][40] = 28,
+ [0][0][RTW89_MKK][40] = 127,
+ [0][0][RTW89_IC][40] = 68,
+ [0][0][RTW89_KCC][40] = 44,
+ [0][0][RTW89_ACMA][40] = 84,
+ [0][0][RTW89_CN][40] = 54,
+ [0][0][RTW89_UK][40] = 24,
+ [0][0][RTW89_FCC][42] = 70,
+ [0][0][RTW89_ETSI][42] = 28,
+ [0][0][RTW89_MKK][42] = 127,
+ [0][0][RTW89_IC][42] = 70,
+ [0][0][RTW89_KCC][42] = 44,
+ [0][0][RTW89_ACMA][42] = 84,
+ [0][0][RTW89_CN][42] = 54,
+ [0][0][RTW89_UK][42] = 24,
+ [0][0][RTW89_FCC][44] = 62,
+ [0][0][RTW89_ETSI][44] = 28,
+ [0][0][RTW89_MKK][44] = 127,
+ [0][0][RTW89_IC][44] = 62,
+ [0][0][RTW89_KCC][44] = 44,
+ [0][0][RTW89_ACMA][44] = 84,
+ [0][0][RTW89_CN][44] = 54,
+ [0][0][RTW89_UK][44] = 24,
+ [0][0][RTW89_FCC][46] = 62,
+ [0][0][RTW89_ETSI][46] = 28,
+ [0][0][RTW89_MKK][46] = 127,
+ [0][0][RTW89_IC][46] = 62,
+ [0][0][RTW89_KCC][46] = 44,
+ [0][0][RTW89_ACMA][46] = 84,
+ [0][0][RTW89_CN][46] = 54,
+ [0][0][RTW89_UK][46] = 24,
+ [0][0][RTW89_FCC][48] = 42,
+ [0][0][RTW89_ETSI][48] = 127,
+ [0][0][RTW89_MKK][48] = 127,
+ [0][0][RTW89_IC][48] = 127,
+ [0][0][RTW89_KCC][48] = 127,
+ [0][0][RTW89_ACMA][48] = 127,
+ [0][0][RTW89_CN][48] = 127,
+ [0][0][RTW89_UK][48] = 127,
+ [0][0][RTW89_FCC][50] = 42,
+ [0][0][RTW89_ETSI][50] = 127,
+ [0][0][RTW89_MKK][50] = 127,
+ [0][0][RTW89_IC][50] = 127,
+ [0][0][RTW89_KCC][50] = 127,
+ [0][0][RTW89_ACMA][50] = 127,
+ [0][0][RTW89_CN][50] = 127,
+ [0][0][RTW89_UK][50] = 127,
+ [0][0][RTW89_FCC][52] = 40,
+ [0][0][RTW89_ETSI][52] = 127,
+ [0][0][RTW89_MKK][52] = 127,
+ [0][0][RTW89_IC][52] = 127,
+ [0][0][RTW89_KCC][52] = 127,
+ [0][0][RTW89_ACMA][52] = 127,
+ [0][0][RTW89_CN][52] = 127,
+ [0][0][RTW89_UK][52] = 127,
+ [0][1][RTW89_FCC][0] = 127,
+ [0][1][RTW89_ETSI][0] = 127,
+ [0][1][RTW89_MKK][0] = 127,
+ [0][1][RTW89_IC][0] = 127,
+ [0][1][RTW89_KCC][0] = 127,
+ [0][1][RTW89_ACMA][0] = 127,
+ [0][1][RTW89_CN][0] = 4,
+ [0][1][RTW89_UK][0] = 127,
+ [0][1][RTW89_FCC][2] = 127,
+ [0][1][RTW89_ETSI][2] = 127,
+ [0][1][RTW89_MKK][2] = 127,
+ [0][1][RTW89_IC][2] = 127,
+ [0][1][RTW89_KCC][2] = 127,
+ [0][1][RTW89_ACMA][2] = 127,
+ [0][1][RTW89_CN][2] = 4,
+ [0][1][RTW89_UK][2] = 127,
+ [0][1][RTW89_FCC][4] = 127,
+ [0][1][RTW89_ETSI][4] = 127,
+ [0][1][RTW89_MKK][4] = 127,
+ [0][1][RTW89_IC][4] = 127,
+ [0][1][RTW89_KCC][4] = 127,
+ [0][1][RTW89_ACMA][4] = 127,
+ [0][1][RTW89_CN][4] = 4,
+ [0][1][RTW89_UK][4] = 127,
+ [0][1][RTW89_FCC][6] = 127,
+ [0][1][RTW89_ETSI][6] = 127,
+ [0][1][RTW89_MKK][6] = 127,
+ [0][1][RTW89_IC][6] = 127,
+ [0][1][RTW89_KCC][6] = 127,
+ [0][1][RTW89_ACMA][6] = 127,
+ [0][1][RTW89_CN][6] = 4,
+ [0][1][RTW89_UK][6] = 127,
+ [0][1][RTW89_FCC][8] = 127,
+ [0][1][RTW89_ETSI][8] = 127,
+ [0][1][RTW89_MKK][8] = 127,
+ [0][1][RTW89_IC][8] = 127,
+ [0][1][RTW89_KCC][8] = 127,
+ [0][1][RTW89_ACMA][8] = 127,
+ [0][1][RTW89_CN][8] = 4,
+ [0][1][RTW89_UK][8] = 127,
+ [0][1][RTW89_FCC][10] = 127,
+ [0][1][RTW89_ETSI][10] = 127,
+ [0][1][RTW89_MKK][10] = 127,
+ [0][1][RTW89_IC][10] = 127,
+ [0][1][RTW89_KCC][10] = 127,
+ [0][1][RTW89_ACMA][10] = 127,
+ [0][1][RTW89_CN][10] = 4,
+ [0][1][RTW89_UK][10] = 127,
+ [0][1][RTW89_FCC][12] = 127,
+ [0][1][RTW89_ETSI][12] = 127,
+ [0][1][RTW89_MKK][12] = 127,
+ [0][1][RTW89_IC][12] = 127,
+ [0][1][RTW89_KCC][12] = 127,
+ [0][1][RTW89_ACMA][12] = 127,
+ [0][1][RTW89_CN][12] = 4,
+ [0][1][RTW89_UK][12] = 127,
+ [0][1][RTW89_FCC][14] = 127,
+ [0][1][RTW89_ETSI][14] = 127,
+ [0][1][RTW89_MKK][14] = 127,
+ [0][1][RTW89_IC][14] = 127,
+ [0][1][RTW89_KCC][14] = 127,
+ [0][1][RTW89_ACMA][14] = 127,
+ [0][1][RTW89_CN][14] = 4,
+ [0][1][RTW89_UK][14] = 127,
+ [0][1][RTW89_FCC][15] = 127,
+ [0][1][RTW89_ETSI][15] = 127,
+ [0][1][RTW89_MKK][15] = 127,
+ [0][1][RTW89_IC][15] = 127,
+ [0][1][RTW89_KCC][15] = 127,
+ [0][1][RTW89_ACMA][15] = 127,
+ [0][1][RTW89_CN][15] = 127,
+ [0][1][RTW89_UK][15] = 127,
+ [0][1][RTW89_FCC][17] = 127,
+ [0][1][RTW89_ETSI][17] = 127,
+ [0][1][RTW89_MKK][17] = 127,
+ [0][1][RTW89_IC][17] = 127,
+ [0][1][RTW89_KCC][17] = 127,
+ [0][1][RTW89_ACMA][17] = 127,
+ [0][1][RTW89_CN][17] = 127,
+ [0][1][RTW89_UK][17] = 127,
+ [0][1][RTW89_FCC][19] = 127,
+ [0][1][RTW89_ETSI][19] = 127,
+ [0][1][RTW89_MKK][19] = 127,
+ [0][1][RTW89_IC][19] = 127,
+ [0][1][RTW89_KCC][19] = 127,
+ [0][1][RTW89_ACMA][19] = 127,
+ [0][1][RTW89_CN][19] = 127,
+ [0][1][RTW89_UK][19] = 127,
+ [0][1][RTW89_FCC][21] = 127,
+ [0][1][RTW89_ETSI][21] = 127,
+ [0][1][RTW89_MKK][21] = 127,
+ [0][1][RTW89_IC][21] = 127,
+ [0][1][RTW89_KCC][21] = 127,
+ [0][1][RTW89_ACMA][21] = 127,
+ [0][1][RTW89_CN][21] = 127,
+ [0][1][RTW89_UK][21] = 127,
+ [0][1][RTW89_FCC][23] = 127,
+ [0][1][RTW89_ETSI][23] = 127,
+ [0][1][RTW89_MKK][23] = 127,
+ [0][1][RTW89_IC][23] = 127,
+ [0][1][RTW89_KCC][23] = 127,
+ [0][1][RTW89_ACMA][23] = 127,
+ [0][1][RTW89_CN][23] = 127,
+ [0][1][RTW89_UK][23] = 127,
+ [0][1][RTW89_FCC][25] = 127,
+ [0][1][RTW89_ETSI][25] = 127,
+ [0][1][RTW89_MKK][25] = 127,
+ [0][1][RTW89_IC][25] = 127,
+ [0][1][RTW89_KCC][25] = 127,
+ [0][1][RTW89_ACMA][25] = 127,
+ [0][1][RTW89_CN][25] = 127,
+ [0][1][RTW89_UK][25] = 127,
+ [0][1][RTW89_FCC][27] = 127,
+ [0][1][RTW89_ETSI][27] = 127,
+ [0][1][RTW89_MKK][27] = 127,
+ [0][1][RTW89_IC][27] = 127,
+ [0][1][RTW89_KCC][27] = 127,
+ [0][1][RTW89_ACMA][27] = 127,
+ [0][1][RTW89_CN][27] = 127,
+ [0][1][RTW89_UK][27] = 127,
+ [0][1][RTW89_FCC][29] = 127,
+ [0][1][RTW89_ETSI][29] = 127,
+ [0][1][RTW89_MKK][29] = 127,
+ [0][1][RTW89_IC][29] = 127,
+ [0][1][RTW89_KCC][29] = 127,
+ [0][1][RTW89_ACMA][29] = 127,
+ [0][1][RTW89_CN][29] = 127,
+ [0][1][RTW89_UK][29] = 127,
+ [0][1][RTW89_FCC][31] = 127,
+ [0][1][RTW89_ETSI][31] = 127,
+ [0][1][RTW89_MKK][31] = 127,
+ [0][1][RTW89_IC][31] = 127,
+ [0][1][RTW89_KCC][31] = 127,
+ [0][1][RTW89_ACMA][31] = 127,
+ [0][1][RTW89_CN][31] = 127,
+ [0][1][RTW89_UK][31] = 127,
+ [0][1][RTW89_FCC][33] = 127,
+ [0][1][RTW89_ETSI][33] = 127,
+ [0][1][RTW89_MKK][33] = 127,
+ [0][1][RTW89_IC][33] = 127,
+ [0][1][RTW89_KCC][33] = 127,
+ [0][1][RTW89_ACMA][33] = 127,
+ [0][1][RTW89_CN][33] = 127,
+ [0][1][RTW89_UK][33] = 127,
+ [0][1][RTW89_FCC][35] = 127,
+ [0][1][RTW89_ETSI][35] = 127,
+ [0][1][RTW89_MKK][35] = 127,
+ [0][1][RTW89_IC][35] = 127,
+ [0][1][RTW89_KCC][35] = 127,
+ [0][1][RTW89_ACMA][35] = 127,
+ [0][1][RTW89_CN][35] = 127,
+ [0][1][RTW89_UK][35] = 127,
+ [0][1][RTW89_FCC][37] = 127,
+ [0][1][RTW89_ETSI][37] = 127,
+ [0][1][RTW89_MKK][37] = 127,
+ [0][1][RTW89_IC][37] = 127,
+ [0][1][RTW89_KCC][37] = 127,
+ [0][1][RTW89_ACMA][37] = 127,
+ [0][1][RTW89_CN][37] = 127,
+ [0][1][RTW89_UK][37] = 127,
+ [0][1][RTW89_FCC][38] = 127,
+ [0][1][RTW89_ETSI][38] = 127,
+ [0][1][RTW89_MKK][38] = 127,
+ [0][1][RTW89_IC][38] = 127,
+ [0][1][RTW89_KCC][38] = 127,
+ [0][1][RTW89_ACMA][38] = 127,
+ [0][1][RTW89_CN][38] = 42,
+ [0][1][RTW89_UK][38] = 127,
+ [0][1][RTW89_FCC][40] = 127,
+ [0][1][RTW89_ETSI][40] = 127,
+ [0][1][RTW89_MKK][40] = 127,
+ [0][1][RTW89_IC][40] = 127,
+ [0][1][RTW89_KCC][40] = 127,
+ [0][1][RTW89_ACMA][40] = 127,
+ [0][1][RTW89_CN][40] = 42,
+ [0][1][RTW89_UK][40] = 127,
+ [0][1][RTW89_FCC][42] = 127,
+ [0][1][RTW89_ETSI][42] = 127,
+ [0][1][RTW89_MKK][42] = 127,
+ [0][1][RTW89_IC][42] = 127,
+ [0][1][RTW89_KCC][42] = 127,
+ [0][1][RTW89_ACMA][42] = 127,
+ [0][1][RTW89_CN][42] = 42,
+ [0][1][RTW89_UK][42] = 127,
+ [0][1][RTW89_FCC][44] = 127,
+ [0][1][RTW89_ETSI][44] = 127,
+ [0][1][RTW89_MKK][44] = 127,
+ [0][1][RTW89_IC][44] = 127,
+ [0][1][RTW89_KCC][44] = 127,
+ [0][1][RTW89_ACMA][44] = 127,
+ [0][1][RTW89_CN][44] = 42,
+ [0][1][RTW89_UK][44] = 127,
+ [0][1][RTW89_FCC][46] = 127,
+ [0][1][RTW89_ETSI][46] = 127,
+ [0][1][RTW89_MKK][46] = 127,
+ [0][1][RTW89_IC][46] = 127,
+ [0][1][RTW89_KCC][46] = 127,
+ [0][1][RTW89_ACMA][46] = 127,
+ [0][1][RTW89_CN][46] = 42,
+ [0][1][RTW89_UK][46] = 127,
+ [0][1][RTW89_FCC][48] = 127,
+ [0][1][RTW89_ETSI][48] = 127,
+ [0][1][RTW89_MKK][48] = 127,
+ [0][1][RTW89_IC][48] = 127,
+ [0][1][RTW89_KCC][48] = 127,
+ [0][1][RTW89_ACMA][48] = 127,
+ [0][1][RTW89_CN][48] = 127,
+ [0][1][RTW89_UK][48] = 127,
+ [0][1][RTW89_FCC][50] = 127,
+ [0][1][RTW89_ETSI][50] = 127,
+ [0][1][RTW89_MKK][50] = 127,
+ [0][1][RTW89_IC][50] = 127,
+ [0][1][RTW89_KCC][50] = 127,
+ [0][1][RTW89_ACMA][50] = 127,
+ [0][1][RTW89_CN][50] = 127,
+ [0][1][RTW89_UK][50] = 127,
+ [0][1][RTW89_FCC][52] = 127,
+ [0][1][RTW89_ETSI][52] = 127,
+ [0][1][RTW89_MKK][52] = 127,
+ [0][1][RTW89_IC][52] = 127,
+ [0][1][RTW89_KCC][52] = 127,
+ [0][1][RTW89_ACMA][52] = 127,
+ [0][1][RTW89_CN][52] = 127,
+ [0][1][RTW89_UK][52] = 127,
+ [1][0][RTW89_FCC][0] = 64,
+ [1][0][RTW89_ETSI][0] = 34,
+ [1][0][RTW89_MKK][0] = 38,
+ [1][0][RTW89_IC][0] = 38,
+ [1][0][RTW89_KCC][0] = 52,
+ [1][0][RTW89_ACMA][0] = 34,
+ [1][0][RTW89_CN][0] = 26,
+ [1][0][RTW89_UK][0] = 34,
+ [1][0][RTW89_FCC][2] = 66,
+ [1][0][RTW89_ETSI][2] = 34,
+ [1][0][RTW89_MKK][2] = 38,
+ [1][0][RTW89_IC][2] = 38,
+ [1][0][RTW89_KCC][2] = 52,
+ [1][0][RTW89_ACMA][2] = 34,
+ [1][0][RTW89_CN][2] = 26,
+ [1][0][RTW89_UK][2] = 34,
+ [1][0][RTW89_FCC][4] = 62,
+ [1][0][RTW89_ETSI][4] = 34,
+ [1][0][RTW89_MKK][4] = 36,
+ [1][0][RTW89_IC][4] = 38,
+ [1][0][RTW89_KCC][4] = 52,
+ [1][0][RTW89_ACMA][4] = 34,
+ [1][0][RTW89_CN][4] = 26,
+ [1][0][RTW89_UK][4] = 34,
+ [1][0][RTW89_FCC][6] = 62,
+ [1][0][RTW89_ETSI][6] = 34,
+ [1][0][RTW89_MKK][6] = 36,
+ [1][0][RTW89_IC][6] = 38,
+ [1][0][RTW89_KCC][6] = 32,
+ [1][0][RTW89_ACMA][6] = 34,
+ [1][0][RTW89_CN][6] = 26,
+ [1][0][RTW89_UK][6] = 34,
+ [1][0][RTW89_FCC][8] = 62,
+ [1][0][RTW89_ETSI][8] = 34,
+ [1][0][RTW89_MKK][8] = 38,
+ [1][0][RTW89_IC][8] = 62,
+ [1][0][RTW89_KCC][8] = 52,
+ [1][0][RTW89_ACMA][8] = 34,
+ [1][0][RTW89_CN][8] = 26,
+ [1][0][RTW89_UK][8] = 34,
+ [1][0][RTW89_FCC][10] = 62,
+ [1][0][RTW89_ETSI][10] = 34,
+ [1][0][RTW89_MKK][10] = 38,
+ [1][0][RTW89_IC][10] = 62,
+ [1][0][RTW89_KCC][10] = 52,
+ [1][0][RTW89_ACMA][10] = 34,
+ [1][0][RTW89_CN][10] = 26,
+ [1][0][RTW89_UK][10] = 34,
+ [1][0][RTW89_FCC][12] = 62,
+ [1][0][RTW89_ETSI][12] = 34,
+ [1][0][RTW89_MKK][12] = 38,
+ [1][0][RTW89_IC][12] = 62,
+ [1][0][RTW89_KCC][12] = 54,
+ [1][0][RTW89_ACMA][12] = 34,
+ [1][0][RTW89_CN][12] = 26,
+ [1][0][RTW89_UK][12] = 34,
+ [1][0][RTW89_FCC][14] = 64,
+ [1][0][RTW89_ETSI][14] = 34,
+ [1][0][RTW89_MKK][14] = 38,
+ [1][0][RTW89_IC][14] = 64,
+ [1][0][RTW89_KCC][14] = 54,
+ [1][0][RTW89_ACMA][14] = 34,
+ [1][0][RTW89_CN][14] = 26,
+ [1][0][RTW89_UK][14] = 34,
+ [1][0][RTW89_FCC][15] = 62,
+ [1][0][RTW89_ETSI][15] = 34,
+ [1][0][RTW89_MKK][15] = 58,
+ [1][0][RTW89_IC][15] = 62,
+ [1][0][RTW89_KCC][15] = 54,
+ [1][0][RTW89_ACMA][15] = 34,
+ [1][0][RTW89_CN][15] = 127,
+ [1][0][RTW89_UK][15] = 34,
+ [1][0][RTW89_FCC][17] = 62,
+ [1][0][RTW89_ETSI][17] = 34,
+ [1][0][RTW89_MKK][17] = 58,
+ [1][0][RTW89_IC][17] = 62,
+ [1][0][RTW89_KCC][17] = 54,
+ [1][0][RTW89_ACMA][17] = 34,
+ [1][0][RTW89_CN][17] = 127,
+ [1][0][RTW89_UK][17] = 34,
+ [1][0][RTW89_FCC][19] = 64,
+ [1][0][RTW89_ETSI][19] = 34,
+ [1][0][RTW89_MKK][19] = 58,
+ [1][0][RTW89_IC][19] = 64,
+ [1][0][RTW89_KCC][19] = 54,
+ [1][0][RTW89_ACMA][19] = 34,
+ [1][0][RTW89_CN][19] = 127,
+ [1][0][RTW89_UK][19] = 34,
+ [1][0][RTW89_FCC][21] = 64,
+ [1][0][RTW89_ETSI][21] = 34,
+ [1][0][RTW89_MKK][21] = 58,
+ [1][0][RTW89_IC][21] = 64,
+ [1][0][RTW89_KCC][21] = 54,
+ [1][0][RTW89_ACMA][21] = 34,
+ [1][0][RTW89_CN][21] = 127,
+ [1][0][RTW89_UK][21] = 34,
+ [1][0][RTW89_FCC][23] = 64,
+ [1][0][RTW89_ETSI][23] = 34,
+ [1][0][RTW89_MKK][23] = 58,
+ [1][0][RTW89_IC][23] = 64,
+ [1][0][RTW89_KCC][23] = 54,
+ [1][0][RTW89_ACMA][23] = 34,
+ [1][0][RTW89_CN][23] = 127,
+ [1][0][RTW89_UK][23] = 34,
+ [1][0][RTW89_FCC][25] = 64,
+ [1][0][RTW89_ETSI][25] = 34,
+ [1][0][RTW89_MKK][25] = 58,
+ [1][0][RTW89_IC][25] = 127,
+ [1][0][RTW89_KCC][25] = 54,
+ [1][0][RTW89_ACMA][25] = 127,
+ [1][0][RTW89_CN][25] = 127,
+ [1][0][RTW89_UK][25] = 34,
+ [1][0][RTW89_FCC][27] = 64,
+ [1][0][RTW89_ETSI][27] = 34,
+ [1][0][RTW89_MKK][27] = 58,
+ [1][0][RTW89_IC][27] = 127,
+ [1][0][RTW89_KCC][27] = 54,
+ [1][0][RTW89_ACMA][27] = 127,
+ [1][0][RTW89_CN][27] = 127,
+ [1][0][RTW89_UK][27] = 34,
+ [1][0][RTW89_FCC][29] = 64,
+ [1][0][RTW89_ETSI][29] = 34,
+ [1][0][RTW89_MKK][29] = 58,
+ [1][0][RTW89_IC][29] = 127,
+ [1][0][RTW89_KCC][29] = 54,
+ [1][0][RTW89_ACMA][29] = 127,
+ [1][0][RTW89_CN][29] = 127,
+ [1][0][RTW89_UK][29] = 34,
+ [1][0][RTW89_FCC][31] = 64,
+ [1][0][RTW89_ETSI][31] = 34,
+ [1][0][RTW89_MKK][31] = 58,
+ [1][0][RTW89_IC][31] = 64,
+ [1][0][RTW89_KCC][31] = 54,
+ [1][0][RTW89_ACMA][31] = 34,
+ [1][0][RTW89_CN][31] = 127,
+ [1][0][RTW89_UK][31] = 34,
+ [1][0][RTW89_FCC][33] = 64,
+ [1][0][RTW89_ETSI][33] = 34,
+ [1][0][RTW89_MKK][33] = 58,
+ [1][0][RTW89_IC][33] = 64,
+ [1][0][RTW89_KCC][33] = 54,
+ [1][0][RTW89_ACMA][33] = 34,
+ [1][0][RTW89_CN][33] = 127,
+ [1][0][RTW89_UK][33] = 34,
+ [1][0][RTW89_FCC][35] = 64,
+ [1][0][RTW89_ETSI][35] = 34,
+ [1][0][RTW89_MKK][35] = 58,
+ [1][0][RTW89_IC][35] = 64,
+ [1][0][RTW89_KCC][35] = 54,
+ [1][0][RTW89_ACMA][35] = 34,
+ [1][0][RTW89_CN][35] = 127,
+ [1][0][RTW89_UK][35] = 34,
+ [1][0][RTW89_FCC][37] = 78,
+ [1][0][RTW89_ETSI][37] = 127,
+ [1][0][RTW89_MKK][37] = 56,
+ [1][0][RTW89_IC][37] = 78,
+ [1][0][RTW89_KCC][37] = 54,
+ [1][0][RTW89_ACMA][37] = 62,
+ [1][0][RTW89_CN][37] = 127,
+ [1][0][RTW89_UK][37] = 62,
+ [1][0][RTW89_FCC][38] = 82,
+ [1][0][RTW89_ETSI][38] = 28,
+ [1][0][RTW89_MKK][38] = 127,
+ [1][0][RTW89_IC][38] = 82,
+ [1][0][RTW89_KCC][38] = 54,
+ [1][0][RTW89_ACMA][38] = 84,
+ [1][0][RTW89_CN][38] = 66,
+ [1][0][RTW89_UK][38] = 34,
+ [1][0][RTW89_FCC][40] = 82,
+ [1][0][RTW89_ETSI][40] = 28,
+ [1][0][RTW89_MKK][40] = 127,
+ [1][0][RTW89_IC][40] = 82,
+ [1][0][RTW89_KCC][40] = 54,
+ [1][0][RTW89_ACMA][40] = 84,
+ [1][0][RTW89_CN][40] = 66,
+ [1][0][RTW89_UK][40] = 34,
+ [1][0][RTW89_FCC][42] = 78,
+ [1][0][RTW89_ETSI][42] = 28,
+ [1][0][RTW89_MKK][42] = 127,
+ [1][0][RTW89_IC][42] = 78,
+ [1][0][RTW89_KCC][42] = 54,
+ [1][0][RTW89_ACMA][42] = 84,
+ [1][0][RTW89_CN][42] = 66,
+ [1][0][RTW89_UK][42] = 34,
+ [1][0][RTW89_FCC][44] = 82,
+ [1][0][RTW89_ETSI][44] = 28,
+ [1][0][RTW89_MKK][44] = 127,
+ [1][0][RTW89_IC][44] = 82,
+ [1][0][RTW89_KCC][44] = 54,
+ [1][0][RTW89_ACMA][44] = 84,
+ [1][0][RTW89_CN][44] = 66,
+ [1][0][RTW89_UK][44] = 34,
+ [1][0][RTW89_FCC][46] = 82,
+ [1][0][RTW89_ETSI][46] = 28,
+ [1][0][RTW89_MKK][46] = 127,
+ [1][0][RTW89_IC][46] = 82,
+ [1][0][RTW89_KCC][46] = 54,
+ [1][0][RTW89_ACMA][46] = 84,
+ [1][0][RTW89_CN][46] = 66,
+ [1][0][RTW89_UK][46] = 34,
+ [1][0][RTW89_FCC][48] = 52,
+ [1][0][RTW89_ETSI][48] = 127,
+ [1][0][RTW89_MKK][48] = 127,
+ [1][0][RTW89_IC][48] = 127,
+ [1][0][RTW89_KCC][48] = 127,
+ [1][0][RTW89_ACMA][48] = 127,
+ [1][0][RTW89_CN][48] = 127,
+ [1][0][RTW89_UK][48] = 127,
+ [1][0][RTW89_FCC][50] = 52,
+ [1][0][RTW89_ETSI][50] = 127,
+ [1][0][RTW89_MKK][50] = 127,
+ [1][0][RTW89_IC][50] = 127,
+ [1][0][RTW89_KCC][50] = 127,
+ [1][0][RTW89_ACMA][50] = 127,
+ [1][0][RTW89_CN][50] = 127,
+ [1][0][RTW89_UK][50] = 127,
+ [1][0][RTW89_FCC][52] = 52,
+ [1][0][RTW89_ETSI][52] = 127,
+ [1][0][RTW89_MKK][52] = 127,
+ [1][0][RTW89_IC][52] = 127,
+ [1][0][RTW89_KCC][52] = 127,
+ [1][0][RTW89_ACMA][52] = 127,
+ [1][0][RTW89_CN][52] = 127,
+ [1][0][RTW89_UK][52] = 127,
+ [1][1][RTW89_FCC][0] = 127,
+ [1][1][RTW89_ETSI][0] = 127,
+ [1][1][RTW89_MKK][0] = 127,
+ [1][1][RTW89_IC][0] = 127,
+ [1][1][RTW89_KCC][0] = 127,
+ [1][1][RTW89_ACMA][0] = 127,
+ [1][1][RTW89_CN][0] = 14,
+ [1][1][RTW89_UK][0] = 127,
+ [1][1][RTW89_FCC][2] = 127,
+ [1][1][RTW89_ETSI][2] = 127,
+ [1][1][RTW89_MKK][2] = 127,
+ [1][1][RTW89_IC][2] = 127,
+ [1][1][RTW89_KCC][2] = 127,
+ [1][1][RTW89_ACMA][2] = 127,
+ [1][1][RTW89_CN][2] = 14,
+ [1][1][RTW89_UK][2] = 127,
+ [1][1][RTW89_FCC][4] = 127,
+ [1][1][RTW89_ETSI][4] = 127,
+ [1][1][RTW89_MKK][4] = 127,
+ [1][1][RTW89_IC][4] = 127,
+ [1][1][RTW89_KCC][4] = 127,
+ [1][1][RTW89_ACMA][4] = 127,
+ [1][1][RTW89_CN][4] = 14,
+ [1][1][RTW89_UK][4] = 127,
+ [1][1][RTW89_FCC][6] = 127,
+ [1][1][RTW89_ETSI][6] = 127,
+ [1][1][RTW89_MKK][6] = 127,
+ [1][1][RTW89_IC][6] = 127,
+ [1][1][RTW89_KCC][6] = 127,
+ [1][1][RTW89_ACMA][6] = 127,
+ [1][1][RTW89_CN][6] = 14,
+ [1][1][RTW89_UK][6] = 127,
+ [1][1][RTW89_FCC][8] = 127,
+ [1][1][RTW89_ETSI][8] = 127,
+ [1][1][RTW89_MKK][8] = 127,
+ [1][1][RTW89_IC][8] = 127,
+ [1][1][RTW89_KCC][8] = 127,
+ [1][1][RTW89_ACMA][8] = 127,
+ [1][1][RTW89_CN][8] = 14,
+ [1][1][RTW89_UK][8] = 127,
+ [1][1][RTW89_FCC][10] = 127,
+ [1][1][RTW89_ETSI][10] = 127,
+ [1][1][RTW89_MKK][10] = 127,
+ [1][1][RTW89_IC][10] = 127,
+ [1][1][RTW89_KCC][10] = 127,
+ [1][1][RTW89_ACMA][10] = 127,
+ [1][1][RTW89_CN][10] = 14,
+ [1][1][RTW89_UK][10] = 127,
+ [1][1][RTW89_FCC][12] = 127,
+ [1][1][RTW89_ETSI][12] = 127,
+ [1][1][RTW89_MKK][12] = 127,
+ [1][1][RTW89_IC][12] = 127,
+ [1][1][RTW89_KCC][12] = 127,
+ [1][1][RTW89_ACMA][12] = 127,
+ [1][1][RTW89_CN][12] = 14,
+ [1][1][RTW89_UK][12] = 127,
+ [1][1][RTW89_FCC][14] = 127,
+ [1][1][RTW89_ETSI][14] = 127,
+ [1][1][RTW89_MKK][14] = 127,
+ [1][1][RTW89_IC][14] = 127,
+ [1][1][RTW89_KCC][14] = 127,
+ [1][1][RTW89_ACMA][14] = 127,
+ [1][1][RTW89_CN][14] = 14,
+ [1][1][RTW89_UK][14] = 127,
+ [1][1][RTW89_FCC][15] = 127,
+ [1][1][RTW89_ETSI][15] = 127,
+ [1][1][RTW89_MKK][15] = 127,
+ [1][1][RTW89_IC][15] = 127,
+ [1][1][RTW89_KCC][15] = 127,
+ [1][1][RTW89_ACMA][15] = 127,
+ [1][1][RTW89_CN][15] = 127,
+ [1][1][RTW89_UK][15] = 127,
+ [1][1][RTW89_FCC][17] = 127,
+ [1][1][RTW89_ETSI][17] = 127,
+ [1][1][RTW89_MKK][17] = 127,
+ [1][1][RTW89_IC][17] = 127,
+ [1][1][RTW89_KCC][17] = 127,
+ [1][1][RTW89_ACMA][17] = 127,
+ [1][1][RTW89_CN][17] = 127,
+ [1][1][RTW89_UK][17] = 127,
+ [1][1][RTW89_FCC][19] = 127,
+ [1][1][RTW89_ETSI][19] = 127,
+ [1][1][RTW89_MKK][19] = 127,
+ [1][1][RTW89_IC][19] = 127,
+ [1][1][RTW89_KCC][19] = 127,
+ [1][1][RTW89_ACMA][19] = 127,
+ [1][1][RTW89_CN][19] = 127,
+ [1][1][RTW89_UK][19] = 127,
+ [1][1][RTW89_FCC][21] = 127,
+ [1][1][RTW89_ETSI][21] = 127,
+ [1][1][RTW89_MKK][21] = 127,
+ [1][1][RTW89_IC][21] = 127,
+ [1][1][RTW89_KCC][21] = 127,
+ [1][1][RTW89_ACMA][21] = 127,
+ [1][1][RTW89_CN][21] = 127,
+ [1][1][RTW89_UK][21] = 127,
+ [1][1][RTW89_FCC][23] = 127,
+ [1][1][RTW89_ETSI][23] = 127,
+ [1][1][RTW89_MKK][23] = 127,
+ [1][1][RTW89_IC][23] = 127,
+ [1][1][RTW89_KCC][23] = 127,
+ [1][1][RTW89_ACMA][23] = 127,
+ [1][1][RTW89_CN][23] = 127,
+ [1][1][RTW89_UK][23] = 127,
+ [1][1][RTW89_FCC][25] = 127,
+ [1][1][RTW89_ETSI][25] = 127,
+ [1][1][RTW89_MKK][25] = 127,
+ [1][1][RTW89_IC][25] = 127,
+ [1][1][RTW89_KCC][25] = 127,
+ [1][1][RTW89_ACMA][25] = 127,
+ [1][1][RTW89_CN][25] = 127,
+ [1][1][RTW89_UK][25] = 127,
+ [1][1][RTW89_FCC][27] = 127,
+ [1][1][RTW89_ETSI][27] = 127,
+ [1][1][RTW89_MKK][27] = 127,
+ [1][1][RTW89_IC][27] = 127,
+ [1][1][RTW89_KCC][27] = 127,
+ [1][1][RTW89_ACMA][27] = 127,
+ [1][1][RTW89_CN][27] = 127,
+ [1][1][RTW89_UK][27] = 127,
+ [1][1][RTW89_FCC][29] = 127,
+ [1][1][RTW89_ETSI][29] = 127,
+ [1][1][RTW89_MKK][29] = 127,
+ [1][1][RTW89_IC][29] = 127,
+ [1][1][RTW89_KCC][29] = 127,
+ [1][1][RTW89_ACMA][29] = 127,
+ [1][1][RTW89_CN][29] = 127,
+ [1][1][RTW89_UK][29] = 127,
+ [1][1][RTW89_FCC][31] = 127,
+ [1][1][RTW89_ETSI][31] = 127,
+ [1][1][RTW89_MKK][31] = 127,
+ [1][1][RTW89_IC][31] = 127,
+ [1][1][RTW89_KCC][31] = 127,
+ [1][1][RTW89_ACMA][31] = 127,
+ [1][1][RTW89_CN][31] = 127,
+ [1][1][RTW89_UK][31] = 127,
+ [1][1][RTW89_FCC][33] = 127,
+ [1][1][RTW89_ETSI][33] = 127,
+ [1][1][RTW89_MKK][33] = 127,
+ [1][1][RTW89_IC][33] = 127,
+ [1][1][RTW89_KCC][33] = 127,
+ [1][1][RTW89_ACMA][33] = 127,
+ [1][1][RTW89_CN][33] = 127,
+ [1][1][RTW89_UK][33] = 127,
+ [1][1][RTW89_FCC][35] = 127,
+ [1][1][RTW89_ETSI][35] = 127,
+ [1][1][RTW89_MKK][35] = 127,
+ [1][1][RTW89_IC][35] = 127,
+ [1][1][RTW89_KCC][35] = 127,
+ [1][1][RTW89_ACMA][35] = 127,
+ [1][1][RTW89_CN][35] = 127,
+ [1][1][RTW89_UK][35] = 127,
+ [1][1][RTW89_FCC][37] = 127,
+ [1][1][RTW89_ETSI][37] = 127,
+ [1][1][RTW89_MKK][37] = 127,
+ [1][1][RTW89_IC][37] = 127,
+ [1][1][RTW89_KCC][37] = 127,
+ [1][1][RTW89_ACMA][37] = 127,
+ [1][1][RTW89_CN][37] = 127,
+ [1][1][RTW89_UK][37] = 127,
+ [1][1][RTW89_FCC][38] = 127,
+ [1][1][RTW89_ETSI][38] = 127,
+ [1][1][RTW89_MKK][38] = 127,
+ [1][1][RTW89_IC][38] = 127,
+ [1][1][RTW89_KCC][38] = 127,
+ [1][1][RTW89_ACMA][38] = 127,
+ [1][1][RTW89_CN][38] = 54,
+ [1][1][RTW89_UK][38] = 127,
+ [1][1][RTW89_FCC][40] = 127,
+ [1][1][RTW89_ETSI][40] = 127,
+ [1][1][RTW89_MKK][40] = 127,
+ [1][1][RTW89_IC][40] = 127,
+ [1][1][RTW89_KCC][40] = 127,
+ [1][1][RTW89_ACMA][40] = 127,
+ [1][1][RTW89_CN][40] = 54,
+ [1][1][RTW89_UK][40] = 127,
+ [1][1][RTW89_FCC][42] = 127,
+ [1][1][RTW89_ETSI][42] = 127,
+ [1][1][RTW89_MKK][42] = 127,
+ [1][1][RTW89_IC][42] = 127,
+ [1][1][RTW89_KCC][42] = 127,
+ [1][1][RTW89_ACMA][42] = 127,
+ [1][1][RTW89_CN][42] = 54,
+ [1][1][RTW89_UK][42] = 127,
+ [1][1][RTW89_FCC][44] = 127,
+ [1][1][RTW89_ETSI][44] = 127,
+ [1][1][RTW89_MKK][44] = 127,
+ [1][1][RTW89_IC][44] = 127,
+ [1][1][RTW89_KCC][44] = 127,
+ [1][1][RTW89_ACMA][44] = 127,
+ [1][1][RTW89_CN][44] = 54,
+ [1][1][RTW89_UK][44] = 127,
+ [1][1][RTW89_FCC][46] = 127,
+ [1][1][RTW89_ETSI][46] = 127,
+ [1][1][RTW89_MKK][46] = 127,
+ [1][1][RTW89_IC][46] = 127,
+ [1][1][RTW89_KCC][46] = 127,
+ [1][1][RTW89_ACMA][46] = 127,
+ [1][1][RTW89_CN][46] = 54,
+ [1][1][RTW89_UK][46] = 127,
+ [1][1][RTW89_FCC][48] = 127,
+ [1][1][RTW89_ETSI][48] = 127,
+ [1][1][RTW89_MKK][48] = 127,
+ [1][1][RTW89_IC][48] = 127,
+ [1][1][RTW89_KCC][48] = 127,
+ [1][1][RTW89_ACMA][48] = 127,
+ [1][1][RTW89_CN][48] = 127,
+ [1][1][RTW89_UK][48] = 127,
+ [1][1][RTW89_FCC][50] = 127,
+ [1][1][RTW89_ETSI][50] = 127,
+ [1][1][RTW89_MKK][50] = 127,
+ [1][1][RTW89_IC][50] = 127,
+ [1][1][RTW89_KCC][50] = 127,
+ [1][1][RTW89_ACMA][50] = 127,
+ [1][1][RTW89_CN][50] = 127,
+ [1][1][RTW89_UK][50] = 127,
+ [1][1][RTW89_FCC][52] = 127,
+ [1][1][RTW89_ETSI][52] = 127,
+ [1][1][RTW89_MKK][52] = 127,
+ [1][1][RTW89_IC][52] = 127,
+ [1][1][RTW89_KCC][52] = 127,
+ [1][1][RTW89_ACMA][52] = 127,
+ [1][1][RTW89_CN][52] = 127,
+ [1][1][RTW89_UK][52] = 127,
+ [2][0][RTW89_FCC][0] = 78,
+ [2][0][RTW89_ETSI][0] = 46,
+ [2][0][RTW89_MKK][0] = 48,
+ [2][0][RTW89_IC][0] = 50,
+ [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_ACMA][0] = 46,
+ [2][0][RTW89_CN][0] = 40,
+ [2][0][RTW89_UK][0] = 46,
+ [2][0][RTW89_FCC][2] = 74,
+ [2][0][RTW89_ETSI][2] = 46,
+ [2][0][RTW89_MKK][2] = 48,
+ [2][0][RTW89_IC][2] = 48,
+ [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_ACMA][2] = 46,
+ [2][0][RTW89_CN][2] = 40,
+ [2][0][RTW89_UK][2] = 46,
+ [2][0][RTW89_FCC][4] = 74,
+ [2][0][RTW89_ETSI][4] = 46,
+ [2][0][RTW89_MKK][4] = 48,
+ [2][0][RTW89_IC][4] = 48,
+ [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_ACMA][4] = 46,
+ [2][0][RTW89_CN][4] = 40,
+ [2][0][RTW89_UK][4] = 46,
+ [2][0][RTW89_FCC][6] = 74,
+ [2][0][RTW89_ETSI][6] = 46,
+ [2][0][RTW89_MKK][6] = 48,
+ [2][0][RTW89_IC][6] = 48,
+ [2][0][RTW89_KCC][6] = 40,
+ [2][0][RTW89_ACMA][6] = 46,
+ [2][0][RTW89_CN][6] = 40,
+ [2][0][RTW89_UK][6] = 46,
+ [2][0][RTW89_FCC][8] = 74,
+ [2][0][RTW89_ETSI][8] = 46,
+ [2][0][RTW89_MKK][8] = 48,
+ [2][0][RTW89_IC][8] = 64,
+ [2][0][RTW89_KCC][8] = 66,
+ [2][0][RTW89_ACMA][8] = 46,
+ [2][0][RTW89_CN][8] = 40,
+ [2][0][RTW89_UK][8] = 46,
+ [2][0][RTW89_FCC][10] = 74,
+ [2][0][RTW89_ETSI][10] = 46,
+ [2][0][RTW89_MKK][10] = 48,
+ [2][0][RTW89_IC][10] = 64,
+ [2][0][RTW89_KCC][10] = 66,
+ [2][0][RTW89_ACMA][10] = 46,
+ [2][0][RTW89_CN][10] = 40,
+ [2][0][RTW89_UK][10] = 46,
+ [2][0][RTW89_FCC][12] = 74,
+ [2][0][RTW89_ETSI][12] = 46,
+ [2][0][RTW89_MKK][12] = 48,
+ [2][0][RTW89_IC][12] = 64,
+ [2][0][RTW89_KCC][12] = 64,
+ [2][0][RTW89_ACMA][12] = 46,
+ [2][0][RTW89_CN][12] = 40,
+ [2][0][RTW89_UK][12] = 46,
+ [2][0][RTW89_FCC][14] = 80,
+ [2][0][RTW89_ETSI][14] = 46,
+ [2][0][RTW89_MKK][14] = 48,
+ [2][0][RTW89_IC][14] = 64,
+ [2][0][RTW89_KCC][14] = 64,
+ [2][0][RTW89_ACMA][14] = 46,
+ [2][0][RTW89_CN][14] = 40,
+ [2][0][RTW89_UK][14] = 46,
+ [2][0][RTW89_FCC][15] = 72,
+ [2][0][RTW89_ETSI][15] = 46,
+ [2][0][RTW89_MKK][15] = 70,
+ [2][0][RTW89_IC][15] = 72,
+ [2][0][RTW89_KCC][15] = 66,
+ [2][0][RTW89_ACMA][15] = 46,
+ [2][0][RTW89_CN][15] = 127,
+ [2][0][RTW89_UK][15] = 46,
+ [2][0][RTW89_FCC][17] = 72,
+ [2][0][RTW89_ETSI][17] = 46,
+ [2][0][RTW89_MKK][17] = 70,
+ [2][0][RTW89_IC][17] = 72,
+ [2][0][RTW89_KCC][17] = 66,
+ [2][0][RTW89_ACMA][17] = 46,
+ [2][0][RTW89_CN][17] = 127,
+ [2][0][RTW89_UK][17] = 46,
+ [2][0][RTW89_FCC][19] = 70,
+ [2][0][RTW89_ETSI][19] = 46,
+ [2][0][RTW89_MKK][19] = 70,
+ [2][0][RTW89_IC][19] = 70,
+ [2][0][RTW89_KCC][19] = 66,
+ [2][0][RTW89_ACMA][19] = 46,
+ [2][0][RTW89_CN][19] = 127,
+ [2][0][RTW89_UK][19] = 46,
+ [2][0][RTW89_FCC][21] = 70,
+ [2][0][RTW89_ETSI][21] = 46,
+ [2][0][RTW89_MKK][21] = 70,
+ [2][0][RTW89_IC][21] = 70,
+ [2][0][RTW89_KCC][21] = 66,
+ [2][0][RTW89_ACMA][21] = 46,
+ [2][0][RTW89_CN][21] = 127,
+ [2][0][RTW89_UK][21] = 46,
+ [2][0][RTW89_FCC][23] = 70,
+ [2][0][RTW89_ETSI][23] = 46,
+ [2][0][RTW89_MKK][23] = 70,
+ [2][0][RTW89_IC][23] = 70,
+ [2][0][RTW89_KCC][23] = 66,
+ [2][0][RTW89_ACMA][23] = 46,
+ [2][0][RTW89_CN][23] = 127,
+ [2][0][RTW89_UK][23] = 46,
+ [2][0][RTW89_FCC][25] = 70,
+ [2][0][RTW89_ETSI][25] = 46,
+ [2][0][RTW89_MKK][25] = 70,
+ [2][0][RTW89_IC][25] = 127,
+ [2][0][RTW89_KCC][25] = 66,
+ [2][0][RTW89_ACMA][25] = 127,
+ [2][0][RTW89_CN][25] = 127,
+ [2][0][RTW89_UK][25] = 46,
+ [2][0][RTW89_FCC][27] = 70,
+ [2][0][RTW89_ETSI][27] = 46,
+ [2][0][RTW89_MKK][27] = 70,
+ [2][0][RTW89_IC][27] = 127,
+ [2][0][RTW89_KCC][27] = 64,
+ [2][0][RTW89_ACMA][27] = 127,
+ [2][0][RTW89_CN][27] = 127,
+ [2][0][RTW89_UK][27] = 46,
+ [2][0][RTW89_FCC][29] = 70,
+ [2][0][RTW89_ETSI][29] = 46,
+ [2][0][RTW89_MKK][29] = 70,
+ [2][0][RTW89_IC][29] = 127,
+ [2][0][RTW89_KCC][29] = 64,
+ [2][0][RTW89_ACMA][29] = 127,
+ [2][0][RTW89_CN][29] = 127,
+ [2][0][RTW89_UK][29] = 46,
+ [2][0][RTW89_FCC][31] = 70,
+ [2][0][RTW89_ETSI][31] = 46,
+ [2][0][RTW89_MKK][31] = 70,
+ [2][0][RTW89_IC][31] = 70,
+ [2][0][RTW89_KCC][31] = 64,
+ [2][0][RTW89_ACMA][31] = 46,
+ [2][0][RTW89_CN][31] = 127,
+ [2][0][RTW89_UK][31] = 46,
+ [2][0][RTW89_FCC][33] = 70,
+ [2][0][RTW89_ETSI][33] = 46,
+ [2][0][RTW89_MKK][33] = 70,
+ [2][0][RTW89_IC][33] = 70,
+ [2][0][RTW89_KCC][33] = 64,
+ [2][0][RTW89_ACMA][33] = 46,
+ [2][0][RTW89_CN][33] = 127,
+ [2][0][RTW89_UK][33] = 46,
+ [2][0][RTW89_FCC][35] = 70,
+ [2][0][RTW89_ETSI][35] = 46,
+ [2][0][RTW89_MKK][35] = 70,
+ [2][0][RTW89_IC][35] = 70,
+ [2][0][RTW89_KCC][35] = 64,
+ [2][0][RTW89_ACMA][35] = 46,
+ [2][0][RTW89_CN][35] = 127,
+ [2][0][RTW89_UK][35] = 46,
+ [2][0][RTW89_FCC][37] = 84,
+ [2][0][RTW89_ETSI][37] = 127,
+ [2][0][RTW89_MKK][37] = 68,
+ [2][0][RTW89_IC][37] = 84,
+ [2][0][RTW89_KCC][37] = 66,
+ [2][0][RTW89_ACMA][37] = 74,
+ [2][0][RTW89_CN][37] = 127,
+ [2][0][RTW89_UK][37] = 74,
+ [2][0][RTW89_FCC][38] = 84,
+ [2][0][RTW89_ETSI][38] = 28,
+ [2][0][RTW89_MKK][38] = 127,
+ [2][0][RTW89_IC][38] = 84,
+ [2][0][RTW89_KCC][38] = 64,
+ [2][0][RTW89_ACMA][38] = 84,
+ [2][0][RTW89_CN][38] = 68,
+ [2][0][RTW89_UK][38] = 46,
+ [2][0][RTW89_FCC][40] = 84,
+ [2][0][RTW89_ETSI][40] = 28,
+ [2][0][RTW89_MKK][40] = 127,
+ [2][0][RTW89_IC][40] = 84,
+ [2][0][RTW89_KCC][40] = 64,
+ [2][0][RTW89_ACMA][40] = 84,
+ [2][0][RTW89_CN][40] = 68,
+ [2][0][RTW89_UK][40] = 46,
+ [2][0][RTW89_FCC][42] = 80,
+ [2][0][RTW89_ETSI][42] = 28,
+ [2][0][RTW89_MKK][42] = 127,
+ [2][0][RTW89_IC][42] = 80,
+ [2][0][RTW89_KCC][42] = 66,
+ [2][0][RTW89_ACMA][42] = 84,
+ [2][0][RTW89_CN][42] = 68,
+ [2][0][RTW89_UK][42] = 46,
+ [2][0][RTW89_FCC][44] = 82,
+ [2][0][RTW89_ETSI][44] = 28,
+ [2][0][RTW89_MKK][44] = 127,
+ [2][0][RTW89_IC][44] = 82,
+ [2][0][RTW89_KCC][44] = 66,
+ [2][0][RTW89_ACMA][44] = 84,
+ [2][0][RTW89_CN][44] = 68,
+ [2][0][RTW89_UK][44] = 46,
+ [2][0][RTW89_FCC][46] = 82,
+ [2][0][RTW89_ETSI][46] = 28,
+ [2][0][RTW89_MKK][46] = 127,
+ [2][0][RTW89_IC][46] = 82,
+ [2][0][RTW89_KCC][46] = 66,
+ [2][0][RTW89_ACMA][46] = 84,
+ [2][0][RTW89_CN][46] = 68,
+ [2][0][RTW89_UK][46] = 46,
+ [2][0][RTW89_FCC][48] = 64,
+ [2][0][RTW89_ETSI][48] = 127,
+ [2][0][RTW89_MKK][48] = 127,
+ [2][0][RTW89_IC][48] = 127,
+ [2][0][RTW89_KCC][48] = 127,
+ [2][0][RTW89_ACMA][48] = 127,
+ [2][0][RTW89_CN][48] = 127,
+ [2][0][RTW89_UK][48] = 127,
+ [2][0][RTW89_FCC][50] = 64,
+ [2][0][RTW89_ETSI][50] = 127,
+ [2][0][RTW89_MKK][50] = 127,
+ [2][0][RTW89_IC][50] = 127,
+ [2][0][RTW89_KCC][50] = 127,
+ [2][0][RTW89_ACMA][50] = 127,
+ [2][0][RTW89_CN][50] = 127,
+ [2][0][RTW89_UK][50] = 127,
+ [2][0][RTW89_FCC][52] = 60,
+ [2][0][RTW89_ETSI][52] = 127,
+ [2][0][RTW89_MKK][52] = 127,
+ [2][0][RTW89_IC][52] = 127,
+ [2][0][RTW89_KCC][52] = 127,
+ [2][0][RTW89_ACMA][52] = 127,
+ [2][0][RTW89_CN][52] = 127,
+ [2][0][RTW89_UK][52] = 127,
+ [2][1][RTW89_FCC][0] = 127,
+ [2][1][RTW89_ETSI][0] = 127,
+ [2][1][RTW89_MKK][0] = 127,
+ [2][1][RTW89_IC][0] = 127,
+ [2][1][RTW89_KCC][0] = 127,
+ [2][1][RTW89_ACMA][0] = 127,
+ [2][1][RTW89_CN][0] = 28,
+ [2][1][RTW89_UK][0] = 127,
+ [2][1][RTW89_FCC][2] = 127,
+ [2][1][RTW89_ETSI][2] = 127,
+ [2][1][RTW89_MKK][2] = 127,
+ [2][1][RTW89_IC][2] = 127,
+ [2][1][RTW89_KCC][2] = 127,
+ [2][1][RTW89_ACMA][2] = 127,
+ [2][1][RTW89_CN][2] = 28,
+ [2][1][RTW89_UK][2] = 127,
+ [2][1][RTW89_FCC][4] = 127,
+ [2][1][RTW89_ETSI][4] = 127,
+ [2][1][RTW89_MKK][4] = 127,
+ [2][1][RTW89_IC][4] = 127,
+ [2][1][RTW89_KCC][4] = 127,
+ [2][1][RTW89_ACMA][4] = 127,
+ [2][1][RTW89_CN][4] = 28,
+ [2][1][RTW89_UK][4] = 127,
+ [2][1][RTW89_FCC][6] = 127,
+ [2][1][RTW89_ETSI][6] = 127,
+ [2][1][RTW89_MKK][6] = 127,
+ [2][1][RTW89_IC][6] = 127,
+ [2][1][RTW89_KCC][6] = 127,
+ [2][1][RTW89_ACMA][6] = 127,
+ [2][1][RTW89_CN][6] = 28,
+ [2][1][RTW89_UK][6] = 127,
+ [2][1][RTW89_FCC][8] = 127,
+ [2][1][RTW89_ETSI][8] = 127,
+ [2][1][RTW89_MKK][8] = 127,
+ [2][1][RTW89_IC][8] = 127,
+ [2][1][RTW89_KCC][8] = 127,
+ [2][1][RTW89_ACMA][8] = 127,
+ [2][1][RTW89_CN][8] = 28,
+ [2][1][RTW89_UK][8] = 127,
+ [2][1][RTW89_FCC][10] = 127,
+ [2][1][RTW89_ETSI][10] = 127,
+ [2][1][RTW89_MKK][10] = 127,
+ [2][1][RTW89_IC][10] = 127,
+ [2][1][RTW89_KCC][10] = 127,
+ [2][1][RTW89_ACMA][10] = 127,
+ [2][1][RTW89_CN][10] = 28,
+ [2][1][RTW89_UK][10] = 127,
+ [2][1][RTW89_FCC][12] = 127,
+ [2][1][RTW89_ETSI][12] = 127,
+ [2][1][RTW89_MKK][12] = 127,
+ [2][1][RTW89_IC][12] = 127,
+ [2][1][RTW89_KCC][12] = 127,
+ [2][1][RTW89_ACMA][12] = 127,
+ [2][1][RTW89_CN][12] = 28,
+ [2][1][RTW89_UK][12] = 127,
+ [2][1][RTW89_FCC][14] = 127,
+ [2][1][RTW89_ETSI][14] = 127,
+ [2][1][RTW89_MKK][14] = 127,
+ [2][1][RTW89_IC][14] = 127,
+ [2][1][RTW89_KCC][14] = 127,
+ [2][1][RTW89_ACMA][14] = 127,
+ [2][1][RTW89_CN][14] = 28,
+ [2][1][RTW89_UK][14] = 127,
+ [2][1][RTW89_FCC][15] = 127,
+ [2][1][RTW89_ETSI][15] = 127,
+ [2][1][RTW89_MKK][15] = 127,
+ [2][1][RTW89_IC][15] = 127,
+ [2][1][RTW89_KCC][15] = 127,
+ [2][1][RTW89_ACMA][15] = 127,
+ [2][1][RTW89_CN][15] = 127,
+ [2][1][RTW89_UK][15] = 127,
+ [2][1][RTW89_FCC][17] = 127,
+ [2][1][RTW89_ETSI][17] = 127,
+ [2][1][RTW89_MKK][17] = 127,
+ [2][1][RTW89_IC][17] = 127,
+ [2][1][RTW89_KCC][17] = 127,
+ [2][1][RTW89_ACMA][17] = 127,
+ [2][1][RTW89_CN][17] = 127,
+ [2][1][RTW89_UK][17] = 127,
+ [2][1][RTW89_FCC][19] = 127,
+ [2][1][RTW89_ETSI][19] = 127,
+ [2][1][RTW89_MKK][19] = 127,
+ [2][1][RTW89_IC][19] = 127,
+ [2][1][RTW89_KCC][19] = 127,
+ [2][1][RTW89_ACMA][19] = 127,
+ [2][1][RTW89_CN][19] = 127,
+ [2][1][RTW89_UK][19] = 127,
+ [2][1][RTW89_FCC][21] = 127,
+ [2][1][RTW89_ETSI][21] = 127,
+ [2][1][RTW89_MKK][21] = 127,
+ [2][1][RTW89_IC][21] = 127,
+ [2][1][RTW89_KCC][21] = 127,
+ [2][1][RTW89_ACMA][21] = 127,
+ [2][1][RTW89_CN][21] = 127,
+ [2][1][RTW89_UK][21] = 127,
+ [2][1][RTW89_FCC][23] = 127,
+ [2][1][RTW89_ETSI][23] = 127,
+ [2][1][RTW89_MKK][23] = 127,
+ [2][1][RTW89_IC][23] = 127,
+ [2][1][RTW89_KCC][23] = 127,
+ [2][1][RTW89_ACMA][23] = 127,
+ [2][1][RTW89_CN][23] = 127,
+ [2][1][RTW89_UK][23] = 127,
+ [2][1][RTW89_FCC][25] = 127,
+ [2][1][RTW89_ETSI][25] = 127,
+ [2][1][RTW89_MKK][25] = 127,
+ [2][1][RTW89_IC][25] = 127,
+ [2][1][RTW89_KCC][25] = 127,
+ [2][1][RTW89_ACMA][25] = 127,
+ [2][1][RTW89_CN][25] = 127,
+ [2][1][RTW89_UK][25] = 127,
+ [2][1][RTW89_FCC][27] = 127,
+ [2][1][RTW89_ETSI][27] = 127,
+ [2][1][RTW89_MKK][27] = 127,
+ [2][1][RTW89_IC][27] = 127,
+ [2][1][RTW89_KCC][27] = 127,
+ [2][1][RTW89_ACMA][27] = 127,
+ [2][1][RTW89_CN][27] = 127,
+ [2][1][RTW89_UK][27] = 127,
+ [2][1][RTW89_FCC][29] = 127,
+ [2][1][RTW89_ETSI][29] = 127,
+ [2][1][RTW89_MKK][29] = 127,
+ [2][1][RTW89_IC][29] = 127,
+ [2][1][RTW89_KCC][29] = 127,
+ [2][1][RTW89_ACMA][29] = 127,
+ [2][1][RTW89_CN][29] = 127,
+ [2][1][RTW89_UK][29] = 127,
+ [2][1][RTW89_FCC][31] = 127,
+ [2][1][RTW89_ETSI][31] = 127,
+ [2][1][RTW89_MKK][31] = 127,
+ [2][1][RTW89_IC][31] = 127,
+ [2][1][RTW89_KCC][31] = 127,
+ [2][1][RTW89_ACMA][31] = 127,
+ [2][1][RTW89_CN][31] = 127,
+ [2][1][RTW89_UK][31] = 127,
+ [2][1][RTW89_FCC][33] = 127,
+ [2][1][RTW89_ETSI][33] = 127,
+ [2][1][RTW89_MKK][33] = 127,
+ [2][1][RTW89_IC][33] = 127,
+ [2][1][RTW89_KCC][33] = 127,
+ [2][1][RTW89_ACMA][33] = 127,
+ [2][1][RTW89_CN][33] = 127,
+ [2][1][RTW89_UK][33] = 127,
+ [2][1][RTW89_FCC][35] = 127,
+ [2][1][RTW89_ETSI][35] = 127,
+ [2][1][RTW89_MKK][35] = 127,
+ [2][1][RTW89_IC][35] = 127,
+ [2][1][RTW89_KCC][35] = 127,
+ [2][1][RTW89_ACMA][35] = 127,
+ [2][1][RTW89_CN][35] = 127,
+ [2][1][RTW89_UK][35] = 127,
+ [2][1][RTW89_FCC][37] = 127,
+ [2][1][RTW89_ETSI][37] = 127,
+ [2][1][RTW89_MKK][37] = 127,
+ [2][1][RTW89_IC][37] = 127,
+ [2][1][RTW89_KCC][37] = 127,
+ [2][1][RTW89_ACMA][37] = 127,
+ [2][1][RTW89_CN][37] = 127,
+ [2][1][RTW89_UK][37] = 127,
+ [2][1][RTW89_FCC][38] = 127,
+ [2][1][RTW89_ETSI][38] = 127,
+ [2][1][RTW89_MKK][38] = 127,
+ [2][1][RTW89_IC][38] = 127,
+ [2][1][RTW89_KCC][38] = 127,
+ [2][1][RTW89_ACMA][38] = 127,
+ [2][1][RTW89_CN][38] = 56,
+ [2][1][RTW89_UK][38] = 127,
+ [2][1][RTW89_FCC][40] = 127,
+ [2][1][RTW89_ETSI][40] = 127,
+ [2][1][RTW89_MKK][40] = 127,
+ [2][1][RTW89_IC][40] = 127,
+ [2][1][RTW89_KCC][40] = 127,
+ [2][1][RTW89_ACMA][40] = 127,
+ [2][1][RTW89_CN][40] = 56,
+ [2][1][RTW89_UK][40] = 127,
+ [2][1][RTW89_FCC][42] = 127,
+ [2][1][RTW89_ETSI][42] = 127,
+ [2][1][RTW89_MKK][42] = 127,
+ [2][1][RTW89_IC][42] = 127,
+ [2][1][RTW89_KCC][42] = 127,
+ [2][1][RTW89_ACMA][42] = 127,
+ [2][1][RTW89_CN][42] = 56,
+ [2][1][RTW89_UK][42] = 127,
+ [2][1][RTW89_FCC][44] = 127,
+ [2][1][RTW89_ETSI][44] = 127,
+ [2][1][RTW89_MKK][44] = 127,
+ [2][1][RTW89_IC][44] = 127,
+ [2][1][RTW89_KCC][44] = 127,
+ [2][1][RTW89_ACMA][44] = 127,
+ [2][1][RTW89_CN][44] = 56,
+ [2][1][RTW89_UK][44] = 127,
+ [2][1][RTW89_FCC][46] = 127,
+ [2][1][RTW89_ETSI][46] = 127,
+ [2][1][RTW89_MKK][46] = 127,
+ [2][1][RTW89_IC][46] = 127,
+ [2][1][RTW89_KCC][46] = 127,
+ [2][1][RTW89_ACMA][46] = 127,
+ [2][1][RTW89_CN][46] = 56,
+ [2][1][RTW89_UK][46] = 127,
+ [2][1][RTW89_FCC][48] = 127,
+ [2][1][RTW89_ETSI][48] = 127,
+ [2][1][RTW89_MKK][48] = 127,
+ [2][1][RTW89_IC][48] = 127,
+ [2][1][RTW89_KCC][48] = 127,
+ [2][1][RTW89_ACMA][48] = 127,
+ [2][1][RTW89_CN][48] = 127,
+ [2][1][RTW89_UK][48] = 127,
+ [2][1][RTW89_FCC][50] = 127,
+ [2][1][RTW89_ETSI][50] = 127,
+ [2][1][RTW89_MKK][50] = 127,
+ [2][1][RTW89_IC][50] = 127,
+ [2][1][RTW89_KCC][50] = 127,
+ [2][1][RTW89_ACMA][50] = 127,
+ [2][1][RTW89_CN][50] = 127,
+ [2][1][RTW89_UK][50] = 127,
+ [2][1][RTW89_FCC][52] = 127,
+ [2][1][RTW89_ETSI][52] = 127,
+ [2][1][RTW89_MKK][52] = 127,
+ [2][1][RTW89_IC][52] = 127,
+ [2][1][RTW89_KCC][52] = 127,
+ [2][1][RTW89_ACMA][52] = 127,
+ [2][1][RTW89_CN][52] = 127,
+ [2][1][RTW89_UK][52] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_2g_type2[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
+ [0][0][0][0][RTW89_WW][0] = 58,
+ [0][0][0][0][RTW89_WW][1] = 58,
+ [0][0][0][0][RTW89_WW][2] = 58,
+ [0][0][0][0][RTW89_WW][3] = 58,
+ [0][0][0][0][RTW89_WW][4] = 58,
+ [0][0][0][0][RTW89_WW][5] = 58,
+ [0][0][0][0][RTW89_WW][6] = 58,
+ [0][0][0][0][RTW89_WW][7] = 58,
+ [0][0][0][0][RTW89_WW][8] = 58,
+ [0][0][0][0][RTW89_WW][9] = 58,
+ [0][0][0][0][RTW89_WW][10] = 58,
+ [0][0][0][0][RTW89_WW][11] = 58,
+ [0][0][0][0][RTW89_WW][12] = 52,
+ [0][0][0][0][RTW89_WW][13] = 76,
+ [0][1][0][0][RTW89_WW][0] = 0,
+ [0][1][0][0][RTW89_WW][1] = 0,
+ [0][1][0][0][RTW89_WW][2] = 0,
+ [0][1][0][0][RTW89_WW][3] = 0,
+ [0][1][0][0][RTW89_WW][4] = 0,
+ [0][1][0][0][RTW89_WW][5] = 0,
+ [0][1][0][0][RTW89_WW][6] = 0,
+ [0][1][0][0][RTW89_WW][7] = 0,
+ [0][1][0][0][RTW89_WW][8] = 0,
+ [0][1][0][0][RTW89_WW][9] = 0,
+ [0][1][0][0][RTW89_WW][10] = 0,
+ [0][1][0][0][RTW89_WW][11] = 0,
+ [0][1][0][0][RTW89_WW][12] = 0,
+ [0][1][0][0][RTW89_WW][13] = 0,
+ [1][0][0][0][RTW89_WW][0] = 0,
+ [1][0][0][0][RTW89_WW][1] = 0,
+ [1][0][0][0][RTW89_WW][2] = 58,
+ [1][0][0][0][RTW89_WW][3] = 58,
+ [1][0][0][0][RTW89_WW][4] = 58,
+ [1][0][0][0][RTW89_WW][5] = 58,
+ [1][0][0][0][RTW89_WW][6] = 58,
+ [1][0][0][0][RTW89_WW][7] = 58,
+ [1][0][0][0][RTW89_WW][8] = 58,
+ [1][0][0][0][RTW89_WW][9] = 58,
+ [1][0][0][0][RTW89_WW][10] = 58,
+ [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] = 0,
+ [1][1][0][0][RTW89_WW][3] = 0,
+ [1][1][0][0][RTW89_WW][4] = 0,
+ [1][1][0][0][RTW89_WW][5] = 0,
+ [1][1][0][0][RTW89_WW][6] = 0,
+ [1][1][0][0][RTW89_WW][7] = 0,
+ [1][1][0][0][RTW89_WW][8] = 0,
+ [1][1][0][0][RTW89_WW][9] = 0,
+ [1][1][0][0][RTW89_WW][10] = 0,
+ [1][1][0][0][RTW89_WW][11] = 0,
+ [1][1][0][0][RTW89_WW][12] = 0,
+ [1][1][0][0][RTW89_WW][13] = 0,
+ [0][0][1][0][RTW89_WW][0] = 58,
+ [0][0][1][0][RTW89_WW][1] = 60,
+ [0][0][1][0][RTW89_WW][2] = 60,
+ [0][0][1][0][RTW89_WW][3] = 60,
+ [0][0][1][0][RTW89_WW][4] = 60,
+ [0][0][1][0][RTW89_WW][5] = 60,
+ [0][0][1][0][RTW89_WW][6] = 60,
+ [0][0][1][0][RTW89_WW][7] = 60,
+ [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] = 60,
+ [0][0][1][0][RTW89_WW][12] = 58,
+ [0][0][1][0][RTW89_WW][13] = 0,
+ [0][1][1][0][RTW89_WW][0] = 0,
+ [0][1][1][0][RTW89_WW][1] = 0,
+ [0][1][1][0][RTW89_WW][2] = 0,
+ [0][1][1][0][RTW89_WW][3] = 0,
+ [0][1][1][0][RTW89_WW][4] = 0,
+ [0][1][1][0][RTW89_WW][5] = 0,
+ [0][1][1][0][RTW89_WW][6] = 0,
+ [0][1][1][0][RTW89_WW][7] = 0,
+ [0][1][1][0][RTW89_WW][8] = 0,
+ [0][1][1][0][RTW89_WW][9] = 0,
+ [0][1][1][0][RTW89_WW][10] = 0,
+ [0][1][1][0][RTW89_WW][11] = 0,
+ [0][1][1][0][RTW89_WW][12] = 0,
+ [0][1][1][0][RTW89_WW][13] = 0,
+ [0][0][2][0][RTW89_WW][0] = 60,
+ [0][0][2][0][RTW89_WW][1] = 60,
+ [0][0][2][0][RTW89_WW][2] = 60,
+ [0][0][2][0][RTW89_WW][3] = 60,
+ [0][0][2][0][RTW89_WW][4] = 60,
+ [0][0][2][0][RTW89_WW][5] = 60,
+ [0][0][2][0][RTW89_WW][6] = 60,
+ [0][0][2][0][RTW89_WW][7] = 60,
+ [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] = 60,
+ [0][0][2][0][RTW89_WW][12] = 60,
+ [0][0][2][0][RTW89_WW][13] = 0,
+ [0][1][2][0][RTW89_WW][0] = 0,
+ [0][1][2][0][RTW89_WW][1] = 0,
+ [0][1][2][0][RTW89_WW][2] = 0,
+ [0][1][2][0][RTW89_WW][3] = 0,
+ [0][1][2][0][RTW89_WW][4] = 0,
+ [0][1][2][0][RTW89_WW][5] = 0,
+ [0][1][2][0][RTW89_WW][6] = 0,
+ [0][1][2][0][RTW89_WW][7] = 0,
+ [0][1][2][0][RTW89_WW][8] = 0,
+ [0][1][2][0][RTW89_WW][9] = 0,
+ [0][1][2][0][RTW89_WW][10] = 0,
+ [0][1][2][0][RTW89_WW][11] = 0,
+ [0][1][2][0][RTW89_WW][12] = 0,
+ [0][1][2][0][RTW89_WW][13] = 0,
+ [0][1][2][1][RTW89_WW][0] = 0,
+ [0][1][2][1][RTW89_WW][1] = 0,
+ [0][1][2][1][RTW89_WW][2] = 0,
+ [0][1][2][1][RTW89_WW][3] = 0,
+ [0][1][2][1][RTW89_WW][4] = 0,
+ [0][1][2][1][RTW89_WW][5] = 0,
+ [0][1][2][1][RTW89_WW][6] = 0,
+ [0][1][2][1][RTW89_WW][7] = 0,
+ [0][1][2][1][RTW89_WW][8] = 0,
+ [0][1][2][1][RTW89_WW][9] = 0,
+ [0][1][2][1][RTW89_WW][10] = 0,
+ [0][1][2][1][RTW89_WW][11] = 0,
+ [0][1][2][1][RTW89_WW][12] = 0,
+ [0][1][2][1][RTW89_WW][13] = 0,
+ [1][0][2][0][RTW89_WW][0] = 0,
+ [1][0][2][0][RTW89_WW][1] = 0,
+ [1][0][2][0][RTW89_WW][2] = 58,
+ [1][0][2][0][RTW89_WW][3] = 58,
+ [1][0][2][0][RTW89_WW][4] = 58,
+ [1][0][2][0][RTW89_WW][5] = 58,
+ [1][0][2][0][RTW89_WW][6] = 58,
+ [1][0][2][0][RTW89_WW][7] = 58,
+ [1][0][2][0][RTW89_WW][8] = 58,
+ [1][0][2][0][RTW89_WW][9] = 58,
+ [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] = 0,
+ [1][1][2][0][RTW89_WW][3] = 0,
+ [1][1][2][0][RTW89_WW][4] = 0,
+ [1][1][2][0][RTW89_WW][5] = 0,
+ [1][1][2][0][RTW89_WW][6] = 0,
+ [1][1][2][0][RTW89_WW][7] = 0,
+ [1][1][2][0][RTW89_WW][8] = 0,
+ [1][1][2][0][RTW89_WW][9] = 0,
+ [1][1][2][0][RTW89_WW][10] = 0,
+ [1][1][2][0][RTW89_WW][11] = 0,
+ [1][1][2][0][RTW89_WW][12] = 0,
+ [1][1][2][0][RTW89_WW][13] = 0,
+ [1][1][2][1][RTW89_WW][0] = 0,
+ [1][1][2][1][RTW89_WW][1] = 0,
+ [1][1][2][1][RTW89_WW][2] = 0,
+ [1][1][2][1][RTW89_WW][3] = 0,
+ [1][1][2][1][RTW89_WW][4] = 0,
+ [1][1][2][1][RTW89_WW][5] = 0,
+ [1][1][2][1][RTW89_WW][6] = 0,
+ [1][1][2][1][RTW89_WW][7] = 0,
+ [1][1][2][1][RTW89_WW][8] = 0,
+ [1][1][2][1][RTW89_WW][9] = 0,
+ [1][1][2][1][RTW89_WW][10] = 0,
+ [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] = 82,
+ [0][0][0][0][RTW89_ETSI][0] = 58,
+ [0][0][0][0][RTW89_MKK][0] = 68,
+ [0][0][0][0][RTW89_IC][0] = 82,
+ [0][0][0][0][RTW89_KCC][0] = 68,
+ [0][0][0][0][RTW89_ACMA][0] = 58,
+ [0][0][0][0][RTW89_CN][0] = 60,
+ [0][0][0][0][RTW89_UK][0] = 58,
+ [0][0][0][0][RTW89_FCC][1] = 82,
+ [0][0][0][0][RTW89_ETSI][1] = 58,
+ [0][0][0][0][RTW89_MKK][1] = 68,
+ [0][0][0][0][RTW89_IC][1] = 82,
+ [0][0][0][0][RTW89_KCC][1] = 68,
+ [0][0][0][0][RTW89_ACMA][1] = 58,
+ [0][0][0][0][RTW89_CN][1] = 60,
+ [0][0][0][0][RTW89_UK][1] = 58,
+ [0][0][0][0][RTW89_FCC][2] = 82,
+ [0][0][0][0][RTW89_ETSI][2] = 58,
+ [0][0][0][0][RTW89_MKK][2] = 68,
+ [0][0][0][0][RTW89_IC][2] = 82,
+ [0][0][0][0][RTW89_KCC][2] = 68,
+ [0][0][0][0][RTW89_ACMA][2] = 58,
+ [0][0][0][0][RTW89_CN][2] = 60,
+ [0][0][0][0][RTW89_UK][2] = 58,
+ [0][0][0][0][RTW89_FCC][3] = 82,
+ [0][0][0][0][RTW89_ETSI][3] = 58,
+ [0][0][0][0][RTW89_MKK][3] = 68,
+ [0][0][0][0][RTW89_IC][3] = 82,
+ [0][0][0][0][RTW89_KCC][3] = 68,
+ [0][0][0][0][RTW89_ACMA][3] = 58,
+ [0][0][0][0][RTW89_CN][3] = 60,
+ [0][0][0][0][RTW89_UK][3] = 58,
+ [0][0][0][0][RTW89_FCC][4] = 82,
+ [0][0][0][0][RTW89_ETSI][4] = 58,
+ [0][0][0][0][RTW89_MKK][4] = 68,
+ [0][0][0][0][RTW89_IC][4] = 82,
+ [0][0][0][0][RTW89_KCC][4] = 68,
+ [0][0][0][0][RTW89_ACMA][4] = 58,
+ [0][0][0][0][RTW89_CN][4] = 60,
+ [0][0][0][0][RTW89_UK][4] = 58,
+ [0][0][0][0][RTW89_FCC][5] = 82,
+ [0][0][0][0][RTW89_ETSI][5] = 58,
+ [0][0][0][0][RTW89_MKK][5] = 68,
+ [0][0][0][0][RTW89_IC][5] = 82,
+ [0][0][0][0][RTW89_KCC][5] = 68,
+ [0][0][0][0][RTW89_ACMA][5] = 58,
+ [0][0][0][0][RTW89_CN][5] = 60,
+ [0][0][0][0][RTW89_UK][5] = 58,
+ [0][0][0][0][RTW89_FCC][6] = 82,
+ [0][0][0][0][RTW89_ETSI][6] = 58,
+ [0][0][0][0][RTW89_MKK][6] = 68,
+ [0][0][0][0][RTW89_IC][6] = 82,
+ [0][0][0][0][RTW89_KCC][6] = 68,
+ [0][0][0][0][RTW89_ACMA][6] = 58,
+ [0][0][0][0][RTW89_CN][6] = 60,
+ [0][0][0][0][RTW89_UK][6] = 58,
+ [0][0][0][0][RTW89_FCC][7] = 82,
+ [0][0][0][0][RTW89_ETSI][7] = 58,
+ [0][0][0][0][RTW89_MKK][7] = 68,
+ [0][0][0][0][RTW89_IC][7] = 82,
+ [0][0][0][0][RTW89_KCC][7] = 68,
+ [0][0][0][0][RTW89_ACMA][7] = 58,
+ [0][0][0][0][RTW89_CN][7] = 60,
+ [0][0][0][0][RTW89_UK][7] = 58,
+ [0][0][0][0][RTW89_FCC][8] = 82,
+ [0][0][0][0][RTW89_ETSI][8] = 58,
+ [0][0][0][0][RTW89_MKK][8] = 68,
+ [0][0][0][0][RTW89_IC][8] = 82,
+ [0][0][0][0][RTW89_KCC][8] = 68,
+ [0][0][0][0][RTW89_ACMA][8] = 58,
+ [0][0][0][0][RTW89_CN][8] = 60,
+ [0][0][0][0][RTW89_UK][8] = 58,
+ [0][0][0][0][RTW89_FCC][9] = 82,
+ [0][0][0][0][RTW89_ETSI][9] = 58,
+ [0][0][0][0][RTW89_MKK][9] = 68,
+ [0][0][0][0][RTW89_IC][9] = 82,
+ [0][0][0][0][RTW89_KCC][9] = 68,
+ [0][0][0][0][RTW89_ACMA][9] = 58,
+ [0][0][0][0][RTW89_CN][9] = 60,
+ [0][0][0][0][RTW89_UK][9] = 58,
+ [0][0][0][0][RTW89_FCC][10] = 80,
+ [0][0][0][0][RTW89_ETSI][10] = 58,
+ [0][0][0][0][RTW89_MKK][10] = 68,
+ [0][0][0][0][RTW89_IC][10] = 80,
+ [0][0][0][0][RTW89_KCC][10] = 68,
+ [0][0][0][0][RTW89_ACMA][10] = 58,
+ [0][0][0][0][RTW89_CN][10] = 60,
+ [0][0][0][0][RTW89_UK][10] = 58,
+ [0][0][0][0][RTW89_FCC][11] = 60,
+ [0][0][0][0][RTW89_ETSI][11] = 58,
+ [0][0][0][0][RTW89_MKK][11] = 68,
+ [0][0][0][0][RTW89_IC][11] = 60,
+ [0][0][0][0][RTW89_KCC][11] = 68,
+ [0][0][0][0][RTW89_ACMA][11] = 58,
+ [0][0][0][0][RTW89_CN][11] = 60,
+ [0][0][0][0][RTW89_UK][11] = 58,
+ [0][0][0][0][RTW89_FCC][12] = 52,
+ [0][0][0][0][RTW89_ETSI][12] = 58,
+ [0][0][0][0][RTW89_MKK][12] = 68,
+ [0][0][0][0][RTW89_IC][12] = 52,
+ [0][0][0][0][RTW89_KCC][12] = 68,
+ [0][0][0][0][RTW89_ACMA][12] = 58,
+ [0][0][0][0][RTW89_CN][12] = 60,
+ [0][0][0][0][RTW89_UK][12] = 58,
+ [0][0][0][0][RTW89_FCC][13] = 127,
+ [0][0][0][0][RTW89_ETSI][13] = 127,
+ [0][0][0][0][RTW89_MKK][13] = 76,
+ [0][0][0][0][RTW89_IC][13] = 127,
+ [0][0][0][0][RTW89_KCC][13] = 127,
+ [0][0][0][0][RTW89_ACMA][13] = 127,
+ [0][0][0][0][RTW89_CN][13] = 127,
+ [0][0][0][0][RTW89_UK][13] = 127,
+ [0][1][0][0][RTW89_FCC][0] = 127,
+ [0][1][0][0][RTW89_ETSI][0] = 127,
+ [0][1][0][0][RTW89_MKK][0] = 127,
+ [0][1][0][0][RTW89_IC][0] = 127,
+ [0][1][0][0][RTW89_KCC][0] = 127,
+ [0][1][0][0][RTW89_ACMA][0] = 127,
+ [0][1][0][0][RTW89_CN][0] = 127,
+ [0][1][0][0][RTW89_UK][0] = 127,
+ [0][1][0][0][RTW89_FCC][1] = 127,
+ [0][1][0][0][RTW89_ETSI][1] = 127,
+ [0][1][0][0][RTW89_MKK][1] = 127,
+ [0][1][0][0][RTW89_IC][1] = 127,
+ [0][1][0][0][RTW89_KCC][1] = 127,
+ [0][1][0][0][RTW89_ACMA][1] = 127,
+ [0][1][0][0][RTW89_CN][1] = 127,
+ [0][1][0][0][RTW89_UK][1] = 127,
+ [0][1][0][0][RTW89_FCC][2] = 127,
+ [0][1][0][0][RTW89_ETSI][2] = 127,
+ [0][1][0][0][RTW89_MKK][2] = 127,
+ [0][1][0][0][RTW89_IC][2] = 127,
+ [0][1][0][0][RTW89_KCC][2] = 127,
+ [0][1][0][0][RTW89_ACMA][2] = 127,
+ [0][1][0][0][RTW89_CN][2] = 127,
+ [0][1][0][0][RTW89_UK][2] = 127,
+ [0][1][0][0][RTW89_FCC][3] = 127,
+ [0][1][0][0][RTW89_ETSI][3] = 127,
+ [0][1][0][0][RTW89_MKK][3] = 127,
+ [0][1][0][0][RTW89_IC][3] = 127,
+ [0][1][0][0][RTW89_KCC][3] = 127,
+ [0][1][0][0][RTW89_ACMA][3] = 127,
+ [0][1][0][0][RTW89_CN][3] = 127,
+ [0][1][0][0][RTW89_UK][3] = 127,
+ [0][1][0][0][RTW89_FCC][4] = 127,
+ [0][1][0][0][RTW89_ETSI][4] = 127,
+ [0][1][0][0][RTW89_MKK][4] = 127,
+ [0][1][0][0][RTW89_IC][4] = 127,
+ [0][1][0][0][RTW89_KCC][4] = 127,
+ [0][1][0][0][RTW89_ACMA][4] = 127,
+ [0][1][0][0][RTW89_CN][4] = 127,
+ [0][1][0][0][RTW89_UK][4] = 127,
+ [0][1][0][0][RTW89_FCC][5] = 127,
+ [0][1][0][0][RTW89_ETSI][5] = 127,
+ [0][1][0][0][RTW89_MKK][5] = 127,
+ [0][1][0][0][RTW89_IC][5] = 127,
+ [0][1][0][0][RTW89_KCC][5] = 127,
+ [0][1][0][0][RTW89_ACMA][5] = 127,
+ [0][1][0][0][RTW89_CN][5] = 127,
+ [0][1][0][0][RTW89_UK][5] = 127,
+ [0][1][0][0][RTW89_FCC][6] = 127,
+ [0][1][0][0][RTW89_ETSI][6] = 127,
+ [0][1][0][0][RTW89_MKK][6] = 127,
+ [0][1][0][0][RTW89_IC][6] = 127,
+ [0][1][0][0][RTW89_KCC][6] = 127,
+ [0][1][0][0][RTW89_ACMA][6] = 127,
+ [0][1][0][0][RTW89_CN][6] = 127,
+ [0][1][0][0][RTW89_UK][6] = 127,
+ [0][1][0][0][RTW89_FCC][7] = 127,
+ [0][1][0][0][RTW89_ETSI][7] = 127,
+ [0][1][0][0][RTW89_MKK][7] = 127,
+ [0][1][0][0][RTW89_IC][7] = 127,
+ [0][1][0][0][RTW89_KCC][7] = 127,
+ [0][1][0][0][RTW89_ACMA][7] = 127,
+ [0][1][0][0][RTW89_CN][7] = 127,
+ [0][1][0][0][RTW89_UK][7] = 127,
+ [0][1][0][0][RTW89_FCC][8] = 127,
+ [0][1][0][0][RTW89_ETSI][8] = 127,
+ [0][1][0][0][RTW89_MKK][8] = 127,
+ [0][1][0][0][RTW89_IC][8] = 127,
+ [0][1][0][0][RTW89_KCC][8] = 127,
+ [0][1][0][0][RTW89_ACMA][8] = 127,
+ [0][1][0][0][RTW89_CN][8] = 127,
+ [0][1][0][0][RTW89_UK][8] = 127,
+ [0][1][0][0][RTW89_FCC][9] = 127,
+ [0][1][0][0][RTW89_ETSI][9] = 127,
+ [0][1][0][0][RTW89_MKK][9] = 127,
+ [0][1][0][0][RTW89_IC][9] = 127,
+ [0][1][0][0][RTW89_KCC][9] = 127,
+ [0][1][0][0][RTW89_ACMA][9] = 127,
+ [0][1][0][0][RTW89_CN][9] = 127,
+ [0][1][0][0][RTW89_UK][9] = 127,
+ [0][1][0][0][RTW89_FCC][10] = 127,
+ [0][1][0][0][RTW89_ETSI][10] = 127,
+ [0][1][0][0][RTW89_MKK][10] = 127,
+ [0][1][0][0][RTW89_IC][10] = 127,
+ [0][1][0][0][RTW89_KCC][10] = 127,
+ [0][1][0][0][RTW89_ACMA][10] = 127,
+ [0][1][0][0][RTW89_CN][10] = 127,
+ [0][1][0][0][RTW89_UK][10] = 127,
+ [0][1][0][0][RTW89_FCC][11] = 127,
+ [0][1][0][0][RTW89_ETSI][11] = 127,
+ [0][1][0][0][RTW89_MKK][11] = 127,
+ [0][1][0][0][RTW89_IC][11] = 127,
+ [0][1][0][0][RTW89_KCC][11] = 127,
+ [0][1][0][0][RTW89_ACMA][11] = 127,
+ [0][1][0][0][RTW89_CN][11] = 127,
+ [0][1][0][0][RTW89_UK][11] = 127,
+ [0][1][0][0][RTW89_FCC][12] = 127,
+ [0][1][0][0][RTW89_ETSI][12] = 127,
+ [0][1][0][0][RTW89_MKK][12] = 127,
+ [0][1][0][0][RTW89_IC][12] = 127,
+ [0][1][0][0][RTW89_KCC][12] = 127,
+ [0][1][0][0][RTW89_ACMA][12] = 127,
+ [0][1][0][0][RTW89_CN][12] = 127,
+ [0][1][0][0][RTW89_UK][12] = 127,
+ [0][1][0][0][RTW89_FCC][13] = 127,
+ [0][1][0][0][RTW89_ETSI][13] = 127,
+ [0][1][0][0][RTW89_MKK][13] = 127,
+ [0][1][0][0][RTW89_IC][13] = 127,
+ [0][1][0][0][RTW89_KCC][13] = 127,
+ [0][1][0][0][RTW89_ACMA][13] = 127,
+ [0][1][0][0][RTW89_CN][13] = 127,
+ [0][1][0][0][RTW89_UK][13] = 127,
+ [1][0][0][0][RTW89_FCC][0] = 127,
+ [1][0][0][0][RTW89_ETSI][0] = 127,
+ [1][0][0][0][RTW89_MKK][0] = 127,
+ [1][0][0][0][RTW89_IC][0] = 127,
+ [1][0][0][0][RTW89_KCC][0] = 127,
+ [1][0][0][0][RTW89_ACMA][0] = 127,
+ [1][0][0][0][RTW89_CN][0] = 127,
+ [1][0][0][0][RTW89_UK][0] = 127,
+ [1][0][0][0][RTW89_FCC][1] = 127,
+ [1][0][0][0][RTW89_ETSI][1] = 127,
+ [1][0][0][0][RTW89_MKK][1] = 127,
+ [1][0][0][0][RTW89_IC][1] = 127,
+ [1][0][0][0][RTW89_KCC][1] = 127,
+ [1][0][0][0][RTW89_ACMA][1] = 127,
+ [1][0][0][0][RTW89_CN][1] = 127,
+ [1][0][0][0][RTW89_UK][1] = 127,
+ [1][0][0][0][RTW89_FCC][2] = 127,
+ [1][0][0][0][RTW89_ETSI][2] = 58,
+ [1][0][0][0][RTW89_MKK][2] = 70,
+ [1][0][0][0][RTW89_IC][2] = 127,
+ [1][0][0][0][RTW89_KCC][2] = 68,
+ [1][0][0][0][RTW89_ACMA][2] = 58,
+ [1][0][0][0][RTW89_CN][2] = 60,
+ [1][0][0][0][RTW89_UK][2] = 58,
+ [1][0][0][0][RTW89_FCC][3] = 127,
+ [1][0][0][0][RTW89_ETSI][3] = 58,
+ [1][0][0][0][RTW89_MKK][3] = 76,
+ [1][0][0][0][RTW89_IC][3] = 127,
+ [1][0][0][0][RTW89_KCC][3] = 68,
+ [1][0][0][0][RTW89_ACMA][3] = 58,
+ [1][0][0][0][RTW89_CN][3] = 60,
+ [1][0][0][0][RTW89_UK][3] = 58,
+ [1][0][0][0][RTW89_FCC][4] = 127,
+ [1][0][0][0][RTW89_ETSI][4] = 58,
+ [1][0][0][0][RTW89_MKK][4] = 76,
+ [1][0][0][0][RTW89_IC][4] = 127,
+ [1][0][0][0][RTW89_KCC][4] = 68,
+ [1][0][0][0][RTW89_ACMA][4] = 58,
+ [1][0][0][0][RTW89_CN][4] = 60,
+ [1][0][0][0][RTW89_UK][4] = 58,
+ [1][0][0][0][RTW89_FCC][5] = 127,
+ [1][0][0][0][RTW89_ETSI][5] = 58,
+ [1][0][0][0][RTW89_MKK][5] = 76,
+ [1][0][0][0][RTW89_IC][5] = 127,
+ [1][0][0][0][RTW89_KCC][5] = 68,
+ [1][0][0][0][RTW89_ACMA][5] = 58,
+ [1][0][0][0][RTW89_CN][5] = 60,
+ [1][0][0][0][RTW89_UK][5] = 58,
+ [1][0][0][0][RTW89_FCC][6] = 127,
+ [1][0][0][0][RTW89_ETSI][6] = 58,
+ [1][0][0][0][RTW89_MKK][6] = 76,
+ [1][0][0][0][RTW89_IC][6] = 127,
+ [1][0][0][0][RTW89_KCC][6] = 68,
+ [1][0][0][0][RTW89_ACMA][6] = 58,
+ [1][0][0][0][RTW89_CN][6] = 60,
+ [1][0][0][0][RTW89_UK][6] = 58,
+ [1][0][0][0][RTW89_FCC][7] = 127,
+ [1][0][0][0][RTW89_ETSI][7] = 58,
+ [1][0][0][0][RTW89_MKK][7] = 76,
+ [1][0][0][0][RTW89_IC][7] = 127,
+ [1][0][0][0][RTW89_KCC][7] = 68,
+ [1][0][0][0][RTW89_ACMA][7] = 58,
+ [1][0][0][0][RTW89_CN][7] = 60,
+ [1][0][0][0][RTW89_UK][7] = 58,
+ [1][0][0][0][RTW89_FCC][8] = 127,
+ [1][0][0][0][RTW89_ETSI][8] = 58,
+ [1][0][0][0][RTW89_MKK][8] = 76,
+ [1][0][0][0][RTW89_IC][8] = 127,
+ [1][0][0][0][RTW89_KCC][8] = 68,
+ [1][0][0][0][RTW89_ACMA][8] = 58,
+ [1][0][0][0][RTW89_CN][8] = 60,
+ [1][0][0][0][RTW89_UK][8] = 58,
+ [1][0][0][0][RTW89_FCC][9] = 127,
+ [1][0][0][0][RTW89_ETSI][9] = 58,
+ [1][0][0][0][RTW89_MKK][9] = 76,
+ [1][0][0][0][RTW89_IC][9] = 127,
+ [1][0][0][0][RTW89_KCC][9] = 68,
+ [1][0][0][0][RTW89_ACMA][9] = 58,
+ [1][0][0][0][RTW89_CN][9] = 60,
+ [1][0][0][0][RTW89_UK][9] = 58,
+ [1][0][0][0][RTW89_FCC][10] = 127,
+ [1][0][0][0][RTW89_ETSI][10] = 58,
+ [1][0][0][0][RTW89_MKK][10] = 66,
+ [1][0][0][0][RTW89_IC][10] = 127,
+ [1][0][0][0][RTW89_KCC][10] = 68,
+ [1][0][0][0][RTW89_ACMA][10] = 58,
+ [1][0][0][0][RTW89_CN][10] = 60,
+ [1][0][0][0][RTW89_UK][10] = 58,
+ [1][0][0][0][RTW89_FCC][11] = 127,
+ [1][0][0][0][RTW89_ETSI][11] = 127,
+ [1][0][0][0][RTW89_MKK][11] = 127,
+ [1][0][0][0][RTW89_IC][11] = 127,
+ [1][0][0][0][RTW89_KCC][11] = 127,
+ [1][0][0][0][RTW89_ACMA][11] = 127,
+ [1][0][0][0][RTW89_CN][11] = 127,
+ [1][0][0][0][RTW89_UK][11] = 127,
+ [1][0][0][0][RTW89_FCC][12] = 127,
+ [1][0][0][0][RTW89_ETSI][12] = 127,
+ [1][0][0][0][RTW89_MKK][12] = 127,
+ [1][0][0][0][RTW89_IC][12] = 127,
+ [1][0][0][0][RTW89_KCC][12] = 127,
+ [1][0][0][0][RTW89_ACMA][12] = 127,
+ [1][0][0][0][RTW89_CN][12] = 127,
+ [1][0][0][0][RTW89_UK][12] = 127,
+ [1][0][0][0][RTW89_FCC][13] = 127,
+ [1][0][0][0][RTW89_ETSI][13] = 127,
+ [1][0][0][0][RTW89_MKK][13] = 127,
+ [1][0][0][0][RTW89_IC][13] = 127,
+ [1][0][0][0][RTW89_KCC][13] = 127,
+ [1][0][0][0][RTW89_ACMA][13] = 127,
+ [1][0][0][0][RTW89_CN][13] = 127,
+ [1][0][0][0][RTW89_UK][13] = 127,
+ [1][1][0][0][RTW89_FCC][0] = 127,
+ [1][1][0][0][RTW89_ETSI][0] = 127,
+ [1][1][0][0][RTW89_MKK][0] = 127,
+ [1][1][0][0][RTW89_IC][0] = 127,
+ [1][1][0][0][RTW89_KCC][0] = 127,
+ [1][1][0][0][RTW89_ACMA][0] = 127,
+ [1][1][0][0][RTW89_CN][0] = 127,
+ [1][1][0][0][RTW89_UK][0] = 127,
+ [1][1][0][0][RTW89_FCC][1] = 127,
+ [1][1][0][0][RTW89_ETSI][1] = 127,
+ [1][1][0][0][RTW89_MKK][1] = 127,
+ [1][1][0][0][RTW89_IC][1] = 127,
+ [1][1][0][0][RTW89_KCC][1] = 127,
+ [1][1][0][0][RTW89_ACMA][1] = 127,
+ [1][1][0][0][RTW89_CN][1] = 127,
+ [1][1][0][0][RTW89_UK][1] = 127,
+ [1][1][0][0][RTW89_FCC][2] = 127,
+ [1][1][0][0][RTW89_ETSI][2] = 127,
+ [1][1][0][0][RTW89_MKK][2] = 127,
+ [1][1][0][0][RTW89_IC][2] = 127,
+ [1][1][0][0][RTW89_KCC][2] = 127,
+ [1][1][0][0][RTW89_ACMA][2] = 127,
+ [1][1][0][0][RTW89_CN][2] = 127,
+ [1][1][0][0][RTW89_UK][2] = 127,
+ [1][1][0][0][RTW89_FCC][3] = 127,
+ [1][1][0][0][RTW89_ETSI][3] = 127,
+ [1][1][0][0][RTW89_MKK][3] = 127,
+ [1][1][0][0][RTW89_IC][3] = 127,
+ [1][1][0][0][RTW89_KCC][3] = 127,
+ [1][1][0][0][RTW89_ACMA][3] = 127,
+ [1][1][0][0][RTW89_CN][3] = 127,
+ [1][1][0][0][RTW89_UK][3] = 127,
+ [1][1][0][0][RTW89_FCC][4] = 127,
+ [1][1][0][0][RTW89_ETSI][4] = 127,
+ [1][1][0][0][RTW89_MKK][4] = 127,
+ [1][1][0][0][RTW89_IC][4] = 127,
+ [1][1][0][0][RTW89_KCC][4] = 127,
+ [1][1][0][0][RTW89_ACMA][4] = 127,
+ [1][1][0][0][RTW89_CN][4] = 127,
+ [1][1][0][0][RTW89_UK][4] = 127,
+ [1][1][0][0][RTW89_FCC][5] = 127,
+ [1][1][0][0][RTW89_ETSI][5] = 127,
+ [1][1][0][0][RTW89_MKK][5] = 127,
+ [1][1][0][0][RTW89_IC][5] = 127,
+ [1][1][0][0][RTW89_KCC][5] = 127,
+ [1][1][0][0][RTW89_ACMA][5] = 127,
+ [1][1][0][0][RTW89_CN][5] = 127,
+ [1][1][0][0][RTW89_UK][5] = 127,
+ [1][1][0][0][RTW89_FCC][6] = 127,
+ [1][1][0][0][RTW89_ETSI][6] = 127,
+ [1][1][0][0][RTW89_MKK][6] = 127,
+ [1][1][0][0][RTW89_IC][6] = 127,
+ [1][1][0][0][RTW89_KCC][6] = 127,
+ [1][1][0][0][RTW89_ACMA][6] = 127,
+ [1][1][0][0][RTW89_CN][6] = 127,
+ [1][1][0][0][RTW89_UK][6] = 127,
+ [1][1][0][0][RTW89_FCC][7] = 127,
+ [1][1][0][0][RTW89_ETSI][7] = 127,
+ [1][1][0][0][RTW89_MKK][7] = 127,
+ [1][1][0][0][RTW89_IC][7] = 127,
+ [1][1][0][0][RTW89_KCC][7] = 127,
+ [1][1][0][0][RTW89_ACMA][7] = 127,
+ [1][1][0][0][RTW89_CN][7] = 127,
+ [1][1][0][0][RTW89_UK][7] = 127,
+ [1][1][0][0][RTW89_FCC][8] = 127,
+ [1][1][0][0][RTW89_ETSI][8] = 127,
+ [1][1][0][0][RTW89_MKK][8] = 127,
+ [1][1][0][0][RTW89_IC][8] = 127,
+ [1][1][0][0][RTW89_KCC][8] = 127,
+ [1][1][0][0][RTW89_ACMA][8] = 127,
+ [1][1][0][0][RTW89_CN][8] = 127,
+ [1][1][0][0][RTW89_UK][8] = 127,
+ [1][1][0][0][RTW89_FCC][9] = 127,
+ [1][1][0][0][RTW89_ETSI][9] = 127,
+ [1][1][0][0][RTW89_MKK][9] = 127,
+ [1][1][0][0][RTW89_IC][9] = 127,
+ [1][1][0][0][RTW89_KCC][9] = 127,
+ [1][1][0][0][RTW89_ACMA][9] = 127,
+ [1][1][0][0][RTW89_CN][9] = 127,
+ [1][1][0][0][RTW89_UK][9] = 127,
+ [1][1][0][0][RTW89_FCC][10] = 127,
+ [1][1][0][0][RTW89_ETSI][10] = 127,
+ [1][1][0][0][RTW89_MKK][10] = 127,
+ [1][1][0][0][RTW89_IC][10] = 127,
+ [1][1][0][0][RTW89_KCC][10] = 127,
+ [1][1][0][0][RTW89_ACMA][10] = 127,
+ [1][1][0][0][RTW89_CN][10] = 127,
+ [1][1][0][0][RTW89_UK][10] = 127,
+ [1][1][0][0][RTW89_FCC][11] = 127,
+ [1][1][0][0][RTW89_ETSI][11] = 127,
+ [1][1][0][0][RTW89_MKK][11] = 127,
+ [1][1][0][0][RTW89_IC][11] = 127,
+ [1][1][0][0][RTW89_KCC][11] = 127,
+ [1][1][0][0][RTW89_ACMA][11] = 127,
+ [1][1][0][0][RTW89_CN][11] = 127,
+ [1][1][0][0][RTW89_UK][11] = 127,
+ [1][1][0][0][RTW89_FCC][12] = 127,
+ [1][1][0][0][RTW89_ETSI][12] = 127,
+ [1][1][0][0][RTW89_MKK][12] = 127,
+ [1][1][0][0][RTW89_IC][12] = 127,
+ [1][1][0][0][RTW89_KCC][12] = 127,
+ [1][1][0][0][RTW89_ACMA][12] = 127,
+ [1][1][0][0][RTW89_CN][12] = 127,
+ [1][1][0][0][RTW89_UK][12] = 127,
+ [1][1][0][0][RTW89_FCC][13] = 127,
+ [1][1][0][0][RTW89_ETSI][13] = 127,
+ [1][1][0][0][RTW89_MKK][13] = 127,
+ [1][1][0][0][RTW89_IC][13] = 127,
+ [1][1][0][0][RTW89_KCC][13] = 127,
+ [1][1][0][0][RTW89_ACMA][13] = 127,
+ [1][1][0][0][RTW89_CN][13] = 127,
+ [1][1][0][0][RTW89_UK][13] = 127,
+ [0][0][1][0][RTW89_FCC][0] = 78,
+ [0][0][1][0][RTW89_ETSI][0] = 58,
+ [0][0][1][0][RTW89_MKK][0] = 72,
+ [0][0][1][0][RTW89_IC][0] = 78,
+ [0][0][1][0][RTW89_KCC][0] = 76,
+ [0][0][1][0][RTW89_ACMA][0] = 58,
+ [0][0][1][0][RTW89_CN][0] = 60,
+ [0][0][1][0][RTW89_UK][0] = 58,
+ [0][0][1][0][RTW89_FCC][1] = 78,
+ [0][0][1][0][RTW89_ETSI][1] = 60,
+ [0][0][1][0][RTW89_MKK][1] = 74,
+ [0][0][1][0][RTW89_IC][1] = 78,
+ [0][0][1][0][RTW89_KCC][1] = 76,
+ [0][0][1][0][RTW89_ACMA][1] = 60,
+ [0][0][1][0][RTW89_CN][1] = 60,
+ [0][0][1][0][RTW89_UK][1] = 60,
+ [0][0][1][0][RTW89_FCC][2] = 80,
+ [0][0][1][0][RTW89_ETSI][2] = 60,
+ [0][0][1][0][RTW89_MKK][2] = 74,
+ [0][0][1][0][RTW89_IC][2] = 80,
+ [0][0][1][0][RTW89_KCC][2] = 76,
+ [0][0][1][0][RTW89_ACMA][2] = 60,
+ [0][0][1][0][RTW89_CN][2] = 60,
+ [0][0][1][0][RTW89_UK][2] = 60,
+ [0][0][1][0][RTW89_FCC][3] = 80,
+ [0][0][1][0][RTW89_ETSI][3] = 60,
+ [0][0][1][0][RTW89_MKK][3] = 74,
+ [0][0][1][0][RTW89_IC][3] = 80,
+ [0][0][1][0][RTW89_KCC][3] = 76,
+ [0][0][1][0][RTW89_ACMA][3] = 60,
+ [0][0][1][0][RTW89_CN][3] = 60,
+ [0][0][1][0][RTW89_UK][3] = 60,
+ [0][0][1][0][RTW89_FCC][4] = 80,
+ [0][0][1][0][RTW89_ETSI][4] = 60,
+ [0][0][1][0][RTW89_MKK][4] = 74,
+ [0][0][1][0][RTW89_IC][4] = 80,
+ [0][0][1][0][RTW89_KCC][4] = 76,
+ [0][0][1][0][RTW89_ACMA][4] = 60,
+ [0][0][1][0][RTW89_CN][4] = 60,
+ [0][0][1][0][RTW89_UK][4] = 60,
+ [0][0][1][0][RTW89_FCC][5] = 80,
+ [0][0][1][0][RTW89_ETSI][5] = 60,
+ [0][0][1][0][RTW89_MKK][5] = 74,
+ [0][0][1][0][RTW89_IC][5] = 80,
+ [0][0][1][0][RTW89_KCC][5] = 76,
+ [0][0][1][0][RTW89_ACMA][5] = 60,
+ [0][0][1][0][RTW89_CN][5] = 60,
+ [0][0][1][0][RTW89_UK][5] = 60,
+ [0][0][1][0][RTW89_FCC][6] = 80,
+ [0][0][1][0][RTW89_ETSI][6] = 60,
+ [0][0][1][0][RTW89_MKK][6] = 74,
+ [0][0][1][0][RTW89_IC][6] = 80,
+ [0][0][1][0][RTW89_KCC][6] = 76,
+ [0][0][1][0][RTW89_ACMA][6] = 60,
+ [0][0][1][0][RTW89_CN][6] = 60,
+ [0][0][1][0][RTW89_UK][6] = 60,
+ [0][0][1][0][RTW89_FCC][7] = 80,
+ [0][0][1][0][RTW89_ETSI][7] = 60,
+ [0][0][1][0][RTW89_MKK][7] = 74,
+ [0][0][1][0][RTW89_IC][7] = 80,
+ [0][0][1][0][RTW89_KCC][7] = 76,
+ [0][0][1][0][RTW89_ACMA][7] = 60,
+ [0][0][1][0][RTW89_CN][7] = 60,
+ [0][0][1][0][RTW89_UK][7] = 60,
+ [0][0][1][0][RTW89_FCC][8] = 80,
+ [0][0][1][0][RTW89_ETSI][8] = 60,
+ [0][0][1][0][RTW89_MKK][8] = 74,
+ [0][0][1][0][RTW89_IC][8] = 80,
+ [0][0][1][0][RTW89_KCC][8] = 76,
+ [0][0][1][0][RTW89_ACMA][8] = 60,
+ [0][0][1][0][RTW89_CN][8] = 60,
+ [0][0][1][0][RTW89_UK][8] = 60,
+ [0][0][1][0][RTW89_FCC][9] = 76,
+ [0][0][1][0][RTW89_ETSI][9] = 60,
+ [0][0][1][0][RTW89_MKK][9] = 74,
+ [0][0][1][0][RTW89_IC][9] = 76,
+ [0][0][1][0][RTW89_KCC][9] = 74,
+ [0][0][1][0][RTW89_ACMA][9] = 60,
+ [0][0][1][0][RTW89_CN][9] = 60,
+ [0][0][1][0][RTW89_UK][9] = 60,
+ [0][0][1][0][RTW89_FCC][10] = 76,
+ [0][0][1][0][RTW89_ETSI][10] = 60,
+ [0][0][1][0][RTW89_MKK][10] = 74,
+ [0][0][1][0][RTW89_IC][10] = 76,
+ [0][0][1][0][RTW89_KCC][10] = 74,
+ [0][0][1][0][RTW89_ACMA][10] = 60,
+ [0][0][1][0][RTW89_CN][10] = 60,
+ [0][0][1][0][RTW89_UK][10] = 60,
+ [0][0][1][0][RTW89_FCC][11] = 68,
+ [0][0][1][0][RTW89_ETSI][11] = 60,
+ [0][0][1][0][RTW89_MKK][11] = 74,
+ [0][0][1][0][RTW89_IC][11] = 68,
+ [0][0][1][0][RTW89_KCC][11] = 74,
+ [0][0][1][0][RTW89_ACMA][11] = 60,
+ [0][0][1][0][RTW89_CN][11] = 60,
+ [0][0][1][0][RTW89_UK][11] = 60,
+ [0][0][1][0][RTW89_FCC][12] = 64,
+ [0][0][1][0][RTW89_ETSI][12] = 58,
+ [0][0][1][0][RTW89_MKK][12] = 70,
+ [0][0][1][0][RTW89_IC][12] = 64,
+ [0][0][1][0][RTW89_KCC][12] = 74,
+ [0][0][1][0][RTW89_ACMA][12] = 58,
+ [0][0][1][0][RTW89_CN][12] = 60,
+ [0][0][1][0][RTW89_UK][12] = 58,
+ [0][0][1][0][RTW89_FCC][13] = 127,
+ [0][0][1][0][RTW89_ETSI][13] = 127,
+ [0][0][1][0][RTW89_MKK][13] = 127,
+ [0][0][1][0][RTW89_IC][13] = 127,
+ [0][0][1][0][RTW89_KCC][13] = 127,
+ [0][0][1][0][RTW89_ACMA][13] = 127,
+ [0][0][1][0][RTW89_CN][13] = 127,
+ [0][0][1][0][RTW89_UK][13] = 127,
+ [0][1][1][0][RTW89_FCC][0] = 127,
+ [0][1][1][0][RTW89_ETSI][0] = 127,
+ [0][1][1][0][RTW89_MKK][0] = 127,
+ [0][1][1][0][RTW89_IC][0] = 127,
+ [0][1][1][0][RTW89_KCC][0] = 127,
+ [0][1][1][0][RTW89_ACMA][0] = 127,
+ [0][1][1][0][RTW89_CN][0] = 127,
+ [0][1][1][0][RTW89_UK][0] = 127,
+ [0][1][1][0][RTW89_FCC][1] = 127,
+ [0][1][1][0][RTW89_ETSI][1] = 127,
+ [0][1][1][0][RTW89_MKK][1] = 127,
+ [0][1][1][0][RTW89_IC][1] = 127,
+ [0][1][1][0][RTW89_KCC][1] = 127,
+ [0][1][1][0][RTW89_ACMA][1] = 127,
+ [0][1][1][0][RTW89_CN][1] = 127,
+ [0][1][1][0][RTW89_UK][1] = 127,
+ [0][1][1][0][RTW89_FCC][2] = 127,
+ [0][1][1][0][RTW89_ETSI][2] = 127,
+ [0][1][1][0][RTW89_MKK][2] = 127,
+ [0][1][1][0][RTW89_IC][2] = 127,
+ [0][1][1][0][RTW89_KCC][2] = 127,
+ [0][1][1][0][RTW89_ACMA][2] = 127,
+ [0][1][1][0][RTW89_CN][2] = 127,
+ [0][1][1][0][RTW89_UK][2] = 127,
+ [0][1][1][0][RTW89_FCC][3] = 127,
+ [0][1][1][0][RTW89_ETSI][3] = 127,
+ [0][1][1][0][RTW89_MKK][3] = 127,
+ [0][1][1][0][RTW89_IC][3] = 127,
+ [0][1][1][0][RTW89_KCC][3] = 127,
+ [0][1][1][0][RTW89_ACMA][3] = 127,
+ [0][1][1][0][RTW89_CN][3] = 127,
+ [0][1][1][0][RTW89_UK][3] = 127,
+ [0][1][1][0][RTW89_FCC][4] = 127,
+ [0][1][1][0][RTW89_ETSI][4] = 127,
+ [0][1][1][0][RTW89_MKK][4] = 127,
+ [0][1][1][0][RTW89_IC][4] = 127,
+ [0][1][1][0][RTW89_KCC][4] = 127,
+ [0][1][1][0][RTW89_ACMA][4] = 127,
+ [0][1][1][0][RTW89_CN][4] = 127,
+ [0][1][1][0][RTW89_UK][4] = 127,
+ [0][1][1][0][RTW89_FCC][5] = 127,
+ [0][1][1][0][RTW89_ETSI][5] = 127,
+ [0][1][1][0][RTW89_MKK][5] = 127,
+ [0][1][1][0][RTW89_IC][5] = 127,
+ [0][1][1][0][RTW89_KCC][5] = 127,
+ [0][1][1][0][RTW89_ACMA][5] = 127,
+ [0][1][1][0][RTW89_CN][5] = 127,
+ [0][1][1][0][RTW89_UK][5] = 127,
+ [0][1][1][0][RTW89_FCC][6] = 127,
+ [0][1][1][0][RTW89_ETSI][6] = 127,
+ [0][1][1][0][RTW89_MKK][6] = 127,
+ [0][1][1][0][RTW89_IC][6] = 127,
+ [0][1][1][0][RTW89_KCC][6] = 127,
+ [0][1][1][0][RTW89_ACMA][6] = 127,
+ [0][1][1][0][RTW89_CN][6] = 127,
+ [0][1][1][0][RTW89_UK][6] = 127,
+ [0][1][1][0][RTW89_FCC][7] = 127,
+ [0][1][1][0][RTW89_ETSI][7] = 127,
+ [0][1][1][0][RTW89_MKK][7] = 127,
+ [0][1][1][0][RTW89_IC][7] = 127,
+ [0][1][1][0][RTW89_KCC][7] = 127,
+ [0][1][1][0][RTW89_ACMA][7] = 127,
+ [0][1][1][0][RTW89_CN][7] = 127,
+ [0][1][1][0][RTW89_UK][7] = 127,
+ [0][1][1][0][RTW89_FCC][8] = 127,
+ [0][1][1][0][RTW89_ETSI][8] = 127,
+ [0][1][1][0][RTW89_MKK][8] = 127,
+ [0][1][1][0][RTW89_IC][8] = 127,
+ [0][1][1][0][RTW89_KCC][8] = 127,
+ [0][1][1][0][RTW89_ACMA][8] = 127,
+ [0][1][1][0][RTW89_CN][8] = 127,
+ [0][1][1][0][RTW89_UK][8] = 127,
+ [0][1][1][0][RTW89_FCC][9] = 127,
+ [0][1][1][0][RTW89_ETSI][9] = 127,
+ [0][1][1][0][RTW89_MKK][9] = 127,
+ [0][1][1][0][RTW89_IC][9] = 127,
+ [0][1][1][0][RTW89_KCC][9] = 127,
+ [0][1][1][0][RTW89_ACMA][9] = 127,
+ [0][1][1][0][RTW89_CN][9] = 127,
+ [0][1][1][0][RTW89_UK][9] = 127,
+ [0][1][1][0][RTW89_FCC][10] = 127,
+ [0][1][1][0][RTW89_ETSI][10] = 127,
+ [0][1][1][0][RTW89_MKK][10] = 127,
+ [0][1][1][0][RTW89_IC][10] = 127,
+ [0][1][1][0][RTW89_KCC][10] = 127,
+ [0][1][1][0][RTW89_ACMA][10] = 127,
+ [0][1][1][0][RTW89_CN][10] = 127,
+ [0][1][1][0][RTW89_UK][10] = 127,
+ [0][1][1][0][RTW89_FCC][11] = 127,
+ [0][1][1][0][RTW89_ETSI][11] = 127,
+ [0][1][1][0][RTW89_MKK][11] = 127,
+ [0][1][1][0][RTW89_IC][11] = 127,
+ [0][1][1][0][RTW89_KCC][11] = 127,
+ [0][1][1][0][RTW89_ACMA][11] = 127,
+ [0][1][1][0][RTW89_CN][11] = 127,
+ [0][1][1][0][RTW89_UK][11] = 127,
+ [0][1][1][0][RTW89_FCC][12] = 127,
+ [0][1][1][0][RTW89_ETSI][12] = 127,
+ [0][1][1][0][RTW89_MKK][12] = 127,
+ [0][1][1][0][RTW89_IC][12] = 127,
+ [0][1][1][0][RTW89_KCC][12] = 127,
+ [0][1][1][0][RTW89_ACMA][12] = 127,
+ [0][1][1][0][RTW89_CN][12] = 127,
+ [0][1][1][0][RTW89_UK][12] = 127,
+ [0][1][1][0][RTW89_FCC][13] = 127,
+ [0][1][1][0][RTW89_ETSI][13] = 127,
+ [0][1][1][0][RTW89_MKK][13] = 127,
+ [0][1][1][0][RTW89_IC][13] = 127,
+ [0][1][1][0][RTW89_KCC][13] = 127,
+ [0][1][1][0][RTW89_ACMA][13] = 127,
+ [0][1][1][0][RTW89_CN][13] = 127,
+ [0][1][1][0][RTW89_UK][13] = 127,
+ [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_ETSI][0] = 60,
+ [0][0][2][0][RTW89_MKK][0] = 72,
+ [0][0][2][0][RTW89_IC][0] = 78,
+ [0][0][2][0][RTW89_KCC][0] = 76,
+ [0][0][2][0][RTW89_ACMA][0] = 60,
+ [0][0][2][0][RTW89_CN][0] = 60,
+ [0][0][2][0][RTW89_UK][0] = 60,
+ [0][0][2][0][RTW89_FCC][1] = 78,
+ [0][0][2][0][RTW89_ETSI][1] = 60,
+ [0][0][2][0][RTW89_MKK][1] = 76,
+ [0][0][2][0][RTW89_IC][1] = 78,
+ [0][0][2][0][RTW89_KCC][1] = 76,
+ [0][0][2][0][RTW89_ACMA][1] = 60,
+ [0][0][2][0][RTW89_CN][1] = 60,
+ [0][0][2][0][RTW89_UK][1] = 60,
+ [0][0][2][0][RTW89_FCC][2] = 80,
+ [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_KCC][2] = 76,
+ [0][0][2][0][RTW89_ACMA][2] = 60,
+ [0][0][2][0][RTW89_CN][2] = 60,
+ [0][0][2][0][RTW89_UK][2] = 60,
+ [0][0][2][0][RTW89_FCC][3] = 80,
+ [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_KCC][3] = 76,
+ [0][0][2][0][RTW89_ACMA][3] = 60,
+ [0][0][2][0][RTW89_CN][3] = 60,
+ [0][0][2][0][RTW89_UK][3] = 60,
+ [0][0][2][0][RTW89_FCC][4] = 80,
+ [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_KCC][4] = 76,
+ [0][0][2][0][RTW89_ACMA][4] = 60,
+ [0][0][2][0][RTW89_CN][4] = 60,
+ [0][0][2][0][RTW89_UK][4] = 60,
+ [0][0][2][0][RTW89_FCC][5] = 80,
+ [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_KCC][5] = 76,
+ [0][0][2][0][RTW89_ACMA][5] = 60,
+ [0][0][2][0][RTW89_CN][5] = 60,
+ [0][0][2][0][RTW89_UK][5] = 60,
+ [0][0][2][0][RTW89_FCC][6] = 80,
+ [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_KCC][6] = 76,
+ [0][0][2][0][RTW89_ACMA][6] = 60,
+ [0][0][2][0][RTW89_CN][6] = 60,
+ [0][0][2][0][RTW89_UK][6] = 60,
+ [0][0][2][0][RTW89_FCC][7] = 80,
+ [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_KCC][7] = 76,
+ [0][0][2][0][RTW89_ACMA][7] = 60,
+ [0][0][2][0][RTW89_CN][7] = 60,
+ [0][0][2][0][RTW89_UK][7] = 60,
+ [0][0][2][0][RTW89_FCC][8] = 78,
+ [0][0][2][0][RTW89_ETSI][8] = 60,
+ [0][0][2][0][RTW89_MKK][8] = 76,
+ [0][0][2][0][RTW89_IC][8] = 78,
+ [0][0][2][0][RTW89_KCC][8] = 76,
+ [0][0][2][0][RTW89_ACMA][8] = 60,
+ [0][0][2][0][RTW89_CN][8] = 60,
+ [0][0][2][0][RTW89_UK][8] = 60,
+ [0][0][2][0][RTW89_FCC][9] = 74,
+ [0][0][2][0][RTW89_ETSI][9] = 60,
+ [0][0][2][0][RTW89_MKK][9] = 76,
+ [0][0][2][0][RTW89_IC][9] = 74,
+ [0][0][2][0][RTW89_KCC][9] = 76,
+ [0][0][2][0][RTW89_ACMA][9] = 60,
+ [0][0][2][0][RTW89_CN][9] = 60,
+ [0][0][2][0][RTW89_UK][9] = 60,
+ [0][0][2][0][RTW89_FCC][10] = 74,
+ [0][0][2][0][RTW89_ETSI][10] = 60,
+ [0][0][2][0][RTW89_MKK][10] = 76,
+ [0][0][2][0][RTW89_IC][10] = 74,
+ [0][0][2][0][RTW89_KCC][10] = 76,
+ [0][0][2][0][RTW89_ACMA][10] = 60,
+ [0][0][2][0][RTW89_CN][10] = 60,
+ [0][0][2][0][RTW89_UK][10] = 60,
+ [0][0][2][0][RTW89_FCC][11] = 68,
+ [0][0][2][0][RTW89_ETSI][11] = 60,
+ [0][0][2][0][RTW89_MKK][11] = 76,
+ [0][0][2][0][RTW89_IC][11] = 68,
+ [0][0][2][0][RTW89_KCC][11] = 76,
+ [0][0][2][0][RTW89_ACMA][11] = 60,
+ [0][0][2][0][RTW89_CN][11] = 60,
+ [0][0][2][0][RTW89_UK][11] = 60,
+ [0][0][2][0][RTW89_FCC][12] = 68,
+ [0][0][2][0][RTW89_ETSI][12] = 60,
+ [0][0][2][0][RTW89_MKK][12] = 70,
+ [0][0][2][0][RTW89_IC][12] = 68,
+ [0][0][2][0][RTW89_KCC][12] = 76,
+ [0][0][2][0][RTW89_ACMA][12] = 60,
+ [0][0][2][0][RTW89_CN][12] = 60,
+ [0][0][2][0][RTW89_UK][12] = 60,
+ [0][0][2][0][RTW89_FCC][13] = 127,
+ [0][0][2][0][RTW89_ETSI][13] = 127,
+ [0][0][2][0][RTW89_MKK][13] = 127,
+ [0][0][2][0][RTW89_IC][13] = 127,
+ [0][0][2][0][RTW89_KCC][13] = 127,
+ [0][0][2][0][RTW89_ACMA][13] = 127,
+ [0][0][2][0][RTW89_CN][13] = 127,
+ [0][0][2][0][RTW89_UK][13] = 127,
+ [0][1][2][0][RTW89_FCC][0] = 127,
+ [0][1][2][0][RTW89_ETSI][0] = 127,
+ [0][1][2][0][RTW89_MKK][0] = 127,
+ [0][1][2][0][RTW89_IC][0] = 127,
+ [0][1][2][0][RTW89_KCC][0] = 127,
+ [0][1][2][0][RTW89_ACMA][0] = 127,
+ [0][1][2][0][RTW89_CN][0] = 127,
+ [0][1][2][0][RTW89_UK][0] = 127,
+ [0][1][2][0][RTW89_FCC][1] = 127,
+ [0][1][2][0][RTW89_ETSI][1] = 127,
+ [0][1][2][0][RTW89_MKK][1] = 127,
+ [0][1][2][0][RTW89_IC][1] = 127,
+ [0][1][2][0][RTW89_KCC][1] = 127,
+ [0][1][2][0][RTW89_ACMA][1] = 127,
+ [0][1][2][0][RTW89_CN][1] = 127,
+ [0][1][2][0][RTW89_UK][1] = 127,
+ [0][1][2][0][RTW89_FCC][2] = 127,
+ [0][1][2][0][RTW89_ETSI][2] = 127,
+ [0][1][2][0][RTW89_MKK][2] = 127,
+ [0][1][2][0][RTW89_IC][2] = 127,
+ [0][1][2][0][RTW89_KCC][2] = 127,
+ [0][1][2][0][RTW89_ACMA][2] = 127,
+ [0][1][2][0][RTW89_CN][2] = 127,
+ [0][1][2][0][RTW89_UK][2] = 127,
+ [0][1][2][0][RTW89_FCC][3] = 127,
+ [0][1][2][0][RTW89_ETSI][3] = 127,
+ [0][1][2][0][RTW89_MKK][3] = 127,
+ [0][1][2][0][RTW89_IC][3] = 127,
+ [0][1][2][0][RTW89_KCC][3] = 127,
+ [0][1][2][0][RTW89_ACMA][3] = 127,
+ [0][1][2][0][RTW89_CN][3] = 127,
+ [0][1][2][0][RTW89_UK][3] = 127,
+ [0][1][2][0][RTW89_FCC][4] = 127,
+ [0][1][2][0][RTW89_ETSI][4] = 127,
+ [0][1][2][0][RTW89_MKK][4] = 127,
+ [0][1][2][0][RTW89_IC][4] = 127,
+ [0][1][2][0][RTW89_KCC][4] = 127,
+ [0][1][2][0][RTW89_ACMA][4] = 127,
+ [0][1][2][0][RTW89_CN][4] = 127,
+ [0][1][2][0][RTW89_UK][4] = 127,
+ [0][1][2][0][RTW89_FCC][5] = 127,
+ [0][1][2][0][RTW89_ETSI][5] = 127,
+ [0][1][2][0][RTW89_MKK][5] = 127,
+ [0][1][2][0][RTW89_IC][5] = 127,
+ [0][1][2][0][RTW89_KCC][5] = 127,
+ [0][1][2][0][RTW89_ACMA][5] = 127,
+ [0][1][2][0][RTW89_CN][5] = 127,
+ [0][1][2][0][RTW89_UK][5] = 127,
+ [0][1][2][0][RTW89_FCC][6] = 127,
+ [0][1][2][0][RTW89_ETSI][6] = 127,
+ [0][1][2][0][RTW89_MKK][6] = 127,
+ [0][1][2][0][RTW89_IC][6] = 127,
+ [0][1][2][0][RTW89_KCC][6] = 127,
+ [0][1][2][0][RTW89_ACMA][6] = 127,
+ [0][1][2][0][RTW89_CN][6] = 127,
+ [0][1][2][0][RTW89_UK][6] = 127,
+ [0][1][2][0][RTW89_FCC][7] = 127,
+ [0][1][2][0][RTW89_ETSI][7] = 127,
+ [0][1][2][0][RTW89_MKK][7] = 127,
+ [0][1][2][0][RTW89_IC][7] = 127,
+ [0][1][2][0][RTW89_KCC][7] = 127,
+ [0][1][2][0][RTW89_ACMA][7] = 127,
+ [0][1][2][0][RTW89_CN][7] = 127,
+ [0][1][2][0][RTW89_UK][7] = 127,
+ [0][1][2][0][RTW89_FCC][8] = 127,
+ [0][1][2][0][RTW89_ETSI][8] = 127,
+ [0][1][2][0][RTW89_MKK][8] = 127,
+ [0][1][2][0][RTW89_IC][8] = 127,
+ [0][1][2][0][RTW89_KCC][8] = 127,
+ [0][1][2][0][RTW89_ACMA][8] = 127,
+ [0][1][2][0][RTW89_CN][8] = 127,
+ [0][1][2][0][RTW89_UK][8] = 127,
+ [0][1][2][0][RTW89_FCC][9] = 127,
+ [0][1][2][0][RTW89_ETSI][9] = 127,
+ [0][1][2][0][RTW89_MKK][9] = 127,
+ [0][1][2][0][RTW89_IC][9] = 127,
+ [0][1][2][0][RTW89_KCC][9] = 127,
+ [0][1][2][0][RTW89_ACMA][9] = 127,
+ [0][1][2][0][RTW89_CN][9] = 127,
+ [0][1][2][0][RTW89_UK][9] = 127,
+ [0][1][2][0][RTW89_FCC][10] = 127,
+ [0][1][2][0][RTW89_ETSI][10] = 127,
+ [0][1][2][0][RTW89_MKK][10] = 127,
+ [0][1][2][0][RTW89_IC][10] = 127,
+ [0][1][2][0][RTW89_KCC][10] = 127,
+ [0][1][2][0][RTW89_ACMA][10] = 127,
+ [0][1][2][0][RTW89_CN][10] = 127,
+ [0][1][2][0][RTW89_UK][10] = 127,
+ [0][1][2][0][RTW89_FCC][11] = 127,
+ [0][1][2][0][RTW89_ETSI][11] = 127,
+ [0][1][2][0][RTW89_MKK][11] = 127,
+ [0][1][2][0][RTW89_IC][11] = 127,
+ [0][1][2][0][RTW89_KCC][11] = 127,
+ [0][1][2][0][RTW89_ACMA][11] = 127,
+ [0][1][2][0][RTW89_CN][11] = 127,
+ [0][1][2][0][RTW89_UK][11] = 127,
+ [0][1][2][0][RTW89_FCC][12] = 127,
+ [0][1][2][0][RTW89_ETSI][12] = 127,
+ [0][1][2][0][RTW89_MKK][12] = 127,
+ [0][1][2][0][RTW89_IC][12] = 127,
+ [0][1][2][0][RTW89_KCC][12] = 127,
+ [0][1][2][0][RTW89_ACMA][12] = 127,
+ [0][1][2][0][RTW89_CN][12] = 127,
+ [0][1][2][0][RTW89_UK][12] = 127,
+ [0][1][2][0][RTW89_FCC][13] = 127,
+ [0][1][2][0][RTW89_ETSI][13] = 127,
+ [0][1][2][0][RTW89_MKK][13] = 127,
+ [0][1][2][0][RTW89_IC][13] = 127,
+ [0][1][2][0][RTW89_KCC][13] = 127,
+ [0][1][2][0][RTW89_ACMA][13] = 127,
+ [0][1][2][0][RTW89_CN][13] = 127,
+ [0][1][2][0][RTW89_UK][13] = 127,
+ [0][1][2][1][RTW89_FCC][0] = 127,
+ [0][1][2][1][RTW89_ETSI][0] = 127,
+ [0][1][2][1][RTW89_MKK][0] = 127,
+ [0][1][2][1][RTW89_IC][0] = 127,
+ [0][1][2][1][RTW89_KCC][0] = 127,
+ [0][1][2][1][RTW89_ACMA][0] = 127,
+ [0][1][2][1][RTW89_CN][0] = 127,
+ [0][1][2][1][RTW89_UK][0] = 127,
+ [0][1][2][1][RTW89_FCC][1] = 127,
+ [0][1][2][1][RTW89_ETSI][1] = 127,
+ [0][1][2][1][RTW89_MKK][1] = 127,
+ [0][1][2][1][RTW89_IC][1] = 127,
+ [0][1][2][1][RTW89_KCC][1] = 127,
+ [0][1][2][1][RTW89_ACMA][1] = 127,
+ [0][1][2][1][RTW89_CN][1] = 127,
+ [0][1][2][1][RTW89_UK][1] = 127,
+ [0][1][2][1][RTW89_FCC][2] = 127,
+ [0][1][2][1][RTW89_ETSI][2] = 127,
+ [0][1][2][1][RTW89_MKK][2] = 127,
+ [0][1][2][1][RTW89_IC][2] = 127,
+ [0][1][2][1][RTW89_KCC][2] = 127,
+ [0][1][2][1][RTW89_ACMA][2] = 127,
+ [0][1][2][1][RTW89_CN][2] = 127,
+ [0][1][2][1][RTW89_UK][2] = 127,
+ [0][1][2][1][RTW89_FCC][3] = 127,
+ [0][1][2][1][RTW89_ETSI][3] = 127,
+ [0][1][2][1][RTW89_MKK][3] = 127,
+ [0][1][2][1][RTW89_IC][3] = 127,
+ [0][1][2][1][RTW89_KCC][3] = 127,
+ [0][1][2][1][RTW89_ACMA][3] = 127,
+ [0][1][2][1][RTW89_CN][3] = 127,
+ [0][1][2][1][RTW89_UK][3] = 127,
+ [0][1][2][1][RTW89_FCC][4] = 127,
+ [0][1][2][1][RTW89_ETSI][4] = 127,
+ [0][1][2][1][RTW89_MKK][4] = 127,
+ [0][1][2][1][RTW89_IC][4] = 127,
+ [0][1][2][1][RTW89_KCC][4] = 127,
+ [0][1][2][1][RTW89_ACMA][4] = 127,
+ [0][1][2][1][RTW89_CN][4] = 127,
+ [0][1][2][1][RTW89_UK][4] = 127,
+ [0][1][2][1][RTW89_FCC][5] = 127,
+ [0][1][2][1][RTW89_ETSI][5] = 127,
+ [0][1][2][1][RTW89_MKK][5] = 127,
+ [0][1][2][1][RTW89_IC][5] = 127,
+ [0][1][2][1][RTW89_KCC][5] = 127,
+ [0][1][2][1][RTW89_ACMA][5] = 127,
+ [0][1][2][1][RTW89_CN][5] = 127,
+ [0][1][2][1][RTW89_UK][5] = 127,
+ [0][1][2][1][RTW89_FCC][6] = 127,
+ [0][1][2][1][RTW89_ETSI][6] = 127,
+ [0][1][2][1][RTW89_MKK][6] = 127,
+ [0][1][2][1][RTW89_IC][6] = 127,
+ [0][1][2][1][RTW89_KCC][6] = 127,
+ [0][1][2][1][RTW89_ACMA][6] = 127,
+ [0][1][2][1][RTW89_CN][6] = 127,
+ [0][1][2][1][RTW89_UK][6] = 127,
+ [0][1][2][1][RTW89_FCC][7] = 127,
+ [0][1][2][1][RTW89_ETSI][7] = 127,
+ [0][1][2][1][RTW89_MKK][7] = 127,
+ [0][1][2][1][RTW89_IC][7] = 127,
+ [0][1][2][1][RTW89_KCC][7] = 127,
+ [0][1][2][1][RTW89_ACMA][7] = 127,
+ [0][1][2][1][RTW89_CN][7] = 127,
+ [0][1][2][1][RTW89_UK][7] = 127,
+ [0][1][2][1][RTW89_FCC][8] = 127,
+ [0][1][2][1][RTW89_ETSI][8] = 127,
+ [0][1][2][1][RTW89_MKK][8] = 127,
+ [0][1][2][1][RTW89_IC][8] = 127,
+ [0][1][2][1][RTW89_KCC][8] = 127,
+ [0][1][2][1][RTW89_ACMA][8] = 127,
+ [0][1][2][1][RTW89_CN][8] = 127,
+ [0][1][2][1][RTW89_UK][8] = 127,
+ [0][1][2][1][RTW89_FCC][9] = 127,
+ [0][1][2][1][RTW89_ETSI][9] = 127,
+ [0][1][2][1][RTW89_MKK][9] = 127,
+ [0][1][2][1][RTW89_IC][9] = 127,
+ [0][1][2][1][RTW89_KCC][9] = 127,
+ [0][1][2][1][RTW89_ACMA][9] = 127,
+ [0][1][2][1][RTW89_CN][9] = 127,
+ [0][1][2][1][RTW89_UK][9] = 127,
+ [0][1][2][1][RTW89_FCC][10] = 127,
+ [0][1][2][1][RTW89_ETSI][10] = 127,
+ [0][1][2][1][RTW89_MKK][10] = 127,
+ [0][1][2][1][RTW89_IC][10] = 127,
+ [0][1][2][1][RTW89_KCC][10] = 127,
+ [0][1][2][1][RTW89_ACMA][10] = 127,
+ [0][1][2][1][RTW89_CN][10] = 127,
+ [0][1][2][1][RTW89_UK][10] = 127,
+ [0][1][2][1][RTW89_FCC][11] = 127,
+ [0][1][2][1][RTW89_ETSI][11] = 127,
+ [0][1][2][1][RTW89_MKK][11] = 127,
+ [0][1][2][1][RTW89_IC][11] = 127,
+ [0][1][2][1][RTW89_KCC][11] = 127,
+ [0][1][2][1][RTW89_ACMA][11] = 127,
+ [0][1][2][1][RTW89_CN][11] = 127,
+ [0][1][2][1][RTW89_UK][11] = 127,
+ [0][1][2][1][RTW89_FCC][12] = 127,
+ [0][1][2][1][RTW89_ETSI][12] = 127,
+ [0][1][2][1][RTW89_MKK][12] = 127,
+ [0][1][2][1][RTW89_IC][12] = 127,
+ [0][1][2][1][RTW89_KCC][12] = 127,
+ [0][1][2][1][RTW89_ACMA][12] = 127,
+ [0][1][2][1][RTW89_CN][12] = 127,
+ [0][1][2][1][RTW89_UK][12] = 127,
+ [0][1][2][1][RTW89_FCC][13] = 127,
+ [0][1][2][1][RTW89_ETSI][13] = 127,
+ [0][1][2][1][RTW89_MKK][13] = 127,
+ [0][1][2][1][RTW89_IC][13] = 127,
+ [0][1][2][1][RTW89_KCC][13] = 127,
+ [0][1][2][1][RTW89_ACMA][13] = 127,
+ [0][1][2][1][RTW89_CN][13] = 127,
+ [0][1][2][1][RTW89_UK][13] = 127,
+ [1][0][2][0][RTW89_FCC][0] = 127,
+ [1][0][2][0][RTW89_ETSI][0] = 127,
+ [1][0][2][0][RTW89_MKK][0] = 127,
+ [1][0][2][0][RTW89_IC][0] = 127,
+ [1][0][2][0][RTW89_KCC][0] = 127,
+ [1][0][2][0][RTW89_ACMA][0] = 127,
+ [1][0][2][0][RTW89_CN][0] = 127,
+ [1][0][2][0][RTW89_UK][0] = 127,
+ [1][0][2][0][RTW89_FCC][1] = 127,
+ [1][0][2][0][RTW89_ETSI][1] = 127,
+ [1][0][2][0][RTW89_MKK][1] = 127,
+ [1][0][2][0][RTW89_IC][1] = 127,
+ [1][0][2][0][RTW89_KCC][1] = 127,
+ [1][0][2][0][RTW89_ACMA][1] = 127,
+ [1][0][2][0][RTW89_CN][1] = 127,
+ [1][0][2][0][RTW89_UK][1] = 127,
+ [1][0][2][0][RTW89_FCC][2] = 70,
+ [1][0][2][0][RTW89_ETSI][2] = 58,
+ [1][0][2][0][RTW89_MKK][2] = 76,
+ [1][0][2][0][RTW89_IC][2] = 70,
+ [1][0][2][0][RTW89_KCC][2] = 76,
+ [1][0][2][0][RTW89_ACMA][2] = 58,
+ [1][0][2][0][RTW89_CN][2] = 60,
+ [1][0][2][0][RTW89_UK][2] = 58,
+ [1][0][2][0][RTW89_FCC][3] = 70,
+ [1][0][2][0][RTW89_ETSI][3] = 58,
+ [1][0][2][0][RTW89_MKK][3] = 76,
+ [1][0][2][0][RTW89_IC][3] = 70,
+ [1][0][2][0][RTW89_KCC][3] = 76,
+ [1][0][2][0][RTW89_ACMA][3] = 58,
+ [1][0][2][0][RTW89_CN][3] = 60,
+ [1][0][2][0][RTW89_UK][3] = 58,
+ [1][0][2][0][RTW89_FCC][4] = 74,
+ [1][0][2][0][RTW89_ETSI][4] = 58,
+ [1][0][2][0][RTW89_MKK][4] = 76,
+ [1][0][2][0][RTW89_IC][4] = 74,
+ [1][0][2][0][RTW89_KCC][4] = 76,
+ [1][0][2][0][RTW89_ACMA][4] = 58,
+ [1][0][2][0][RTW89_CN][4] = 60,
+ [1][0][2][0][RTW89_UK][4] = 58,
+ [1][0][2][0][RTW89_FCC][5] = 76,
+ [1][0][2][0][RTW89_ETSI][5] = 58,
+ [1][0][2][0][RTW89_MKK][5] = 76,
+ [1][0][2][0][RTW89_IC][5] = 76,
+ [1][0][2][0][RTW89_KCC][5] = 76,
+ [1][0][2][0][RTW89_ACMA][5] = 58,
+ [1][0][2][0][RTW89_CN][5] = 60,
+ [1][0][2][0][RTW89_UK][5] = 58,
+ [1][0][2][0][RTW89_FCC][6] = 76,
+ [1][0][2][0][RTW89_ETSI][6] = 58,
+ [1][0][2][0][RTW89_MKK][6] = 76,
+ [1][0][2][0][RTW89_IC][6] = 76,
+ [1][0][2][0][RTW89_KCC][6] = 76,
+ [1][0][2][0][RTW89_ACMA][6] = 58,
+ [1][0][2][0][RTW89_CN][6] = 60,
+ [1][0][2][0][RTW89_UK][6] = 58,
+ [1][0][2][0][RTW89_FCC][7] = 76,
+ [1][0][2][0][RTW89_ETSI][7] = 58,
+ [1][0][2][0][RTW89_MKK][7] = 76,
+ [1][0][2][0][RTW89_IC][7] = 76,
+ [1][0][2][0][RTW89_KCC][7] = 76,
+ [1][0][2][0][RTW89_ACMA][7] = 58,
+ [1][0][2][0][RTW89_CN][7] = 60,
+ [1][0][2][0][RTW89_UK][7] = 58,
+ [1][0][2][0][RTW89_FCC][8] = 78,
+ [1][0][2][0][RTW89_ETSI][8] = 58,
+ [1][0][2][0][RTW89_MKK][8] = 76,
+ [1][0][2][0][RTW89_IC][8] = 78,
+ [1][0][2][0][RTW89_KCC][8] = 76,
+ [1][0][2][0][RTW89_ACMA][8] = 58,
+ [1][0][2][0][RTW89_CN][8] = 60,
+ [1][0][2][0][RTW89_UK][8] = 58,
+ [1][0][2][0][RTW89_FCC][9] = 74,
+ [1][0][2][0][RTW89_ETSI][9] = 58,
+ [1][0][2][0][RTW89_MKK][9] = 76,
+ [1][0][2][0][RTW89_IC][9] = 74,
+ [1][0][2][0][RTW89_KCC][9] = 76,
+ [1][0][2][0][RTW89_ACMA][9] = 58,
+ [1][0][2][0][RTW89_CN][9] = 60,
+ [1][0][2][0][RTW89_UK][9] = 58,
+ [1][0][2][0][RTW89_FCC][10] = 68,
+ [1][0][2][0][RTW89_ETSI][10] = 58,
+ [1][0][2][0][RTW89_MKK][10] = 76,
+ [1][0][2][0][RTW89_IC][10] = 68,
+ [1][0][2][0][RTW89_KCC][10] = 76,
+ [1][0][2][0][RTW89_ACMA][10] = 58,
+ [1][0][2][0][RTW89_CN][10] = 60,
+ [1][0][2][0][RTW89_UK][10] = 58,
+ [1][0][2][0][RTW89_FCC][11] = 127,
+ [1][0][2][0][RTW89_ETSI][11] = 127,
+ [1][0][2][0][RTW89_MKK][11] = 127,
+ [1][0][2][0][RTW89_IC][11] = 127,
+ [1][0][2][0][RTW89_KCC][11] = 127,
+ [1][0][2][0][RTW89_ACMA][11] = 127,
+ [1][0][2][0][RTW89_CN][11] = 127,
+ [1][0][2][0][RTW89_UK][11] = 127,
+ [1][0][2][0][RTW89_FCC][12] = 127,
+ [1][0][2][0][RTW89_ETSI][12] = 127,
+ [1][0][2][0][RTW89_MKK][12] = 127,
+ [1][0][2][0][RTW89_IC][12] = 127,
+ [1][0][2][0][RTW89_KCC][12] = 127,
+ [1][0][2][0][RTW89_ACMA][12] = 127,
+ [1][0][2][0][RTW89_CN][12] = 127,
+ [1][0][2][0][RTW89_UK][12] = 127,
+ [1][0][2][0][RTW89_FCC][13] = 127,
+ [1][0][2][0][RTW89_ETSI][13] = 127,
+ [1][0][2][0][RTW89_MKK][13] = 127,
+ [1][0][2][0][RTW89_IC][13] = 127,
+ [1][0][2][0][RTW89_KCC][13] = 127,
+ [1][0][2][0][RTW89_ACMA][13] = 127,
+ [1][0][2][0][RTW89_CN][13] = 127,
+ [1][0][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_FCC][0] = 127,
+ [1][1][2][0][RTW89_ETSI][0] = 127,
+ [1][1][2][0][RTW89_MKK][0] = 127,
+ [1][1][2][0][RTW89_IC][0] = 127,
+ [1][1][2][0][RTW89_KCC][0] = 127,
+ [1][1][2][0][RTW89_ACMA][0] = 127,
+ [1][1][2][0][RTW89_CN][0] = 127,
+ [1][1][2][0][RTW89_UK][0] = 127,
+ [1][1][2][0][RTW89_FCC][1] = 127,
+ [1][1][2][0][RTW89_ETSI][1] = 127,
+ [1][1][2][0][RTW89_MKK][1] = 127,
+ [1][1][2][0][RTW89_IC][1] = 127,
+ [1][1][2][0][RTW89_KCC][1] = 127,
+ [1][1][2][0][RTW89_ACMA][1] = 127,
+ [1][1][2][0][RTW89_CN][1] = 127,
+ [1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_FCC][2] = 127,
+ [1][1][2][0][RTW89_ETSI][2] = 127,
+ [1][1][2][0][RTW89_MKK][2] = 127,
+ [1][1][2][0][RTW89_IC][2] = 127,
+ [1][1][2][0][RTW89_KCC][2] = 127,
+ [1][1][2][0][RTW89_ACMA][2] = 127,
+ [1][1][2][0][RTW89_CN][2] = 127,
+ [1][1][2][0][RTW89_UK][2] = 127,
+ [1][1][2][0][RTW89_FCC][3] = 127,
+ [1][1][2][0][RTW89_ETSI][3] = 127,
+ [1][1][2][0][RTW89_MKK][3] = 127,
+ [1][1][2][0][RTW89_IC][3] = 127,
+ [1][1][2][0][RTW89_KCC][3] = 127,
+ [1][1][2][0][RTW89_ACMA][3] = 127,
+ [1][1][2][0][RTW89_CN][3] = 127,
+ [1][1][2][0][RTW89_UK][3] = 127,
+ [1][1][2][0][RTW89_FCC][4] = 127,
+ [1][1][2][0][RTW89_ETSI][4] = 127,
+ [1][1][2][0][RTW89_MKK][4] = 127,
+ [1][1][2][0][RTW89_IC][4] = 127,
+ [1][1][2][0][RTW89_KCC][4] = 127,
+ [1][1][2][0][RTW89_ACMA][4] = 127,
+ [1][1][2][0][RTW89_CN][4] = 127,
+ [1][1][2][0][RTW89_UK][4] = 127,
+ [1][1][2][0][RTW89_FCC][5] = 127,
+ [1][1][2][0][RTW89_ETSI][5] = 127,
+ [1][1][2][0][RTW89_MKK][5] = 127,
+ [1][1][2][0][RTW89_IC][5] = 127,
+ [1][1][2][0][RTW89_KCC][5] = 127,
+ [1][1][2][0][RTW89_ACMA][5] = 127,
+ [1][1][2][0][RTW89_CN][5] = 127,
+ [1][1][2][0][RTW89_UK][5] = 127,
+ [1][1][2][0][RTW89_FCC][6] = 127,
+ [1][1][2][0][RTW89_ETSI][6] = 127,
+ [1][1][2][0][RTW89_MKK][6] = 127,
+ [1][1][2][0][RTW89_IC][6] = 127,
+ [1][1][2][0][RTW89_KCC][6] = 127,
+ [1][1][2][0][RTW89_ACMA][6] = 127,
+ [1][1][2][0][RTW89_CN][6] = 127,
+ [1][1][2][0][RTW89_UK][6] = 127,
+ [1][1][2][0][RTW89_FCC][7] = 127,
+ [1][1][2][0][RTW89_ETSI][7] = 127,
+ [1][1][2][0][RTW89_MKK][7] = 127,
+ [1][1][2][0][RTW89_IC][7] = 127,
+ [1][1][2][0][RTW89_KCC][7] = 127,
+ [1][1][2][0][RTW89_ACMA][7] = 127,
+ [1][1][2][0][RTW89_CN][7] = 127,
+ [1][1][2][0][RTW89_UK][7] = 127,
+ [1][1][2][0][RTW89_FCC][8] = 127,
+ [1][1][2][0][RTW89_ETSI][8] = 127,
+ [1][1][2][0][RTW89_MKK][8] = 127,
+ [1][1][2][0][RTW89_IC][8] = 127,
+ [1][1][2][0][RTW89_KCC][8] = 127,
+ [1][1][2][0][RTW89_ACMA][8] = 127,
+ [1][1][2][0][RTW89_CN][8] = 127,
+ [1][1][2][0][RTW89_UK][8] = 127,
+ [1][1][2][0][RTW89_FCC][9] = 127,
+ [1][1][2][0][RTW89_ETSI][9] = 127,
+ [1][1][2][0][RTW89_MKK][9] = 127,
+ [1][1][2][0][RTW89_IC][9] = 127,
+ [1][1][2][0][RTW89_KCC][9] = 127,
+ [1][1][2][0][RTW89_ACMA][9] = 127,
+ [1][1][2][0][RTW89_CN][9] = 127,
+ [1][1][2][0][RTW89_UK][9] = 127,
+ [1][1][2][0][RTW89_FCC][10] = 127,
+ [1][1][2][0][RTW89_ETSI][10] = 127,
+ [1][1][2][0][RTW89_MKK][10] = 127,
+ [1][1][2][0][RTW89_IC][10] = 127,
+ [1][1][2][0][RTW89_KCC][10] = 127,
+ [1][1][2][0][RTW89_ACMA][10] = 127,
+ [1][1][2][0][RTW89_CN][10] = 127,
+ [1][1][2][0][RTW89_UK][10] = 127,
+ [1][1][2][0][RTW89_FCC][11] = 127,
+ [1][1][2][0][RTW89_ETSI][11] = 127,
+ [1][1][2][0][RTW89_MKK][11] = 127,
+ [1][1][2][0][RTW89_IC][11] = 127,
+ [1][1][2][0][RTW89_KCC][11] = 127,
+ [1][1][2][0][RTW89_ACMA][11] = 127,
+ [1][1][2][0][RTW89_CN][11] = 127,
+ [1][1][2][0][RTW89_UK][11] = 127,
+ [1][1][2][0][RTW89_FCC][12] = 127,
+ [1][1][2][0][RTW89_ETSI][12] = 127,
+ [1][1][2][0][RTW89_MKK][12] = 127,
+ [1][1][2][0][RTW89_IC][12] = 127,
+ [1][1][2][0][RTW89_KCC][12] = 127,
+ [1][1][2][0][RTW89_ACMA][12] = 127,
+ [1][1][2][0][RTW89_CN][12] = 127,
+ [1][1][2][0][RTW89_UK][12] = 127,
+ [1][1][2][0][RTW89_FCC][13] = 127,
+ [1][1][2][0][RTW89_ETSI][13] = 127,
+ [1][1][2][0][RTW89_MKK][13] = 127,
+ [1][1][2][0][RTW89_IC][13] = 127,
+ [1][1][2][0][RTW89_KCC][13] = 127,
+ [1][1][2][0][RTW89_ACMA][13] = 127,
+ [1][1][2][0][RTW89_CN][13] = 127,
+ [1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_FCC][0] = 127,
+ [1][1][2][1][RTW89_ETSI][0] = 127,
+ [1][1][2][1][RTW89_MKK][0] = 127,
+ [1][1][2][1][RTW89_IC][0] = 127,
+ [1][1][2][1][RTW89_KCC][0] = 127,
+ [1][1][2][1][RTW89_ACMA][0] = 127,
+ [1][1][2][1][RTW89_CN][0] = 127,
+ [1][1][2][1][RTW89_UK][0] = 127,
+ [1][1][2][1][RTW89_FCC][1] = 127,
+ [1][1][2][1][RTW89_ETSI][1] = 127,
+ [1][1][2][1][RTW89_MKK][1] = 127,
+ [1][1][2][1][RTW89_IC][1] = 127,
+ [1][1][2][1][RTW89_KCC][1] = 127,
+ [1][1][2][1][RTW89_ACMA][1] = 127,
+ [1][1][2][1][RTW89_CN][1] = 127,
+ [1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_FCC][2] = 127,
+ [1][1][2][1][RTW89_ETSI][2] = 127,
+ [1][1][2][1][RTW89_MKK][2] = 127,
+ [1][1][2][1][RTW89_IC][2] = 127,
+ [1][1][2][1][RTW89_KCC][2] = 127,
+ [1][1][2][1][RTW89_ACMA][2] = 127,
+ [1][1][2][1][RTW89_CN][2] = 127,
+ [1][1][2][1][RTW89_UK][2] = 127,
+ [1][1][2][1][RTW89_FCC][3] = 127,
+ [1][1][2][1][RTW89_ETSI][3] = 127,
+ [1][1][2][1][RTW89_MKK][3] = 127,
+ [1][1][2][1][RTW89_IC][3] = 127,
+ [1][1][2][1][RTW89_KCC][3] = 127,
+ [1][1][2][1][RTW89_ACMA][3] = 127,
+ [1][1][2][1][RTW89_CN][3] = 127,
+ [1][1][2][1][RTW89_UK][3] = 127,
+ [1][1][2][1][RTW89_FCC][4] = 127,
+ [1][1][2][1][RTW89_ETSI][4] = 127,
+ [1][1][2][1][RTW89_MKK][4] = 127,
+ [1][1][2][1][RTW89_IC][4] = 127,
+ [1][1][2][1][RTW89_KCC][4] = 127,
+ [1][1][2][1][RTW89_ACMA][4] = 127,
+ [1][1][2][1][RTW89_CN][4] = 127,
+ [1][1][2][1][RTW89_UK][4] = 127,
+ [1][1][2][1][RTW89_FCC][5] = 127,
+ [1][1][2][1][RTW89_ETSI][5] = 127,
+ [1][1][2][1][RTW89_MKK][5] = 127,
+ [1][1][2][1][RTW89_IC][5] = 127,
+ [1][1][2][1][RTW89_KCC][5] = 127,
+ [1][1][2][1][RTW89_ACMA][5] = 127,
+ [1][1][2][1][RTW89_CN][5] = 127,
+ [1][1][2][1][RTW89_UK][5] = 127,
+ [1][1][2][1][RTW89_FCC][6] = 127,
+ [1][1][2][1][RTW89_ETSI][6] = 127,
+ [1][1][2][1][RTW89_MKK][6] = 127,
+ [1][1][2][1][RTW89_IC][6] = 127,
+ [1][1][2][1][RTW89_KCC][6] = 127,
+ [1][1][2][1][RTW89_ACMA][6] = 127,
+ [1][1][2][1][RTW89_CN][6] = 127,
+ [1][1][2][1][RTW89_UK][6] = 127,
+ [1][1][2][1][RTW89_FCC][7] = 127,
+ [1][1][2][1][RTW89_ETSI][7] = 127,
+ [1][1][2][1][RTW89_MKK][7] = 127,
+ [1][1][2][1][RTW89_IC][7] = 127,
+ [1][1][2][1][RTW89_KCC][7] = 127,
+ [1][1][2][1][RTW89_ACMA][7] = 127,
+ [1][1][2][1][RTW89_CN][7] = 127,
+ [1][1][2][1][RTW89_UK][7] = 127,
+ [1][1][2][1][RTW89_FCC][8] = 127,
+ [1][1][2][1][RTW89_ETSI][8] = 127,
+ [1][1][2][1][RTW89_MKK][8] = 127,
+ [1][1][2][1][RTW89_IC][8] = 127,
+ [1][1][2][1][RTW89_KCC][8] = 127,
+ [1][1][2][1][RTW89_ACMA][8] = 127,
+ [1][1][2][1][RTW89_CN][8] = 127,
+ [1][1][2][1][RTW89_UK][8] = 127,
+ [1][1][2][1][RTW89_FCC][9] = 127,
+ [1][1][2][1][RTW89_ETSI][9] = 127,
+ [1][1][2][1][RTW89_MKK][9] = 127,
+ [1][1][2][1][RTW89_IC][9] = 127,
+ [1][1][2][1][RTW89_KCC][9] = 127,
+ [1][1][2][1][RTW89_ACMA][9] = 127,
+ [1][1][2][1][RTW89_CN][9] = 127,
+ [1][1][2][1][RTW89_UK][9] = 127,
+ [1][1][2][1][RTW89_FCC][10] = 127,
+ [1][1][2][1][RTW89_ETSI][10] = 127,
+ [1][1][2][1][RTW89_MKK][10] = 127,
+ [1][1][2][1][RTW89_IC][10] = 127,
+ [1][1][2][1][RTW89_KCC][10] = 127,
+ [1][1][2][1][RTW89_ACMA][10] = 127,
+ [1][1][2][1][RTW89_CN][10] = 127,
+ [1][1][2][1][RTW89_UK][10] = 127,
+ [1][1][2][1][RTW89_FCC][11] = 127,
+ [1][1][2][1][RTW89_ETSI][11] = 127,
+ [1][1][2][1][RTW89_MKK][11] = 127,
+ [1][1][2][1][RTW89_IC][11] = 127,
+ [1][1][2][1][RTW89_KCC][11] = 127,
+ [1][1][2][1][RTW89_ACMA][11] = 127,
+ [1][1][2][1][RTW89_CN][11] = 127,
+ [1][1][2][1][RTW89_UK][11] = 127,
+ [1][1][2][1][RTW89_FCC][12] = 127,
+ [1][1][2][1][RTW89_ETSI][12] = 127,
+ [1][1][2][1][RTW89_MKK][12] = 127,
+ [1][1][2][1][RTW89_IC][12] = 127,
+ [1][1][2][1][RTW89_KCC][12] = 127,
+ [1][1][2][1][RTW89_ACMA][12] = 127,
+ [1][1][2][1][RTW89_CN][12] = 127,
+ [1][1][2][1][RTW89_UK][12] = 127,
+ [1][1][2][1][RTW89_FCC][13] = 127,
+ [1][1][2][1][RTW89_ETSI][13] = 127,
+ [1][1][2][1][RTW89_MKK][13] = 127,
+ [1][1][2][1][RTW89_IC][13] = 127,
+ [1][1][2][1][RTW89_KCC][13] = 127,
+ [1][1][2][1][RTW89_ACMA][13] = 127,
+ [1][1][2][1][RTW89_CN][13] = 127,
+ [1][1][2][1][RTW89_UK][13] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
+ [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
+ [0][0][1][0][RTW89_WW][0] = 58,
+ [0][0][1][0][RTW89_WW][2] = 58,
+ [0][0][1][0][RTW89_WW][4] = 58,
+ [0][0][1][0][RTW89_WW][6] = 50,
+ [0][0][1][0][RTW89_WW][8] = 58,
+ [0][0][1][0][RTW89_WW][10] = 58,
+ [0][0][1][0][RTW89_WW][12] = 58,
+ [0][0][1][0][RTW89_WW][14] = 58,
+ [0][0][1][0][RTW89_WW][15] = 58,
+ [0][0][1][0][RTW89_WW][17] = 60,
+ [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][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] = 74,
+ [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] = 72,
+ [0][0][1][0][RTW89_WW][50] = 72,
+ [0][0][1][0][RTW89_WW][52] = 72,
+ [0][1][1][0][RTW89_WW][0] = 0,
+ [0][1][1][0][RTW89_WW][2] = 0,
+ [0][1][1][0][RTW89_WW][4] = 0,
+ [0][1][1][0][RTW89_WW][6] = 0,
+ [0][1][1][0][RTW89_WW][8] = 0,
+ [0][1][1][0][RTW89_WW][10] = 0,
+ [0][1][1][0][RTW89_WW][12] = 0,
+ [0][1][1][0][RTW89_WW][14] = 0,
+ [0][1][1][0][RTW89_WW][15] = 0,
+ [0][1][1][0][RTW89_WW][17] = 0,
+ [0][1][1][0][RTW89_WW][19] = 0,
+ [0][1][1][0][RTW89_WW][21] = 0,
+ [0][1][1][0][RTW89_WW][23] = 0,
+ [0][1][1][0][RTW89_WW][25] = 0,
+ [0][1][1][0][RTW89_WW][27] = 0,
+ [0][1][1][0][RTW89_WW][29] = 0,
+ [0][1][1][0][RTW89_WW][31] = 0,
+ [0][1][1][0][RTW89_WW][33] = 0,
+ [0][1][1][0][RTW89_WW][35] = 0,
+ [0][1][1][0][RTW89_WW][37] = 0,
+ [0][1][1][0][RTW89_WW][38] = 0,
+ [0][1][1][0][RTW89_WW][40] = 0,
+ [0][1][1][0][RTW89_WW][42] = 0,
+ [0][1][1][0][RTW89_WW][44] = 0,
+ [0][1][1][0][RTW89_WW][46] = 0,
+ [0][1][1][0][RTW89_WW][48] = 0,
+ [0][1][1][0][RTW89_WW][50] = 0,
+ [0][1][1][0][RTW89_WW][52] = 0,
+ [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] = 54,
+ [0][0][2][0][RTW89_WW][8] = 62,
+ [0][0][2][0][RTW89_WW][10] = 62,
+ [0][0][2][0][RTW89_WW][12] = 62,
+ [0][0][2][0][RTW89_WW][14] = 62,
+ [0][0][2][0][RTW89_WW][15] = 60,
+ [0][0][2][0][RTW89_WW][17] = 62,
+ [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][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] = 74,
+ [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] = 74,
+ [0][0][2][0][RTW89_WW][50] = 74,
+ [0][0][2][0][RTW89_WW][52] = 74,
+ [0][1][2][0][RTW89_WW][0] = 0,
+ [0][1][2][0][RTW89_WW][2] = 0,
+ [0][1][2][0][RTW89_WW][4] = 0,
+ [0][1][2][0][RTW89_WW][6] = 0,
+ [0][1][2][0][RTW89_WW][8] = 0,
+ [0][1][2][0][RTW89_WW][10] = 0,
+ [0][1][2][0][RTW89_WW][12] = 0,
+ [0][1][2][0][RTW89_WW][14] = 0,
+ [0][1][2][0][RTW89_WW][15] = 0,
+ [0][1][2][0][RTW89_WW][17] = 0,
+ [0][1][2][0][RTW89_WW][19] = 0,
+ [0][1][2][0][RTW89_WW][21] = 0,
+ [0][1][2][0][RTW89_WW][23] = 0,
+ [0][1][2][0][RTW89_WW][25] = 0,
+ [0][1][2][0][RTW89_WW][27] = 0,
+ [0][1][2][0][RTW89_WW][29] = 0,
+ [0][1][2][0][RTW89_WW][31] = 0,
+ [0][1][2][0][RTW89_WW][33] = 0,
+ [0][1][2][0][RTW89_WW][35] = 0,
+ [0][1][2][0][RTW89_WW][37] = 0,
+ [0][1][2][0][RTW89_WW][38] = 0,
+ [0][1][2][0][RTW89_WW][40] = 0,
+ [0][1][2][0][RTW89_WW][42] = 0,
+ [0][1][2][0][RTW89_WW][44] = 0,
+ [0][1][2][0][RTW89_WW][46] = 0,
+ [0][1][2][0][RTW89_WW][48] = 0,
+ [0][1][2][0][RTW89_WW][50] = 0,
+ [0][1][2][0][RTW89_WW][52] = 0,
+ [0][1][2][1][RTW89_WW][0] = 0,
+ [0][1][2][1][RTW89_WW][2] = 0,
+ [0][1][2][1][RTW89_WW][4] = 0,
+ [0][1][2][1][RTW89_WW][6] = 0,
+ [0][1][2][1][RTW89_WW][8] = 0,
+ [0][1][2][1][RTW89_WW][10] = 0,
+ [0][1][2][1][RTW89_WW][12] = 0,
+ [0][1][2][1][RTW89_WW][14] = 0,
+ [0][1][2][1][RTW89_WW][15] = 0,
+ [0][1][2][1][RTW89_WW][17] = 0,
+ [0][1][2][1][RTW89_WW][19] = 0,
+ [0][1][2][1][RTW89_WW][21] = 0,
+ [0][1][2][1][RTW89_WW][23] = 0,
+ [0][1][2][1][RTW89_WW][25] = 0,
+ [0][1][2][1][RTW89_WW][27] = 0,
+ [0][1][2][1][RTW89_WW][29] = 0,
+ [0][1][2][1][RTW89_WW][31] = 0,
+ [0][1][2][1][RTW89_WW][33] = 0,
+ [0][1][2][1][RTW89_WW][35] = 0,
+ [0][1][2][1][RTW89_WW][37] = 0,
+ [0][1][2][1][RTW89_WW][38] = 0,
+ [0][1][2][1][RTW89_WW][40] = 0,
+ [0][1][2][1][RTW89_WW][42] = 0,
+ [0][1][2][1][RTW89_WW][44] = 0,
+ [0][1][2][1][RTW89_WW][46] = 0,
+ [0][1][2][1][RTW89_WW][48] = 0,
+ [0][1][2][1][RTW89_WW][50] = 0,
+ [0][1][2][1][RTW89_WW][52] = 0,
+ [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][5] = 62,
+ [1][0][2][0][RTW89_WW][9] = 64,
+ [1][0][2][0][RTW89_WW][13] = 64,
+ [1][0][2][0][RTW89_WW][16] = 66,
+ [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][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] = 80,
+ [1][1][2][0][RTW89_WW][1] = 0,
+ [1][1][2][0][RTW89_WW][5] = 0,
+ [1][1][2][0][RTW89_WW][9] = 0,
+ [1][1][2][0][RTW89_WW][13] = 0,
+ [1][1][2][0][RTW89_WW][16] = 0,
+ [1][1][2][0][RTW89_WW][20] = 0,
+ [1][1][2][0][RTW89_WW][24] = 0,
+ [1][1][2][0][RTW89_WW][28] = 0,
+ [1][1][2][0][RTW89_WW][32] = 0,
+ [1][1][2][0][RTW89_WW][36] = 0,
+ [1][1][2][0][RTW89_WW][39] = 0,
+ [1][1][2][0][RTW89_WW][43] = 0,
+ [1][1][2][0][RTW89_WW][47] = 0,
+ [1][1][2][0][RTW89_WW][51] = 0,
+ [1][1][2][1][RTW89_WW][1] = 0,
+ [1][1][2][1][RTW89_WW][5] = 0,
+ [1][1][2][1][RTW89_WW][9] = 0,
+ [1][1][2][1][RTW89_WW][13] = 0,
+ [1][1][2][1][RTW89_WW][16] = 0,
+ [1][1][2][1][RTW89_WW][20] = 0,
+ [1][1][2][1][RTW89_WW][24] = 0,
+ [1][1][2][1][RTW89_WW][28] = 0,
+ [1][1][2][1][RTW89_WW][32] = 0,
+ [1][1][2][1][RTW89_WW][36] = 0,
+ [1][1][2][1][RTW89_WW][39] = 0,
+ [1][1][2][1][RTW89_WW][43] = 0,
+ [1][1][2][1][RTW89_WW][47] = 0,
+ [1][1][2][1][RTW89_WW][51] = 0,
+ [2][0][2][0][RTW89_WW][3] = 62,
+ [2][0][2][0][RTW89_WW][11] = 62,
+ [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][26] = 64,
+ [2][0][2][0][RTW89_WW][34] = 68,
+ [2][0][2][0][RTW89_WW][41] = 30,
+ [2][0][2][0][RTW89_WW][49] = 72,
+ [2][1][2][0][RTW89_WW][3] = 0,
+ [2][1][2][0][RTW89_WW][11] = 0,
+ [2][1][2][0][RTW89_WW][18] = 0,
+ [2][1][2][0][RTW89_WW][26] = 0,
+ [2][1][2][0][RTW89_WW][34] = 0,
+ [2][1][2][0][RTW89_WW][41] = 0,
+ [2][1][2][0][RTW89_WW][49] = 0,
+ [2][1][2][1][RTW89_WW][3] = 0,
+ [2][1][2][1][RTW89_WW][11] = 0,
+ [2][1][2][1][RTW89_WW][18] = 0,
+ [2][1][2][1][RTW89_WW][26] = 0,
+ [2][1][2][1][RTW89_WW][34] = 0,
+ [2][1][2][1][RTW89_WW][41] = 0,
+ [2][1][2][1][RTW89_WW][49] = 0,
+ [3][0][2][0][RTW89_WW][7] = 58,
+ [3][0][2][0][RTW89_WW][22] = 58,
+ [3][0][2][0][RTW89_WW][45] = 0,
+ [3][1][2][0][RTW89_WW][7] = 0,
+ [3][1][2][0][RTW89_WW][22] = 0,
+ [3][1][2][0][RTW89_WW][45] = 0,
+ [3][1][2][1][RTW89_WW][7] = 0,
+ [3][1][2][1][RTW89_WW][22] = 0,
+ [3][1][2][1][RTW89_WW][45] = 0,
+ [0][0][1][0][RTW89_FCC][0] = 78,
+ [0][0][1][0][RTW89_ETSI][0] = 58,
+ [0][0][1][0][RTW89_MKK][0] = 60,
+ [0][0][1][0][RTW89_IC][0] = 62,
+ [0][0][1][0][RTW89_KCC][0] = 74,
+ [0][0][1][0][RTW89_ACMA][0] = 58,
+ [0][0][1][0][RTW89_CN][0] = 60,
+ [0][0][1][0][RTW89_UK][0] = 58,
+ [0][0][1][0][RTW89_FCC][2] = 78,
+ [0][0][1][0][RTW89_ETSI][2] = 58,
+ [0][0][1][0][RTW89_MKK][2] = 60,
+ [0][0][1][0][RTW89_IC][2] = 62,
+ [0][0][1][0][RTW89_KCC][2] = 74,
+ [0][0][1][0][RTW89_ACMA][2] = 58,
+ [0][0][1][0][RTW89_CN][2] = 60,
+ [0][0][1][0][RTW89_UK][2] = 58,
+ [0][0][1][0][RTW89_FCC][4] = 78,
+ [0][0][1][0][RTW89_ETSI][4] = 58,
+ [0][0][1][0][RTW89_MKK][4] = 60,
+ [0][0][1][0][RTW89_IC][4] = 62,
+ [0][0][1][0][RTW89_KCC][4] = 74,
+ [0][0][1][0][RTW89_ACMA][4] = 58,
+ [0][0][1][0][RTW89_CN][4] = 60,
+ [0][0][1][0][RTW89_UK][4] = 58,
+ [0][0][1][0][RTW89_FCC][6] = 78,
+ [0][0][1][0][RTW89_ETSI][6] = 58,
+ [0][0][1][0][RTW89_MKK][6] = 60,
+ [0][0][1][0][RTW89_IC][6] = 62,
+ [0][0][1][0][RTW89_KCC][6] = 50,
+ [0][0][1][0][RTW89_ACMA][6] = 58,
+ [0][0][1][0][RTW89_CN][6] = 60,
+ [0][0][1][0][RTW89_UK][6] = 58,
+ [0][0][1][0][RTW89_FCC][8] = 78,
+ [0][0][1][0][RTW89_ETSI][8] = 58,
+ [0][0][1][0][RTW89_MKK][8] = 60,
+ [0][0][1][0][RTW89_IC][8] = 62,
+ [0][0][1][0][RTW89_KCC][8] = 74,
+ [0][0][1][0][RTW89_ACMA][8] = 58,
+ [0][0][1][0][RTW89_CN][8] = 60,
+ [0][0][1][0][RTW89_UK][8] = 58,
+ [0][0][1][0][RTW89_FCC][10] = 78,
+ [0][0][1][0][RTW89_ETSI][10] = 58,
+ [0][0][1][0][RTW89_MKK][10] = 60,
+ [0][0][1][0][RTW89_IC][10] = 64,
+ [0][0][1][0][RTW89_KCC][10] = 74,
+ [0][0][1][0][RTW89_ACMA][10] = 58,
+ [0][0][1][0][RTW89_CN][10] = 60,
+ [0][0][1][0][RTW89_UK][10] = 58,
+ [0][0][1][0][RTW89_FCC][12] = 78,
+ [0][0][1][0][RTW89_ETSI][12] = 58,
+ [0][0][1][0][RTW89_MKK][12] = 60,
+ [0][0][1][0][RTW89_IC][12] = 64,
+ [0][0][1][0][RTW89_KCC][12] = 74,
+ [0][0][1][0][RTW89_ACMA][12] = 58,
+ [0][0][1][0][RTW89_CN][12] = 60,
+ [0][0][1][0][RTW89_UK][12] = 58,
+ [0][0][1][0][RTW89_FCC][14] = 76,
+ [0][0][1][0][RTW89_ETSI][14] = 58,
+ [0][0][1][0][RTW89_MKK][14] = 60,
+ [0][0][1][0][RTW89_IC][14] = 62,
+ [0][0][1][0][RTW89_KCC][14] = 74,
+ [0][0][1][0][RTW89_ACMA][14] = 58,
+ [0][0][1][0][RTW89_CN][14] = 60,
+ [0][0][1][0][RTW89_UK][14] = 58,
+ [0][0][1][0][RTW89_FCC][15] = 76,
+ [0][0][1][0][RTW89_ETSI][15] = 58,
+ [0][0][1][0][RTW89_MKK][15] = 74,
+ [0][0][1][0][RTW89_IC][15] = 76,
+ [0][0][1][0][RTW89_KCC][15] = 74,
+ [0][0][1][0][RTW89_ACMA][15] = 58,
+ [0][0][1][0][RTW89_CN][15] = 127,
+ [0][0][1][0][RTW89_UK][15] = 58,
+ [0][0][1][0][RTW89_FCC][17] = 78,
+ [0][0][1][0][RTW89_ETSI][17] = 60,
+ [0][0][1][0][RTW89_MKK][17] = 74,
+ [0][0][1][0][RTW89_IC][17] = 78,
+ [0][0][1][0][RTW89_KCC][17] = 74,
+ [0][0][1][0][RTW89_ACMA][17] = 60,
+ [0][0][1][0][RTW89_CN][17] = 127,
+ [0][0][1][0][RTW89_UK][17] = 60,
+ [0][0][1][0][RTW89_FCC][19] = 78,
+ [0][0][1][0][RTW89_ETSI][19] = 60,
+ [0][0][1][0][RTW89_MKK][19] = 74,
+ [0][0][1][0][RTW89_IC][19] = 78,
+ [0][0][1][0][RTW89_KCC][19] = 74,
+ [0][0][1][0][RTW89_ACMA][19] = 60,
+ [0][0][1][0][RTW89_CN][19] = 127,
+ [0][0][1][0][RTW89_UK][19] = 60,
+ [0][0][1][0][RTW89_FCC][21] = 78,
+ [0][0][1][0][RTW89_ETSI][21] = 60,
+ [0][0][1][0][RTW89_MKK][21] = 74,
+ [0][0][1][0][RTW89_IC][21] = 78,
+ [0][0][1][0][RTW89_KCC][21] = 74,
+ [0][0][1][0][RTW89_ACMA][21] = 60,
+ [0][0][1][0][RTW89_CN][21] = 127,
+ [0][0][1][0][RTW89_UK][21] = 60,
+ [0][0][1][0][RTW89_FCC][23] = 78,
+ [0][0][1][0][RTW89_ETSI][23] = 60,
+ [0][0][1][0][RTW89_MKK][23] = 74,
+ [0][0][1][0][RTW89_IC][23] = 78,
+ [0][0][1][0][RTW89_KCC][23] = 74,
+ [0][0][1][0][RTW89_ACMA][23] = 60,
+ [0][0][1][0][RTW89_CN][23] = 127,
+ [0][0][1][0][RTW89_UK][23] = 60,
+ [0][0][1][0][RTW89_FCC][25] = 78,
+ [0][0][1][0][RTW89_ETSI][25] = 60,
+ [0][0][1][0][RTW89_MKK][25] = 74,
+ [0][0][1][0][RTW89_IC][25] = 127,
+ [0][0][1][0][RTW89_KCC][25] = 74,
+ [0][0][1][0][RTW89_ACMA][25] = 127,
+ [0][0][1][0][RTW89_CN][25] = 127,
+ [0][0][1][0][RTW89_UK][25] = 60,
+ [0][0][1][0][RTW89_FCC][27] = 78,
+ [0][0][1][0][RTW89_ETSI][27] = 60,
+ [0][0][1][0][RTW89_MKK][27] = 74,
+ [0][0][1][0][RTW89_IC][27] = 127,
+ [0][0][1][0][RTW89_KCC][27] = 74,
+ [0][0][1][0][RTW89_ACMA][27] = 127,
+ [0][0][1][0][RTW89_CN][27] = 127,
+ [0][0][1][0][RTW89_UK][27] = 60,
+ [0][0][1][0][RTW89_FCC][29] = 78,
+ [0][0][1][0][RTW89_ETSI][29] = 60,
+ [0][0][1][0][RTW89_MKK][29] = 74,
+ [0][0][1][0][RTW89_IC][29] = 127,
+ [0][0][1][0][RTW89_KCC][29] = 74,
+ [0][0][1][0][RTW89_ACMA][29] = 127,
+ [0][0][1][0][RTW89_CN][29] = 127,
+ [0][0][1][0][RTW89_UK][29] = 60,
+ [0][0][1][0][RTW89_FCC][31] = 78,
+ [0][0][1][0][RTW89_ETSI][31] = 60,
+ [0][0][1][0][RTW89_MKK][31] = 74,
+ [0][0][1][0][RTW89_IC][31] = 78,
+ [0][0][1][0][RTW89_KCC][31] = 74,
+ [0][0][1][0][RTW89_ACMA][31] = 60,
+ [0][0][1][0][RTW89_CN][31] = 127,
+ [0][0][1][0][RTW89_UK][31] = 60,
+ [0][0][1][0][RTW89_FCC][33] = 78,
+ [0][0][1][0][RTW89_ETSI][33] = 60,
+ [0][0][1][0][RTW89_MKK][33] = 74,
+ [0][0][1][0][RTW89_IC][33] = 78,
+ [0][0][1][0][RTW89_KCC][33] = 74,
+ [0][0][1][0][RTW89_ACMA][33] = 60,
+ [0][0][1][0][RTW89_CN][33] = 127,
+ [0][0][1][0][RTW89_UK][33] = 60,
+ [0][0][1][0][RTW89_FCC][35] = 70,
+ [0][0][1][0][RTW89_ETSI][35] = 60,
+ [0][0][1][0][RTW89_MKK][35] = 74,
+ [0][0][1][0][RTW89_IC][35] = 70,
+ [0][0][1][0][RTW89_KCC][35] = 74,
+ [0][0][1][0][RTW89_ACMA][35] = 60,
+ [0][0][1][0][RTW89_CN][35] = 127,
+ [0][0][1][0][RTW89_UK][35] = 60,
+ [0][0][1][0][RTW89_FCC][37] = 78,
+ [0][0][1][0][RTW89_ETSI][37] = 127,
+ [0][0][1][0][RTW89_MKK][37] = 74,
+ [0][0][1][0][RTW89_IC][37] = 78,
+ [0][0][1][0][RTW89_KCC][37] = 74,
+ [0][0][1][0][RTW89_ACMA][37] = 74,
+ [0][0][1][0][RTW89_CN][37] = 127,
+ [0][0][1][0][RTW89_UK][37] = 74,
+ [0][0][1][0][RTW89_FCC][38] = 78,
+ [0][0][1][0][RTW89_ETSI][38] = 30,
+ [0][0][1][0][RTW89_MKK][38] = 127,
+ [0][0][1][0][RTW89_IC][38] = 78,
+ [0][0][1][0][RTW89_KCC][38] = 70,
+ [0][0][1][0][RTW89_ACMA][38] = 74,
+ [0][0][1][0][RTW89_CN][38] = 74,
+ [0][0][1][0][RTW89_UK][38] = 58,
+ [0][0][1][0][RTW89_FCC][40] = 78,
+ [0][0][1][0][RTW89_ETSI][40] = 30,
+ [0][0][1][0][RTW89_MKK][40] = 127,
+ [0][0][1][0][RTW89_IC][40] = 78,
+ [0][0][1][0][RTW89_KCC][40] = 74,
+ [0][0][1][0][RTW89_ACMA][40] = 74,
+ [0][0][1][0][RTW89_CN][40] = 74,
+ [0][0][1][0][RTW89_UK][40] = 58,
+ [0][0][1][0][RTW89_FCC][42] = 78,
+ [0][0][1][0][RTW89_ETSI][42] = 30,
+ [0][0][1][0][RTW89_MKK][42] = 127,
+ [0][0][1][0][RTW89_IC][42] = 78,
+ [0][0][1][0][RTW89_KCC][42] = 74,
+ [0][0][1][0][RTW89_ACMA][42] = 74,
+ [0][0][1][0][RTW89_CN][42] = 74,
+ [0][0][1][0][RTW89_UK][42] = 58,
+ [0][0][1][0][RTW89_FCC][44] = 78,
+ [0][0][1][0][RTW89_ETSI][44] = 30,
+ [0][0][1][0][RTW89_MKK][44] = 127,
+ [0][0][1][0][RTW89_IC][44] = 78,
+ [0][0][1][0][RTW89_KCC][44] = 74,
+ [0][0][1][0][RTW89_ACMA][44] = 74,
+ [0][0][1][0][RTW89_CN][44] = 74,
+ [0][0][1][0][RTW89_UK][44] = 58,
+ [0][0][1][0][RTW89_FCC][46] = 78,
+ [0][0][1][0][RTW89_ETSI][46] = 30,
+ [0][0][1][0][RTW89_MKK][46] = 127,
+ [0][0][1][0][RTW89_IC][46] = 78,
+ [0][0][1][0][RTW89_KCC][46] = 74,
+ [0][0][1][0][RTW89_ACMA][46] = 74,
+ [0][0][1][0][RTW89_CN][46] = 74,
+ [0][0][1][0][RTW89_UK][46] = 58,
+ [0][0][1][0][RTW89_FCC][48] = 72,
+ [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_KCC][48] = 127,
+ [0][0][1][0][RTW89_ACMA][48] = 127,
+ [0][0][1][0][RTW89_CN][48] = 127,
+ [0][0][1][0][RTW89_UK][48] = 127,
+ [0][0][1][0][RTW89_FCC][50] = 72,
+ [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_KCC][50] = 127,
+ [0][0][1][0][RTW89_ACMA][50] = 127,
+ [0][0][1][0][RTW89_CN][50] = 127,
+ [0][0][1][0][RTW89_UK][50] = 127,
+ [0][0][1][0][RTW89_FCC][52] = 72,
+ [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_KCC][52] = 127,
+ [0][0][1][0][RTW89_ACMA][52] = 127,
+ [0][0][1][0][RTW89_CN][52] = 127,
+ [0][0][1][0][RTW89_UK][52] = 127,
+ [0][1][1][0][RTW89_FCC][0] = 127,
+ [0][1][1][0][RTW89_ETSI][0] = 127,
+ [0][1][1][0][RTW89_MKK][0] = 127,
+ [0][1][1][0][RTW89_IC][0] = 127,
+ [0][1][1][0][RTW89_KCC][0] = 127,
+ [0][1][1][0][RTW89_ACMA][0] = 127,
+ [0][1][1][0][RTW89_CN][0] = 127,
+ [0][1][1][0][RTW89_UK][0] = 127,
+ [0][1][1][0][RTW89_FCC][2] = 127,
+ [0][1][1][0][RTW89_ETSI][2] = 127,
+ [0][1][1][0][RTW89_MKK][2] = 127,
+ [0][1][1][0][RTW89_IC][2] = 127,
+ [0][1][1][0][RTW89_KCC][2] = 127,
+ [0][1][1][0][RTW89_ACMA][2] = 127,
+ [0][1][1][0][RTW89_CN][2] = 127,
+ [0][1][1][0][RTW89_UK][2] = 127,
+ [0][1][1][0][RTW89_FCC][4] = 127,
+ [0][1][1][0][RTW89_ETSI][4] = 127,
+ [0][1][1][0][RTW89_MKK][4] = 127,
+ [0][1][1][0][RTW89_IC][4] = 127,
+ [0][1][1][0][RTW89_KCC][4] = 127,
+ [0][1][1][0][RTW89_ACMA][4] = 127,
+ [0][1][1][0][RTW89_CN][4] = 127,
+ [0][1][1][0][RTW89_UK][4] = 127,
+ [0][1][1][0][RTW89_FCC][6] = 127,
+ [0][1][1][0][RTW89_ETSI][6] = 127,
+ [0][1][1][0][RTW89_MKK][6] = 127,
+ [0][1][1][0][RTW89_IC][6] = 127,
+ [0][1][1][0][RTW89_KCC][6] = 127,
+ [0][1][1][0][RTW89_ACMA][6] = 127,
+ [0][1][1][0][RTW89_CN][6] = 127,
+ [0][1][1][0][RTW89_UK][6] = 127,
+ [0][1][1][0][RTW89_FCC][8] = 127,
+ [0][1][1][0][RTW89_ETSI][8] = 127,
+ [0][1][1][0][RTW89_MKK][8] = 127,
+ [0][1][1][0][RTW89_IC][8] = 127,
+ [0][1][1][0][RTW89_KCC][8] = 127,
+ [0][1][1][0][RTW89_ACMA][8] = 127,
+ [0][1][1][0][RTW89_CN][8] = 127,
+ [0][1][1][0][RTW89_UK][8] = 127,
+ [0][1][1][0][RTW89_FCC][10] = 127,
+ [0][1][1][0][RTW89_ETSI][10] = 127,
+ [0][1][1][0][RTW89_MKK][10] = 127,
+ [0][1][1][0][RTW89_IC][10] = 127,
+ [0][1][1][0][RTW89_KCC][10] = 127,
+ [0][1][1][0][RTW89_ACMA][10] = 127,
+ [0][1][1][0][RTW89_CN][10] = 127,
+ [0][1][1][0][RTW89_UK][10] = 127,
+ [0][1][1][0][RTW89_FCC][12] = 127,
+ [0][1][1][0][RTW89_ETSI][12] = 127,
+ [0][1][1][0][RTW89_MKK][12] = 127,
+ [0][1][1][0][RTW89_IC][12] = 127,
+ [0][1][1][0][RTW89_KCC][12] = 127,
+ [0][1][1][0][RTW89_ACMA][12] = 127,
+ [0][1][1][0][RTW89_CN][12] = 127,
+ [0][1][1][0][RTW89_UK][12] = 127,
+ [0][1][1][0][RTW89_FCC][14] = 127,
+ [0][1][1][0][RTW89_ETSI][14] = 127,
+ [0][1][1][0][RTW89_MKK][14] = 127,
+ [0][1][1][0][RTW89_IC][14] = 127,
+ [0][1][1][0][RTW89_KCC][14] = 127,
+ [0][1][1][0][RTW89_ACMA][14] = 127,
+ [0][1][1][0][RTW89_CN][14] = 127,
+ [0][1][1][0][RTW89_UK][14] = 127,
+ [0][1][1][0][RTW89_FCC][15] = 127,
+ [0][1][1][0][RTW89_ETSI][15] = 127,
+ [0][1][1][0][RTW89_MKK][15] = 127,
+ [0][1][1][0][RTW89_IC][15] = 127,
+ [0][1][1][0][RTW89_KCC][15] = 127,
+ [0][1][1][0][RTW89_ACMA][15] = 127,
+ [0][1][1][0][RTW89_CN][15] = 127,
+ [0][1][1][0][RTW89_UK][15] = 127,
+ [0][1][1][0][RTW89_FCC][17] = 127,
+ [0][1][1][0][RTW89_ETSI][17] = 127,
+ [0][1][1][0][RTW89_MKK][17] = 127,
+ [0][1][1][0][RTW89_IC][17] = 127,
+ [0][1][1][0][RTW89_KCC][17] = 127,
+ [0][1][1][0][RTW89_ACMA][17] = 127,
+ [0][1][1][0][RTW89_CN][17] = 127,
+ [0][1][1][0][RTW89_UK][17] = 127,
+ [0][1][1][0][RTW89_FCC][19] = 127,
+ [0][1][1][0][RTW89_ETSI][19] = 127,
+ [0][1][1][0][RTW89_MKK][19] = 127,
+ [0][1][1][0][RTW89_IC][19] = 127,
+ [0][1][1][0][RTW89_KCC][19] = 127,
+ [0][1][1][0][RTW89_ACMA][19] = 127,
+ [0][1][1][0][RTW89_CN][19] = 127,
+ [0][1][1][0][RTW89_UK][19] = 127,
+ [0][1][1][0][RTW89_FCC][21] = 127,
+ [0][1][1][0][RTW89_ETSI][21] = 127,
+ [0][1][1][0][RTW89_MKK][21] = 127,
+ [0][1][1][0][RTW89_IC][21] = 127,
+ [0][1][1][0][RTW89_KCC][21] = 127,
+ [0][1][1][0][RTW89_ACMA][21] = 127,
+ [0][1][1][0][RTW89_CN][21] = 127,
+ [0][1][1][0][RTW89_UK][21] = 127,
+ [0][1][1][0][RTW89_FCC][23] = 127,
+ [0][1][1][0][RTW89_ETSI][23] = 127,
+ [0][1][1][0][RTW89_MKK][23] = 127,
+ [0][1][1][0][RTW89_IC][23] = 127,
+ [0][1][1][0][RTW89_KCC][23] = 127,
+ [0][1][1][0][RTW89_ACMA][23] = 127,
+ [0][1][1][0][RTW89_CN][23] = 127,
+ [0][1][1][0][RTW89_UK][23] = 127,
+ [0][1][1][0][RTW89_FCC][25] = 127,
+ [0][1][1][0][RTW89_ETSI][25] = 127,
+ [0][1][1][0][RTW89_MKK][25] = 127,
+ [0][1][1][0][RTW89_IC][25] = 127,
+ [0][1][1][0][RTW89_KCC][25] = 127,
+ [0][1][1][0][RTW89_ACMA][25] = 127,
+ [0][1][1][0][RTW89_CN][25] = 127,
+ [0][1][1][0][RTW89_UK][25] = 127,
+ [0][1][1][0][RTW89_FCC][27] = 127,
+ [0][1][1][0][RTW89_ETSI][27] = 127,
+ [0][1][1][0][RTW89_MKK][27] = 127,
+ [0][1][1][0][RTW89_IC][27] = 127,
+ [0][1][1][0][RTW89_KCC][27] = 127,
+ [0][1][1][0][RTW89_ACMA][27] = 127,
+ [0][1][1][0][RTW89_CN][27] = 127,
+ [0][1][1][0][RTW89_UK][27] = 127,
+ [0][1][1][0][RTW89_FCC][29] = 127,
+ [0][1][1][0][RTW89_ETSI][29] = 127,
+ [0][1][1][0][RTW89_MKK][29] = 127,
+ [0][1][1][0][RTW89_IC][29] = 127,
+ [0][1][1][0][RTW89_KCC][29] = 127,
+ [0][1][1][0][RTW89_ACMA][29] = 127,
+ [0][1][1][0][RTW89_CN][29] = 127,
+ [0][1][1][0][RTW89_UK][29] = 127,
+ [0][1][1][0][RTW89_FCC][31] = 127,
+ [0][1][1][0][RTW89_ETSI][31] = 127,
+ [0][1][1][0][RTW89_MKK][31] = 127,
+ [0][1][1][0][RTW89_IC][31] = 127,
+ [0][1][1][0][RTW89_KCC][31] = 127,
+ [0][1][1][0][RTW89_ACMA][31] = 127,
+ [0][1][1][0][RTW89_CN][31] = 127,
+ [0][1][1][0][RTW89_UK][31] = 127,
+ [0][1][1][0][RTW89_FCC][33] = 127,
+ [0][1][1][0][RTW89_ETSI][33] = 127,
+ [0][1][1][0][RTW89_MKK][33] = 127,
+ [0][1][1][0][RTW89_IC][33] = 127,
+ [0][1][1][0][RTW89_KCC][33] = 127,
+ [0][1][1][0][RTW89_ACMA][33] = 127,
+ [0][1][1][0][RTW89_CN][33] = 127,
+ [0][1][1][0][RTW89_UK][33] = 127,
+ [0][1][1][0][RTW89_FCC][35] = 127,
+ [0][1][1][0][RTW89_ETSI][35] = 127,
+ [0][1][1][0][RTW89_MKK][35] = 127,
+ [0][1][1][0][RTW89_IC][35] = 127,
+ [0][1][1][0][RTW89_KCC][35] = 127,
+ [0][1][1][0][RTW89_ACMA][35] = 127,
+ [0][1][1][0][RTW89_CN][35] = 127,
+ [0][1][1][0][RTW89_UK][35] = 127,
+ [0][1][1][0][RTW89_FCC][37] = 127,
+ [0][1][1][0][RTW89_ETSI][37] = 127,
+ [0][1][1][0][RTW89_MKK][37] = 127,
+ [0][1][1][0][RTW89_IC][37] = 127,
+ [0][1][1][0][RTW89_KCC][37] = 127,
+ [0][1][1][0][RTW89_ACMA][37] = 127,
+ [0][1][1][0][RTW89_CN][37] = 127,
+ [0][1][1][0][RTW89_UK][37] = 127,
+ [0][1][1][0][RTW89_FCC][38] = 127,
+ [0][1][1][0][RTW89_ETSI][38] = 127,
+ [0][1][1][0][RTW89_MKK][38] = 127,
+ [0][1][1][0][RTW89_IC][38] = 127,
+ [0][1][1][0][RTW89_KCC][38] = 127,
+ [0][1][1][0][RTW89_ACMA][38] = 127,
+ [0][1][1][0][RTW89_CN][38] = 127,
+ [0][1][1][0][RTW89_UK][38] = 127,
+ [0][1][1][0][RTW89_FCC][40] = 127,
+ [0][1][1][0][RTW89_ETSI][40] = 127,
+ [0][1][1][0][RTW89_MKK][40] = 127,
+ [0][1][1][0][RTW89_IC][40] = 127,
+ [0][1][1][0][RTW89_KCC][40] = 127,
+ [0][1][1][0][RTW89_ACMA][40] = 127,
+ [0][1][1][0][RTW89_CN][40] = 127,
+ [0][1][1][0][RTW89_UK][40] = 127,
+ [0][1][1][0][RTW89_FCC][42] = 127,
+ [0][1][1][0][RTW89_ETSI][42] = 127,
+ [0][1][1][0][RTW89_MKK][42] = 127,
+ [0][1][1][0][RTW89_IC][42] = 127,
+ [0][1][1][0][RTW89_KCC][42] = 127,
+ [0][1][1][0][RTW89_ACMA][42] = 127,
+ [0][1][1][0][RTW89_CN][42] = 127,
+ [0][1][1][0][RTW89_UK][42] = 127,
+ [0][1][1][0][RTW89_FCC][44] = 127,
+ [0][1][1][0][RTW89_ETSI][44] = 127,
+ [0][1][1][0][RTW89_MKK][44] = 127,
+ [0][1][1][0][RTW89_IC][44] = 127,
+ [0][1][1][0][RTW89_KCC][44] = 127,
+ [0][1][1][0][RTW89_ACMA][44] = 127,
+ [0][1][1][0][RTW89_CN][44] = 127,
+ [0][1][1][0][RTW89_UK][44] = 127,
+ [0][1][1][0][RTW89_FCC][46] = 127,
+ [0][1][1][0][RTW89_ETSI][46] = 127,
+ [0][1][1][0][RTW89_MKK][46] = 127,
+ [0][1][1][0][RTW89_IC][46] = 127,
+ [0][1][1][0][RTW89_KCC][46] = 127,
+ [0][1][1][0][RTW89_ACMA][46] = 127,
+ [0][1][1][0][RTW89_CN][46] = 127,
+ [0][1][1][0][RTW89_UK][46] = 127,
+ [0][1][1][0][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][1][0][RTW89_ACMA][48] = 127,
+ [0][1][1][0][RTW89_CN][48] = 127,
+ [0][1][1][0][RTW89_UK][48] = 127,
+ [0][1][1][0][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][1][0][RTW89_ACMA][50] = 127,
+ [0][1][1][0][RTW89_CN][50] = 127,
+ [0][1][1][0][RTW89_UK][50] = 127,
+ [0][1][1][0][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][1][0][RTW89_ACMA][52] = 127,
+ [0][1][1][0][RTW89_CN][52] = 127,
+ [0][1][1][0][RTW89_UK][52] = 127,
+ [0][0][2][0][RTW89_FCC][0] = 76,
+ [0][0][2][0][RTW89_ETSI][0] = 62,
+ [0][0][2][0][RTW89_MKK][0] = 62,
+ [0][0][2][0][RTW89_IC][0] = 64,
+ [0][0][2][0][RTW89_KCC][0] = 74,
+ [0][0][2][0][RTW89_ACMA][0] = 62,
+ [0][0][2][0][RTW89_CN][0] = 62,
+ [0][0][2][0][RTW89_UK][0] = 62,
+ [0][0][2][0][RTW89_FCC][2] = 78,
+ [0][0][2][0][RTW89_ETSI][2] = 62,
+ [0][0][2][0][RTW89_MKK][2] = 62,
+ [0][0][2][0][RTW89_IC][2] = 64,
+ [0][0][2][0][RTW89_KCC][2] = 74,
+ [0][0][2][0][RTW89_ACMA][2] = 62,
+ [0][0][2][0][RTW89_CN][2] = 62,
+ [0][0][2][0][RTW89_UK][2] = 62,
+ [0][0][2][0][RTW89_FCC][4] = 78,
+ [0][0][2][0][RTW89_ETSI][4] = 62,
+ [0][0][2][0][RTW89_MKK][4] = 62,
+ [0][0][2][0][RTW89_IC][4] = 64,
+ [0][0][2][0][RTW89_KCC][4] = 74,
+ [0][0][2][0][RTW89_ACMA][4] = 62,
+ [0][0][2][0][RTW89_CN][4] = 62,
+ [0][0][2][0][RTW89_UK][4] = 62,
+ [0][0][2][0][RTW89_FCC][6] = 78,
+ [0][0][2][0][RTW89_ETSI][6] = 62,
+ [0][0][2][0][RTW89_MKK][6] = 62,
+ [0][0][2][0][RTW89_IC][6] = 64,
+ [0][0][2][0][RTW89_KCC][6] = 54,
+ [0][0][2][0][RTW89_ACMA][6] = 62,
+ [0][0][2][0][RTW89_CN][6] = 62,
+ [0][0][2][0][RTW89_UK][6] = 62,
+ [0][0][2][0][RTW89_FCC][8] = 78,
+ [0][0][2][0][RTW89_ETSI][8] = 62,
+ [0][0][2][0][RTW89_MKK][8] = 62,
+ [0][0][2][0][RTW89_IC][8] = 64,
+ [0][0][2][0][RTW89_KCC][8] = 74,
+ [0][0][2][0][RTW89_ACMA][8] = 62,
+ [0][0][2][0][RTW89_CN][8] = 62,
+ [0][0][2][0][RTW89_UK][8] = 62,
+ [0][0][2][0][RTW89_FCC][10] = 78,
+ [0][0][2][0][RTW89_ETSI][10] = 62,
+ [0][0][2][0][RTW89_MKK][10] = 62,
+ [0][0][2][0][RTW89_IC][10] = 64,
+ [0][0][2][0][RTW89_KCC][10] = 74,
+ [0][0][2][0][RTW89_ACMA][10] = 62,
+ [0][0][2][0][RTW89_CN][10] = 62,
+ [0][0][2][0][RTW89_UK][10] = 62,
+ [0][0][2][0][RTW89_FCC][12] = 78,
+ [0][0][2][0][RTW89_ETSI][12] = 62,
+ [0][0][2][0][RTW89_MKK][12] = 62,
+ [0][0][2][0][RTW89_IC][12] = 64,
+ [0][0][2][0][RTW89_KCC][12] = 74,
+ [0][0][2][0][RTW89_ACMA][12] = 62,
+ [0][0][2][0][RTW89_CN][12] = 62,
+ [0][0][2][0][RTW89_UK][12] = 62,
+ [0][0][2][0][RTW89_FCC][14] = 74,
+ [0][0][2][0][RTW89_ETSI][14] = 62,
+ [0][0][2][0][RTW89_MKK][14] = 62,
+ [0][0][2][0][RTW89_IC][14] = 64,
+ [0][0][2][0][RTW89_KCC][14] = 74,
+ [0][0][2][0][RTW89_ACMA][14] = 62,
+ [0][0][2][0][RTW89_CN][14] = 62,
+ [0][0][2][0][RTW89_UK][14] = 62,
+ [0][0][2][0][RTW89_FCC][15] = 74,
+ [0][0][2][0][RTW89_ETSI][15] = 60,
+ [0][0][2][0][RTW89_MKK][15] = 74,
+ [0][0][2][0][RTW89_IC][15] = 74,
+ [0][0][2][0][RTW89_KCC][15] = 74,
+ [0][0][2][0][RTW89_ACMA][15] = 60,
+ [0][0][2][0][RTW89_CN][15] = 127,
+ [0][0][2][0][RTW89_UK][15] = 60,
+ [0][0][2][0][RTW89_FCC][17] = 78,
+ [0][0][2][0][RTW89_ETSI][17] = 62,
+ [0][0][2][0][RTW89_MKK][17] = 74,
+ [0][0][2][0][RTW89_IC][17] = 78,
+ [0][0][2][0][RTW89_KCC][17] = 74,
+ [0][0][2][0][RTW89_ACMA][17] = 62,
+ [0][0][2][0][RTW89_CN][17] = 127,
+ [0][0][2][0][RTW89_UK][17] = 62,
+ [0][0][2][0][RTW89_FCC][19] = 78,
+ [0][0][2][0][RTW89_ETSI][19] = 62,
+ [0][0][2][0][RTW89_MKK][19] = 74,
+ [0][0][2][0][RTW89_IC][19] = 78,
+ [0][0][2][0][RTW89_KCC][19] = 74,
+ [0][0][2][0][RTW89_ACMA][19] = 62,
+ [0][0][2][0][RTW89_CN][19] = 127,
+ [0][0][2][0][RTW89_UK][19] = 62,
+ [0][0][2][0][RTW89_FCC][21] = 78,
+ [0][0][2][0][RTW89_ETSI][21] = 62,
+ [0][0][2][0][RTW89_MKK][21] = 74,
+ [0][0][2][0][RTW89_IC][21] = 78,
+ [0][0][2][0][RTW89_KCC][21] = 74,
+ [0][0][2][0][RTW89_ACMA][21] = 62,
+ [0][0][2][0][RTW89_CN][21] = 127,
+ [0][0][2][0][RTW89_UK][21] = 62,
+ [0][0][2][0][RTW89_FCC][23] = 78,
+ [0][0][2][0][RTW89_ETSI][23] = 62,
+ [0][0][2][0][RTW89_MKK][23] = 74,
+ [0][0][2][0][RTW89_IC][23] = 78,
+ [0][0][2][0][RTW89_KCC][23] = 74,
+ [0][0][2][0][RTW89_ACMA][23] = 62,
+ [0][0][2][0][RTW89_CN][23] = 127,
+ [0][0][2][0][RTW89_UK][23] = 62,
+ [0][0][2][0][RTW89_FCC][25] = 78,
+ [0][0][2][0][RTW89_ETSI][25] = 62,
+ [0][0][2][0][RTW89_MKK][25] = 74,
+ [0][0][2][0][RTW89_IC][25] = 127,
+ [0][0][2][0][RTW89_KCC][25] = 74,
+ [0][0][2][0][RTW89_ACMA][25] = 127,
+ [0][0][2][0][RTW89_CN][25] = 127,
+ [0][0][2][0][RTW89_UK][25] = 62,
+ [0][0][2][0][RTW89_FCC][27] = 78,
+ [0][0][2][0][RTW89_ETSI][27] = 62,
+ [0][0][2][0][RTW89_MKK][27] = 74,
+ [0][0][2][0][RTW89_IC][27] = 127,
+ [0][0][2][0][RTW89_KCC][27] = 74,
+ [0][0][2][0][RTW89_ACMA][27] = 127,
+ [0][0][2][0][RTW89_CN][27] = 127,
+ [0][0][2][0][RTW89_UK][27] = 62,
+ [0][0][2][0][RTW89_FCC][29] = 78,
+ [0][0][2][0][RTW89_ETSI][29] = 62,
+ [0][0][2][0][RTW89_MKK][29] = 74,
+ [0][0][2][0][RTW89_IC][29] = 127,
+ [0][0][2][0][RTW89_KCC][29] = 74,
+ [0][0][2][0][RTW89_ACMA][29] = 127,
+ [0][0][2][0][RTW89_CN][29] = 127,
+ [0][0][2][0][RTW89_UK][29] = 62,
+ [0][0][2][0][RTW89_FCC][31] = 78,
+ [0][0][2][0][RTW89_ETSI][31] = 62,
+ [0][0][2][0][RTW89_MKK][31] = 74,
+ [0][0][2][0][RTW89_IC][31] = 78,
+ [0][0][2][0][RTW89_KCC][31] = 74,
+ [0][0][2][0][RTW89_ACMA][31] = 62,
+ [0][0][2][0][RTW89_CN][31] = 127,
+ [0][0][2][0][RTW89_UK][31] = 62,
+ [0][0][2][0][RTW89_FCC][33] = 78,
+ [0][0][2][0][RTW89_ETSI][33] = 62,
+ [0][0][2][0][RTW89_MKK][33] = 74,
+ [0][0][2][0][RTW89_IC][33] = 78,
+ [0][0][2][0][RTW89_KCC][33] = 74,
+ [0][0][2][0][RTW89_ACMA][33] = 62,
+ [0][0][2][0][RTW89_CN][33] = 127,
+ [0][0][2][0][RTW89_UK][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] = 74,
+ [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_KCC][35] = 74,
+ [0][0][2][0][RTW89_ACMA][35] = 62,
+ [0][0][2][0][RTW89_CN][35] = 127,
+ [0][0][2][0][RTW89_UK][35] = 62,
+ [0][0][2][0][RTW89_FCC][37] = 78,
+ [0][0][2][0][RTW89_ETSI][37] = 127,
+ [0][0][2][0][RTW89_MKK][37] = 74,
+ [0][0][2][0][RTW89_IC][37] = 78,
+ [0][0][2][0][RTW89_KCC][37] = 74,
+ [0][0][2][0][RTW89_ACMA][37] = 74,
+ [0][0][2][0][RTW89_CN][37] = 127,
+ [0][0][2][0][RTW89_UK][37] = 74,
+ [0][0][2][0][RTW89_FCC][38] = 78,
+ [0][0][2][0][RTW89_ETSI][38] = 30,
+ [0][0][2][0][RTW89_MKK][38] = 127,
+ [0][0][2][0][RTW89_IC][38] = 78,
+ [0][0][2][0][RTW89_KCC][38] = 66,
+ [0][0][2][0][RTW89_ACMA][38] = 74,
+ [0][0][2][0][RTW89_CN][38] = 74,
+ [0][0][2][0][RTW89_UK][38] = 60,
+ [0][0][2][0][RTW89_FCC][40] = 78,
+ [0][0][2][0][RTW89_ETSI][40] = 30,
+ [0][0][2][0][RTW89_MKK][40] = 127,
+ [0][0][2][0][RTW89_IC][40] = 78,
+ [0][0][2][0][RTW89_KCC][40] = 74,
+ [0][0][2][0][RTW89_ACMA][40] = 74,
+ [0][0][2][0][RTW89_CN][40] = 74,
+ [0][0][2][0][RTW89_UK][40] = 60,
+ [0][0][2][0][RTW89_FCC][42] = 78,
+ [0][0][2][0][RTW89_ETSI][42] = 30,
+ [0][0][2][0][RTW89_MKK][42] = 127,
+ [0][0][2][0][RTW89_IC][42] = 78,
+ [0][0][2][0][RTW89_KCC][42] = 74,
+ [0][0][2][0][RTW89_ACMA][42] = 74,
+ [0][0][2][0][RTW89_CN][42] = 74,
+ [0][0][2][0][RTW89_UK][42] = 60,
+ [0][0][2][0][RTW89_FCC][44] = 78,
+ [0][0][2][0][RTW89_ETSI][44] = 30,
+ [0][0][2][0][RTW89_MKK][44] = 127,
+ [0][0][2][0][RTW89_IC][44] = 78,
+ [0][0][2][0][RTW89_KCC][44] = 74,
+ [0][0][2][0][RTW89_ACMA][44] = 74,
+ [0][0][2][0][RTW89_CN][44] = 74,
+ [0][0][2][0][RTW89_UK][44] = 60,
+ [0][0][2][0][RTW89_FCC][46] = 78,
+ [0][0][2][0][RTW89_ETSI][46] = 30,
+ [0][0][2][0][RTW89_MKK][46] = 127,
+ [0][0][2][0][RTW89_IC][46] = 78,
+ [0][0][2][0][RTW89_KCC][46] = 74,
+ [0][0][2][0][RTW89_ACMA][46] = 74,
+ [0][0][2][0][RTW89_CN][46] = 74,
+ [0][0][2][0][RTW89_UK][46] = 60,
+ [0][0][2][0][RTW89_FCC][48] = 74,
+ [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_KCC][48] = 127,
+ [0][0][2][0][RTW89_ACMA][48] = 127,
+ [0][0][2][0][RTW89_CN][48] = 127,
+ [0][0][2][0][RTW89_UK][48] = 127,
+ [0][0][2][0][RTW89_FCC][50] = 74,
+ [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_KCC][50] = 127,
+ [0][0][2][0][RTW89_ACMA][50] = 127,
+ [0][0][2][0][RTW89_CN][50] = 127,
+ [0][0][2][0][RTW89_UK][50] = 127,
+ [0][0][2][0][RTW89_FCC][52] = 74,
+ [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_KCC][52] = 127,
+ [0][0][2][0][RTW89_ACMA][52] = 127,
+ [0][0][2][0][RTW89_CN][52] = 127,
+ [0][0][2][0][RTW89_UK][52] = 127,
+ [0][1][2][0][RTW89_FCC][0] = 127,
+ [0][1][2][0][RTW89_ETSI][0] = 127,
+ [0][1][2][0][RTW89_MKK][0] = 127,
+ [0][1][2][0][RTW89_IC][0] = 127,
+ [0][1][2][0][RTW89_KCC][0] = 127,
+ [0][1][2][0][RTW89_ACMA][0] = 127,
+ [0][1][2][0][RTW89_CN][0] = 127,
+ [0][1][2][0][RTW89_UK][0] = 127,
+ [0][1][2][0][RTW89_FCC][2] = 127,
+ [0][1][2][0][RTW89_ETSI][2] = 127,
+ [0][1][2][0][RTW89_MKK][2] = 127,
+ [0][1][2][0][RTW89_IC][2] = 127,
+ [0][1][2][0][RTW89_KCC][2] = 127,
+ [0][1][2][0][RTW89_ACMA][2] = 127,
+ [0][1][2][0][RTW89_CN][2] = 127,
+ [0][1][2][0][RTW89_UK][2] = 127,
+ [0][1][2][0][RTW89_FCC][4] = 127,
+ [0][1][2][0][RTW89_ETSI][4] = 127,
+ [0][1][2][0][RTW89_MKK][4] = 127,
+ [0][1][2][0][RTW89_IC][4] = 127,
+ [0][1][2][0][RTW89_KCC][4] = 127,
+ [0][1][2][0][RTW89_ACMA][4] = 127,
+ [0][1][2][0][RTW89_CN][4] = 127,
+ [0][1][2][0][RTW89_UK][4] = 127,
+ [0][1][2][0][RTW89_FCC][6] = 127,
+ [0][1][2][0][RTW89_ETSI][6] = 127,
+ [0][1][2][0][RTW89_MKK][6] = 127,
+ [0][1][2][0][RTW89_IC][6] = 127,
+ [0][1][2][0][RTW89_KCC][6] = 127,
+ [0][1][2][0][RTW89_ACMA][6] = 127,
+ [0][1][2][0][RTW89_CN][6] = 127,
+ [0][1][2][0][RTW89_UK][6] = 127,
+ [0][1][2][0][RTW89_FCC][8] = 127,
+ [0][1][2][0][RTW89_ETSI][8] = 127,
+ [0][1][2][0][RTW89_MKK][8] = 127,
+ [0][1][2][0][RTW89_IC][8] = 127,
+ [0][1][2][0][RTW89_KCC][8] = 127,
+ [0][1][2][0][RTW89_ACMA][8] = 127,
+ [0][1][2][0][RTW89_CN][8] = 127,
+ [0][1][2][0][RTW89_UK][8] = 127,
+ [0][1][2][0][RTW89_FCC][10] = 127,
+ [0][1][2][0][RTW89_ETSI][10] = 127,
+ [0][1][2][0][RTW89_MKK][10] = 127,
+ [0][1][2][0][RTW89_IC][10] = 127,
+ [0][1][2][0][RTW89_KCC][10] = 127,
+ [0][1][2][0][RTW89_ACMA][10] = 127,
+ [0][1][2][0][RTW89_CN][10] = 127,
+ [0][1][2][0][RTW89_UK][10] = 127,
+ [0][1][2][0][RTW89_FCC][12] = 127,
+ [0][1][2][0][RTW89_ETSI][12] = 127,
+ [0][1][2][0][RTW89_MKK][12] = 127,
+ [0][1][2][0][RTW89_IC][12] = 127,
+ [0][1][2][0][RTW89_KCC][12] = 127,
+ [0][1][2][0][RTW89_ACMA][12] = 127,
+ [0][1][2][0][RTW89_CN][12] = 127,
+ [0][1][2][0][RTW89_UK][12] = 127,
+ [0][1][2][0][RTW89_FCC][14] = 127,
+ [0][1][2][0][RTW89_ETSI][14] = 127,
+ [0][1][2][0][RTW89_MKK][14] = 127,
+ [0][1][2][0][RTW89_IC][14] = 127,
+ [0][1][2][0][RTW89_KCC][14] = 127,
+ [0][1][2][0][RTW89_ACMA][14] = 127,
+ [0][1][2][0][RTW89_CN][14] = 127,
+ [0][1][2][0][RTW89_UK][14] = 127,
+ [0][1][2][0][RTW89_FCC][15] = 127,
+ [0][1][2][0][RTW89_ETSI][15] = 127,
+ [0][1][2][0][RTW89_MKK][15] = 127,
+ [0][1][2][0][RTW89_IC][15] = 127,
+ [0][1][2][0][RTW89_KCC][15] = 127,
+ [0][1][2][0][RTW89_ACMA][15] = 127,
+ [0][1][2][0][RTW89_CN][15] = 127,
+ [0][1][2][0][RTW89_UK][15] = 127,
+ [0][1][2][0][RTW89_FCC][17] = 127,
+ [0][1][2][0][RTW89_ETSI][17] = 127,
+ [0][1][2][0][RTW89_MKK][17] = 127,
+ [0][1][2][0][RTW89_IC][17] = 127,
+ [0][1][2][0][RTW89_KCC][17] = 127,
+ [0][1][2][0][RTW89_ACMA][17] = 127,
+ [0][1][2][0][RTW89_CN][17] = 127,
+ [0][1][2][0][RTW89_UK][17] = 127,
+ [0][1][2][0][RTW89_FCC][19] = 127,
+ [0][1][2][0][RTW89_ETSI][19] = 127,
+ [0][1][2][0][RTW89_MKK][19] = 127,
+ [0][1][2][0][RTW89_IC][19] = 127,
+ [0][1][2][0][RTW89_KCC][19] = 127,
+ [0][1][2][0][RTW89_ACMA][19] = 127,
+ [0][1][2][0][RTW89_CN][19] = 127,
+ [0][1][2][0][RTW89_UK][19] = 127,
+ [0][1][2][0][RTW89_FCC][21] = 127,
+ [0][1][2][0][RTW89_ETSI][21] = 127,
+ [0][1][2][0][RTW89_MKK][21] = 127,
+ [0][1][2][0][RTW89_IC][21] = 127,
+ [0][1][2][0][RTW89_KCC][21] = 127,
+ [0][1][2][0][RTW89_ACMA][21] = 127,
+ [0][1][2][0][RTW89_CN][21] = 127,
+ [0][1][2][0][RTW89_UK][21] = 127,
+ [0][1][2][0][RTW89_FCC][23] = 127,
+ [0][1][2][0][RTW89_ETSI][23] = 127,
+ [0][1][2][0][RTW89_MKK][23] = 127,
+ [0][1][2][0][RTW89_IC][23] = 127,
+ [0][1][2][0][RTW89_KCC][23] = 127,
+ [0][1][2][0][RTW89_ACMA][23] = 127,
+ [0][1][2][0][RTW89_CN][23] = 127,
+ [0][1][2][0][RTW89_UK][23] = 127,
+ [0][1][2][0][RTW89_FCC][25] = 127,
+ [0][1][2][0][RTW89_ETSI][25] = 127,
+ [0][1][2][0][RTW89_MKK][25] = 127,
+ [0][1][2][0][RTW89_IC][25] = 127,
+ [0][1][2][0][RTW89_KCC][25] = 127,
+ [0][1][2][0][RTW89_ACMA][25] = 127,
+ [0][1][2][0][RTW89_CN][25] = 127,
+ [0][1][2][0][RTW89_UK][25] = 127,
+ [0][1][2][0][RTW89_FCC][27] = 127,
+ [0][1][2][0][RTW89_ETSI][27] = 127,
+ [0][1][2][0][RTW89_MKK][27] = 127,
+ [0][1][2][0][RTW89_IC][27] = 127,
+ [0][1][2][0][RTW89_KCC][27] = 127,
+ [0][1][2][0][RTW89_ACMA][27] = 127,
+ [0][1][2][0][RTW89_CN][27] = 127,
+ [0][1][2][0][RTW89_UK][27] = 127,
+ [0][1][2][0][RTW89_FCC][29] = 127,
+ [0][1][2][0][RTW89_ETSI][29] = 127,
+ [0][1][2][0][RTW89_MKK][29] = 127,
+ [0][1][2][0][RTW89_IC][29] = 127,
+ [0][1][2][0][RTW89_KCC][29] = 127,
+ [0][1][2][0][RTW89_ACMA][29] = 127,
+ [0][1][2][0][RTW89_CN][29] = 127,
+ [0][1][2][0][RTW89_UK][29] = 127,
+ [0][1][2][0][RTW89_FCC][31] = 127,
+ [0][1][2][0][RTW89_ETSI][31] = 127,
+ [0][1][2][0][RTW89_MKK][31] = 127,
+ [0][1][2][0][RTW89_IC][31] = 127,
+ [0][1][2][0][RTW89_KCC][31] = 127,
+ [0][1][2][0][RTW89_ACMA][31] = 127,
+ [0][1][2][0][RTW89_CN][31] = 127,
+ [0][1][2][0][RTW89_UK][31] = 127,
+ [0][1][2][0][RTW89_FCC][33] = 127,
+ [0][1][2][0][RTW89_ETSI][33] = 127,
+ [0][1][2][0][RTW89_MKK][33] = 127,
+ [0][1][2][0][RTW89_IC][33] = 127,
+ [0][1][2][0][RTW89_KCC][33] = 127,
+ [0][1][2][0][RTW89_ACMA][33] = 127,
+ [0][1][2][0][RTW89_CN][33] = 127,
+ [0][1][2][0][RTW89_UK][33] = 127,
+ [0][1][2][0][RTW89_FCC][35] = 127,
+ [0][1][2][0][RTW89_ETSI][35] = 127,
+ [0][1][2][0][RTW89_MKK][35] = 127,
+ [0][1][2][0][RTW89_IC][35] = 127,
+ [0][1][2][0][RTW89_KCC][35] = 127,
+ [0][1][2][0][RTW89_ACMA][35] = 127,
+ [0][1][2][0][RTW89_CN][35] = 127,
+ [0][1][2][0][RTW89_UK][35] = 127,
+ [0][1][2][0][RTW89_FCC][37] = 127,
+ [0][1][2][0][RTW89_ETSI][37] = 127,
+ [0][1][2][0][RTW89_MKK][37] = 127,
+ [0][1][2][0][RTW89_IC][37] = 127,
+ [0][1][2][0][RTW89_KCC][37] = 127,
+ [0][1][2][0][RTW89_ACMA][37] = 127,
+ [0][1][2][0][RTW89_CN][37] = 127,
+ [0][1][2][0][RTW89_UK][37] = 127,
+ [0][1][2][0][RTW89_FCC][38] = 127,
+ [0][1][2][0][RTW89_ETSI][38] = 127,
+ [0][1][2][0][RTW89_MKK][38] = 127,
+ [0][1][2][0][RTW89_IC][38] = 127,
+ [0][1][2][0][RTW89_KCC][38] = 127,
+ [0][1][2][0][RTW89_ACMA][38] = 127,
+ [0][1][2][0][RTW89_CN][38] = 127,
+ [0][1][2][0][RTW89_UK][38] = 127,
+ [0][1][2][0][RTW89_FCC][40] = 127,
+ [0][1][2][0][RTW89_ETSI][40] = 127,
+ [0][1][2][0][RTW89_MKK][40] = 127,
+ [0][1][2][0][RTW89_IC][40] = 127,
+ [0][1][2][0][RTW89_KCC][40] = 127,
+ [0][1][2][0][RTW89_ACMA][40] = 127,
+ [0][1][2][0][RTW89_CN][40] = 127,
+ [0][1][2][0][RTW89_UK][40] = 127,
+ [0][1][2][0][RTW89_FCC][42] = 127,
+ [0][1][2][0][RTW89_ETSI][42] = 127,
+ [0][1][2][0][RTW89_MKK][42] = 127,
+ [0][1][2][0][RTW89_IC][42] = 127,
+ [0][1][2][0][RTW89_KCC][42] = 127,
+ [0][1][2][0][RTW89_ACMA][42] = 127,
+ [0][1][2][0][RTW89_CN][42] = 127,
+ [0][1][2][0][RTW89_UK][42] = 127,
+ [0][1][2][0][RTW89_FCC][44] = 127,
+ [0][1][2][0][RTW89_ETSI][44] = 127,
+ [0][1][2][0][RTW89_MKK][44] = 127,
+ [0][1][2][0][RTW89_IC][44] = 127,
+ [0][1][2][0][RTW89_KCC][44] = 127,
+ [0][1][2][0][RTW89_ACMA][44] = 127,
+ [0][1][2][0][RTW89_CN][44] = 127,
+ [0][1][2][0][RTW89_UK][44] = 127,
+ [0][1][2][0][RTW89_FCC][46] = 127,
+ [0][1][2][0][RTW89_ETSI][46] = 127,
+ [0][1][2][0][RTW89_MKK][46] = 127,
+ [0][1][2][0][RTW89_IC][46] = 127,
+ [0][1][2][0][RTW89_KCC][46] = 127,
+ [0][1][2][0][RTW89_ACMA][46] = 127,
+ [0][1][2][0][RTW89_CN][46] = 127,
+ [0][1][2][0][RTW89_UK][46] = 127,
+ [0][1][2][0][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][2][0][RTW89_ACMA][48] = 127,
+ [0][1][2][0][RTW89_CN][48] = 127,
+ [0][1][2][0][RTW89_UK][48] = 127,
+ [0][1][2][0][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][2][0][RTW89_ACMA][50] = 127,
+ [0][1][2][0][RTW89_CN][50] = 127,
+ [0][1][2][0][RTW89_UK][50] = 127,
+ [0][1][2][0][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][2][0][RTW89_ACMA][52] = 127,
+ [0][1][2][0][RTW89_CN][52] = 127,
+ [0][1][2][0][RTW89_UK][52] = 127,
+ [0][1][2][1][RTW89_FCC][0] = 127,
+ [0][1][2][1][RTW89_ETSI][0] = 127,
+ [0][1][2][1][RTW89_MKK][0] = 127,
+ [0][1][2][1][RTW89_IC][0] = 127,
+ [0][1][2][1][RTW89_KCC][0] = 127,
+ [0][1][2][1][RTW89_ACMA][0] = 127,
+ [0][1][2][1][RTW89_CN][0] = 127,
+ [0][1][2][1][RTW89_UK][0] = 127,
+ [0][1][2][1][RTW89_FCC][2] = 127,
+ [0][1][2][1][RTW89_ETSI][2] = 127,
+ [0][1][2][1][RTW89_MKK][2] = 127,
+ [0][1][2][1][RTW89_IC][2] = 127,
+ [0][1][2][1][RTW89_KCC][2] = 127,
+ [0][1][2][1][RTW89_ACMA][2] = 127,
+ [0][1][2][1][RTW89_CN][2] = 127,
+ [0][1][2][1][RTW89_UK][2] = 127,
+ [0][1][2][1][RTW89_FCC][4] = 127,
+ [0][1][2][1][RTW89_ETSI][4] = 127,
+ [0][1][2][1][RTW89_MKK][4] = 127,
+ [0][1][2][1][RTW89_IC][4] = 127,
+ [0][1][2][1][RTW89_KCC][4] = 127,
+ [0][1][2][1][RTW89_ACMA][4] = 127,
+ [0][1][2][1][RTW89_CN][4] = 127,
+ [0][1][2][1][RTW89_UK][4] = 127,
+ [0][1][2][1][RTW89_FCC][6] = 127,
+ [0][1][2][1][RTW89_ETSI][6] = 127,
+ [0][1][2][1][RTW89_MKK][6] = 127,
+ [0][1][2][1][RTW89_IC][6] = 127,
+ [0][1][2][1][RTW89_KCC][6] = 127,
+ [0][1][2][1][RTW89_ACMA][6] = 127,
+ [0][1][2][1][RTW89_CN][6] = 127,
+ [0][1][2][1][RTW89_UK][6] = 127,
+ [0][1][2][1][RTW89_FCC][8] = 127,
+ [0][1][2][1][RTW89_ETSI][8] = 127,
+ [0][1][2][1][RTW89_MKK][8] = 127,
+ [0][1][2][1][RTW89_IC][8] = 127,
+ [0][1][2][1][RTW89_KCC][8] = 127,
+ [0][1][2][1][RTW89_ACMA][8] = 127,
+ [0][1][2][1][RTW89_CN][8] = 127,
+ [0][1][2][1][RTW89_UK][8] = 127,
+ [0][1][2][1][RTW89_FCC][10] = 127,
+ [0][1][2][1][RTW89_ETSI][10] = 127,
+ [0][1][2][1][RTW89_MKK][10] = 127,
+ [0][1][2][1][RTW89_IC][10] = 127,
+ [0][1][2][1][RTW89_KCC][10] = 127,
+ [0][1][2][1][RTW89_ACMA][10] = 127,
+ [0][1][2][1][RTW89_CN][10] = 127,
+ [0][1][2][1][RTW89_UK][10] = 127,
+ [0][1][2][1][RTW89_FCC][12] = 127,
+ [0][1][2][1][RTW89_ETSI][12] = 127,
+ [0][1][2][1][RTW89_MKK][12] = 127,
+ [0][1][2][1][RTW89_IC][12] = 127,
+ [0][1][2][1][RTW89_KCC][12] = 127,
+ [0][1][2][1][RTW89_ACMA][12] = 127,
+ [0][1][2][1][RTW89_CN][12] = 127,
+ [0][1][2][1][RTW89_UK][12] = 127,
+ [0][1][2][1][RTW89_FCC][14] = 127,
+ [0][1][2][1][RTW89_ETSI][14] = 127,
+ [0][1][2][1][RTW89_MKK][14] = 127,
+ [0][1][2][1][RTW89_IC][14] = 127,
+ [0][1][2][1][RTW89_KCC][14] = 127,
+ [0][1][2][1][RTW89_ACMA][14] = 127,
+ [0][1][2][1][RTW89_CN][14] = 127,
+ [0][1][2][1][RTW89_UK][14] = 127,
+ [0][1][2][1][RTW89_FCC][15] = 127,
+ [0][1][2][1][RTW89_ETSI][15] = 127,
+ [0][1][2][1][RTW89_MKK][15] = 127,
+ [0][1][2][1][RTW89_IC][15] = 127,
+ [0][1][2][1][RTW89_KCC][15] = 127,
+ [0][1][2][1][RTW89_ACMA][15] = 127,
+ [0][1][2][1][RTW89_CN][15] = 127,
+ [0][1][2][1][RTW89_UK][15] = 127,
+ [0][1][2][1][RTW89_FCC][17] = 127,
+ [0][1][2][1][RTW89_ETSI][17] = 127,
+ [0][1][2][1][RTW89_MKK][17] = 127,
+ [0][1][2][1][RTW89_IC][17] = 127,
+ [0][1][2][1][RTW89_KCC][17] = 127,
+ [0][1][2][1][RTW89_ACMA][17] = 127,
+ [0][1][2][1][RTW89_CN][17] = 127,
+ [0][1][2][1][RTW89_UK][17] = 127,
+ [0][1][2][1][RTW89_FCC][19] = 127,
+ [0][1][2][1][RTW89_ETSI][19] = 127,
+ [0][1][2][1][RTW89_MKK][19] = 127,
+ [0][1][2][1][RTW89_IC][19] = 127,
+ [0][1][2][1][RTW89_KCC][19] = 127,
+ [0][1][2][1][RTW89_ACMA][19] = 127,
+ [0][1][2][1][RTW89_CN][19] = 127,
+ [0][1][2][1][RTW89_UK][19] = 127,
+ [0][1][2][1][RTW89_FCC][21] = 127,
+ [0][1][2][1][RTW89_ETSI][21] = 127,
+ [0][1][2][1][RTW89_MKK][21] = 127,
+ [0][1][2][1][RTW89_IC][21] = 127,
+ [0][1][2][1][RTW89_KCC][21] = 127,
+ [0][1][2][1][RTW89_ACMA][21] = 127,
+ [0][1][2][1][RTW89_CN][21] = 127,
+ [0][1][2][1][RTW89_UK][21] = 127,
+ [0][1][2][1][RTW89_FCC][23] = 127,
+ [0][1][2][1][RTW89_ETSI][23] = 127,
+ [0][1][2][1][RTW89_MKK][23] = 127,
+ [0][1][2][1][RTW89_IC][23] = 127,
+ [0][1][2][1][RTW89_KCC][23] = 127,
+ [0][1][2][1][RTW89_ACMA][23] = 127,
+ [0][1][2][1][RTW89_CN][23] = 127,
+ [0][1][2][1][RTW89_UK][23] = 127,
+ [0][1][2][1][RTW89_FCC][25] = 127,
+ [0][1][2][1][RTW89_ETSI][25] = 127,
+ [0][1][2][1][RTW89_MKK][25] = 127,
+ [0][1][2][1][RTW89_IC][25] = 127,
+ [0][1][2][1][RTW89_KCC][25] = 127,
+ [0][1][2][1][RTW89_ACMA][25] = 127,
+ [0][1][2][1][RTW89_CN][25] = 127,
+ [0][1][2][1][RTW89_UK][25] = 127,
+ [0][1][2][1][RTW89_FCC][27] = 127,
+ [0][1][2][1][RTW89_ETSI][27] = 127,
+ [0][1][2][1][RTW89_MKK][27] = 127,
+ [0][1][2][1][RTW89_IC][27] = 127,
+ [0][1][2][1][RTW89_KCC][27] = 127,
+ [0][1][2][1][RTW89_ACMA][27] = 127,
+ [0][1][2][1][RTW89_CN][27] = 127,
+ [0][1][2][1][RTW89_UK][27] = 127,
+ [0][1][2][1][RTW89_FCC][29] = 127,
+ [0][1][2][1][RTW89_ETSI][29] = 127,
+ [0][1][2][1][RTW89_MKK][29] = 127,
+ [0][1][2][1][RTW89_IC][29] = 127,
+ [0][1][2][1][RTW89_KCC][29] = 127,
+ [0][1][2][1][RTW89_ACMA][29] = 127,
+ [0][1][2][1][RTW89_CN][29] = 127,
+ [0][1][2][1][RTW89_UK][29] = 127,
+ [0][1][2][1][RTW89_FCC][31] = 127,
+ [0][1][2][1][RTW89_ETSI][31] = 127,
+ [0][1][2][1][RTW89_MKK][31] = 127,
+ [0][1][2][1][RTW89_IC][31] = 127,
+ [0][1][2][1][RTW89_KCC][31] = 127,
+ [0][1][2][1][RTW89_ACMA][31] = 127,
+ [0][1][2][1][RTW89_CN][31] = 127,
+ [0][1][2][1][RTW89_UK][31] = 127,
+ [0][1][2][1][RTW89_FCC][33] = 127,
+ [0][1][2][1][RTW89_ETSI][33] = 127,
+ [0][1][2][1][RTW89_MKK][33] = 127,
+ [0][1][2][1][RTW89_IC][33] = 127,
+ [0][1][2][1][RTW89_KCC][33] = 127,
+ [0][1][2][1][RTW89_ACMA][33] = 127,
+ [0][1][2][1][RTW89_CN][33] = 127,
+ [0][1][2][1][RTW89_UK][33] = 127,
+ [0][1][2][1][RTW89_FCC][35] = 127,
+ [0][1][2][1][RTW89_ETSI][35] = 127,
+ [0][1][2][1][RTW89_MKK][35] = 127,
+ [0][1][2][1][RTW89_IC][35] = 127,
+ [0][1][2][1][RTW89_KCC][35] = 127,
+ [0][1][2][1][RTW89_ACMA][35] = 127,
+ [0][1][2][1][RTW89_CN][35] = 127,
+ [0][1][2][1][RTW89_UK][35] = 127,
+ [0][1][2][1][RTW89_FCC][37] = 127,
+ [0][1][2][1][RTW89_ETSI][37] = 127,
+ [0][1][2][1][RTW89_MKK][37] = 127,
+ [0][1][2][1][RTW89_IC][37] = 127,
+ [0][1][2][1][RTW89_KCC][37] = 127,
+ [0][1][2][1][RTW89_ACMA][37] = 127,
+ [0][1][2][1][RTW89_CN][37] = 127,
+ [0][1][2][1][RTW89_UK][37] = 127,
+ [0][1][2][1][RTW89_FCC][38] = 127,
+ [0][1][2][1][RTW89_ETSI][38] = 127,
+ [0][1][2][1][RTW89_MKK][38] = 127,
+ [0][1][2][1][RTW89_IC][38] = 127,
+ [0][1][2][1][RTW89_KCC][38] = 127,
+ [0][1][2][1][RTW89_ACMA][38] = 127,
+ [0][1][2][1][RTW89_CN][38] = 127,
+ [0][1][2][1][RTW89_UK][38] = 127,
+ [0][1][2][1][RTW89_FCC][40] = 127,
+ [0][1][2][1][RTW89_ETSI][40] = 127,
+ [0][1][2][1][RTW89_MKK][40] = 127,
+ [0][1][2][1][RTW89_IC][40] = 127,
+ [0][1][2][1][RTW89_KCC][40] = 127,
+ [0][1][2][1][RTW89_ACMA][40] = 127,
+ [0][1][2][1][RTW89_CN][40] = 127,
+ [0][1][2][1][RTW89_UK][40] = 127,
+ [0][1][2][1][RTW89_FCC][42] = 127,
+ [0][1][2][1][RTW89_ETSI][42] = 127,
+ [0][1][2][1][RTW89_MKK][42] = 127,
+ [0][1][2][1][RTW89_IC][42] = 127,
+ [0][1][2][1][RTW89_KCC][42] = 127,
+ [0][1][2][1][RTW89_ACMA][42] = 127,
+ [0][1][2][1][RTW89_CN][42] = 127,
+ [0][1][2][1][RTW89_UK][42] = 127,
+ [0][1][2][1][RTW89_FCC][44] = 127,
+ [0][1][2][1][RTW89_ETSI][44] = 127,
+ [0][1][2][1][RTW89_MKK][44] = 127,
+ [0][1][2][1][RTW89_IC][44] = 127,
+ [0][1][2][1][RTW89_KCC][44] = 127,
+ [0][1][2][1][RTW89_ACMA][44] = 127,
+ [0][1][2][1][RTW89_CN][44] = 127,
+ [0][1][2][1][RTW89_UK][44] = 127,
+ [0][1][2][1][RTW89_FCC][46] = 127,
+ [0][1][2][1][RTW89_ETSI][46] = 127,
+ [0][1][2][1][RTW89_MKK][46] = 127,
+ [0][1][2][1][RTW89_IC][46] = 127,
+ [0][1][2][1][RTW89_KCC][46] = 127,
+ [0][1][2][1][RTW89_ACMA][46] = 127,
+ [0][1][2][1][RTW89_CN][46] = 127,
+ [0][1][2][1][RTW89_UK][46] = 127,
+ [0][1][2][1][RTW89_FCC][48] = 127,
+ [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_KCC][48] = 127,
+ [0][1][2][1][RTW89_ACMA][48] = 127,
+ [0][1][2][1][RTW89_CN][48] = 127,
+ [0][1][2][1][RTW89_UK][48] = 127,
+ [0][1][2][1][RTW89_FCC][50] = 127,
+ [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_KCC][50] = 127,
+ [0][1][2][1][RTW89_ACMA][50] = 127,
+ [0][1][2][1][RTW89_CN][50] = 127,
+ [0][1][2][1][RTW89_UK][50] = 127,
+ [0][1][2][1][RTW89_FCC][52] = 127,
+ [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_KCC][52] = 127,
+ [0][1][2][1][RTW89_ACMA][52] = 127,
+ [0][1][2][1][RTW89_CN][52] = 127,
+ [0][1][2][1][RTW89_UK][52] = 127,
+ [1][0][2][0][RTW89_FCC][1] = 66,
+ [1][0][2][0][RTW89_ETSI][1] = 64,
+ [1][0][2][0][RTW89_MKK][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_KCC][1] = 74,
+ [1][0][2][0][RTW89_ACMA][1] = 64,
+ [1][0][2][0][RTW89_CN][1] = 64,
+ [1][0][2][0][RTW89_UK][1] = 64,
+ [1][0][2][0][RTW89_FCC][5] = 80,
+ [1][0][2][0][RTW89_ETSI][5] = 64,
+ [1][0][2][0][RTW89_MKK][5] = 62,
+ [1][0][2][0][RTW89_IC][5] = 64,
+ [1][0][2][0][RTW89_KCC][5] = 66,
+ [1][0][2][0][RTW89_ACMA][5] = 64,
+ [1][0][2][0][RTW89_CN][5] = 64,
+ [1][0][2][0][RTW89_UK][5] = 64,
+ [1][0][2][0][RTW89_FCC][9] = 80,
+ [1][0][2][0][RTW89_ETSI][9] = 64,
+ [1][0][2][0][RTW89_MKK][9] = 64,
+ [1][0][2][0][RTW89_IC][9] = 64,
+ [1][0][2][0][RTW89_KCC][9] = 76,
+ [1][0][2][0][RTW89_ACMA][9] = 64,
+ [1][0][2][0][RTW89_CN][9] = 64,
+ [1][0][2][0][RTW89_UK][9] = 64,
+ [1][0][2][0][RTW89_FCC][13] = 64,
+ [1][0][2][0][RTW89_ETSI][13] = 64,
+ [1][0][2][0][RTW89_MKK][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_KCC][13] = 72,
+ [1][0][2][0][RTW89_ACMA][13] = 64,
+ [1][0][2][0][RTW89_CN][13] = 64,
+ [1][0][2][0][RTW89_UK][13] = 64,
+ [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_ETSI][16] = 66,
+ [1][0][2][0][RTW89_MKK][16] = 76,
+ [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_KCC][16] = 74,
+ [1][0][2][0][RTW89_ACMA][16] = 66,
+ [1][0][2][0][RTW89_CN][16] = 127,
+ [1][0][2][0][RTW89_UK][16] = 66,
+ [1][0][2][0][RTW89_FCC][20] = 80,
+ [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_KCC][20] = 74,
+ [1][0][2][0][RTW89_ACMA][20] = 66,
+ [1][0][2][0][RTW89_CN][20] = 127,
+ [1][0][2][0][RTW89_UK][20] = 66,
+ [1][0][2][0][RTW89_FCC][24] = 80,
+ [1][0][2][0][RTW89_ETSI][24] = 66,
+ [1][0][2][0][RTW89_MKK][24] = 76,
+ [1][0][2][0][RTW89_IC][24] = 127,
+ [1][0][2][0][RTW89_KCC][24] = 74,
+ [1][0][2][0][RTW89_ACMA][24] = 127,
+ [1][0][2][0][RTW89_CN][24] = 127,
+ [1][0][2][0][RTW89_UK][24] = 66,
+ [1][0][2][0][RTW89_FCC][28] = 80,
+ [1][0][2][0][RTW89_ETSI][28] = 66,
+ [1][0][2][0][RTW89_MKK][28] = 76,
+ [1][0][2][0][RTW89_IC][28] = 127,
+ [1][0][2][0][RTW89_KCC][28] = 74,
+ [1][0][2][0][RTW89_ACMA][28] = 127,
+ [1][0][2][0][RTW89_CN][28] = 127,
+ [1][0][2][0][RTW89_UK][28] = 66,
+ [1][0][2][0][RTW89_FCC][32] = 74,
+ [1][0][2][0][RTW89_ETSI][32] = 66,
+ [1][0][2][0][RTW89_MKK][32] = 76,
+ [1][0][2][0][RTW89_IC][32] = 74,
+ [1][0][2][0][RTW89_KCC][32] = 76,
+ [1][0][2][0][RTW89_ACMA][32] = 66,
+ [1][0][2][0][RTW89_CN][32] = 127,
+ [1][0][2][0][RTW89_UK][32] = 66,
+ [1][0][2][0][RTW89_FCC][36] = 78,
+ [1][0][2][0][RTW89_ETSI][36] = 127,
+ [1][0][2][0][RTW89_MKK][36] = 76,
+ [1][0][2][0][RTW89_IC][36] = 78,
+ [1][0][2][0][RTW89_KCC][36] = 76,
+ [1][0][2][0][RTW89_ACMA][36] = 76,
+ [1][0][2][0][RTW89_CN][36] = 127,
+ [1][0][2][0][RTW89_UK][36] = 76,
+ [1][0][2][0][RTW89_FCC][39] = 80,
+ [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_KCC][39] = 68,
+ [1][0][2][0][RTW89_ACMA][39] = 76,
+ [1][0][2][0][RTW89_CN][39] = 70,
+ [1][0][2][0][RTW89_UK][39] = 64,
+ [1][0][2][0][RTW89_FCC][43] = 80,
+ [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_KCC][43] = 76,
+ [1][0][2][0][RTW89_ACMA][43] = 76,
+ [1][0][2][0][RTW89_CN][43] = 76,
+ [1][0][2][0][RTW89_UK][43] = 64,
+ [1][0][2][0][RTW89_FCC][47] = 80,
+ [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_KCC][47] = 127,
+ [1][0][2][0][RTW89_ACMA][47] = 127,
+ [1][0][2][0][RTW89_CN][47] = 127,
+ [1][0][2][0][RTW89_UK][47] = 127,
+ [1][0][2][0][RTW89_FCC][51] = 80,
+ [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_KCC][51] = 127,
+ [1][0][2][0][RTW89_ACMA][51] = 127,
+ [1][0][2][0][RTW89_CN][51] = 127,
+ [1][0][2][0][RTW89_UK][51] = 127,
+ [1][1][2][0][RTW89_FCC][1] = 127,
+ [1][1][2][0][RTW89_ETSI][1] = 127,
+ [1][1][2][0][RTW89_MKK][1] = 127,
+ [1][1][2][0][RTW89_IC][1] = 127,
+ [1][1][2][0][RTW89_KCC][1] = 127,
+ [1][1][2][0][RTW89_ACMA][1] = 127,
+ [1][1][2][0][RTW89_CN][1] = 127,
+ [1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_FCC][5] = 127,
+ [1][1][2][0][RTW89_ETSI][5] = 127,
+ [1][1][2][0][RTW89_MKK][5] = 127,
+ [1][1][2][0][RTW89_IC][5] = 127,
+ [1][1][2][0][RTW89_KCC][5] = 127,
+ [1][1][2][0][RTW89_ACMA][5] = 127,
+ [1][1][2][0][RTW89_CN][5] = 127,
+ [1][1][2][0][RTW89_UK][5] = 127,
+ [1][1][2][0][RTW89_FCC][9] = 127,
+ [1][1][2][0][RTW89_ETSI][9] = 127,
+ [1][1][2][0][RTW89_MKK][9] = 127,
+ [1][1][2][0][RTW89_IC][9] = 127,
+ [1][1][2][0][RTW89_KCC][9] = 127,
+ [1][1][2][0][RTW89_ACMA][9] = 127,
+ [1][1][2][0][RTW89_CN][9] = 127,
+ [1][1][2][0][RTW89_UK][9] = 127,
+ [1][1][2][0][RTW89_FCC][13] = 127,
+ [1][1][2][0][RTW89_ETSI][13] = 127,
+ [1][1][2][0][RTW89_MKK][13] = 127,
+ [1][1][2][0][RTW89_IC][13] = 127,
+ [1][1][2][0][RTW89_KCC][13] = 127,
+ [1][1][2][0][RTW89_ACMA][13] = 127,
+ [1][1][2][0][RTW89_CN][13] = 127,
+ [1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_FCC][16] = 127,
+ [1][1][2][0][RTW89_ETSI][16] = 127,
+ [1][1][2][0][RTW89_MKK][16] = 127,
+ [1][1][2][0][RTW89_IC][16] = 127,
+ [1][1][2][0][RTW89_KCC][16] = 127,
+ [1][1][2][0][RTW89_ACMA][16] = 127,
+ [1][1][2][0][RTW89_CN][16] = 127,
+ [1][1][2][0][RTW89_UK][16] = 127,
+ [1][1][2][0][RTW89_FCC][20] = 127,
+ [1][1][2][0][RTW89_ETSI][20] = 127,
+ [1][1][2][0][RTW89_MKK][20] = 127,
+ [1][1][2][0][RTW89_IC][20] = 127,
+ [1][1][2][0][RTW89_KCC][20] = 127,
+ [1][1][2][0][RTW89_ACMA][20] = 127,
+ [1][1][2][0][RTW89_CN][20] = 127,
+ [1][1][2][0][RTW89_UK][20] = 127,
+ [1][1][2][0][RTW89_FCC][24] = 127,
+ [1][1][2][0][RTW89_ETSI][24] = 127,
+ [1][1][2][0][RTW89_MKK][24] = 127,
+ [1][1][2][0][RTW89_IC][24] = 127,
+ [1][1][2][0][RTW89_KCC][24] = 127,
+ [1][1][2][0][RTW89_ACMA][24] = 127,
+ [1][1][2][0][RTW89_CN][24] = 127,
+ [1][1][2][0][RTW89_UK][24] = 127,
+ [1][1][2][0][RTW89_FCC][28] = 127,
+ [1][1][2][0][RTW89_ETSI][28] = 127,
+ [1][1][2][0][RTW89_MKK][28] = 127,
+ [1][1][2][0][RTW89_IC][28] = 127,
+ [1][1][2][0][RTW89_KCC][28] = 127,
+ [1][1][2][0][RTW89_ACMA][28] = 127,
+ [1][1][2][0][RTW89_CN][28] = 127,
+ [1][1][2][0][RTW89_UK][28] = 127,
+ [1][1][2][0][RTW89_FCC][32] = 127,
+ [1][1][2][0][RTW89_ETSI][32] = 127,
+ [1][1][2][0][RTW89_MKK][32] = 127,
+ [1][1][2][0][RTW89_IC][32] = 127,
+ [1][1][2][0][RTW89_KCC][32] = 127,
+ [1][1][2][0][RTW89_ACMA][32] = 127,
+ [1][1][2][0][RTW89_CN][32] = 127,
+ [1][1][2][0][RTW89_UK][32] = 127,
+ [1][1][2][0][RTW89_FCC][36] = 127,
+ [1][1][2][0][RTW89_ETSI][36] = 127,
+ [1][1][2][0][RTW89_MKK][36] = 127,
+ [1][1][2][0][RTW89_IC][36] = 127,
+ [1][1][2][0][RTW89_KCC][36] = 127,
+ [1][1][2][0][RTW89_ACMA][36] = 127,
+ [1][1][2][0][RTW89_CN][36] = 127,
+ [1][1][2][0][RTW89_UK][36] = 127,
+ [1][1][2][0][RTW89_FCC][39] = 127,
+ [1][1][2][0][RTW89_ETSI][39] = 127,
+ [1][1][2][0][RTW89_MKK][39] = 127,
+ [1][1][2][0][RTW89_IC][39] = 127,
+ [1][1][2][0][RTW89_KCC][39] = 127,
+ [1][1][2][0][RTW89_ACMA][39] = 127,
+ [1][1][2][0][RTW89_CN][39] = 127,
+ [1][1][2][0][RTW89_UK][39] = 127,
+ [1][1][2][0][RTW89_FCC][43] = 127,
+ [1][1][2][0][RTW89_ETSI][43] = 127,
+ [1][1][2][0][RTW89_MKK][43] = 127,
+ [1][1][2][0][RTW89_IC][43] = 127,
+ [1][1][2][0][RTW89_KCC][43] = 127,
+ [1][1][2][0][RTW89_ACMA][43] = 127,
+ [1][1][2][0][RTW89_CN][43] = 127,
+ [1][1][2][0][RTW89_UK][43] = 127,
+ [1][1][2][0][RTW89_FCC][47] = 127,
+ [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_KCC][47] = 127,
+ [1][1][2][0][RTW89_ACMA][47] = 127,
+ [1][1][2][0][RTW89_CN][47] = 127,
+ [1][1][2][0][RTW89_UK][47] = 127,
+ [1][1][2][0][RTW89_FCC][51] = 127,
+ [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_KCC][51] = 127,
+ [1][1][2][0][RTW89_ACMA][51] = 127,
+ [1][1][2][0][RTW89_CN][51] = 127,
+ [1][1][2][0][RTW89_UK][51] = 127,
+ [1][1][2][1][RTW89_FCC][1] = 127,
+ [1][1][2][1][RTW89_ETSI][1] = 127,
+ [1][1][2][1][RTW89_MKK][1] = 127,
+ [1][1][2][1][RTW89_IC][1] = 127,
+ [1][1][2][1][RTW89_KCC][1] = 127,
+ [1][1][2][1][RTW89_ACMA][1] = 127,
+ [1][1][2][1][RTW89_CN][1] = 127,
+ [1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_FCC][5] = 127,
+ [1][1][2][1][RTW89_ETSI][5] = 127,
+ [1][1][2][1][RTW89_MKK][5] = 127,
+ [1][1][2][1][RTW89_IC][5] = 127,
+ [1][1][2][1][RTW89_KCC][5] = 127,
+ [1][1][2][1][RTW89_ACMA][5] = 127,
+ [1][1][2][1][RTW89_CN][5] = 127,
+ [1][1][2][1][RTW89_UK][5] = 127,
+ [1][1][2][1][RTW89_FCC][9] = 127,
+ [1][1][2][1][RTW89_ETSI][9] = 127,
+ [1][1][2][1][RTW89_MKK][9] = 127,
+ [1][1][2][1][RTW89_IC][9] = 127,
+ [1][1][2][1][RTW89_KCC][9] = 127,
+ [1][1][2][1][RTW89_ACMA][9] = 127,
+ [1][1][2][1][RTW89_CN][9] = 127,
+ [1][1][2][1][RTW89_UK][9] = 127,
+ [1][1][2][1][RTW89_FCC][13] = 127,
+ [1][1][2][1][RTW89_ETSI][13] = 127,
+ [1][1][2][1][RTW89_MKK][13] = 127,
+ [1][1][2][1][RTW89_IC][13] = 127,
+ [1][1][2][1][RTW89_KCC][13] = 127,
+ [1][1][2][1][RTW89_ACMA][13] = 127,
+ [1][1][2][1][RTW89_CN][13] = 127,
+ [1][1][2][1][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_FCC][16] = 127,
+ [1][1][2][1][RTW89_ETSI][16] = 127,
+ [1][1][2][1][RTW89_MKK][16] = 127,
+ [1][1][2][1][RTW89_IC][16] = 127,
+ [1][1][2][1][RTW89_KCC][16] = 127,
+ [1][1][2][1][RTW89_ACMA][16] = 127,
+ [1][1][2][1][RTW89_CN][16] = 127,
+ [1][1][2][1][RTW89_UK][16] = 127,
+ [1][1][2][1][RTW89_FCC][20] = 127,
+ [1][1][2][1][RTW89_ETSI][20] = 127,
+ [1][1][2][1][RTW89_MKK][20] = 127,
+ [1][1][2][1][RTW89_IC][20] = 127,
+ [1][1][2][1][RTW89_KCC][20] = 127,
+ [1][1][2][1][RTW89_ACMA][20] = 127,
+ [1][1][2][1][RTW89_CN][20] = 127,
+ [1][1][2][1][RTW89_UK][20] = 127,
+ [1][1][2][1][RTW89_FCC][24] = 127,
+ [1][1][2][1][RTW89_ETSI][24] = 127,
+ [1][1][2][1][RTW89_MKK][24] = 127,
+ [1][1][2][1][RTW89_IC][24] = 127,
+ [1][1][2][1][RTW89_KCC][24] = 127,
+ [1][1][2][1][RTW89_ACMA][24] = 127,
+ [1][1][2][1][RTW89_CN][24] = 127,
+ [1][1][2][1][RTW89_UK][24] = 127,
+ [1][1][2][1][RTW89_FCC][28] = 127,
+ [1][1][2][1][RTW89_ETSI][28] = 127,
+ [1][1][2][1][RTW89_MKK][28] = 127,
+ [1][1][2][1][RTW89_IC][28] = 127,
+ [1][1][2][1][RTW89_KCC][28] = 127,
+ [1][1][2][1][RTW89_ACMA][28] = 127,
+ [1][1][2][1][RTW89_CN][28] = 127,
+ [1][1][2][1][RTW89_UK][28] = 127,
+ [1][1][2][1][RTW89_FCC][32] = 127,
+ [1][1][2][1][RTW89_ETSI][32] = 127,
+ [1][1][2][1][RTW89_MKK][32] = 127,
+ [1][1][2][1][RTW89_IC][32] = 127,
+ [1][1][2][1][RTW89_KCC][32] = 127,
+ [1][1][2][1][RTW89_ACMA][32] = 127,
+ [1][1][2][1][RTW89_CN][32] = 127,
+ [1][1][2][1][RTW89_UK][32] = 127,
+ [1][1][2][1][RTW89_FCC][36] = 127,
+ [1][1][2][1][RTW89_ETSI][36] = 127,
+ [1][1][2][1][RTW89_MKK][36] = 127,
+ [1][1][2][1][RTW89_IC][36] = 127,
+ [1][1][2][1][RTW89_KCC][36] = 127,
+ [1][1][2][1][RTW89_ACMA][36] = 127,
+ [1][1][2][1][RTW89_CN][36] = 127,
+ [1][1][2][1][RTW89_UK][36] = 127,
+ [1][1][2][1][RTW89_FCC][39] = 127,
+ [1][1][2][1][RTW89_ETSI][39] = 127,
+ [1][1][2][1][RTW89_MKK][39] = 127,
+ [1][1][2][1][RTW89_IC][39] = 127,
+ [1][1][2][1][RTW89_KCC][39] = 127,
+ [1][1][2][1][RTW89_ACMA][39] = 127,
+ [1][1][2][1][RTW89_CN][39] = 127,
+ [1][1][2][1][RTW89_UK][39] = 127,
+ [1][1][2][1][RTW89_FCC][43] = 127,
+ [1][1][2][1][RTW89_ETSI][43] = 127,
+ [1][1][2][1][RTW89_MKK][43] = 127,
+ [1][1][2][1][RTW89_IC][43] = 127,
+ [1][1][2][1][RTW89_KCC][43] = 127,
+ [1][1][2][1][RTW89_ACMA][43] = 127,
+ [1][1][2][1][RTW89_CN][43] = 127,
+ [1][1][2][1][RTW89_UK][43] = 127,
+ [1][1][2][1][RTW89_FCC][47] = 127,
+ [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_KCC][47] = 127,
+ [1][1][2][1][RTW89_ACMA][47] = 127,
+ [1][1][2][1][RTW89_CN][47] = 127,
+ [1][1][2][1][RTW89_UK][47] = 127,
+ [1][1][2][1][RTW89_FCC][51] = 127,
+ [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_KCC][51] = 127,
+ [1][1][2][1][RTW89_ACMA][51] = 127,
+ [1][1][2][1][RTW89_CN][51] = 127,
+ [1][1][2][1][RTW89_UK][51] = 127,
+ [2][0][2][0][RTW89_FCC][3] = 72,
+ [2][0][2][0][RTW89_ETSI][3] = 64,
+ [2][0][2][0][RTW89_MKK][3] = 62,
+ [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_KCC][3] = 68,
+ [2][0][2][0][RTW89_ACMA][3] = 64,
+ [2][0][2][0][RTW89_CN][3] = 64,
+ [2][0][2][0][RTW89_UK][3] = 64,
+ [2][0][2][0][RTW89_FCC][11] = 62,
+ [2][0][2][0][RTW89_ETSI][11] = 64,
+ [2][0][2][0][RTW89_MKK][11] = 64,
+ [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_KCC][11] = 68,
+ [2][0][2][0][RTW89_ACMA][11] = 64,
+ [2][0][2][0][RTW89_CN][11] = 64,
+ [2][0][2][0][RTW89_UK][11] = 64,
+ [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_ETSI][18] = 64,
+ [2][0][2][0][RTW89_MKK][18] = 68,
+ [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_KCC][18] = 68,
+ [2][0][2][0][RTW89_ACMA][18] = 64,
+ [2][0][2][0][RTW89_CN][18] = 127,
+ [2][0][2][0][RTW89_UK][18] = 64,
+ [2][0][2][0][RTW89_FCC][26] = 72,
+ [2][0][2][0][RTW89_ETSI][26] = 64,
+ [2][0][2][0][RTW89_MKK][26] = 68,
+ [2][0][2][0][RTW89_IC][26] = 127,
+ [2][0][2][0][RTW89_KCC][26] = 68,
+ [2][0][2][0][RTW89_ACMA][26] = 127,
+ [2][0][2][0][RTW89_CN][26] = 127,
+ [2][0][2][0][RTW89_UK][26] = 64,
+ [2][0][2][0][RTW89_FCC][34] = 72,
+ [2][0][2][0][RTW89_ETSI][34] = 127,
+ [2][0][2][0][RTW89_MKK][34] = 68,
+ [2][0][2][0][RTW89_IC][34] = 72,
+ [2][0][2][0][RTW89_KCC][34] = 68,
+ [2][0][2][0][RTW89_ACMA][34] = 68,
+ [2][0][2][0][RTW89_CN][34] = 127,
+ [2][0][2][0][RTW89_UK][34] = 68,
+ [2][0][2][0][RTW89_FCC][41] = 72,
+ [2][0][2][0][RTW89_ETSI][41] = 30,
+ [2][0][2][0][RTW89_MKK][41] = 127,
+ [2][0][2][0][RTW89_IC][41] = 72,
+ [2][0][2][0][RTW89_KCC][41] = 64,
+ [2][0][2][0][RTW89_ACMA][41] = 68,
+ [2][0][2][0][RTW89_CN][41] = 68,
+ [2][0][2][0][RTW89_UK][41] = 64,
+ [2][0][2][0][RTW89_FCC][49] = 72,
+ [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_KCC][49] = 127,
+ [2][0][2][0][RTW89_ACMA][49] = 127,
+ [2][0][2][0][RTW89_CN][49] = 127,
+ [2][0][2][0][RTW89_UK][49] = 127,
+ [2][1][2][0][RTW89_FCC][3] = 127,
+ [2][1][2][0][RTW89_ETSI][3] = 127,
+ [2][1][2][0][RTW89_MKK][3] = 127,
+ [2][1][2][0][RTW89_IC][3] = 127,
+ [2][1][2][0][RTW89_KCC][3] = 127,
+ [2][1][2][0][RTW89_ACMA][3] = 127,
+ [2][1][2][0][RTW89_CN][3] = 127,
+ [2][1][2][0][RTW89_UK][3] = 127,
+ [2][1][2][0][RTW89_FCC][11] = 127,
+ [2][1][2][0][RTW89_ETSI][11] = 127,
+ [2][1][2][0][RTW89_MKK][11] = 127,
+ [2][1][2][0][RTW89_IC][11] = 127,
+ [2][1][2][0][RTW89_KCC][11] = 127,
+ [2][1][2][0][RTW89_ACMA][11] = 127,
+ [2][1][2][0][RTW89_CN][11] = 127,
+ [2][1][2][0][RTW89_UK][11] = 127,
+ [2][1][2][0][RTW89_FCC][18] = 127,
+ [2][1][2][0][RTW89_ETSI][18] = 127,
+ [2][1][2][0][RTW89_MKK][18] = 127,
+ [2][1][2][0][RTW89_IC][18] = 127,
+ [2][1][2][0][RTW89_KCC][18] = 127,
+ [2][1][2][0][RTW89_ACMA][18] = 127,
+ [2][1][2][0][RTW89_CN][18] = 127,
+ [2][1][2][0][RTW89_UK][18] = 127,
+ [2][1][2][0][RTW89_FCC][26] = 127,
+ [2][1][2][0][RTW89_ETSI][26] = 127,
+ [2][1][2][0][RTW89_MKK][26] = 127,
+ [2][1][2][0][RTW89_IC][26] = 127,
+ [2][1][2][0][RTW89_KCC][26] = 127,
+ [2][1][2][0][RTW89_ACMA][26] = 127,
+ [2][1][2][0][RTW89_CN][26] = 127,
+ [2][1][2][0][RTW89_UK][26] = 127,
+ [2][1][2][0][RTW89_FCC][34] = 127,
+ [2][1][2][0][RTW89_ETSI][34] = 127,
+ [2][1][2][0][RTW89_MKK][34] = 127,
+ [2][1][2][0][RTW89_IC][34] = 127,
+ [2][1][2][0][RTW89_KCC][34] = 127,
+ [2][1][2][0][RTW89_ACMA][34] = 127,
+ [2][1][2][0][RTW89_CN][34] = 127,
+ [2][1][2][0][RTW89_UK][34] = 127,
+ [2][1][2][0][RTW89_FCC][41] = 127,
+ [2][1][2][0][RTW89_ETSI][41] = 127,
+ [2][1][2][0][RTW89_MKK][41] = 127,
+ [2][1][2][0][RTW89_IC][41] = 127,
+ [2][1][2][0][RTW89_KCC][41] = 127,
+ [2][1][2][0][RTW89_ACMA][41] = 127,
+ [2][1][2][0][RTW89_CN][41] = 127,
+ [2][1][2][0][RTW89_UK][41] = 127,
+ [2][1][2][0][RTW89_FCC][49] = 127,
+ [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_KCC][49] = 127,
+ [2][1][2][0][RTW89_ACMA][49] = 127,
+ [2][1][2][0][RTW89_CN][49] = 127,
+ [2][1][2][0][RTW89_UK][49] = 127,
+ [2][1][2][1][RTW89_FCC][3] = 127,
+ [2][1][2][1][RTW89_ETSI][3] = 127,
+ [2][1][2][1][RTW89_MKK][3] = 127,
+ [2][1][2][1][RTW89_IC][3] = 127,
+ [2][1][2][1][RTW89_KCC][3] = 127,
+ [2][1][2][1][RTW89_ACMA][3] = 127,
+ [2][1][2][1][RTW89_CN][3] = 127,
+ [2][1][2][1][RTW89_UK][3] = 127,
+ [2][1][2][1][RTW89_FCC][11] = 127,
+ [2][1][2][1][RTW89_ETSI][11] = 127,
+ [2][1][2][1][RTW89_MKK][11] = 127,
+ [2][1][2][1][RTW89_IC][11] = 127,
+ [2][1][2][1][RTW89_KCC][11] = 127,
+ [2][1][2][1][RTW89_ACMA][11] = 127,
+ [2][1][2][1][RTW89_CN][11] = 127,
+ [2][1][2][1][RTW89_UK][11] = 127,
+ [2][1][2][1][RTW89_FCC][18] = 127,
+ [2][1][2][1][RTW89_ETSI][18] = 127,
+ [2][1][2][1][RTW89_MKK][18] = 127,
+ [2][1][2][1][RTW89_IC][18] = 127,
+ [2][1][2][1][RTW89_KCC][18] = 127,
+ [2][1][2][1][RTW89_ACMA][18] = 127,
+ [2][1][2][1][RTW89_CN][18] = 127,
+ [2][1][2][1][RTW89_UK][18] = 127,
+ [2][1][2][1][RTW89_FCC][26] = 127,
+ [2][1][2][1][RTW89_ETSI][26] = 127,
+ [2][1][2][1][RTW89_MKK][26] = 127,
+ [2][1][2][1][RTW89_IC][26] = 127,
+ [2][1][2][1][RTW89_KCC][26] = 127,
+ [2][1][2][1][RTW89_ACMA][26] = 127,
+ [2][1][2][1][RTW89_CN][26] = 127,
+ [2][1][2][1][RTW89_UK][26] = 127,
+ [2][1][2][1][RTW89_FCC][34] = 127,
+ [2][1][2][1][RTW89_ETSI][34] = 127,
+ [2][1][2][1][RTW89_MKK][34] = 127,
+ [2][1][2][1][RTW89_IC][34] = 127,
+ [2][1][2][1][RTW89_KCC][34] = 127,
+ [2][1][2][1][RTW89_ACMA][34] = 127,
+ [2][1][2][1][RTW89_CN][34] = 127,
+ [2][1][2][1][RTW89_UK][34] = 127,
+ [2][1][2][1][RTW89_FCC][41] = 127,
+ [2][1][2][1][RTW89_ETSI][41] = 127,
+ [2][1][2][1][RTW89_MKK][41] = 127,
+ [2][1][2][1][RTW89_IC][41] = 127,
+ [2][1][2][1][RTW89_KCC][41] = 127,
+ [2][1][2][1][RTW89_ACMA][41] = 127,
+ [2][1][2][1][RTW89_CN][41] = 127,
+ [2][1][2][1][RTW89_UK][41] = 127,
+ [2][1][2][1][RTW89_FCC][49] = 127,
+ [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_KCC][49] = 127,
+ [2][1][2][1][RTW89_ACMA][49] = 127,
+ [2][1][2][1][RTW89_CN][49] = 127,
+ [2][1][2][1][RTW89_UK][49] = 127,
+ [3][0][2][0][RTW89_FCC][7] = 127,
+ [3][0][2][0][RTW89_ETSI][7] = 127,
+ [3][0][2][0][RTW89_MKK][7] = 127,
+ [3][0][2][0][RTW89_IC][7] = 127,
+ [3][0][2][0][RTW89_KCC][7] = 127,
+ [3][0][2][0][RTW89_ACMA][7] = 127,
+ [3][0][2][0][RTW89_CN][7] = 58,
+ [3][0][2][0][RTW89_UK][7] = 127,
+ [3][0][2][0][RTW89_FCC][22] = 127,
+ [3][0][2][0][RTW89_ETSI][22] = 127,
+ [3][0][2][0][RTW89_MKK][22] = 127,
+ [3][0][2][0][RTW89_IC][22] = 127,
+ [3][0][2][0][RTW89_KCC][22] = 127,
+ [3][0][2][0][RTW89_ACMA][22] = 127,
+ [3][0][2][0][RTW89_CN][22] = 58,
+ [3][0][2][0][RTW89_UK][22] = 127,
+ [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_KCC][45] = 127,
+ [3][0][2][0][RTW89_ACMA][45] = 127,
+ [3][0][2][0][RTW89_CN][45] = 127,
+ [3][0][2][0][RTW89_UK][45] = 127,
+ [3][1][2][0][RTW89_FCC][7] = 127,
+ [3][1][2][0][RTW89_ETSI][7] = 127,
+ [3][1][2][0][RTW89_MKK][7] = 127,
+ [3][1][2][0][RTW89_IC][7] = 127,
+ [3][1][2][0][RTW89_KCC][7] = 127,
+ [3][1][2][0][RTW89_ACMA][7] = 127,
+ [3][1][2][0][RTW89_CN][7] = 127,
+ [3][1][2][0][RTW89_UK][7] = 127,
+ [3][1][2][0][RTW89_FCC][22] = 127,
+ [3][1][2][0][RTW89_ETSI][22] = 127,
+ [3][1][2][0][RTW89_MKK][22] = 127,
+ [3][1][2][0][RTW89_IC][22] = 127,
+ [3][1][2][0][RTW89_KCC][22] = 127,
+ [3][1][2][0][RTW89_ACMA][22] = 127,
+ [3][1][2][0][RTW89_CN][22] = 127,
+ [3][1][2][0][RTW89_UK][22] = 127,
+ [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_KCC][45] = 127,
+ [3][1][2][0][RTW89_ACMA][45] = 127,
+ [3][1][2][0][RTW89_CN][45] = 127,
+ [3][1][2][0][RTW89_UK][45] = 127,
+ [3][1][2][1][RTW89_FCC][7] = 127,
+ [3][1][2][1][RTW89_ETSI][7] = 127,
+ [3][1][2][1][RTW89_MKK][7] = 127,
+ [3][1][2][1][RTW89_IC][7] = 127,
+ [3][1][2][1][RTW89_KCC][7] = 127,
+ [3][1][2][1][RTW89_ACMA][7] = 127,
+ [3][1][2][1][RTW89_CN][7] = 127,
+ [3][1][2][1][RTW89_UK][7] = 127,
+ [3][1][2][1][RTW89_FCC][22] = 127,
+ [3][1][2][1][RTW89_ETSI][22] = 127,
+ [3][1][2][1][RTW89_MKK][22] = 127,
+ [3][1][2][1][RTW89_IC][22] = 127,
+ [3][1][2][1][RTW89_KCC][22] = 127,
+ [3][1][2][1][RTW89_ACMA][22] = 127,
+ [3][1][2][1][RTW89_CN][22] = 127,
+ [3][1][2][1][RTW89_UK][22] = 127,
+ [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,
+ [3][1][2][1][RTW89_KCC][45] = 127,
+ [3][1][2][1][RTW89_ACMA][45] = 127,
+ [3][1][2][1][RTW89_CN][45] = 127,
+ [3][1][2][1][RTW89_UK][45] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_ru_2g_type2[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
+ [0][0][RTW89_WW][0] = 30,
+ [0][0][RTW89_WW][1] = 30,
+ [0][0][RTW89_WW][2] = 30,
+ [0][0][RTW89_WW][3] = 30,
+ [0][0][RTW89_WW][4] = 30,
+ [0][0][RTW89_WW][5] = 30,
+ [0][0][RTW89_WW][6] = 30,
+ [0][0][RTW89_WW][7] = 30,
+ [0][0][RTW89_WW][8] = 30,
+ [0][0][RTW89_WW][9] = 30,
+ [0][0][RTW89_WW][10] = 30,
+ [0][0][RTW89_WW][11] = 30,
+ [0][0][RTW89_WW][12] = 30,
+ [0][0][RTW89_WW][13] = 0,
+ [0][1][RTW89_WW][0] = 20,
+ [0][1][RTW89_WW][1] = 22,
+ [0][1][RTW89_WW][2] = 22,
+ [0][1][RTW89_WW][3] = 22,
+ [0][1][RTW89_WW][4] = 22,
+ [0][1][RTW89_WW][5] = 22,
+ [0][1][RTW89_WW][6] = 22,
+ [0][1][RTW89_WW][7] = 22,
+ [0][1][RTW89_WW][8] = 22,
+ [0][1][RTW89_WW][9] = 22,
+ [0][1][RTW89_WW][10] = 22,
+ [0][1][RTW89_WW][11] = 22,
+ [0][1][RTW89_WW][12] = 20,
+ [0][1][RTW89_WW][13] = 0,
+ [1][0][RTW89_WW][0] = 42,
+ [1][0][RTW89_WW][1] = 42,
+ [1][0][RTW89_WW][2] = 42,
+ [1][0][RTW89_WW][3] = 42,
+ [1][0][RTW89_WW][4] = 42,
+ [1][0][RTW89_WW][5] = 42,
+ [1][0][RTW89_WW][6] = 42,
+ [1][0][RTW89_WW][7] = 42,
+ [1][0][RTW89_WW][8] = 42,
+ [1][0][RTW89_WW][9] = 42,
+ [1][0][RTW89_WW][10] = 42,
+ [1][0][RTW89_WW][11] = 42,
+ [1][0][RTW89_WW][12] = 34,
+ [1][0][RTW89_WW][13] = 0,
+ [1][1][RTW89_WW][0] = 32,
+ [1][1][RTW89_WW][1] = 32,
+ [1][1][RTW89_WW][2] = 32,
+ [1][1][RTW89_WW][3] = 32,
+ [1][1][RTW89_WW][4] = 32,
+ [1][1][RTW89_WW][5] = 32,
+ [1][1][RTW89_WW][6] = 32,
+ [1][1][RTW89_WW][7] = 32,
+ [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][13] = 0,
+ [2][0][RTW89_WW][0] = 54,
+ [2][0][RTW89_WW][1] = 54,
+ [2][0][RTW89_WW][2] = 54,
+ [2][0][RTW89_WW][3] = 54,
+ [2][0][RTW89_WW][4] = 54,
+ [2][0][RTW89_WW][5] = 54,
+ [2][0][RTW89_WW][6] = 54,
+ [2][0][RTW89_WW][7] = 54,
+ [2][0][RTW89_WW][8] = 54,
+ [2][0][RTW89_WW][9] = 54,
+ [2][0][RTW89_WW][10] = 54,
+ [2][0][RTW89_WW][11] = 54,
+ [2][0][RTW89_WW][12] = 34,
+ [2][0][RTW89_WW][13] = 0,
+ [2][1][RTW89_WW][0] = 44,
+ [2][1][RTW89_WW][1] = 44,
+ [2][1][RTW89_WW][2] = 44,
+ [2][1][RTW89_WW][3] = 44,
+ [2][1][RTW89_WW][4] = 44,
+ [2][1][RTW89_WW][5] = 44,
+ [2][1][RTW89_WW][6] = 44,
+ [2][1][RTW89_WW][7] = 44,
+ [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][13] = 0,
+ [0][0][RTW89_FCC][0] = 60,
+ [0][0][RTW89_ETSI][0] = 30,
+ [0][0][RTW89_MKK][0] = 40,
+ [0][0][RTW89_IC][0] = 60,
+ [0][0][RTW89_KCC][0] = 46,
+ [0][0][RTW89_ACMA][0] = 30,
+ [0][0][RTW89_CN][0] = 32,
+ [0][0][RTW89_UK][0] = 30,
+ [0][0][RTW89_FCC][1] = 60,
+ [0][0][RTW89_ETSI][1] = 30,
+ [0][0][RTW89_MKK][1] = 44,
+ [0][0][RTW89_IC][1] = 60,
+ [0][0][RTW89_KCC][1] = 46,
+ [0][0][RTW89_ACMA][1] = 30,
+ [0][0][RTW89_CN][1] = 32,
+ [0][0][RTW89_UK][1] = 30,
+ [0][0][RTW89_FCC][2] = 64,
+ [0][0][RTW89_ETSI][2] = 30,
+ [0][0][RTW89_MKK][2] = 44,
+ [0][0][RTW89_IC][2] = 64,
+ [0][0][RTW89_KCC][2] = 46,
+ [0][0][RTW89_ACMA][2] = 30,
+ [0][0][RTW89_CN][2] = 32,
+ [0][0][RTW89_UK][2] = 30,
+ [0][0][RTW89_FCC][3] = 68,
+ [0][0][RTW89_ETSI][3] = 30,
+ [0][0][RTW89_MKK][3] = 44,
+ [0][0][RTW89_IC][3] = 68,
+ [0][0][RTW89_KCC][3] = 46,
+ [0][0][RTW89_ACMA][3] = 30,
+ [0][0][RTW89_CN][3] = 32,
+ [0][0][RTW89_UK][3] = 30,
+ [0][0][RTW89_FCC][4] = 68,
+ [0][0][RTW89_ETSI][4] = 30,
+ [0][0][RTW89_MKK][4] = 44,
+ [0][0][RTW89_IC][4] = 68,
+ [0][0][RTW89_KCC][4] = 48,
+ [0][0][RTW89_ACMA][4] = 30,
+ [0][0][RTW89_CN][4] = 32,
+ [0][0][RTW89_UK][4] = 30,
+ [0][0][RTW89_FCC][5] = 82,
+ [0][0][RTW89_ETSI][5] = 30,
+ [0][0][RTW89_MKK][5] = 44,
+ [0][0][RTW89_IC][5] = 82,
+ [0][0][RTW89_KCC][5] = 48,
+ [0][0][RTW89_ACMA][5] = 30,
+ [0][0][RTW89_CN][5] = 32,
+ [0][0][RTW89_UK][5] = 30,
+ [0][0][RTW89_FCC][6] = 64,
+ [0][0][RTW89_ETSI][6] = 30,
+ [0][0][RTW89_MKK][6] = 44,
+ [0][0][RTW89_IC][6] = 64,
+ [0][0][RTW89_KCC][6] = 48,
+ [0][0][RTW89_ACMA][6] = 30,
+ [0][0][RTW89_CN][6] = 32,
+ [0][0][RTW89_UK][6] = 30,
+ [0][0][RTW89_FCC][7] = 64,
+ [0][0][RTW89_ETSI][7] = 30,
+ [0][0][RTW89_MKK][7] = 44,
+ [0][0][RTW89_IC][7] = 64,
+ [0][0][RTW89_KCC][7] = 48,
+ [0][0][RTW89_ACMA][7] = 30,
+ [0][0][RTW89_CN][7] = 32,
+ [0][0][RTW89_UK][7] = 30,
+ [0][0][RTW89_FCC][8] = 60,
+ [0][0][RTW89_ETSI][8] = 30,
+ [0][0][RTW89_MKK][8] = 44,
+ [0][0][RTW89_IC][8] = 60,
+ [0][0][RTW89_KCC][8] = 48,
+ [0][0][RTW89_ACMA][8] = 30,
+ [0][0][RTW89_CN][8] = 32,
+ [0][0][RTW89_UK][8] = 30,
+ [0][0][RTW89_FCC][9] = 56,
+ [0][0][RTW89_ETSI][9] = 30,
+ [0][0][RTW89_MKK][9] = 44,
+ [0][0][RTW89_IC][9] = 56,
+ [0][0][RTW89_KCC][9] = 44,
+ [0][0][RTW89_ACMA][9] = 30,
+ [0][0][RTW89_CN][9] = 32,
+ [0][0][RTW89_UK][9] = 30,
+ [0][0][RTW89_FCC][10] = 56,
+ [0][0][RTW89_ETSI][10] = 30,
+ [0][0][RTW89_MKK][10] = 44,
+ [0][0][RTW89_IC][10] = 56,
+ [0][0][RTW89_KCC][10] = 44,
+ [0][0][RTW89_ACMA][10] = 30,
+ [0][0][RTW89_CN][10] = 32,
+ [0][0][RTW89_UK][10] = 30,
+ [0][0][RTW89_FCC][11] = 54,
+ [0][0][RTW89_ETSI][11] = 30,
+ [0][0][RTW89_MKK][11] = 44,
+ [0][0][RTW89_IC][11] = 54,
+ [0][0][RTW89_KCC][11] = 44,
+ [0][0][RTW89_ACMA][11] = 30,
+ [0][0][RTW89_CN][11] = 32,
+ [0][0][RTW89_UK][11] = 30,
+ [0][0][RTW89_FCC][12] = 34,
+ [0][0][RTW89_ETSI][12] = 30,
+ [0][0][RTW89_MKK][12] = 40,
+ [0][0][RTW89_IC][12] = 34,
+ [0][0][RTW89_KCC][12] = 44,
+ [0][0][RTW89_ACMA][12] = 30,
+ [0][0][RTW89_CN][12] = 32,
+ [0][0][RTW89_UK][12] = 30,
+ [0][0][RTW89_FCC][13] = 127,
+ [0][0][RTW89_ETSI][13] = 127,
+ [0][0][RTW89_MKK][13] = 127,
+ [0][0][RTW89_IC][13] = 127,
+ [0][0][RTW89_KCC][13] = 127,
+ [0][0][RTW89_ACMA][13] = 127,
+ [0][0][RTW89_CN][13] = 127,
+ [0][0][RTW89_UK][13] = 127,
+ [0][1][RTW89_FCC][0] = 127,
+ [0][1][RTW89_ETSI][0] = 127,
+ [0][1][RTW89_MKK][0] = 127,
+ [0][1][RTW89_IC][0] = 127,
+ [0][1][RTW89_KCC][0] = 127,
+ [0][1][RTW89_ACMA][0] = 127,
+ [0][1][RTW89_CN][0] = 20,
+ [0][1][RTW89_UK][0] = 127,
+ [0][1][RTW89_FCC][1] = 127,
+ [0][1][RTW89_ETSI][1] = 127,
+ [0][1][RTW89_MKK][1] = 127,
+ [0][1][RTW89_IC][1] = 127,
+ [0][1][RTW89_KCC][1] = 127,
+ [0][1][RTW89_ACMA][1] = 127,
+ [0][1][RTW89_CN][1] = 22,
+ [0][1][RTW89_UK][1] = 127,
+ [0][1][RTW89_FCC][2] = 127,
+ [0][1][RTW89_ETSI][2] = 127,
+ [0][1][RTW89_MKK][2] = 127,
+ [0][1][RTW89_IC][2] = 127,
+ [0][1][RTW89_KCC][2] = 127,
+ [0][1][RTW89_ACMA][2] = 127,
+ [0][1][RTW89_CN][2] = 22,
+ [0][1][RTW89_UK][2] = 127,
+ [0][1][RTW89_FCC][3] = 127,
+ [0][1][RTW89_ETSI][3] = 127,
+ [0][1][RTW89_MKK][3] = 127,
+ [0][1][RTW89_IC][3] = 127,
+ [0][1][RTW89_KCC][3] = 127,
+ [0][1][RTW89_ACMA][3] = 127,
+ [0][1][RTW89_CN][3] = 22,
+ [0][1][RTW89_UK][3] = 127,
+ [0][1][RTW89_FCC][4] = 127,
+ [0][1][RTW89_ETSI][4] = 127,
+ [0][1][RTW89_MKK][4] = 127,
+ [0][1][RTW89_IC][4] = 127,
+ [0][1][RTW89_KCC][4] = 127,
+ [0][1][RTW89_ACMA][4] = 127,
+ [0][1][RTW89_CN][4] = 22,
+ [0][1][RTW89_UK][4] = 127,
+ [0][1][RTW89_FCC][5] = 127,
+ [0][1][RTW89_ETSI][5] = 127,
+ [0][1][RTW89_MKK][5] = 127,
+ [0][1][RTW89_IC][5] = 127,
+ [0][1][RTW89_KCC][5] = 127,
+ [0][1][RTW89_ACMA][5] = 127,
+ [0][1][RTW89_CN][5] = 22,
+ [0][1][RTW89_UK][5] = 127,
+ [0][1][RTW89_FCC][6] = 127,
+ [0][1][RTW89_ETSI][6] = 127,
+ [0][1][RTW89_MKK][6] = 127,
+ [0][1][RTW89_IC][6] = 127,
+ [0][1][RTW89_KCC][6] = 127,
+ [0][1][RTW89_ACMA][6] = 127,
+ [0][1][RTW89_CN][6] = 22,
+ [0][1][RTW89_UK][6] = 127,
+ [0][1][RTW89_FCC][7] = 127,
+ [0][1][RTW89_ETSI][7] = 127,
+ [0][1][RTW89_MKK][7] = 127,
+ [0][1][RTW89_IC][7] = 127,
+ [0][1][RTW89_KCC][7] = 127,
+ [0][1][RTW89_ACMA][7] = 127,
+ [0][1][RTW89_CN][7] = 22,
+ [0][1][RTW89_UK][7] = 127,
+ [0][1][RTW89_FCC][8] = 127,
+ [0][1][RTW89_ETSI][8] = 127,
+ [0][1][RTW89_MKK][8] = 127,
+ [0][1][RTW89_IC][8] = 127,
+ [0][1][RTW89_KCC][8] = 127,
+ [0][1][RTW89_ACMA][8] = 127,
+ [0][1][RTW89_CN][8] = 22,
+ [0][1][RTW89_UK][8] = 127,
+ [0][1][RTW89_FCC][9] = 127,
+ [0][1][RTW89_ETSI][9] = 127,
+ [0][1][RTW89_MKK][9] = 127,
+ [0][1][RTW89_IC][9] = 127,
+ [0][1][RTW89_KCC][9] = 127,
+ [0][1][RTW89_ACMA][9] = 127,
+ [0][1][RTW89_CN][9] = 22,
+ [0][1][RTW89_UK][9] = 127,
+ [0][1][RTW89_FCC][10] = 127,
+ [0][1][RTW89_ETSI][10] = 127,
+ [0][1][RTW89_MKK][10] = 127,
+ [0][1][RTW89_IC][10] = 127,
+ [0][1][RTW89_KCC][10] = 127,
+ [0][1][RTW89_ACMA][10] = 127,
+ [0][1][RTW89_CN][10] = 22,
+ [0][1][RTW89_UK][10] = 127,
+ [0][1][RTW89_FCC][11] = 127,
+ [0][1][RTW89_ETSI][11] = 127,
+ [0][1][RTW89_MKK][11] = 127,
+ [0][1][RTW89_IC][11] = 127,
+ [0][1][RTW89_KCC][11] = 127,
+ [0][1][RTW89_ACMA][11] = 127,
+ [0][1][RTW89_CN][11] = 22,
+ [0][1][RTW89_UK][11] = 127,
+ [0][1][RTW89_FCC][12] = 127,
+ [0][1][RTW89_ETSI][12] = 127,
+ [0][1][RTW89_MKK][12] = 127,
+ [0][1][RTW89_IC][12] = 127,
+ [0][1][RTW89_KCC][12] = 127,
+ [0][1][RTW89_ACMA][12] = 127,
+ [0][1][RTW89_CN][12] = 20,
+ [0][1][RTW89_UK][12] = 127,
+ [0][1][RTW89_FCC][13] = 127,
+ [0][1][RTW89_ETSI][13] = 127,
+ [0][1][RTW89_MKK][13] = 127,
+ [0][1][RTW89_IC][13] = 127,
+ [0][1][RTW89_KCC][13] = 127,
+ [0][1][RTW89_ACMA][13] = 127,
+ [0][1][RTW89_CN][13] = 127,
+ [0][1][RTW89_UK][13] = 127,
+ [1][0][RTW89_FCC][0] = 70,
+ [1][0][RTW89_ETSI][0] = 42,
+ [1][0][RTW89_MKK][0] = 52,
+ [1][0][RTW89_IC][0] = 70,
+ [1][0][RTW89_KCC][0] = 56,
+ [1][0][RTW89_ACMA][0] = 42,
+ [1][0][RTW89_CN][0] = 42,
+ [1][0][RTW89_UK][0] = 42,
+ [1][0][RTW89_FCC][1] = 70,
+ [1][0][RTW89_ETSI][1] = 42,
+ [1][0][RTW89_MKK][1] = 52,
+ [1][0][RTW89_IC][1] = 70,
+ [1][0][RTW89_KCC][1] = 56,
+ [1][0][RTW89_ACMA][1] = 42,
+ [1][0][RTW89_CN][1] = 44,
+ [1][0][RTW89_UK][1] = 42,
+ [1][0][RTW89_FCC][2] = 74,
+ [1][0][RTW89_ETSI][2] = 42,
+ [1][0][RTW89_MKK][2] = 52,
+ [1][0][RTW89_IC][2] = 74,
+ [1][0][RTW89_KCC][2] = 56,
+ [1][0][RTW89_ACMA][2] = 42,
+ [1][0][RTW89_CN][2] = 44,
+ [1][0][RTW89_UK][2] = 42,
+ [1][0][RTW89_FCC][3] = 76,
+ [1][0][RTW89_ETSI][3] = 42,
+ [1][0][RTW89_MKK][3] = 52,
+ [1][0][RTW89_IC][3] = 76,
+ [1][0][RTW89_KCC][3] = 56,
+ [1][0][RTW89_ACMA][3] = 42,
+ [1][0][RTW89_CN][3] = 44,
+ [1][0][RTW89_UK][3] = 42,
+ [1][0][RTW89_FCC][4] = 76,
+ [1][0][RTW89_ETSI][4] = 42,
+ [1][0][RTW89_MKK][4] = 52,
+ [1][0][RTW89_IC][4] = 76,
+ [1][0][RTW89_KCC][4] = 56,
+ [1][0][RTW89_ACMA][4] = 42,
+ [1][0][RTW89_CN][4] = 44,
+ [1][0][RTW89_UK][4] = 42,
+ [1][0][RTW89_FCC][5] = 82,
+ [1][0][RTW89_ETSI][5] = 42,
+ [1][0][RTW89_MKK][5] = 52,
+ [1][0][RTW89_IC][5] = 82,
+ [1][0][RTW89_KCC][5] = 56,
+ [1][0][RTW89_ACMA][5] = 42,
+ [1][0][RTW89_CN][5] = 44,
+ [1][0][RTW89_UK][5] = 42,
+ [1][0][RTW89_FCC][6] = 72,
+ [1][0][RTW89_ETSI][6] = 42,
+ [1][0][RTW89_MKK][6] = 52,
+ [1][0][RTW89_IC][6] = 72,
+ [1][0][RTW89_KCC][6] = 56,
+ [1][0][RTW89_ACMA][6] = 42,
+ [1][0][RTW89_CN][6] = 44,
+ [1][0][RTW89_UK][6] = 42,
+ [1][0][RTW89_FCC][7] = 72,
+ [1][0][RTW89_ETSI][7] = 42,
+ [1][0][RTW89_MKK][7] = 52,
+ [1][0][RTW89_IC][7] = 72,
+ [1][0][RTW89_KCC][7] = 56,
+ [1][0][RTW89_ACMA][7] = 42,
+ [1][0][RTW89_CN][7] = 44,
+ [1][0][RTW89_UK][7] = 42,
+ [1][0][RTW89_FCC][8] = 72,
+ [1][0][RTW89_ETSI][8] = 42,
+ [1][0][RTW89_MKK][8] = 52,
+ [1][0][RTW89_IC][8] = 72,
+ [1][0][RTW89_KCC][8] = 56,
+ [1][0][RTW89_ACMA][8] = 42,
+ [1][0][RTW89_CN][8] = 44,
+ [1][0][RTW89_UK][8] = 42,
+ [1][0][RTW89_FCC][9] = 68,
+ [1][0][RTW89_ETSI][9] = 42,
+ [1][0][RTW89_MKK][9] = 52,
+ [1][0][RTW89_IC][9] = 68,
+ [1][0][RTW89_KCC][9] = 58,
+ [1][0][RTW89_ACMA][9] = 42,
+ [1][0][RTW89_CN][9] = 44,
+ [1][0][RTW89_UK][9] = 42,
+ [1][0][RTW89_FCC][10] = 68,
+ [1][0][RTW89_ETSI][10] = 42,
+ [1][0][RTW89_MKK][10] = 52,
+ [1][0][RTW89_IC][10] = 68,
+ [1][0][RTW89_KCC][10] = 58,
+ [1][0][RTW89_ACMA][10] = 42,
+ [1][0][RTW89_CN][10] = 44,
+ [1][0][RTW89_UK][10] = 42,
+ [1][0][RTW89_FCC][11] = 66,
+ [1][0][RTW89_ETSI][11] = 42,
+ [1][0][RTW89_MKK][11] = 52,
+ [1][0][RTW89_IC][11] = 66,
+ [1][0][RTW89_KCC][11] = 58,
+ [1][0][RTW89_ACMA][11] = 42,
+ [1][0][RTW89_CN][11] = 44,
+ [1][0][RTW89_UK][11] = 42,
+ [1][0][RTW89_FCC][12] = 34,
+ [1][0][RTW89_ETSI][12] = 42,
+ [1][0][RTW89_MKK][12] = 52,
+ [1][0][RTW89_IC][12] = 34,
+ [1][0][RTW89_KCC][12] = 58,
+ [1][0][RTW89_ACMA][12] = 42,
+ [1][0][RTW89_CN][12] = 42,
+ [1][0][RTW89_UK][12] = 42,
+ [1][0][RTW89_FCC][13] = 127,
+ [1][0][RTW89_ETSI][13] = 127,
+ [1][0][RTW89_MKK][13] = 127,
+ [1][0][RTW89_IC][13] = 127,
+ [1][0][RTW89_KCC][13] = 127,
+ [1][0][RTW89_ACMA][13] = 127,
+ [1][0][RTW89_CN][13] = 127,
+ [1][0][RTW89_UK][13] = 127,
+ [1][1][RTW89_FCC][0] = 127,
+ [1][1][RTW89_ETSI][0] = 127,
+ [1][1][RTW89_MKK][0] = 127,
+ [1][1][RTW89_IC][0] = 127,
+ [1][1][RTW89_KCC][0] = 127,
+ [1][1][RTW89_ACMA][0] = 127,
+ [1][1][RTW89_CN][0] = 32,
+ [1][1][RTW89_UK][0] = 127,
+ [1][1][RTW89_FCC][1] = 127,
+ [1][1][RTW89_ETSI][1] = 127,
+ [1][1][RTW89_MKK][1] = 127,
+ [1][1][RTW89_IC][1] = 127,
+ [1][1][RTW89_KCC][1] = 127,
+ [1][1][RTW89_ACMA][1] = 127,
+ [1][1][RTW89_CN][1] = 32,
+ [1][1][RTW89_UK][1] = 127,
+ [1][1][RTW89_FCC][2] = 127,
+ [1][1][RTW89_ETSI][2] = 127,
+ [1][1][RTW89_MKK][2] = 127,
+ [1][1][RTW89_IC][2] = 127,
+ [1][1][RTW89_KCC][2] = 127,
+ [1][1][RTW89_ACMA][2] = 127,
+ [1][1][RTW89_CN][2] = 32,
+ [1][1][RTW89_UK][2] = 127,
+ [1][1][RTW89_FCC][3] = 127,
+ [1][1][RTW89_ETSI][3] = 127,
+ [1][1][RTW89_MKK][3] = 127,
+ [1][1][RTW89_IC][3] = 127,
+ [1][1][RTW89_KCC][3] = 127,
+ [1][1][RTW89_ACMA][3] = 127,
+ [1][1][RTW89_CN][3] = 32,
+ [1][1][RTW89_UK][3] = 127,
+ [1][1][RTW89_FCC][4] = 127,
+ [1][1][RTW89_ETSI][4] = 127,
+ [1][1][RTW89_MKK][4] = 127,
+ [1][1][RTW89_IC][4] = 127,
+ [1][1][RTW89_KCC][4] = 127,
+ [1][1][RTW89_ACMA][4] = 127,
+ [1][1][RTW89_CN][4] = 32,
+ [1][1][RTW89_UK][4] = 127,
+ [1][1][RTW89_FCC][5] = 127,
+ [1][1][RTW89_ETSI][5] = 127,
+ [1][1][RTW89_MKK][5] = 127,
+ [1][1][RTW89_IC][5] = 127,
+ [1][1][RTW89_KCC][5] = 127,
+ [1][1][RTW89_ACMA][5] = 127,
+ [1][1][RTW89_CN][5] = 32,
+ [1][1][RTW89_UK][5] = 127,
+ [1][1][RTW89_FCC][6] = 127,
+ [1][1][RTW89_ETSI][6] = 127,
+ [1][1][RTW89_MKK][6] = 127,
+ [1][1][RTW89_IC][6] = 127,
+ [1][1][RTW89_KCC][6] = 127,
+ [1][1][RTW89_ACMA][6] = 127,
+ [1][1][RTW89_CN][6] = 32,
+ [1][1][RTW89_UK][6] = 127,
+ [1][1][RTW89_FCC][7] = 127,
+ [1][1][RTW89_ETSI][7] = 127,
+ [1][1][RTW89_MKK][7] = 127,
+ [1][1][RTW89_IC][7] = 127,
+ [1][1][RTW89_KCC][7] = 127,
+ [1][1][RTW89_ACMA][7] = 127,
+ [1][1][RTW89_CN][7] = 32,
+ [1][1][RTW89_UK][7] = 127,
+ [1][1][RTW89_FCC][8] = 127,
+ [1][1][RTW89_ETSI][8] = 127,
+ [1][1][RTW89_MKK][8] = 127,
+ [1][1][RTW89_IC][8] = 127,
+ [1][1][RTW89_KCC][8] = 127,
+ [1][1][RTW89_ACMA][8] = 127,
+ [1][1][RTW89_CN][8] = 32,
+ [1][1][RTW89_UK][8] = 127,
+ [1][1][RTW89_FCC][9] = 127,
+ [1][1][RTW89_ETSI][9] = 127,
+ [1][1][RTW89_MKK][9] = 127,
+ [1][1][RTW89_IC][9] = 127,
+ [1][1][RTW89_KCC][9] = 127,
+ [1][1][RTW89_ACMA][9] = 127,
+ [1][1][RTW89_CN][9] = 32,
+ [1][1][RTW89_UK][9] = 127,
+ [1][1][RTW89_FCC][10] = 127,
+ [1][1][RTW89_ETSI][10] = 127,
+ [1][1][RTW89_MKK][10] = 127,
+ [1][1][RTW89_IC][10] = 127,
+ [1][1][RTW89_KCC][10] = 127,
+ [1][1][RTW89_ACMA][10] = 127,
+ [1][1][RTW89_CN][10] = 32,
+ [1][1][RTW89_UK][10] = 127,
+ [1][1][RTW89_FCC][11] = 127,
+ [1][1][RTW89_ETSI][11] = 127,
+ [1][1][RTW89_MKK][11] = 127,
+ [1][1][RTW89_IC][11] = 127,
+ [1][1][RTW89_KCC][11] = 127,
+ [1][1][RTW89_ACMA][11] = 127,
+ [1][1][RTW89_CN][11] = 32,
+ [1][1][RTW89_UK][11] = 127,
+ [1][1][RTW89_FCC][12] = 127,
+ [1][1][RTW89_ETSI][12] = 127,
+ [1][1][RTW89_MKK][12] = 127,
+ [1][1][RTW89_IC][12] = 127,
+ [1][1][RTW89_KCC][12] = 127,
+ [1][1][RTW89_ACMA][12] = 127,
+ [1][1][RTW89_CN][12] = 32,
+ [1][1][RTW89_UK][12] = 127,
+ [1][1][RTW89_FCC][13] = 127,
+ [1][1][RTW89_ETSI][13] = 127,
+ [1][1][RTW89_MKK][13] = 127,
+ [1][1][RTW89_IC][13] = 127,
+ [1][1][RTW89_KCC][13] = 127,
+ [1][1][RTW89_ACMA][13] = 127,
+ [1][1][RTW89_CN][13] = 127,
+ [1][1][RTW89_UK][13] = 127,
+ [2][0][RTW89_FCC][0] = 74,
+ [2][0][RTW89_ETSI][0] = 54,
+ [2][0][RTW89_MKK][0] = 64,
+ [2][0][RTW89_IC][0] = 74,
+ [2][0][RTW89_KCC][0] = 68,
+ [2][0][RTW89_ACMA][0] = 54,
+ [2][0][RTW89_CN][0] = 56,
+ [2][0][RTW89_UK][0] = 54,
+ [2][0][RTW89_FCC][1] = 74,
+ [2][0][RTW89_ETSI][1] = 54,
+ [2][0][RTW89_MKK][1] = 64,
+ [2][0][RTW89_IC][1] = 74,
+ [2][0][RTW89_KCC][1] = 68,
+ [2][0][RTW89_ACMA][1] = 54,
+ [2][0][RTW89_CN][1] = 56,
+ [2][0][RTW89_UK][1] = 54,
+ [2][0][RTW89_FCC][2] = 76,
+ [2][0][RTW89_ETSI][2] = 54,
+ [2][0][RTW89_MKK][2] = 64,
+ [2][0][RTW89_IC][2] = 76,
+ [2][0][RTW89_KCC][2] = 68,
+ [2][0][RTW89_ACMA][2] = 54,
+ [2][0][RTW89_CN][2] = 56,
+ [2][0][RTW89_UK][2] = 54,
+ [2][0][RTW89_FCC][3] = 76,
+ [2][0][RTW89_ETSI][3] = 54,
+ [2][0][RTW89_MKK][3] = 64,
+ [2][0][RTW89_IC][3] = 76,
+ [2][0][RTW89_KCC][3] = 68,
+ [2][0][RTW89_ACMA][3] = 54,
+ [2][0][RTW89_CN][3] = 56,
+ [2][0][RTW89_UK][3] = 54,
+ [2][0][RTW89_FCC][4] = 76,
+ [2][0][RTW89_ETSI][4] = 54,
+ [2][0][RTW89_MKK][4] = 64,
+ [2][0][RTW89_IC][4] = 76,
+ [2][0][RTW89_KCC][4] = 68,
+ [2][0][RTW89_ACMA][4] = 54,
+ [2][0][RTW89_CN][4] = 56,
+ [2][0][RTW89_UK][4] = 54,
+ [2][0][RTW89_FCC][5] = 80,
+ [2][0][RTW89_ETSI][5] = 54,
+ [2][0][RTW89_MKK][5] = 64,
+ [2][0][RTW89_IC][5] = 80,
+ [2][0][RTW89_KCC][5] = 68,
+ [2][0][RTW89_ACMA][5] = 54,
+ [2][0][RTW89_CN][5] = 56,
+ [2][0][RTW89_UK][5] = 54,
+ [2][0][RTW89_FCC][6] = 72,
+ [2][0][RTW89_ETSI][6] = 54,
+ [2][0][RTW89_MKK][6] = 64,
+ [2][0][RTW89_IC][6] = 72,
+ [2][0][RTW89_KCC][6] = 68,
+ [2][0][RTW89_ACMA][6] = 54,
+ [2][0][RTW89_CN][6] = 56,
+ [2][0][RTW89_UK][6] = 54,
+ [2][0][RTW89_FCC][7] = 72,
+ [2][0][RTW89_ETSI][7] = 54,
+ [2][0][RTW89_MKK][7] = 64,
+ [2][0][RTW89_IC][7] = 72,
+ [2][0][RTW89_KCC][7] = 68,
+ [2][0][RTW89_ACMA][7] = 54,
+ [2][0][RTW89_CN][7] = 56,
+ [2][0][RTW89_UK][7] = 54,
+ [2][0][RTW89_FCC][8] = 72,
+ [2][0][RTW89_ETSI][8] = 54,
+ [2][0][RTW89_MKK][8] = 64,
+ [2][0][RTW89_IC][8] = 72,
+ [2][0][RTW89_KCC][8] = 68,
+ [2][0][RTW89_ACMA][8] = 54,
+ [2][0][RTW89_CN][8] = 56,
+ [2][0][RTW89_UK][8] = 54,
+ [2][0][RTW89_FCC][9] = 70,
+ [2][0][RTW89_ETSI][9] = 54,
+ [2][0][RTW89_MKK][9] = 64,
+ [2][0][RTW89_IC][9] = 70,
+ [2][0][RTW89_KCC][9] = 68,
+ [2][0][RTW89_ACMA][9] = 54,
+ [2][0][RTW89_CN][9] = 56,
+ [2][0][RTW89_UK][9] = 54,
+ [2][0][RTW89_FCC][10] = 70,
+ [2][0][RTW89_ETSI][10] = 54,
+ [2][0][RTW89_MKK][10] = 64,
+ [2][0][RTW89_IC][10] = 70,
+ [2][0][RTW89_KCC][10] = 68,
+ [2][0][RTW89_ACMA][10] = 54,
+ [2][0][RTW89_CN][10] = 56,
+ [2][0][RTW89_UK][10] = 54,
+ [2][0][RTW89_FCC][11] = 62,
+ [2][0][RTW89_ETSI][11] = 54,
+ [2][0][RTW89_MKK][11] = 64,
+ [2][0][RTW89_IC][11] = 62,
+ [2][0][RTW89_KCC][11] = 68,
+ [2][0][RTW89_ACMA][11] = 54,
+ [2][0][RTW89_CN][11] = 56,
+ [2][0][RTW89_UK][11] = 54,
+ [2][0][RTW89_FCC][12] = 34,
+ [2][0][RTW89_ETSI][12] = 54,
+ [2][0][RTW89_MKK][12] = 64,
+ [2][0][RTW89_IC][12] = 34,
+ [2][0][RTW89_KCC][12] = 68,
+ [2][0][RTW89_ACMA][12] = 54,
+ [2][0][RTW89_CN][12] = 56,
+ [2][0][RTW89_UK][12] = 54,
+ [2][0][RTW89_FCC][13] = 127,
+ [2][0][RTW89_ETSI][13] = 127,
+ [2][0][RTW89_MKK][13] = 127,
+ [2][0][RTW89_IC][13] = 127,
+ [2][0][RTW89_KCC][13] = 127,
+ [2][0][RTW89_ACMA][13] = 127,
+ [2][0][RTW89_CN][13] = 127,
+ [2][0][RTW89_UK][13] = 127,
+ [2][1][RTW89_FCC][0] = 127,
+ [2][1][RTW89_ETSI][0] = 127,
+ [2][1][RTW89_MKK][0] = 127,
+ [2][1][RTW89_IC][0] = 127,
+ [2][1][RTW89_KCC][0] = 127,
+ [2][1][RTW89_ACMA][0] = 127,
+ [2][1][RTW89_CN][0] = 44,
+ [2][1][RTW89_UK][0] = 127,
+ [2][1][RTW89_FCC][1] = 127,
+ [2][1][RTW89_ETSI][1] = 127,
+ [2][1][RTW89_MKK][1] = 127,
+ [2][1][RTW89_IC][1] = 127,
+ [2][1][RTW89_KCC][1] = 127,
+ [2][1][RTW89_ACMA][1] = 127,
+ [2][1][RTW89_CN][1] = 44,
+ [2][1][RTW89_UK][1] = 127,
+ [2][1][RTW89_FCC][2] = 127,
+ [2][1][RTW89_ETSI][2] = 127,
+ [2][1][RTW89_MKK][2] = 127,
+ [2][1][RTW89_IC][2] = 127,
+ [2][1][RTW89_KCC][2] = 127,
+ [2][1][RTW89_ACMA][2] = 127,
+ [2][1][RTW89_CN][2] = 44,
+ [2][1][RTW89_UK][2] = 127,
+ [2][1][RTW89_FCC][3] = 127,
+ [2][1][RTW89_ETSI][3] = 127,
+ [2][1][RTW89_MKK][3] = 127,
+ [2][1][RTW89_IC][3] = 127,
+ [2][1][RTW89_KCC][3] = 127,
+ [2][1][RTW89_ACMA][3] = 127,
+ [2][1][RTW89_CN][3] = 44,
+ [2][1][RTW89_UK][3] = 127,
+ [2][1][RTW89_FCC][4] = 127,
+ [2][1][RTW89_ETSI][4] = 127,
+ [2][1][RTW89_MKK][4] = 127,
+ [2][1][RTW89_IC][4] = 127,
+ [2][1][RTW89_KCC][4] = 127,
+ [2][1][RTW89_ACMA][4] = 127,
+ [2][1][RTW89_CN][4] = 44,
+ [2][1][RTW89_UK][4] = 127,
+ [2][1][RTW89_FCC][5] = 127,
+ [2][1][RTW89_ETSI][5] = 127,
+ [2][1][RTW89_MKK][5] = 127,
+ [2][1][RTW89_IC][5] = 127,
+ [2][1][RTW89_KCC][5] = 127,
+ [2][1][RTW89_ACMA][5] = 127,
+ [2][1][RTW89_CN][5] = 44,
+ [2][1][RTW89_UK][5] = 127,
+ [2][1][RTW89_FCC][6] = 127,
+ [2][1][RTW89_ETSI][6] = 127,
+ [2][1][RTW89_MKK][6] = 127,
+ [2][1][RTW89_IC][6] = 127,
+ [2][1][RTW89_KCC][6] = 127,
+ [2][1][RTW89_ACMA][6] = 127,
+ [2][1][RTW89_CN][6] = 44,
+ [2][1][RTW89_UK][6] = 127,
+ [2][1][RTW89_FCC][7] = 127,
+ [2][1][RTW89_ETSI][7] = 127,
+ [2][1][RTW89_MKK][7] = 127,
+ [2][1][RTW89_IC][7] = 127,
+ [2][1][RTW89_KCC][7] = 127,
+ [2][1][RTW89_ACMA][7] = 127,
+ [2][1][RTW89_CN][7] = 44,
+ [2][1][RTW89_UK][7] = 127,
+ [2][1][RTW89_FCC][8] = 127,
+ [2][1][RTW89_ETSI][8] = 127,
+ [2][1][RTW89_MKK][8] = 127,
+ [2][1][RTW89_IC][8] = 127,
+ [2][1][RTW89_KCC][8] = 127,
+ [2][1][RTW89_ACMA][8] = 127,
+ [2][1][RTW89_CN][8] = 44,
+ [2][1][RTW89_UK][8] = 127,
+ [2][1][RTW89_FCC][9] = 127,
+ [2][1][RTW89_ETSI][9] = 127,
+ [2][1][RTW89_MKK][9] = 127,
+ [2][1][RTW89_IC][9] = 127,
+ [2][1][RTW89_KCC][9] = 127,
+ [2][1][RTW89_ACMA][9] = 127,
+ [2][1][RTW89_CN][9] = 44,
+ [2][1][RTW89_UK][9] = 127,
+ [2][1][RTW89_FCC][10] = 127,
+ [2][1][RTW89_ETSI][10] = 127,
+ [2][1][RTW89_MKK][10] = 127,
+ [2][1][RTW89_IC][10] = 127,
+ [2][1][RTW89_KCC][10] = 127,
+ [2][1][RTW89_ACMA][10] = 127,
+ [2][1][RTW89_CN][10] = 44,
+ [2][1][RTW89_UK][10] = 127,
+ [2][1][RTW89_FCC][11] = 127,
+ [2][1][RTW89_ETSI][11] = 127,
+ [2][1][RTW89_MKK][11] = 127,
+ [2][1][RTW89_IC][11] = 127,
+ [2][1][RTW89_KCC][11] = 127,
+ [2][1][RTW89_ACMA][11] = 127,
+ [2][1][RTW89_CN][11] = 44,
+ [2][1][RTW89_UK][11] = 127,
+ [2][1][RTW89_FCC][12] = 127,
+ [2][1][RTW89_ETSI][12] = 127,
+ [2][1][RTW89_MKK][12] = 127,
+ [2][1][RTW89_IC][12] = 127,
+ [2][1][RTW89_KCC][12] = 127,
+ [2][1][RTW89_ACMA][12] = 127,
+ [2][1][RTW89_CN][12] = 42,
+ [2][1][RTW89_UK][12] = 127,
+ [2][1][RTW89_FCC][13] = 127,
+ [2][1][RTW89_ETSI][13] = 127,
+ [2][1][RTW89_MKK][13] = 127,
+ [2][1][RTW89_IC][13] = 127,
+ [2][1][RTW89_KCC][13] = 127,
+ [2][1][RTW89_ACMA][13] = 127,
+ [2][1][RTW89_CN][13] = 127,
+ [2][1][RTW89_UK][13] = 127,
+};
+
+static
+const s8 rtw89_8851b_txpwr_lmt_ru_5g_type2[RTW89_RU_NUM][RTW89_NTX_NUM]
+ [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
+ [0][0][RTW89_WW][0] = 16,
+ [0][0][RTW89_WW][2] = 16,
+ [0][0][RTW89_WW][4] = 16,
+ [0][0][RTW89_WW][6] = 16,
+ [0][0][RTW89_WW][8] = 16,
+ [0][0][RTW89_WW][10] = 16,
+ [0][0][RTW89_WW][12] = 16,
+ [0][0][RTW89_WW][14] = 16,
+ [0][0][RTW89_WW][15] = 24,
+ [0][0][RTW89_WW][17] = 24,
+ [0][0][RTW89_WW][19] = 24,
+ [0][0][RTW89_WW][21] = 24,
+ [0][0][RTW89_WW][23] = 24,
+ [0][0][RTW89_WW][25] = 24,
+ [0][0][RTW89_WW][27] = 24,
+ [0][0][RTW89_WW][29] = 24,
+ [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] = 24,
+ [0][0][RTW89_WW][40] = 24,
+ [0][0][RTW89_WW][42] = 24,
+ [0][0][RTW89_WW][44] = 24,
+ [0][0][RTW89_WW][46] = 24,
+ [0][0][RTW89_WW][48] = 40,
+ [0][0][RTW89_WW][50] = 42,
+ [0][0][RTW89_WW][52] = 38,
+ [0][1][RTW89_WW][0] = 4,
+ [0][1][RTW89_WW][2] = 4,
+ [0][1][RTW89_WW][4] = 4,
+ [0][1][RTW89_WW][6] = 4,
+ [0][1][RTW89_WW][8] = 4,
+ [0][1][RTW89_WW][10] = 4,
+ [0][1][RTW89_WW][12] = 4,
+ [0][1][RTW89_WW][14] = 4,
+ [0][1][RTW89_WW][15] = 0,
+ [0][1][RTW89_WW][17] = 0,
+ [0][1][RTW89_WW][19] = 0,
+ [0][1][RTW89_WW][21] = 0,
+ [0][1][RTW89_WW][23] = 0,
+ [0][1][RTW89_WW][25] = 0,
+ [0][1][RTW89_WW][27] = 0,
+ [0][1][RTW89_WW][29] = 0,
+ [0][1][RTW89_WW][31] = 0,
+ [0][1][RTW89_WW][33] = 0,
+ [0][1][RTW89_WW][35] = 0,
+ [0][1][RTW89_WW][37] = 0,
+ [0][1][RTW89_WW][38] = 42,
+ [0][1][RTW89_WW][40] = 42,
+ [0][1][RTW89_WW][42] = 42,
+ [0][1][RTW89_WW][44] = 42,
+ [0][1][RTW89_WW][46] = 42,
+ [0][1][RTW89_WW][48] = 0,
+ [0][1][RTW89_WW][50] = 0,
+ [0][1][RTW89_WW][52] = 0,
+ [1][0][RTW89_WW][0] = 26,
+ [1][0][RTW89_WW][2] = 26,
+ [1][0][RTW89_WW][4] = 26,
+ [1][0][RTW89_WW][6] = 26,
+ [1][0][RTW89_WW][8] = 26,
+ [1][0][RTW89_WW][10] = 26,
+ [1][0][RTW89_WW][12] = 26,
+ [1][0][RTW89_WW][14] = 26,
+ [1][0][RTW89_WW][15] = 34,
+ [1][0][RTW89_WW][17] = 34,
+ [1][0][RTW89_WW][19] = 34,
+ [1][0][RTW89_WW][21] = 34,
+ [1][0][RTW89_WW][23] = 34,
+ [1][0][RTW89_WW][25] = 34,
+ [1][0][RTW89_WW][27] = 34,
+ [1][0][RTW89_WW][29] = 34,
+ [1][0][RTW89_WW][31] = 34,
+ [1][0][RTW89_WW][33] = 34,
+ [1][0][RTW89_WW][35] = 34,
+ [1][0][RTW89_WW][37] = 54,
+ [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] = 52,
+ [1][0][RTW89_WW][50] = 52,
+ [1][0][RTW89_WW][52] = 50,
+ [1][1][RTW89_WW][0] = 14,
+ [1][1][RTW89_WW][2] = 14,
+ [1][1][RTW89_WW][4] = 14,
+ [1][1][RTW89_WW][6] = 14,
+ [1][1][RTW89_WW][8] = 14,
+ [1][1][RTW89_WW][10] = 14,
+ [1][1][RTW89_WW][12] = 14,
+ [1][1][RTW89_WW][14] = 14,
+ [1][1][RTW89_WW][15] = 0,
+ [1][1][RTW89_WW][17] = 0,
+ [1][1][RTW89_WW][19] = 0,
+ [1][1][RTW89_WW][21] = 0,
+ [1][1][RTW89_WW][23] = 0,
+ [1][1][RTW89_WW][25] = 0,
+ [1][1][RTW89_WW][27] = 0,
+ [1][1][RTW89_WW][29] = 0,
+ [1][1][RTW89_WW][31] = 0,
+ [1][1][RTW89_WW][33] = 0,
+ [1][1][RTW89_WW][35] = 0,
+ [1][1][RTW89_WW][37] = 0,
+ [1][1][RTW89_WW][38] = 54,
+ [1][1][RTW89_WW][40] = 54,
+ [1][1][RTW89_WW][42] = 54,
+ [1][1][RTW89_WW][44] = 54,
+ [1][1][RTW89_WW][46] = 54,
+ [1][1][RTW89_WW][48] = 0,
+ [1][1][RTW89_WW][50] = 0,
+ [1][1][RTW89_WW][52] = 0,
+ [2][0][RTW89_WW][0] = 40,
+ [2][0][RTW89_WW][2] = 40,
+ [2][0][RTW89_WW][4] = 40,
+ [2][0][RTW89_WW][6] = 40,
+ [2][0][RTW89_WW][8] = 40,
+ [2][0][RTW89_WW][10] = 40,
+ [2][0][RTW89_WW][12] = 40,
+ [2][0][RTW89_WW][14] = 40,
+ [2][0][RTW89_WW][15] = 46,
+ [2][0][RTW89_WW][17] = 46,
+ [2][0][RTW89_WW][19] = 46,
+ [2][0][RTW89_WW][21] = 46,
+ [2][0][RTW89_WW][23] = 46,
+ [2][0][RTW89_WW][25] = 46,
+ [2][0][RTW89_WW][27] = 46,
+ [2][0][RTW89_WW][29] = 46,
+ [2][0][RTW89_WW][31] = 46,
+ [2][0][RTW89_WW][33] = 46,
+ [2][0][RTW89_WW][35] = 46,
+ [2][0][RTW89_WW][37] = 66,
+ [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] = 62,
+ [2][0][RTW89_WW][50] = 62,
+ [2][0][RTW89_WW][52] = 60,
+ [2][1][RTW89_WW][0] = 28,
+ [2][1][RTW89_WW][2] = 28,
+ [2][1][RTW89_WW][4] = 28,
+ [2][1][RTW89_WW][6] = 28,
+ [2][1][RTW89_WW][8] = 28,
+ [2][1][RTW89_WW][10] = 28,
+ [2][1][RTW89_WW][12] = 28,
+ [2][1][RTW89_WW][14] = 28,
+ [2][1][RTW89_WW][15] = 0,
+ [2][1][RTW89_WW][17] = 0,
+ [2][1][RTW89_WW][19] = 0,
+ [2][1][RTW89_WW][21] = 0,
+ [2][1][RTW89_WW][23] = 0,
+ [2][1][RTW89_WW][25] = 0,
+ [2][1][RTW89_WW][27] = 0,
+ [2][1][RTW89_WW][29] = 0,
+ [2][1][RTW89_WW][31] = 0,
+ [2][1][RTW89_WW][33] = 0,
+ [2][1][RTW89_WW][35] = 0,
+ [2][1][RTW89_WW][37] = 0,
+ [2][1][RTW89_WW][38] = 56,
+ [2][1][RTW89_WW][40] = 56,
+ [2][1][RTW89_WW][42] = 56,
+ [2][1][RTW89_WW][44] = 56,
+ [2][1][RTW89_WW][46] = 56,
+ [2][1][RTW89_WW][48] = 0,
+ [2][1][RTW89_WW][50] = 0,
+ [2][1][RTW89_WW][52] = 0,
+ [0][0][RTW89_FCC][0] = 50,
+ [0][0][RTW89_ETSI][0] = 24,
+ [0][0][RTW89_MKK][0] = 26,
+ [0][0][RTW89_IC][0] = 28,
+ [0][0][RTW89_KCC][0] = 42,
+ [0][0][RTW89_ACMA][0] = 24,
+ [0][0][RTW89_CN][0] = 16,
+ [0][0][RTW89_UK][0] = 24,
+ [0][0][RTW89_FCC][2] = 54,
+ [0][0][RTW89_ETSI][2] = 24,
+ [0][0][RTW89_MKK][2] = 26,
+ [0][0][RTW89_IC][2] = 28,
+ [0][0][RTW89_KCC][2] = 42,
+ [0][0][RTW89_ACMA][2] = 24,
+ [0][0][RTW89_CN][2] = 16,
+ [0][0][RTW89_UK][2] = 24,
+ [0][0][RTW89_FCC][4] = 50,
+ [0][0][RTW89_ETSI][4] = 24,
+ [0][0][RTW89_MKK][4] = 26,
+ [0][0][RTW89_IC][4] = 28,
+ [0][0][RTW89_KCC][4] = 42,
+ [0][0][RTW89_ACMA][4] = 24,
+ [0][0][RTW89_CN][4] = 16,
+ [0][0][RTW89_UK][4] = 24,
+ [0][0][RTW89_FCC][6] = 50,
+ [0][0][RTW89_ETSI][6] = 24,
+ [0][0][RTW89_MKK][6] = 26,
+ [0][0][RTW89_IC][6] = 28,
+ [0][0][RTW89_KCC][6] = 18,
+ [0][0][RTW89_ACMA][6] = 24,
+ [0][0][RTW89_CN][6] = 16,
+ [0][0][RTW89_UK][6] = 24,
+ [0][0][RTW89_FCC][8] = 52,
+ [0][0][RTW89_ETSI][8] = 24,
+ [0][0][RTW89_MKK][8] = 26,
+ [0][0][RTW89_IC][8] = 52,
+ [0][0][RTW89_KCC][8] = 42,
+ [0][0][RTW89_ACMA][8] = 24,
+ [0][0][RTW89_CN][8] = 16,
+ [0][0][RTW89_UK][8] = 24,
+ [0][0][RTW89_FCC][10] = 52,
+ [0][0][RTW89_ETSI][10] = 24,
+ [0][0][RTW89_MKK][10] = 26,
+ [0][0][RTW89_IC][10] = 52,
+ [0][0][RTW89_KCC][10] = 42,
+ [0][0][RTW89_ACMA][10] = 24,
+ [0][0][RTW89_CN][10] = 16,
+ [0][0][RTW89_UK][10] = 24,
+ [0][0][RTW89_FCC][12] = 56,
+ [0][0][RTW89_ETSI][12] = 24,
+ [0][0][RTW89_MKK][12] = 26,
+ [0][0][RTW89_IC][12] = 56,
+ [0][0][RTW89_KCC][12] = 44,
+ [0][0][RTW89_ACMA][12] = 24,
+ [0][0][RTW89_CN][12] = 16,
+ [0][0][RTW89_UK][12] = 24,
+ [0][0][RTW89_FCC][14] = 56,
+ [0][0][RTW89_ETSI][14] = 24,
+ [0][0][RTW89_MKK][14] = 26,
+ [0][0][RTW89_IC][14] = 56,
+ [0][0][RTW89_KCC][14] = 44,
+ [0][0][RTW89_ACMA][14] = 24,
+ [0][0][RTW89_CN][14] = 16,
+ [0][0][RTW89_UK][14] = 24,
+ [0][0][RTW89_FCC][15] = 52,
+ [0][0][RTW89_ETSI][15] = 24,
+ [0][0][RTW89_MKK][15] = 46,
+ [0][0][RTW89_IC][15] = 52,
+ [0][0][RTW89_KCC][15] = 44,
+ [0][0][RTW89_ACMA][15] = 24,
+ [0][0][RTW89_CN][15] = 127,
+ [0][0][RTW89_UK][15] = 24,
+ [0][0][RTW89_FCC][17] = 52,
+ [0][0][RTW89_ETSI][17] = 24,
+ [0][0][RTW89_MKK][17] = 50,
+ [0][0][RTW89_IC][17] = 52,
+ [0][0][RTW89_KCC][17] = 44,
+ [0][0][RTW89_ACMA][17] = 24,
+ [0][0][RTW89_CN][17] = 127,
+ [0][0][RTW89_UK][17] = 24,
+ [0][0][RTW89_FCC][19] = 52,
+ [0][0][RTW89_ETSI][19] = 24,
+ [0][0][RTW89_MKK][19] = 50,
+ [0][0][RTW89_IC][19] = 52,
+ [0][0][RTW89_KCC][19] = 44,
+ [0][0][RTW89_ACMA][19] = 24,
+ [0][0][RTW89_CN][19] = 127,
+ [0][0][RTW89_UK][19] = 24,
+ [0][0][RTW89_FCC][21] = 52,
+ [0][0][RTW89_ETSI][21] = 24,
+ [0][0][RTW89_MKK][21] = 50,
+ [0][0][RTW89_IC][21] = 52,
+ [0][0][RTW89_KCC][21] = 44,
+ [0][0][RTW89_ACMA][21] = 24,
+ [0][0][RTW89_CN][21] = 127,
+ [0][0][RTW89_UK][21] = 24,
+ [0][0][RTW89_FCC][23] = 52,
+ [0][0][RTW89_ETSI][23] = 24,
+ [0][0][RTW89_MKK][23] = 50,
+ [0][0][RTW89_IC][23] = 52,
+ [0][0][RTW89_KCC][23] = 44,
+ [0][0][RTW89_ACMA][23] = 24,
+ [0][0][RTW89_CN][23] = 127,
+ [0][0][RTW89_UK][23] = 24,
+ [0][0][RTW89_FCC][25] = 52,
+ [0][0][RTW89_ETSI][25] = 24,
+ [0][0][RTW89_MKK][25] = 50,
+ [0][0][RTW89_IC][25] = 127,
+ [0][0][RTW89_KCC][25] = 44,
+ [0][0][RTW89_ACMA][25] = 127,
+ [0][0][RTW89_CN][25] = 127,
+ [0][0][RTW89_UK][25] = 24,
+ [0][0][RTW89_FCC][27] = 52,
+ [0][0][RTW89_ETSI][27] = 24,
+ [0][0][RTW89_MKK][27] = 50,
+ [0][0][RTW89_IC][27] = 127,
+ [0][0][RTW89_KCC][27] = 42,
+ [0][0][RTW89_ACMA][27] = 127,
+ [0][0][RTW89_CN][27] = 127,
+ [0][0][RTW89_UK][27] = 24,
+ [0][0][RTW89_FCC][29] = 52,
+ [0][0][RTW89_ETSI][29] = 24,
+ [0][0][RTW89_MKK][29] = 50,
+ [0][0][RTW89_IC][29] = 127,
+ [0][0][RTW89_KCC][29] = 42,
+ [0][0][RTW89_ACMA][29] = 127,
+ [0][0][RTW89_CN][29] = 127,
+ [0][0][RTW89_UK][29] = 24,
+ [0][0][RTW89_FCC][31] = 52,
+ [0][0][RTW89_ETSI][31] = 24,
+ [0][0][RTW89_MKK][31] = 50,
+ [0][0][RTW89_IC][31] = 56,
+ [0][0][RTW89_KCC][31] = 42,
+ [0][0][RTW89_ACMA][31] = 24,
+ [0][0][RTW89_CN][31] = 127,
+ [0][0][RTW89_UK][31] = 24,
+ [0][0][RTW89_FCC][33] = 56,
+ [0][0][RTW89_ETSI][33] = 24,
+ [0][0][RTW89_MKK][33] = 50,
+ [0][0][RTW89_IC][33] = 56,
+ [0][0][RTW89_KCC][33] = 42,
+ [0][0][RTW89_ACMA][33] = 24,
+ [0][0][RTW89_CN][33] = 127,
+ [0][0][RTW89_UK][33] = 24,
+ [0][0][RTW89_FCC][35] = 56,
+ [0][0][RTW89_ETSI][35] = 24,
+ [0][0][RTW89_MKK][35] = 50,
+ [0][0][RTW89_IC][35] = 56,
+ [0][0][RTW89_KCC][35] = 42,
+ [0][0][RTW89_ACMA][35] = 24,
+ [0][0][RTW89_CN][35] = 127,
+ [0][0][RTW89_UK][35] = 24,
+ [0][0][RTW89_FCC][37] = 84,
+ [0][0][RTW89_ETSI][37] = 127,
+ [0][0][RTW89_MKK][37] = 46,
+ [0][0][RTW89_IC][37] = 84,
+ [0][0][RTW89_KCC][37] = 44,
+ [0][0][RTW89_ACMA][37] = 50,
+ [0][0][RTW89_CN][37] = 127,
+ [0][0][RTW89_UK][37] = 52,
+ [0][0][RTW89_FCC][38] = 68,
+ [0][0][RTW89_ETSI][38] = 28,
+ [0][0][RTW89_MKK][38] = 127,
+ [0][0][RTW89_IC][38] = 68,
+ [0][0][RTW89_KCC][38] = 44,
+ [0][0][RTW89_ACMA][38] = 84,
+ [0][0][RTW89_CN][38] = 54,
+ [0][0][RTW89_UK][38] = 24,
+ [0][0][RTW89_FCC][40] = 68,
+ [0][0][RTW89_ETSI][40] = 28,
+ [0][0][RTW89_MKK][40] = 127,
+ [0][0][RTW89_IC][40] = 68,
+ [0][0][RTW89_KCC][40] = 44,
+ [0][0][RTW89_ACMA][40] = 84,
+ [0][0][RTW89_CN][40] = 54,
+ [0][0][RTW89_UK][40] = 24,
+ [0][0][RTW89_FCC][42] = 70,
+ [0][0][RTW89_ETSI][42] = 28,
+ [0][0][RTW89_MKK][42] = 127,
+ [0][0][RTW89_IC][42] = 70,
+ [0][0][RTW89_KCC][42] = 44,
+ [0][0][RTW89_ACMA][42] = 84,
+ [0][0][RTW89_CN][42] = 54,
+ [0][0][RTW89_UK][42] = 24,
+ [0][0][RTW89_FCC][44] = 62,
+ [0][0][RTW89_ETSI][44] = 28,
+ [0][0][RTW89_MKK][44] = 127,
+ [0][0][RTW89_IC][44] = 62,
+ [0][0][RTW89_KCC][44] = 44,
+ [0][0][RTW89_ACMA][44] = 84,
+ [0][0][RTW89_CN][44] = 54,
+ [0][0][RTW89_UK][44] = 24,
+ [0][0][RTW89_FCC][46] = 62,
+ [0][0][RTW89_ETSI][46] = 28,
+ [0][0][RTW89_MKK][46] = 127,
+ [0][0][RTW89_IC][46] = 62,
+ [0][0][RTW89_KCC][46] = 44,
+ [0][0][RTW89_ACMA][46] = 84,
+ [0][0][RTW89_CN][46] = 54,
+ [0][0][RTW89_UK][46] = 24,
+ [0][0][RTW89_FCC][48] = 40,
+ [0][0][RTW89_ETSI][48] = 127,
+ [0][0][RTW89_MKK][48] = 127,
+ [0][0][RTW89_IC][48] = 127,
+ [0][0][RTW89_KCC][48] = 127,
+ [0][0][RTW89_ACMA][48] = 127,
+ [0][0][RTW89_CN][48] = 127,
+ [0][0][RTW89_UK][48] = 127,
+ [0][0][RTW89_FCC][50] = 42,
+ [0][0][RTW89_ETSI][50] = 127,
+ [0][0][RTW89_MKK][50] = 127,
+ [0][0][RTW89_IC][50] = 127,
+ [0][0][RTW89_KCC][50] = 127,
+ [0][0][RTW89_ACMA][50] = 127,
+ [0][0][RTW89_CN][50] = 127,
+ [0][0][RTW89_UK][50] = 127,
+ [0][0][RTW89_FCC][52] = 38,
+ [0][0][RTW89_ETSI][52] = 127,
+ [0][0][RTW89_MKK][52] = 127,
+ [0][0][RTW89_IC][52] = 127,
+ [0][0][RTW89_KCC][52] = 127,
+ [0][0][RTW89_ACMA][52] = 127,
+ [0][0][RTW89_CN][52] = 127,
+ [0][0][RTW89_UK][52] = 127,
+ [0][1][RTW89_FCC][0] = 127,
+ [0][1][RTW89_ETSI][0] = 127,
+ [0][1][RTW89_MKK][0] = 127,
+ [0][1][RTW89_IC][0] = 127,
+ [0][1][RTW89_KCC][0] = 127,
+ [0][1][RTW89_ACMA][0] = 127,
+ [0][1][RTW89_CN][0] = 4,
+ [0][1][RTW89_UK][0] = 127,
+ [0][1][RTW89_FCC][2] = 127,
+ [0][1][RTW89_ETSI][2] = 127,
+ [0][1][RTW89_MKK][2] = 127,
+ [0][1][RTW89_IC][2] = 127,
+ [0][1][RTW89_KCC][2] = 127,
+ [0][1][RTW89_ACMA][2] = 127,
+ [0][1][RTW89_CN][2] = 4,
+ [0][1][RTW89_UK][2] = 127,
+ [0][1][RTW89_FCC][4] = 127,
+ [0][1][RTW89_ETSI][4] = 127,
+ [0][1][RTW89_MKK][4] = 127,
+ [0][1][RTW89_IC][4] = 127,
+ [0][1][RTW89_KCC][4] = 127,
+ [0][1][RTW89_ACMA][4] = 127,
+ [0][1][RTW89_CN][4] = 4,
+ [0][1][RTW89_UK][4] = 127,
+ [0][1][RTW89_FCC][6] = 127,
+ [0][1][RTW89_ETSI][6] = 127,
+ [0][1][RTW89_MKK][6] = 127,
+ [0][1][RTW89_IC][6] = 127,
+ [0][1][RTW89_KCC][6] = 127,
+ [0][1][RTW89_ACMA][6] = 127,
+ [0][1][RTW89_CN][6] = 4,
+ [0][1][RTW89_UK][6] = 127,
+ [0][1][RTW89_FCC][8] = 127,
+ [0][1][RTW89_ETSI][8] = 127,
+ [0][1][RTW89_MKK][8] = 127,
+ [0][1][RTW89_IC][8] = 127,
+ [0][1][RTW89_KCC][8] = 127,
+ [0][1][RTW89_ACMA][8] = 127,
+ [0][1][RTW89_CN][8] = 4,
+ [0][1][RTW89_UK][8] = 127,
+ [0][1][RTW89_FCC][10] = 127,
+ [0][1][RTW89_ETSI][10] = 127,
+ [0][1][RTW89_MKK][10] = 127,
+ [0][1][RTW89_IC][10] = 127,
+ [0][1][RTW89_KCC][10] = 127,
+ [0][1][RTW89_ACMA][10] = 127,
+ [0][1][RTW89_CN][10] = 4,
+ [0][1][RTW89_UK][10] = 127,
+ [0][1][RTW89_FCC][12] = 127,
+ [0][1][RTW89_ETSI][12] = 127,
+ [0][1][RTW89_MKK][12] = 127,
+ [0][1][RTW89_IC][12] = 127,
+ [0][1][RTW89_KCC][12] = 127,
+ [0][1][RTW89_ACMA][12] = 127,
+ [0][1][RTW89_CN][12] = 4,
+ [0][1][RTW89_UK][12] = 127,
+ [0][1][RTW89_FCC][14] = 127,
+ [0][1][RTW89_ETSI][14] = 127,
+ [0][1][RTW89_MKK][14] = 127,
+ [0][1][RTW89_IC][14] = 127,
+ [0][1][RTW89_KCC][14] = 127,
+ [0][1][RTW89_ACMA][14] = 127,
+ [0][1][RTW89_CN][14] = 4,
+ [0][1][RTW89_UK][14] = 127,
+ [0][1][RTW89_FCC][15] = 127,
+ [0][1][RTW89_ETSI][15] = 127,
+ [0][1][RTW89_MKK][15] = 127,
+ [0][1][RTW89_IC][15] = 127,
+ [0][1][RTW89_KCC][15] = 127,
+ [0][1][RTW89_ACMA][15] = 127,
+ [0][1][RTW89_CN][15] = 127,
+ [0][1][RTW89_UK][15] = 127,
+ [0][1][RTW89_FCC][17] = 127,
+ [0][1][RTW89_ETSI][17] = 127,
+ [0][1][RTW89_MKK][17] = 127,
+ [0][1][RTW89_IC][17] = 127,
+ [0][1][RTW89_KCC][17] = 127,
+ [0][1][RTW89_ACMA][17] = 127,
+ [0][1][RTW89_CN][17] = 127,
+ [0][1][RTW89_UK][17] = 127,
+ [0][1][RTW89_FCC][19] = 127,
+ [0][1][RTW89_ETSI][19] = 127,
+ [0][1][RTW89_MKK][19] = 127,
+ [0][1][RTW89_IC][19] = 127,
+ [0][1][RTW89_KCC][19] = 127,
+ [0][1][RTW89_ACMA][19] = 127,
+ [0][1][RTW89_CN][19] = 127,
+ [0][1][RTW89_UK][19] = 127,
+ [0][1][RTW89_FCC][21] = 127,
+ [0][1][RTW89_ETSI][21] = 127,
+ [0][1][RTW89_MKK][21] = 127,
+ [0][1][RTW89_IC][21] = 127,
+ [0][1][RTW89_KCC][21] = 127,
+ [0][1][RTW89_ACMA][21] = 127,
+ [0][1][RTW89_CN][21] = 127,
+ [0][1][RTW89_UK][21] = 127,
+ [0][1][RTW89_FCC][23] = 127,
+ [0][1][RTW89_ETSI][23] = 127,
+ [0][1][RTW89_MKK][23] = 127,
+ [0][1][RTW89_IC][23] = 127,
+ [0][1][RTW89_KCC][23] = 127,
+ [0][1][RTW89_ACMA][23] = 127,
+ [0][1][RTW89_CN][23] = 127,
+ [0][1][RTW89_UK][23] = 127,
+ [0][1][RTW89_FCC][25] = 127,
+ [0][1][RTW89_ETSI][25] = 127,
+ [0][1][RTW89_MKK][25] = 127,
+ [0][1][RTW89_IC][25] = 127,
+ [0][1][RTW89_KCC][25] = 127,
+ [0][1][RTW89_ACMA][25] = 127,
+ [0][1][RTW89_CN][25] = 127,
+ [0][1][RTW89_UK][25] = 127,
+ [0][1][RTW89_FCC][27] = 127,
+ [0][1][RTW89_ETSI][27] = 127,
+ [0][1][RTW89_MKK][27] = 127,
+ [0][1][RTW89_IC][27] = 127,
+ [0][1][RTW89_KCC][27] = 127,
+ [0][1][RTW89_ACMA][27] = 127,
+ [0][1][RTW89_CN][27] = 127,
+ [0][1][RTW89_UK][27] = 127,
+ [0][1][RTW89_FCC][29] = 127,
+ [0][1][RTW89_ETSI][29] = 127,
+ [0][1][RTW89_MKK][29] = 127,
+ [0][1][RTW89_IC][29] = 127,
+ [0][1][RTW89_KCC][29] = 127,
+ [0][1][RTW89_ACMA][29] = 127,
+ [0][1][RTW89_CN][29] = 127,
+ [0][1][RTW89_UK][29] = 127,
+ [0][1][RTW89_FCC][31] = 127,
+ [0][1][RTW89_ETSI][31] = 127,
+ [0][1][RTW89_MKK][31] = 127,
+ [0][1][RTW89_IC][31] = 127,
+ [0][1][RTW89_KCC][31] = 127,
+ [0][1][RTW89_ACMA][31] = 127,
+ [0][1][RTW89_CN][31] = 127,
+ [0][1][RTW89_UK][31] = 127,
+ [0][1][RTW89_FCC][33] = 127,
+ [0][1][RTW89_ETSI][33] = 127,
+ [0][1][RTW89_MKK][33] = 127,
+ [0][1][RTW89_IC][33] = 127,
+ [0][1][RTW89_KCC][33] = 127,
+ [0][1][RTW89_ACMA][33] = 127,
+ [0][1][RTW89_CN][33] = 127,
+ [0][1][RTW89_UK][33] = 127,
+ [0][1][RTW89_FCC][35] = 127,
+ [0][1][RTW89_ETSI][35] = 127,
+ [0][1][RTW89_MKK][35] = 127,
+ [0][1][RTW89_IC][35] = 127,
+ [0][1][RTW89_KCC][35] = 127,
+ [0][1][RTW89_ACMA][35] = 127,
+ [0][1][RTW89_CN][35] = 127,
+ [0][1][RTW89_UK][35] = 127,
+ [0][1][RTW89_FCC][37] = 127,
+ [0][1][RTW89_ETSI][37] = 127,
+ [0][1][RTW89_MKK][37] = 127,
+ [0][1][RTW89_IC][37] = 127,
+ [0][1][RTW89_KCC][37] = 127,
+ [0][1][RTW89_ACMA][37] = 127,
+ [0][1][RTW89_CN][37] = 127,
+ [0][1][RTW89_UK][37] = 127,
+ [0][1][RTW89_FCC][38] = 127,
+ [0][1][RTW89_ETSI][38] = 127,
+ [0][1][RTW89_MKK][38] = 127,
+ [0][1][RTW89_IC][38] = 127,
+ [0][1][RTW89_KCC][38] = 127,
+ [0][1][RTW89_ACMA][38] = 127,
+ [0][1][RTW89_CN][38] = 42,
+ [0][1][RTW89_UK][38] = 127,
+ [0][1][RTW89_FCC][40] = 127,
+ [0][1][RTW89_ETSI][40] = 127,
+ [0][1][RTW89_MKK][40] = 127,
+ [0][1][RTW89_IC][40] = 127,
+ [0][1][RTW89_KCC][40] = 127,
+ [0][1][RTW89_ACMA][40] = 127,
+ [0][1][RTW89_CN][40] = 42,
+ [0][1][RTW89_UK][40] = 127,
+ [0][1][RTW89_FCC][42] = 127,
+ [0][1][RTW89_ETSI][42] = 127,
+ [0][1][RTW89_MKK][42] = 127,
+ [0][1][RTW89_IC][42] = 127,
+ [0][1][RTW89_KCC][42] = 127,
+ [0][1][RTW89_ACMA][42] = 127,
+ [0][1][RTW89_CN][42] = 42,
+ [0][1][RTW89_UK][42] = 127,
+ [0][1][RTW89_FCC][44] = 127,
+ [0][1][RTW89_ETSI][44] = 127,
+ [0][1][RTW89_MKK][44] = 127,
+ [0][1][RTW89_IC][44] = 127,
+ [0][1][RTW89_KCC][44] = 127,
+ [0][1][RTW89_ACMA][44] = 127,
+ [0][1][RTW89_CN][44] = 42,
+ [0][1][RTW89_UK][44] = 127,
+ [0][1][RTW89_FCC][46] = 127,
+ [0][1][RTW89_ETSI][46] = 127,
+ [0][1][RTW89_MKK][46] = 127,
+ [0][1][RTW89_IC][46] = 127,
+ [0][1][RTW89_KCC][46] = 127,
+ [0][1][RTW89_ACMA][46] = 127,
+ [0][1][RTW89_CN][46] = 42,
+ [0][1][RTW89_UK][46] = 127,
+ [0][1][RTW89_FCC][48] = 127,
+ [0][1][RTW89_ETSI][48] = 127,
+ [0][1][RTW89_MKK][48] = 127,
+ [0][1][RTW89_IC][48] = 127,
+ [0][1][RTW89_KCC][48] = 127,
+ [0][1][RTW89_ACMA][48] = 127,
+ [0][1][RTW89_CN][48] = 127,
+ [0][1][RTW89_UK][48] = 127,
+ [0][1][RTW89_FCC][50] = 127,
+ [0][1][RTW89_ETSI][50] = 127,
+ [0][1][RTW89_MKK][50] = 127,
+ [0][1][RTW89_IC][50] = 127,
+ [0][1][RTW89_KCC][50] = 127,
+ [0][1][RTW89_ACMA][50] = 127,
+ [0][1][RTW89_CN][50] = 127,
+ [0][1][RTW89_UK][50] = 127,
+ [0][1][RTW89_FCC][52] = 127,
+ [0][1][RTW89_ETSI][52] = 127,
+ [0][1][RTW89_MKK][52] = 127,
+ [0][1][RTW89_IC][52] = 127,
+ [0][1][RTW89_KCC][52] = 127,
+ [0][1][RTW89_ACMA][52] = 127,
+ [0][1][RTW89_CN][52] = 127,
+ [0][1][RTW89_UK][52] = 127,
+ [1][0][RTW89_FCC][0] = 64,
+ [1][0][RTW89_ETSI][0] = 34,
+ [1][0][RTW89_MKK][0] = 38,
+ [1][0][RTW89_IC][0] = 38,
+ [1][0][RTW89_KCC][0] = 52,
+ [1][0][RTW89_ACMA][0] = 34,
+ [1][0][RTW89_CN][0] = 26,
+ [1][0][RTW89_UK][0] = 34,
+ [1][0][RTW89_FCC][2] = 66,
+ [1][0][RTW89_ETSI][2] = 34,
+ [1][0][RTW89_MKK][2] = 38,
+ [1][0][RTW89_IC][2] = 38,
+ [1][0][RTW89_KCC][2] = 52,
+ [1][0][RTW89_ACMA][2] = 34,
+ [1][0][RTW89_CN][2] = 26,
+ [1][0][RTW89_UK][2] = 34,
+ [1][0][RTW89_FCC][4] = 60,
+ [1][0][RTW89_ETSI][4] = 34,
+ [1][0][RTW89_MKK][4] = 36,
+ [1][0][RTW89_IC][4] = 38,
+ [1][0][RTW89_KCC][4] = 52,
+ [1][0][RTW89_ACMA][4] = 34,
+ [1][0][RTW89_CN][4] = 26,
+ [1][0][RTW89_UK][4] = 34,
+ [1][0][RTW89_FCC][6] = 60,
+ [1][0][RTW89_ETSI][6] = 34,
+ [1][0][RTW89_MKK][6] = 36,
+ [1][0][RTW89_IC][6] = 38,
+ [1][0][RTW89_KCC][6] = 32,
+ [1][0][RTW89_ACMA][6] = 34,
+ [1][0][RTW89_CN][6] = 26,
+ [1][0][RTW89_UK][6] = 34,
+ [1][0][RTW89_FCC][8] = 62,
+ [1][0][RTW89_ETSI][8] = 34,
+ [1][0][RTW89_MKK][8] = 38,
+ [1][0][RTW89_IC][8] = 62,
+ [1][0][RTW89_KCC][8] = 52,
+ [1][0][RTW89_ACMA][8] = 34,
+ [1][0][RTW89_CN][8] = 26,
+ [1][0][RTW89_UK][8] = 34,
+ [1][0][RTW89_FCC][10] = 62,
+ [1][0][RTW89_ETSI][10] = 34,
+ [1][0][RTW89_MKK][10] = 38,
+ [1][0][RTW89_IC][10] = 62,
+ [1][0][RTW89_KCC][10] = 52,
+ [1][0][RTW89_ACMA][10] = 34,
+ [1][0][RTW89_CN][10] = 26,
+ [1][0][RTW89_UK][10] = 34,
+ [1][0][RTW89_FCC][12] = 62,
+ [1][0][RTW89_ETSI][12] = 34,
+ [1][0][RTW89_MKK][12] = 38,
+ [1][0][RTW89_IC][12] = 62,
+ [1][0][RTW89_KCC][12] = 54,
+ [1][0][RTW89_ACMA][12] = 34,
+ [1][0][RTW89_CN][12] = 26,
+ [1][0][RTW89_UK][12] = 34,
+ [1][0][RTW89_FCC][14] = 62,
+ [1][0][RTW89_ETSI][14] = 34,
+ [1][0][RTW89_MKK][14] = 38,
+ [1][0][RTW89_IC][14] = 62,
+ [1][0][RTW89_KCC][14] = 54,
+ [1][0][RTW89_ACMA][14] = 34,
+ [1][0][RTW89_CN][14] = 26,
+ [1][0][RTW89_UK][14] = 34,
+ [1][0][RTW89_FCC][15] = 60,
+ [1][0][RTW89_ETSI][15] = 34,
+ [1][0][RTW89_MKK][15] = 58,
+ [1][0][RTW89_IC][15] = 60,
+ [1][0][RTW89_KCC][15] = 54,
+ [1][0][RTW89_ACMA][15] = 34,
+ [1][0][RTW89_CN][15] = 127,
+ [1][0][RTW89_UK][15] = 34,
+ [1][0][RTW89_FCC][17] = 60,
+ [1][0][RTW89_ETSI][17] = 34,
+ [1][0][RTW89_MKK][17] = 58,
+ [1][0][RTW89_IC][17] = 60,
+ [1][0][RTW89_KCC][17] = 54,
+ [1][0][RTW89_ACMA][17] = 34,
+ [1][0][RTW89_CN][17] = 127,
+ [1][0][RTW89_UK][17] = 34,
+ [1][0][RTW89_FCC][19] = 62,
+ [1][0][RTW89_ETSI][19] = 34,
+ [1][0][RTW89_MKK][19] = 58,
+ [1][0][RTW89_IC][19] = 62,
+ [1][0][RTW89_KCC][19] = 54,
+ [1][0][RTW89_ACMA][19] = 34,
+ [1][0][RTW89_CN][19] = 127,
+ [1][0][RTW89_UK][19] = 34,
+ [1][0][RTW89_FCC][21] = 62,
+ [1][0][RTW89_ETSI][21] = 34,
+ [1][0][RTW89_MKK][21] = 58,
+ [1][0][RTW89_IC][21] = 62,
+ [1][0][RTW89_KCC][21] = 54,
+ [1][0][RTW89_ACMA][21] = 34,
+ [1][0][RTW89_CN][21] = 127,
+ [1][0][RTW89_UK][21] = 34,
+ [1][0][RTW89_FCC][23] = 62,
+ [1][0][RTW89_ETSI][23] = 34,
+ [1][0][RTW89_MKK][23] = 58,
+ [1][0][RTW89_IC][23] = 62,
+ [1][0][RTW89_KCC][23] = 54,
+ [1][0][RTW89_ACMA][23] = 34,
+ [1][0][RTW89_CN][23] = 127,
+ [1][0][RTW89_UK][23] = 34,
+ [1][0][RTW89_FCC][25] = 62,
+ [1][0][RTW89_ETSI][25] = 34,
+ [1][0][RTW89_MKK][25] = 58,
+ [1][0][RTW89_IC][25] = 127,
+ [1][0][RTW89_KCC][25] = 54,
+ [1][0][RTW89_ACMA][25] = 127,
+ [1][0][RTW89_CN][25] = 127,
+ [1][0][RTW89_UK][25] = 34,
+ [1][0][RTW89_FCC][27] = 62,
+ [1][0][RTW89_ETSI][27] = 34,
+ [1][0][RTW89_MKK][27] = 58,
+ [1][0][RTW89_IC][27] = 127,
+ [1][0][RTW89_KCC][27] = 54,
+ [1][0][RTW89_ACMA][27] = 127,
+ [1][0][RTW89_CN][27] = 127,
+ [1][0][RTW89_UK][27] = 34,
+ [1][0][RTW89_FCC][29] = 62,
+ [1][0][RTW89_ETSI][29] = 34,
+ [1][0][RTW89_MKK][29] = 58,
+ [1][0][RTW89_IC][29] = 127,
+ [1][0][RTW89_KCC][29] = 54,
+ [1][0][RTW89_ACMA][29] = 127,
+ [1][0][RTW89_CN][29] = 127,
+ [1][0][RTW89_UK][29] = 34,
+ [1][0][RTW89_FCC][31] = 62,
+ [1][0][RTW89_ETSI][31] = 34,
+ [1][0][RTW89_MKK][31] = 58,
+ [1][0][RTW89_IC][31] = 64,
+ [1][0][RTW89_KCC][31] = 54,
+ [1][0][RTW89_ACMA][31] = 34,
+ [1][0][RTW89_CN][31] = 127,
+ [1][0][RTW89_UK][31] = 34,
+ [1][0][RTW89_FCC][33] = 64,
+ [1][0][RTW89_ETSI][33] = 34,
+ [1][0][RTW89_MKK][33] = 58,
+ [1][0][RTW89_IC][33] = 64,
+ [1][0][RTW89_KCC][33] = 54,
+ [1][0][RTW89_ACMA][33] = 34,
+ [1][0][RTW89_CN][33] = 127,
+ [1][0][RTW89_UK][33] = 34,
+ [1][0][RTW89_FCC][35] = 64,
+ [1][0][RTW89_ETSI][35] = 34,
+ [1][0][RTW89_MKK][35] = 58,
+ [1][0][RTW89_IC][35] = 64,
+ [1][0][RTW89_KCC][35] = 54,
+ [1][0][RTW89_ACMA][35] = 34,
+ [1][0][RTW89_CN][35] = 127,
+ [1][0][RTW89_UK][35] = 34,
+ [1][0][RTW89_FCC][37] = 76,
+ [1][0][RTW89_ETSI][37] = 127,
+ [1][0][RTW89_MKK][37] = 56,
+ [1][0][RTW89_IC][37] = 76,
+ [1][0][RTW89_KCC][37] = 54,
+ [1][0][RTW89_ACMA][37] = 62,
+ [1][0][RTW89_CN][37] = 127,
+ [1][0][RTW89_UK][37] = 62,
+ [1][0][RTW89_FCC][38] = 82,
+ [1][0][RTW89_ETSI][38] = 28,
+ [1][0][RTW89_MKK][38] = 127,
+ [1][0][RTW89_IC][38] = 82,
+ [1][0][RTW89_KCC][38] = 54,
+ [1][0][RTW89_ACMA][38] = 84,
+ [1][0][RTW89_CN][38] = 66,
+ [1][0][RTW89_UK][38] = 34,
+ [1][0][RTW89_FCC][40] = 82,
+ [1][0][RTW89_ETSI][40] = 28,
+ [1][0][RTW89_MKK][40] = 127,
+ [1][0][RTW89_IC][40] = 82,
+ [1][0][RTW89_KCC][40] = 54,
+ [1][0][RTW89_ACMA][40] = 84,
+ [1][0][RTW89_CN][40] = 66,
+ [1][0][RTW89_UK][40] = 34,
+ [1][0][RTW89_FCC][42] = 78,
+ [1][0][RTW89_ETSI][42] = 28,
+ [1][0][RTW89_MKK][42] = 127,
+ [1][0][RTW89_IC][42] = 78,
+ [1][0][RTW89_KCC][42] = 54,
+ [1][0][RTW89_ACMA][42] = 84,
+ [1][0][RTW89_CN][42] = 66,
+ [1][0][RTW89_UK][42] = 34,
+ [1][0][RTW89_FCC][44] = 82,
+ [1][0][RTW89_ETSI][44] = 28,
+ [1][0][RTW89_MKK][44] = 127,
+ [1][0][RTW89_IC][44] = 82,
+ [1][0][RTW89_KCC][44] = 54,
+ [1][0][RTW89_ACMA][44] = 84,
+ [1][0][RTW89_CN][44] = 66,
+ [1][0][RTW89_UK][44] = 34,
+ [1][0][RTW89_FCC][46] = 82,
+ [1][0][RTW89_ETSI][46] = 28,
+ [1][0][RTW89_MKK][46] = 127,
+ [1][0][RTW89_IC][46] = 82,
+ [1][0][RTW89_KCC][46] = 54,
+ [1][0][RTW89_ACMA][46] = 84,
+ [1][0][RTW89_CN][46] = 66,
+ [1][0][RTW89_UK][46] = 34,
+ [1][0][RTW89_FCC][48] = 52,
+ [1][0][RTW89_ETSI][48] = 127,
+ [1][0][RTW89_MKK][48] = 127,
+ [1][0][RTW89_IC][48] = 127,
+ [1][0][RTW89_KCC][48] = 127,
+ [1][0][RTW89_ACMA][48] = 127,
+ [1][0][RTW89_CN][48] = 127,
+ [1][0][RTW89_UK][48] = 127,
+ [1][0][RTW89_FCC][50] = 52,
+ [1][0][RTW89_ETSI][50] = 127,
+ [1][0][RTW89_MKK][50] = 127,
+ [1][0][RTW89_IC][50] = 127,
+ [1][0][RTW89_KCC][50] = 127,
+ [1][0][RTW89_ACMA][50] = 127,
+ [1][0][RTW89_CN][50] = 127,
+ [1][0][RTW89_UK][50] = 127,
+ [1][0][RTW89_FCC][52] = 50,
+ [1][0][RTW89_ETSI][52] = 127,
+ [1][0][RTW89_MKK][52] = 127,
+ [1][0][RTW89_IC][52] = 127,
+ [1][0][RTW89_KCC][52] = 127,
+ [1][0][RTW89_ACMA][52] = 127,
+ [1][0][RTW89_CN][52] = 127,
+ [1][0][RTW89_UK][52] = 127,
+ [1][1][RTW89_FCC][0] = 127,
+ [1][1][RTW89_ETSI][0] = 127,
+ [1][1][RTW89_MKK][0] = 127,
+ [1][1][RTW89_IC][0] = 127,
+ [1][1][RTW89_KCC][0] = 127,
+ [1][1][RTW89_ACMA][0] = 127,
+ [1][1][RTW89_CN][0] = 14,
+ [1][1][RTW89_UK][0] = 127,
+ [1][1][RTW89_FCC][2] = 127,
+ [1][1][RTW89_ETSI][2] = 127,
+ [1][1][RTW89_MKK][2] = 127,
+ [1][1][RTW89_IC][2] = 127,
+ [1][1][RTW89_KCC][2] = 127,
+ [1][1][RTW89_ACMA][2] = 127,
+ [1][1][RTW89_CN][2] = 14,
+ [1][1][RTW89_UK][2] = 127,
+ [1][1][RTW89_FCC][4] = 127,
+ [1][1][RTW89_ETSI][4] = 127,
+ [1][1][RTW89_MKK][4] = 127,
+ [1][1][RTW89_IC][4] = 127,
+ [1][1][RTW89_KCC][4] = 127,
+ [1][1][RTW89_ACMA][4] = 127,
+ [1][1][RTW89_CN][4] = 14,
+ [1][1][RTW89_UK][4] = 127,
+ [1][1][RTW89_FCC][6] = 127,
+ [1][1][RTW89_ETSI][6] = 127,
+ [1][1][RTW89_MKK][6] = 127,
+ [1][1][RTW89_IC][6] = 127,
+ [1][1][RTW89_KCC][6] = 127,
+ [1][1][RTW89_ACMA][6] = 127,
+ [1][1][RTW89_CN][6] = 14,
+ [1][1][RTW89_UK][6] = 127,
+ [1][1][RTW89_FCC][8] = 127,
+ [1][1][RTW89_ETSI][8] = 127,
+ [1][1][RTW89_MKK][8] = 127,
+ [1][1][RTW89_IC][8] = 127,
+ [1][1][RTW89_KCC][8] = 127,
+ [1][1][RTW89_ACMA][8] = 127,
+ [1][1][RTW89_CN][8] = 14,
+ [1][1][RTW89_UK][8] = 127,
+ [1][1][RTW89_FCC][10] = 127,
+ [1][1][RTW89_ETSI][10] = 127,
+ [1][1][RTW89_MKK][10] = 127,
+ [1][1][RTW89_IC][10] = 127,
+ [1][1][RTW89_KCC][10] = 127,
+ [1][1][RTW89_ACMA][10] = 127,
+ [1][1][RTW89_CN][10] = 14,
+ [1][1][RTW89_UK][10] = 127,
+ [1][1][RTW89_FCC][12] = 127,
+ [1][1][RTW89_ETSI][12] = 127,
+ [1][1][RTW89_MKK][12] = 127,
+ [1][1][RTW89_IC][12] = 127,
+ [1][1][RTW89_KCC][12] = 127,
+ [1][1][RTW89_ACMA][12] = 127,
+ [1][1][RTW89_CN][12] = 14,
+ [1][1][RTW89_UK][12] = 127,
+ [1][1][RTW89_FCC][14] = 127,
+ [1][1][RTW89_ETSI][14] = 127,
+ [1][1][RTW89_MKK][14] = 127,
+ [1][1][RTW89_IC][14] = 127,
+ [1][1][RTW89_KCC][14] = 127,
+ [1][1][RTW89_ACMA][14] = 127,
+ [1][1][RTW89_CN][14] = 14,
+ [1][1][RTW89_UK][14] = 127,
+ [1][1][RTW89_FCC][15] = 127,
+ [1][1][RTW89_ETSI][15] = 127,
+ [1][1][RTW89_MKK][15] = 127,
+ [1][1][RTW89_IC][15] = 127,
+ [1][1][RTW89_KCC][15] = 127,
+ [1][1][RTW89_ACMA][15] = 127,
+ [1][1][RTW89_CN][15] = 127,
+ [1][1][RTW89_UK][15] = 127,
+ [1][1][RTW89_FCC][17] = 127,
+ [1][1][RTW89_ETSI][17] = 127,
+ [1][1][RTW89_MKK][17] = 127,
+ [1][1][RTW89_IC][17] = 127,
+ [1][1][RTW89_KCC][17] = 127,
+ [1][1][RTW89_ACMA][17] = 127,
+ [1][1][RTW89_CN][17] = 127,
+ [1][1][RTW89_UK][17] = 127,
+ [1][1][RTW89_FCC][19] = 127,
+ [1][1][RTW89_ETSI][19] = 127,
+ [1][1][RTW89_MKK][19] = 127,
+ [1][1][RTW89_IC][19] = 127,
+ [1][1][RTW89_KCC][19] = 127,
+ [1][1][RTW89_ACMA][19] = 127,
+ [1][1][RTW89_CN][19] = 127,
+ [1][1][RTW89_UK][19] = 127,
+ [1][1][RTW89_FCC][21] = 127,
+ [1][1][RTW89_ETSI][21] = 127,
+ [1][1][RTW89_MKK][21] = 127,
+ [1][1][RTW89_IC][21] = 127,
+ [1][1][RTW89_KCC][21] = 127,
+ [1][1][RTW89_ACMA][21] = 127,
+ [1][1][RTW89_CN][21] = 127,
+ [1][1][RTW89_UK][21] = 127,
+ [1][1][RTW89_FCC][23] = 127,
+ [1][1][RTW89_ETSI][23] = 127,
+ [1][1][RTW89_MKK][23] = 127,
+ [1][1][RTW89_IC][23] = 127,
+ [1][1][RTW89_KCC][23] = 127,
+ [1][1][RTW89_ACMA][23] = 127,
+ [1][1][RTW89_CN][23] = 127,
+ [1][1][RTW89_UK][23] = 127,
+ [1][1][RTW89_FCC][25] = 127,
+ [1][1][RTW89_ETSI][25] = 127,
+ [1][1][RTW89_MKK][25] = 127,
+ [1][1][RTW89_IC][25] = 127,
+ [1][1][RTW89_KCC][25] = 127,
+ [1][1][RTW89_ACMA][25] = 127,
+ [1][1][RTW89_CN][25] = 127,
+ [1][1][RTW89_UK][25] = 127,
+ [1][1][RTW89_FCC][27] = 127,
+ [1][1][RTW89_ETSI][27] = 127,
+ [1][1][RTW89_MKK][27] = 127,
+ [1][1][RTW89_IC][27] = 127,
+ [1][1][RTW89_KCC][27] = 127,
+ [1][1][RTW89_ACMA][27] = 127,
+ [1][1][RTW89_CN][27] = 127,
+ [1][1][RTW89_UK][27] = 127,
+ [1][1][RTW89_FCC][29] = 127,
+ [1][1][RTW89_ETSI][29] = 127,
+ [1][1][RTW89_MKK][29] = 127,
+ [1][1][RTW89_IC][29] = 127,
+ [1][1][RTW89_KCC][29] = 127,
+ [1][1][RTW89_ACMA][29] = 127,
+ [1][1][RTW89_CN][29] = 127,
+ [1][1][RTW89_UK][29] = 127,
+ [1][1][RTW89_FCC][31] = 127,
+ [1][1][RTW89_ETSI][31] = 127,
+ [1][1][RTW89_MKK][31] = 127,
+ [1][1][RTW89_IC][31] = 127,
+ [1][1][RTW89_KCC][31] = 127,
+ [1][1][RTW89_ACMA][31] = 127,
+ [1][1][RTW89_CN][31] = 127,
+ [1][1][RTW89_UK][31] = 127,
+ [1][1][RTW89_FCC][33] = 127,
+ [1][1][RTW89_ETSI][33] = 127,
+ [1][1][RTW89_MKK][33] = 127,
+ [1][1][RTW89_IC][33] = 127,
+ [1][1][RTW89_KCC][33] = 127,
+ [1][1][RTW89_ACMA][33] = 127,
+ [1][1][RTW89_CN][33] = 127,
+ [1][1][RTW89_UK][33] = 127,
+ [1][1][RTW89_FCC][35] = 127,
+ [1][1][RTW89_ETSI][35] = 127,
+ [1][1][RTW89_MKK][35] = 127,
+ [1][1][RTW89_IC][35] = 127,
+ [1][1][RTW89_KCC][35] = 127,
+ [1][1][RTW89_ACMA][35] = 127,
+ [1][1][RTW89_CN][35] = 127,
+ [1][1][RTW89_UK][35] = 127,
+ [1][1][RTW89_FCC][37] = 127,
+ [1][1][RTW89_ETSI][37] = 127,
+ [1][1][RTW89_MKK][37] = 127,
+ [1][1][RTW89_IC][37] = 127,
+ [1][1][RTW89_KCC][37] = 127,
+ [1][1][RTW89_ACMA][37] = 127,
+ [1][1][RTW89_CN][37] = 127,
+ [1][1][RTW89_UK][37] = 127,
+ [1][1][RTW89_FCC][38] = 127,
+ [1][1][RTW89_ETSI][38] = 127,
+ [1][1][RTW89_MKK][38] = 127,
+ [1][1][RTW89_IC][38] = 127,
+ [1][1][RTW89_KCC][38] = 127,
+ [1][1][RTW89_ACMA][38] = 127,
+ [1][1][RTW89_CN][38] = 54,
+ [1][1][RTW89_UK][38] = 127,
+ [1][1][RTW89_FCC][40] = 127,
+ [1][1][RTW89_ETSI][40] = 127,
+ [1][1][RTW89_MKK][40] = 127,
+ [1][1][RTW89_IC][40] = 127,
+ [1][1][RTW89_KCC][40] = 127,
+ [1][1][RTW89_ACMA][40] = 127,
+ [1][1][RTW89_CN][40] = 54,
+ [1][1][RTW89_UK][40] = 127,
+ [1][1][RTW89_FCC][42] = 127,
+ [1][1][RTW89_ETSI][42] = 127,
+ [1][1][RTW89_MKK][42] = 127,
+ [1][1][RTW89_IC][42] = 127,
+ [1][1][RTW89_KCC][42] = 127,
+ [1][1][RTW89_ACMA][42] = 127,
+ [1][1][RTW89_CN][42] = 54,
+ [1][1][RTW89_UK][42] = 127,
+ [1][1][RTW89_FCC][44] = 127,
+ [1][1][RTW89_ETSI][44] = 127,
+ [1][1][RTW89_MKK][44] = 127,
+ [1][1][RTW89_IC][44] = 127,
+ [1][1][RTW89_KCC][44] = 127,
+ [1][1][RTW89_ACMA][44] = 127,
+ [1][1][RTW89_CN][44] = 54,
+ [1][1][RTW89_UK][44] = 127,
+ [1][1][RTW89_FCC][46] = 127,
+ [1][1][RTW89_ETSI][46] = 127,
+ [1][1][RTW89_MKK][46] = 127,
+ [1][1][RTW89_IC][46] = 127,
+ [1][1][RTW89_KCC][46] = 127,
+ [1][1][RTW89_ACMA][46] = 127,
+ [1][1][RTW89_CN][46] = 54,
+ [1][1][RTW89_UK][46] = 127,
+ [1][1][RTW89_FCC][48] = 127,
+ [1][1][RTW89_ETSI][48] = 127,
+ [1][1][RTW89_MKK][48] = 127,
+ [1][1][RTW89_IC][48] = 127,
+ [1][1][RTW89_KCC][48] = 127,
+ [1][1][RTW89_ACMA][48] = 127,
+ [1][1][RTW89_CN][48] = 127,
+ [1][1][RTW89_UK][48] = 127,
+ [1][1][RTW89_FCC][50] = 127,
+ [1][1][RTW89_ETSI][50] = 127,
+ [1][1][RTW89_MKK][50] = 127,
+ [1][1][RTW89_IC][50] = 127,
+ [1][1][RTW89_KCC][50] = 127,
+ [1][1][RTW89_ACMA][50] = 127,
+ [1][1][RTW89_CN][50] = 127,
+ [1][1][RTW89_UK][50] = 127,
+ [1][1][RTW89_FCC][52] = 127,
+ [1][1][RTW89_ETSI][52] = 127,
+ [1][1][RTW89_MKK][52] = 127,
+ [1][1][RTW89_IC][52] = 127,
+ [1][1][RTW89_KCC][52] = 127,
+ [1][1][RTW89_ACMA][52] = 127,
+ [1][1][RTW89_CN][52] = 127,
+ [1][1][RTW89_UK][52] = 127,
+ [2][0][RTW89_FCC][0] = 76,
+ [2][0][RTW89_ETSI][0] = 46,
+ [2][0][RTW89_MKK][0] = 48,
+ [2][0][RTW89_IC][0] = 50,
+ [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_ACMA][0] = 46,
+ [2][0][RTW89_CN][0] = 40,
+ [2][0][RTW89_UK][0] = 46,
+ [2][0][RTW89_FCC][2] = 72,
+ [2][0][RTW89_ETSI][2] = 46,
+ [2][0][RTW89_MKK][2] = 48,
+ [2][0][RTW89_IC][2] = 48,
+ [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_ACMA][2] = 46,
+ [2][0][RTW89_CN][2] = 40,
+ [2][0][RTW89_UK][2] = 46,
+ [2][0][RTW89_FCC][4] = 74,
+ [2][0][RTW89_ETSI][4] = 46,
+ [2][0][RTW89_MKK][4] = 48,
+ [2][0][RTW89_IC][4] = 48,
+ [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_ACMA][4] = 46,
+ [2][0][RTW89_CN][4] = 40,
+ [2][0][RTW89_UK][4] = 46,
+ [2][0][RTW89_FCC][6] = 74,
+ [2][0][RTW89_ETSI][6] = 46,
+ [2][0][RTW89_MKK][6] = 48,
+ [2][0][RTW89_IC][6] = 48,
+ [2][0][RTW89_KCC][6] = 40,
+ [2][0][RTW89_ACMA][6] = 46,
+ [2][0][RTW89_CN][6] = 40,
+ [2][0][RTW89_UK][6] = 46,
+ [2][0][RTW89_FCC][8] = 72,
+ [2][0][RTW89_ETSI][8] = 46,
+ [2][0][RTW89_MKK][8] = 48,
+ [2][0][RTW89_IC][8] = 64,
+ [2][0][RTW89_KCC][8] = 66,
+ [2][0][RTW89_ACMA][8] = 46,
+ [2][0][RTW89_CN][8] = 40,
+ [2][0][RTW89_UK][8] = 46,
+ [2][0][RTW89_FCC][10] = 72,
+ [2][0][RTW89_ETSI][10] = 46,
+ [2][0][RTW89_MKK][10] = 48,
+ [2][0][RTW89_IC][10] = 64,
+ [2][0][RTW89_KCC][10] = 66,
+ [2][0][RTW89_ACMA][10] = 46,
+ [2][0][RTW89_CN][10] = 40,
+ [2][0][RTW89_UK][10] = 46,
+ [2][0][RTW89_FCC][12] = 74,
+ [2][0][RTW89_ETSI][12] = 46,
+ [2][0][RTW89_MKK][12] = 48,
+ [2][0][RTW89_IC][12] = 64,
+ [2][0][RTW89_KCC][12] = 64,
+ [2][0][RTW89_ACMA][12] = 46,
+ [2][0][RTW89_CN][12] = 40,
+ [2][0][RTW89_UK][12] = 46,
+ [2][0][RTW89_FCC][14] = 80,
+ [2][0][RTW89_ETSI][14] = 46,
+ [2][0][RTW89_MKK][14] = 48,
+ [2][0][RTW89_IC][14] = 64,
+ [2][0][RTW89_KCC][14] = 64,
+ [2][0][RTW89_ACMA][14] = 46,
+ [2][0][RTW89_CN][14] = 40,
+ [2][0][RTW89_UK][14] = 46,
+ [2][0][RTW89_FCC][15] = 72,
+ [2][0][RTW89_ETSI][15] = 46,
+ [2][0][RTW89_MKK][15] = 70,
+ [2][0][RTW89_IC][15] = 72,
+ [2][0][RTW89_KCC][15] = 66,
+ [2][0][RTW89_ACMA][15] = 46,
+ [2][0][RTW89_CN][15] = 127,
+ [2][0][RTW89_UK][15] = 46,
+ [2][0][RTW89_FCC][17] = 72,
+ [2][0][RTW89_ETSI][17] = 46,
+ [2][0][RTW89_MKK][17] = 70,
+ [2][0][RTW89_IC][17] = 72,
+ [2][0][RTW89_KCC][17] = 66,
+ [2][0][RTW89_ACMA][17] = 46,
+ [2][0][RTW89_CN][17] = 127,
+ [2][0][RTW89_UK][17] = 46,
+ [2][0][RTW89_FCC][19] = 68,
+ [2][0][RTW89_ETSI][19] = 46,
+ [2][0][RTW89_MKK][19] = 70,
+ [2][0][RTW89_IC][19] = 68,
+ [2][0][RTW89_KCC][19] = 66,
+ [2][0][RTW89_ACMA][19] = 46,
+ [2][0][RTW89_CN][19] = 127,
+ [2][0][RTW89_UK][19] = 46,
+ [2][0][RTW89_FCC][21] = 68,
+ [2][0][RTW89_ETSI][21] = 46,
+ [2][0][RTW89_MKK][21] = 70,
+ [2][0][RTW89_IC][21] = 68,
+ [2][0][RTW89_KCC][21] = 66,
+ [2][0][RTW89_ACMA][21] = 46,
+ [2][0][RTW89_CN][21] = 127,
+ [2][0][RTW89_UK][21] = 46,
+ [2][0][RTW89_FCC][23] = 68,
+ [2][0][RTW89_ETSI][23] = 46,
+ [2][0][RTW89_MKK][23] = 70,
+ [2][0][RTW89_IC][23] = 68,
+ [2][0][RTW89_KCC][23] = 66,
+ [2][0][RTW89_ACMA][23] = 46,
+ [2][0][RTW89_CN][23] = 127,
+ [2][0][RTW89_UK][23] = 46,
+ [2][0][RTW89_FCC][25] = 68,
+ [2][0][RTW89_ETSI][25] = 46,
+ [2][0][RTW89_MKK][25] = 70,
+ [2][0][RTW89_IC][25] = 127,
+ [2][0][RTW89_KCC][25] = 66,
+ [2][0][RTW89_ACMA][25] = 127,
+ [2][0][RTW89_CN][25] = 127,
+ [2][0][RTW89_UK][25] = 46,
+ [2][0][RTW89_FCC][27] = 68,
+ [2][0][RTW89_ETSI][27] = 46,
+ [2][0][RTW89_MKK][27] = 70,
+ [2][0][RTW89_IC][27] = 127,
+ [2][0][RTW89_KCC][27] = 64,
+ [2][0][RTW89_ACMA][27] = 127,
+ [2][0][RTW89_CN][27] = 127,
+ [2][0][RTW89_UK][27] = 46,
+ [2][0][RTW89_FCC][29] = 68,
+ [2][0][RTW89_ETSI][29] = 46,
+ [2][0][RTW89_MKK][29] = 70,
+ [2][0][RTW89_IC][29] = 127,
+ [2][0][RTW89_KCC][29] = 64,
+ [2][0][RTW89_ACMA][29] = 127,
+ [2][0][RTW89_CN][29] = 127,
+ [2][0][RTW89_UK][29] = 46,
+ [2][0][RTW89_FCC][31] = 68,
+ [2][0][RTW89_ETSI][31] = 46,
+ [2][0][RTW89_MKK][31] = 70,
+ [2][0][RTW89_IC][31] = 70,
+ [2][0][RTW89_KCC][31] = 64,
+ [2][0][RTW89_ACMA][31] = 46,
+ [2][0][RTW89_CN][31] = 127,
+ [2][0][RTW89_UK][31] = 46,
+ [2][0][RTW89_FCC][33] = 70,
+ [2][0][RTW89_ETSI][33] = 46,
+ [2][0][RTW89_MKK][33] = 70,
+ [2][0][RTW89_IC][33] = 70,
+ [2][0][RTW89_KCC][33] = 64,
+ [2][0][RTW89_ACMA][33] = 46,
+ [2][0][RTW89_CN][33] = 127,
+ [2][0][RTW89_UK][33] = 46,
+ [2][0][RTW89_FCC][35] = 70,
+ [2][0][RTW89_ETSI][35] = 46,
+ [2][0][RTW89_MKK][35] = 70,
+ [2][0][RTW89_IC][35] = 70,
+ [2][0][RTW89_KCC][35] = 64,
+ [2][0][RTW89_ACMA][35] = 46,
+ [2][0][RTW89_CN][35] = 127,
+ [2][0][RTW89_UK][35] = 46,
+ [2][0][RTW89_FCC][37] = 84,
+ [2][0][RTW89_ETSI][37] = 127,
+ [2][0][RTW89_MKK][37] = 68,
+ [2][0][RTW89_IC][37] = 84,
+ [2][0][RTW89_KCC][37] = 66,
+ [2][0][RTW89_ACMA][37] = 74,
+ [2][0][RTW89_CN][37] = 127,
+ [2][0][RTW89_UK][37] = 74,
+ [2][0][RTW89_FCC][38] = 84,
+ [2][0][RTW89_ETSI][38] = 28,
+ [2][0][RTW89_MKK][38] = 127,
+ [2][0][RTW89_IC][38] = 84,
+ [2][0][RTW89_KCC][38] = 64,
+ [2][0][RTW89_ACMA][38] = 84,
+ [2][0][RTW89_CN][38] = 68,
+ [2][0][RTW89_UK][38] = 46,
+ [2][0][RTW89_FCC][40] = 84,
+ [2][0][RTW89_ETSI][40] = 28,
+ [2][0][RTW89_MKK][40] = 127,
+ [2][0][RTW89_IC][40] = 84,
+ [2][0][RTW89_KCC][40] = 64,
+ [2][0][RTW89_ACMA][40] = 84,
+ [2][0][RTW89_CN][40] = 68,
+ [2][0][RTW89_UK][40] = 46,
+ [2][0][RTW89_FCC][42] = 78,
+ [2][0][RTW89_ETSI][42] = 28,
+ [2][0][RTW89_MKK][42] = 127,
+ [2][0][RTW89_IC][42] = 78,
+ [2][0][RTW89_KCC][42] = 66,
+ [2][0][RTW89_ACMA][42] = 84,
+ [2][0][RTW89_CN][42] = 68,
+ [2][0][RTW89_UK][42] = 46,
+ [2][0][RTW89_FCC][44] = 80,
+ [2][0][RTW89_ETSI][44] = 28,
+ [2][0][RTW89_MKK][44] = 127,
+ [2][0][RTW89_IC][44] = 80,
+ [2][0][RTW89_KCC][44] = 66,
+ [2][0][RTW89_ACMA][44] = 84,
+ [2][0][RTW89_CN][44] = 68,
+ [2][0][RTW89_UK][44] = 46,
+ [2][0][RTW89_FCC][46] = 80,
+ [2][0][RTW89_ETSI][46] = 28,
+ [2][0][RTW89_MKK][46] = 127,
+ [2][0][RTW89_IC][46] = 80,
+ [2][0][RTW89_KCC][46] = 66,
+ [2][0][RTW89_ACMA][46] = 84,
+ [2][0][RTW89_CN][46] = 68,
+ [2][0][RTW89_UK][46] = 46,
+ [2][0][RTW89_FCC][48] = 62,
+ [2][0][RTW89_ETSI][48] = 127,
+ [2][0][RTW89_MKK][48] = 127,
+ [2][0][RTW89_IC][48] = 127,
+ [2][0][RTW89_KCC][48] = 127,
+ [2][0][RTW89_ACMA][48] = 127,
+ [2][0][RTW89_CN][48] = 127,
+ [2][0][RTW89_UK][48] = 127,
+ [2][0][RTW89_FCC][50] = 62,
+ [2][0][RTW89_ETSI][50] = 127,
+ [2][0][RTW89_MKK][50] = 127,
+ [2][0][RTW89_IC][50] = 127,
+ [2][0][RTW89_KCC][50] = 127,
+ [2][0][RTW89_ACMA][50] = 127,
+ [2][0][RTW89_CN][50] = 127,
+ [2][0][RTW89_UK][50] = 127,
+ [2][0][RTW89_FCC][52] = 60,
+ [2][0][RTW89_ETSI][52] = 127,
+ [2][0][RTW89_MKK][52] = 127,
+ [2][0][RTW89_IC][52] = 127,
+ [2][0][RTW89_KCC][52] = 127,
+ [2][0][RTW89_ACMA][52] = 127,
+ [2][0][RTW89_CN][52] = 127,
+ [2][0][RTW89_UK][52] = 127,
+ [2][1][RTW89_FCC][0] = 127,
+ [2][1][RTW89_ETSI][0] = 127,
+ [2][1][RTW89_MKK][0] = 127,
+ [2][1][RTW89_IC][0] = 127,
+ [2][1][RTW89_KCC][0] = 127,
+ [2][1][RTW89_ACMA][0] = 127,
+ [2][1][RTW89_CN][0] = 28,
+ [2][1][RTW89_UK][0] = 127,
+ [2][1][RTW89_FCC][2] = 127,
+ [2][1][RTW89_ETSI][2] = 127,
+ [2][1][RTW89_MKK][2] = 127,
+ [2][1][RTW89_IC][2] = 127,
+ [2][1][RTW89_KCC][2] = 127,
+ [2][1][RTW89_ACMA][2] = 127,
+ [2][1][RTW89_CN][2] = 28,
+ [2][1][RTW89_UK][2] = 127,
+ [2][1][RTW89_FCC][4] = 127,
+ [2][1][RTW89_ETSI][4] = 127,
+ [2][1][RTW89_MKK][4] = 127,
+ [2][1][RTW89_IC][4] = 127,
+ [2][1][RTW89_KCC][4] = 127,
+ [2][1][RTW89_ACMA][4] = 127,
+ [2][1][RTW89_CN][4] = 28,
+ [2][1][RTW89_UK][4] = 127,
+ [2][1][RTW89_FCC][6] = 127,
+ [2][1][RTW89_ETSI][6] = 127,
+ [2][1][RTW89_MKK][6] = 127,
+ [2][1][RTW89_IC][6] = 127,
+ [2][1][RTW89_KCC][6] = 127,
+ [2][1][RTW89_ACMA][6] = 127,
+ [2][1][RTW89_CN][6] = 28,
+ [2][1][RTW89_UK][6] = 127,
+ [2][1][RTW89_FCC][8] = 127,
+ [2][1][RTW89_ETSI][8] = 127,
+ [2][1][RTW89_MKK][8] = 127,
+ [2][1][RTW89_IC][8] = 127,
+ [2][1][RTW89_KCC][8] = 127,
+ [2][1][RTW89_ACMA][8] = 127,
+ [2][1][RTW89_CN][8] = 28,
+ [2][1][RTW89_UK][8] = 127,
+ [2][1][RTW89_FCC][10] = 127,
+ [2][1][RTW89_ETSI][10] = 127,
+ [2][1][RTW89_MKK][10] = 127,
+ [2][1][RTW89_IC][10] = 127,
+ [2][1][RTW89_KCC][10] = 127,
+ [2][1][RTW89_ACMA][10] = 127,
+ [2][1][RTW89_CN][10] = 28,
+ [2][1][RTW89_UK][10] = 127,
+ [2][1][RTW89_FCC][12] = 127,
+ [2][1][RTW89_ETSI][12] = 127,
+ [2][1][RTW89_MKK][12] = 127,
+ [2][1][RTW89_IC][12] = 127,
+ [2][1][RTW89_KCC][12] = 127,
+ [2][1][RTW89_ACMA][12] = 127,
+ [2][1][RTW89_CN][12] = 28,
+ [2][1][RTW89_UK][12] = 127,
+ [2][1][RTW89_FCC][14] = 127,
+ [2][1][RTW89_ETSI][14] = 127,
+ [2][1][RTW89_MKK][14] = 127,
+ [2][1][RTW89_IC][14] = 127,
+ [2][1][RTW89_KCC][14] = 127,
+ [2][1][RTW89_ACMA][14] = 127,
+ [2][1][RTW89_CN][14] = 28,
+ [2][1][RTW89_UK][14] = 127,
+ [2][1][RTW89_FCC][15] = 127,
+ [2][1][RTW89_ETSI][15] = 127,
+ [2][1][RTW89_MKK][15] = 127,
+ [2][1][RTW89_IC][15] = 127,
+ [2][1][RTW89_KCC][15] = 127,
+ [2][1][RTW89_ACMA][15] = 127,
+ [2][1][RTW89_CN][15] = 127,
+ [2][1][RTW89_UK][15] = 127,
+ [2][1][RTW89_FCC][17] = 127,
+ [2][1][RTW89_ETSI][17] = 127,
+ [2][1][RTW89_MKK][17] = 127,
+ [2][1][RTW89_IC][17] = 127,
+ [2][1][RTW89_KCC][17] = 127,
+ [2][1][RTW89_ACMA][17] = 127,
+ [2][1][RTW89_CN][17] = 127,
+ [2][1][RTW89_UK][17] = 127,
+ [2][1][RTW89_FCC][19] = 127,
+ [2][1][RTW89_ETSI][19] = 127,
+ [2][1][RTW89_MKK][19] = 127,
+ [2][1][RTW89_IC][19] = 127,
+ [2][1][RTW89_KCC][19] = 127,
+ [2][1][RTW89_ACMA][19] = 127,
+ [2][1][RTW89_CN][19] = 127,
+ [2][1][RTW89_UK][19] = 127,
+ [2][1][RTW89_FCC][21] = 127,
+ [2][1][RTW89_ETSI][21] = 127,
+ [2][1][RTW89_MKK][21] = 127,
+ [2][1][RTW89_IC][21] = 127,
+ [2][1][RTW89_KCC][21] = 127,
+ [2][1][RTW89_ACMA][21] = 127,
+ [2][1][RTW89_CN][21] = 127,
+ [2][1][RTW89_UK][21] = 127,
+ [2][1][RTW89_FCC][23] = 127,
+ [2][1][RTW89_ETSI][23] = 127,
+ [2][1][RTW89_MKK][23] = 127,
+ [2][1][RTW89_IC][23] = 127,
+ [2][1][RTW89_KCC][23] = 127,
+ [2][1][RTW89_ACMA][23] = 127,
+ [2][1][RTW89_CN][23] = 127,
+ [2][1][RTW89_UK][23] = 127,
+ [2][1][RTW89_FCC][25] = 127,
+ [2][1][RTW89_ETSI][25] = 127,
+ [2][1][RTW89_MKK][25] = 127,
+ [2][1][RTW89_IC][25] = 127,
+ [2][1][RTW89_KCC][25] = 127,
+ [2][1][RTW89_ACMA][25] = 127,
+ [2][1][RTW89_CN][25] = 127,
+ [2][1][RTW89_UK][25] = 127,
+ [2][1][RTW89_FCC][27] = 127,
+ [2][1][RTW89_ETSI][27] = 127,
+ [2][1][RTW89_MKK][27] = 127,
+ [2][1][RTW89_IC][27] = 127,
+ [2][1][RTW89_KCC][27] = 127,
+ [2][1][RTW89_ACMA][27] = 127,
+ [2][1][RTW89_CN][27] = 127,
+ [2][1][RTW89_UK][27] = 127,
+ [2][1][RTW89_FCC][29] = 127,
+ [2][1][RTW89_ETSI][29] = 127,
+ [2][1][RTW89_MKK][29] = 127,
+ [2][1][RTW89_IC][29] = 127,
+ [2][1][RTW89_KCC][29] = 127,
+ [2][1][RTW89_ACMA][29] = 127,
+ [2][1][RTW89_CN][29] = 127,
+ [2][1][RTW89_UK][29] = 127,
+ [2][1][RTW89_FCC][31] = 127,
+ [2][1][RTW89_ETSI][31] = 127,
+ [2][1][RTW89_MKK][31] = 127,
+ [2][1][RTW89_IC][31] = 127,
+ [2][1][RTW89_KCC][31] = 127,
+ [2][1][RTW89_ACMA][31] = 127,
+ [2][1][RTW89_CN][31] = 127,
+ [2][1][RTW89_UK][31] = 127,
+ [2][1][RTW89_FCC][33] = 127,
+ [2][1][RTW89_ETSI][33] = 127,
+ [2][1][RTW89_MKK][33] = 127,
+ [2][1][RTW89_IC][33] = 127,
+ [2][1][RTW89_KCC][33] = 127,
+ [2][1][RTW89_ACMA][33] = 127,
+ [2][1][RTW89_CN][33] = 127,
+ [2][1][RTW89_UK][33] = 127,
+ [2][1][RTW89_FCC][35] = 127,
+ [2][1][RTW89_ETSI][35] = 127,
+ [2][1][RTW89_MKK][35] = 127,
+ [2][1][RTW89_IC][35] = 127,
+ [2][1][RTW89_KCC][35] = 127,
+ [2][1][RTW89_ACMA][35] = 127,
+ [2][1][RTW89_CN][35] = 127,
+ [2][1][RTW89_UK][35] = 127,
+ [2][1][RTW89_FCC][37] = 127,
+ [2][1][RTW89_ETSI][37] = 127,
+ [2][1][RTW89_MKK][37] = 127,
+ [2][1][RTW89_IC][37] = 127,
+ [2][1][RTW89_KCC][37] = 127,
+ [2][1][RTW89_ACMA][37] = 127,
+ [2][1][RTW89_CN][37] = 127,
+ [2][1][RTW89_UK][37] = 127,
+ [2][1][RTW89_FCC][38] = 127,
+ [2][1][RTW89_ETSI][38] = 127,
+ [2][1][RTW89_MKK][38] = 127,
+ [2][1][RTW89_IC][38] = 127,
+ [2][1][RTW89_KCC][38] = 127,
+ [2][1][RTW89_ACMA][38] = 127,
+ [2][1][RTW89_CN][38] = 56,
+ [2][1][RTW89_UK][38] = 127,
+ [2][1][RTW89_FCC][40] = 127,
+ [2][1][RTW89_ETSI][40] = 127,
+ [2][1][RTW89_MKK][40] = 127,
+ [2][1][RTW89_IC][40] = 127,
+ [2][1][RTW89_KCC][40] = 127,
+ [2][1][RTW89_ACMA][40] = 127,
+ [2][1][RTW89_CN][40] = 56,
+ [2][1][RTW89_UK][40] = 127,
+ [2][1][RTW89_FCC][42] = 127,
+ [2][1][RTW89_ETSI][42] = 127,
+ [2][1][RTW89_MKK][42] = 127,
+ [2][1][RTW89_IC][42] = 127,
+ [2][1][RTW89_KCC][42] = 127,
+ [2][1][RTW89_ACMA][42] = 127,
+ [2][1][RTW89_CN][42] = 56,
+ [2][1][RTW89_UK][42] = 127,
+ [2][1][RTW89_FCC][44] = 127,
+ [2][1][RTW89_ETSI][44] = 127,
+ [2][1][RTW89_MKK][44] = 127,
+ [2][1][RTW89_IC][44] = 127,
+ [2][1][RTW89_KCC][44] = 127,
+ [2][1][RTW89_ACMA][44] = 127,
+ [2][1][RTW89_CN][44] = 56,
+ [2][1][RTW89_UK][44] = 127,
+ [2][1][RTW89_FCC][46] = 127,
+ [2][1][RTW89_ETSI][46] = 127,
+ [2][1][RTW89_MKK][46] = 127,
+ [2][1][RTW89_IC][46] = 127,
+ [2][1][RTW89_KCC][46] = 127,
+ [2][1][RTW89_ACMA][46] = 127,
+ [2][1][RTW89_CN][46] = 56,
+ [2][1][RTW89_UK][46] = 127,
+ [2][1][RTW89_FCC][48] = 127,
+ [2][1][RTW89_ETSI][48] = 127,
+ [2][1][RTW89_MKK][48] = 127,
+ [2][1][RTW89_IC][48] = 127,
+ [2][1][RTW89_KCC][48] = 127,
+ [2][1][RTW89_ACMA][48] = 127,
+ [2][1][RTW89_CN][48] = 127,
+ [2][1][RTW89_UK][48] = 127,
+ [2][1][RTW89_FCC][50] = 127,
+ [2][1][RTW89_ETSI][50] = 127,
+ [2][1][RTW89_MKK][50] = 127,
+ [2][1][RTW89_IC][50] = 127,
+ [2][1][RTW89_KCC][50] = 127,
+ [2][1][RTW89_ACMA][50] = 127,
+ [2][1][RTW89_CN][50] = 127,
+ [2][1][RTW89_UK][50] = 127,
+ [2][1][RTW89_FCC][52] = 127,
+ [2][1][RTW89_ETSI][52] = 127,
+ [2][1][RTW89_MKK][52] = 127,
+ [2][1][RTW89_IC][52] = 127,
+ [2][1][RTW89_KCC][52] = 127,
+ [2][1][RTW89_ACMA][52] = 127,
+ [2][1][RTW89_CN][52] = 127,
+ [2][1][RTW89_UK][52] = 127,
+};
+
+const struct rtw89_phy_table rtw89_8851b_phy_bb_table = {
+ .regs = rtw89_8851b_phy_bb_regs,
+ .n_regs = ARRAY_SIZE(rtw89_8851b_phy_bb_regs),
+ .rf_path = 0, /* don't care */
+};
+
+const struct rtw89_phy_table rtw89_8851b_phy_bb_gain_table = {
+ .regs = rtw89_8851b_phy_bb_reg_gain,
+ .n_regs = ARRAY_SIZE(rtw89_8851b_phy_bb_reg_gain),
+ .rf_path = 0, /* don't care */
+};
+
+const struct rtw89_phy_table rtw89_8851b_phy_radioa_table = {
+ .regs = rtw89_8851b_phy_radioa_regs,
+ .n_regs = ARRAY_SIZE(rtw89_8851b_phy_radioa_regs),
+ .rf_path = RF_PATH_A,
+ .config = rtw89_phy_config_rf_reg_v1,
+};
+
+const struct rtw89_phy_table rtw89_8851b_phy_nctl_table = {
+ .regs = rtw89_8851b_phy_nctl_regs,
+ .n_regs = ARRAY_SIZE(rtw89_8851b_phy_nctl_regs),
+ .rf_path = 0, /* don't care */
+};
+
+const struct rtw89_txpwr_table rtw89_8851b_byr_table = {
+ .data = rtw89_8851b_txpwr_byrate,
+ .size = ARRAY_SIZE(rtw89_8851b_txpwr_byrate),
+ .load = rtw89_phy_load_txpwr_byrate,
+};
+
+const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg = {
+ .delta_swingidx_5ga_n = _txpwr_track_delta_swingidx_5ga_n,
+ .delta_swingidx_5ga_p = _txpwr_track_delta_swingidx_5ga_p,
+ .delta_swingidx_2ga_n = _txpwr_track_delta_swingidx_2ga_n,
+ .delta_swingidx_2ga_p = _txpwr_track_delta_swingidx_2ga_p,
+ .delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
+ .delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
+};
+
+const struct rtw89_rfe_parms rtw89_8851b_dflt_parms = {
+ .rule_2ghz = {
+ .lmt = &rtw89_8851b_txpwr_lmt_2g,
+ .lmt_ru = &rtw89_8851b_txpwr_lmt_ru_2g,
+ },
+ .rule_5ghz = {
+ .lmt = &rtw89_8851b_txpwr_lmt_5g,
+ .lmt_ru = &rtw89_8851b_txpwr_lmt_ru_5g,
+ },
+};
+
+static const struct rtw89_rfe_parms rtw89_8851b_rfe_parms_type2 = {
+ .rule_2ghz = {
+ .lmt = &rtw89_8851b_txpwr_lmt_2g_type2,
+ .lmt_ru = &rtw89_8851b_txpwr_lmt_ru_2g_type2,
+ },
+ .rule_5ghz = {
+ .lmt = &rtw89_8851b_txpwr_lmt_5g_type2,
+ .lmt_ru = &rtw89_8851b_txpwr_lmt_ru_5g_type2,
+ },
+};
+
+const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[] = {
+ {
+ .rfe_parms = &rtw89_8851b_rfe_parms_type2,
+ .rfe_type = 2,
+ },
+ {},
+};
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
new file mode 100644
index 000000000000..f2e673ba39c8
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_TABLE_H__
+#define __RTW89_8851B_TABLE_H__
+
+#include "core.h"
+
+extern const struct rtw89_phy_table rtw89_8851b_phy_bb_table;
+extern const struct rtw89_phy_table rtw89_8851b_phy_bb_gain_table;
+extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table;
+extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table;
+extern const struct rtw89_txpwr_table rtw89_8851b_byr_table;
+extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg;
+extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+ [RTW89_REGD_NUM];
+extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms;
+extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[];
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 46907748778b..d7930efd89b7 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -12,6 +12,11 @@
#include "rtw8852a_table.h"
#include "txrx.h"
+#define RTW8852A_FW_FORMAT_MAX 0
+#define RTW8852A_FW_BASENAME "rtw89/rtw8852a_fw"
+#define RTW8852A_MODULE_FIRMWARE \
+ RTW8852A_FW_BASENAME ".bin"
+
static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = {
{128, 1896, grp_0}, /* ACH 0 */
{128, 1896, grp_0}, /* ACH 1 */
@@ -1827,7 +1832,8 @@ rtw8852a_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
static
s8 rtw8852a_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
{
- return clamp_t(s8, val, -100, 0) + 100;
+ /* +6 for compensate offset */
+ return clamp_t(s8, val + 6, -100, 0) + 100;
}
static struct rtw89_btc_rf_trx_para rtw89_btc_8852a_rf_ul[] = {
@@ -2059,7 +2065,8 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
const struct rtw89_chip_info rtw8852a_chip_info = {
.chip_id = RTL8852A,
.ops = &rtw8852a_chip_ops,
- .fw_name = "rtw89/rtw8852a_fw.bin",
+ .fw_basename = RTW8852A_FW_BASENAME,
+ .fw_format_max = RTW8852A_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
.dle_scc_rsvd_size = 0,
@@ -2079,10 +2086,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
&rtw89_8852a_phy_radiob_table,},
.nctl_table = &rtw89_8852a_phy_nctl_table,
.byr_table = &rtw89_8852a_byr_table,
- .txpwr_lmt_2g = &rtw89_8852a_txpwr_lmt_2g,
- .txpwr_lmt_5g = &rtw89_8852a_txpwr_lmt_5g,
- .txpwr_lmt_ru_2g = &rtw89_8852a_txpwr_lmt_ru_2g,
- .txpwr_lmt_ru_5g = &rtw89_8852a_txpwr_lmt_ru_5g,
+ .dflt_parms = &rtw89_8852a_dflt_parms,
+ .rfe_parms_conf = NULL,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = &rtw89_8852a_phy_dig_table,
@@ -2143,8 +2148,9 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
.page_regs = &rtw8852a_page_regs,
.cfo_src_fd = false,
+ .cfo_hw_comp = false,
.dcfo_comp = &rtw8852a_dcfo_comp,
- .dcfo_comp_sft = 3,
+ .dcfo_comp_sft = 10,
.imr_info = &rtw8852a_imr_info,
.rrsr_cfgs = &rtw8852a_rrsr_cfgs,
.bss_clr_map_reg = R_BSS_CLR_MAP,
@@ -2156,7 +2162,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
};
EXPORT_SYMBOL(rtw8852a_chip_info);
-MODULE_FIRMWARE("rtw89/rtw8852a_fw.bin");
+MODULE_FIRMWARE(RTW8852A_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852A driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
index 320bcd4852c6..be54194558ff 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
@@ -43377,6 +43377,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5,
6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10};
+static
const s8 rtw89_8852a_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
@@ -45566,6 +45567,7 @@ const s8 rtw89_8852a_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_UK][13] = 127,
};
+static
const s8 rtw89_8852a_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
@@ -47898,6 +47900,7 @@ const s8 rtw89_8852a_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_UK][41] = 40,
};
+static
const s8 rtw89_8852a_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
[0][0][RTW89_WW][0] = 32,
@@ -48994,6 +48997,7 @@ const s8 rtw89_8852a_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_UK][13] = 127,
};
+static
const s8 rtw89_8852a_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
[0][0][RTW89_WW][0] = 22,
@@ -51043,3 +51047,14 @@ const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table = {
.cfg_lna_a = &rtw89_8852a_lna_gain_a_table,
.cfg_tia_a = &rtw89_8852a_tia_gain_a_table
};
+
+const struct rtw89_rfe_parms rtw89_8852a_dflt_parms = {
+ .rule_2ghz = {
+ .lmt = &rtw89_8852a_txpwr_lmt_2g,
+ .lmt_ru = &rtw89_8852a_txpwr_lmt_ru_2g,
+ },
+ .rule_5ghz = {
+ .lmt = &rtw89_8852a_txpwr_lmt_5g,
+ .lmt_ru = &rtw89_8852a_txpwr_lmt_ru_5g,
+ },
+};
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
index 913796506286..41c379b1044d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
@@ -14,15 +14,6 @@ extern const struct rtw89_phy_table rtw89_8852a_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852a_byr_table;
extern const struct rtw89_phy_dig_gain_table rtw89_8852a_phy_dig_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg;
-extern const s8 rtw89_8852a_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852a_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
-extern const s8 rtw89_8852a_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852a_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
+extern const struct rtw89_rfe_parms rtw89_8852a_dflt_parms;
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index bae80984cfd5..eaa2ea0586bc 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -12,6 +12,11 @@
#include "rtw8852b_table.h"
#include "txrx.h"
+#define RTW8852B_FW_FORMAT_MAX 1
+#define RTW8852B_FW_BASENAME "rtw89/rtw8852b_fw"
+#define RTW8852B_MODULE_FIRMWARE \
+ RTW8852B_FW_BASENAME "-" __stringify(RTW8852B_FW_FORMAT_MAX) ".bin"
+
static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = {
{5, 343, grp_0}, /* ACH 0 */
{5, 343, grp_0}, /* ACH 1 */
@@ -48,6 +53,10 @@ static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = {
&rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
&rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
&rtw89_mac_size.ple_qt58},
+ [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size6,
+ &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+ &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+ &rtw89_mac_size.ple_qt_52b_wow},
[RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
&rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
&rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13,
@@ -323,7 +332,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852b_rf_ul[] = {
{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}, /* the below id is for non-shared-antenna free-run */
{6, 1, 0, 7},
{13, 1, 0, 7},
{13, 1, 0, 7}
@@ -335,7 +344,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852b_rf_dl[] = {
{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}, /* the below id is for non-shared-antenna free-run */
{255, 1, 0, 7},
{255, 1, 0, 7},
{255, 1, 0, 7}
@@ -355,7 +364,9 @@ static const struct rtw89_btc_fbtc_mreg rtw89_btc_8852b_mon_reg[] = {
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
- RTW89_DEF_FBTC_MREG(REG_BT_MODEM, 4, 0x178),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4738),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4688),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4694),
};
static const u8 rtw89_btc_8852b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {70, 60, 50, 40};
@@ -1284,7 +1295,7 @@ static void rtw8852b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en)
static void rtw8852b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
- u8 pri_ch = chan->primary_channel;
+ u8 pri_ch = chan->pri_ch_idx;
bool mask_5m_low;
bool mask_5m_en;
@@ -1292,12 +1303,13 @@ static void rtw8852b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *
case RTW89_CHANNEL_WIDTH_40:
/* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */
mask_5m_en = true;
- mask_5m_low = pri_ch == 2;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWER;
break;
case RTW89_CHANNEL_WIDTH_80:
/* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */
- mask_5m_en = pri_ch == 3 || pri_ch == 4;
- mask_5m_low = pri_ch == 4;
+ mask_5m_en = pri_ch == RTW89_SC_20_UPMOST ||
+ pri_ch == RTW89_SC_20_LOWEST;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWEST;
break;
default:
mask_5m_en = false;
@@ -2267,7 +2279,8 @@ do { \
static
s8 rtw8852b_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
{
- return clamp_t(s8, val, -100, 0) + 100;
+ /* +6 for compensate offset */
+ return clamp_t(s8, val + 6, -100, 0) + 100;
}
static
@@ -2477,10 +2490,20 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.btc_set_policy = rtw89_btc_set_policy_v1,
};
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support rtw_wowlan_stub_8852b = {
+ .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+ .n_patterns = RTW89_MAX_PATTERN_NUM,
+ .pattern_max_len = RTW89_MAX_PATTERN_SIZE,
+ .pattern_min_len = 1,
+};
+#endif
+
const struct rtw89_chip_info rtw8852b_chip_info = {
.chip_id = RTL8852B,
.ops = &rtw8852b_chip_ops,
- .fw_name = "rtw89/rtw8852b_fw.bin",
+ .fw_basename = RTW8852B_FW_BASENAME,
+ .fw_format_max = RTW8852B_FW_FORMAT_MAX,
.try_ce_fw = true,
.fifo_size = 196608,
.dle_scc_rsvd_size = 98304,
@@ -2500,10 +2523,8 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
&rtw89_8852b_phy_radiob_table,},
.nctl_table = &rtw89_8852b_phy_nctl_table,
.byr_table = &rtw89_8852b_byr_table,
- .txpwr_lmt_2g = &rtw89_8852b_txpwr_lmt_2g,
- .txpwr_lmt_5g = &rtw89_8852b_txpwr_lmt_5g,
- .txpwr_lmt_ru_2g = &rtw89_8852b_txpwr_lmt_ru_2g,
- .txpwr_lmt_ru_5g = &rtw89_8852b_txpwr_lmt_ru_5g,
+ .dflt_parms = &rtw89_8852b_dflt_parms,
+ .rfe_parms_conf = NULL,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -2564,8 +2585,9 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.c2h_regs = rtw8852b_c2h_regs,
.page_regs = &rtw8852b_page_regs,
.cfo_src_fd = true,
+ .cfo_hw_comp = true,
.dcfo_comp = &rtw8852b_dcfo_comp,
- .dcfo_comp_sft = 3,
+ .dcfo_comp_sft = 10,
.imr_info = &rtw8852b_imr_info,
.rrsr_cfgs = &rtw8852b_rrsr_cfgs,
.bss_clr_map_reg = R_BSS_CLR_MAP_V1,
@@ -2573,10 +2595,13 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
.edcca_lvl_reg = R_SEG0R_EDCCA_LVL_V1,
+#ifdef CONFIG_PM
+ .wowlan_stub = &rtw_wowlan_stub_8852b,
+#endif
};
EXPORT_SYMBOL(rtw8852b_chip_info);
-MODULE_FIRMWARE("rtw89/rtw8852b_fw.bin");
+MODULE_FIRMWARE(RTW8852B_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852B driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
index a6734965361f..904cdb9e56fa 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
@@ -14706,6 +14706,7 @@ const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[1][1][RTW89_UKRAINE] = 0,
};
+static
const s8 rtw89_8852b_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
@@ -16895,6 +16896,7 @@ const s8 rtw89_8852b_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_UK][13] = 127,
};
+static
const s8 rtw89_8852b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
@@ -19539,6 +19541,7 @@ const s8 rtw89_8852b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_UK][49] = 127,
};
+static
const s8 rtw89_8852b_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
[0][0][RTW89_WW][0] = 32,
@@ -20635,6 +20638,7 @@ const s8 rtw89_8852b_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_UK][13] = 127,
};
+static
const s8 rtw89_8852b_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
[0][0][RTW89_WW][0] = 24,
@@ -22875,3 +22879,14 @@ const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg = {
.delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
};
+
+const struct rtw89_rfe_parms rtw89_8852b_dflt_parms = {
+ .rule_2ghz = {
+ .lmt = &rtw89_8852b_txpwr_lmt_2g,
+ .lmt_ru = &rtw89_8852b_txpwr_lmt_ru_2g,
+ },
+ .rule_5ghz = {
+ .lmt = &rtw89_8852b_txpwr_lmt_5g,
+ .lmt_ru = &rtw89_8852b_txpwr_lmt_ru_5g,
+ },
+};
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
index 114337ac9fb0..5f4161496a58 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
@@ -16,15 +16,6 @@ extern const struct rtw89_txpwr_table rtw89_8852b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg;
extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
-extern const s8 rtw89_8852b_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
-extern const s8 rtw89_8852b_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852b_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
+extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms;
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index ba728fca9188..ceb819a62efc 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -13,6 +13,11 @@
#include "rtw8852c_table.h"
#include "util.h"
+#define RTW8852C_FW_FORMAT_MAX 0
+#define RTW8852C_FW_BASENAME "rtw89/rtw8852c_fw"
+#define RTW8852C_MODULE_FIRMWARE \
+ RTW8852C_FW_BASENAME ".bin"
+
static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_pcie[] = {
{13, 1614, grp_0}, /* ACH 0 */
{13, 1614, grp_0}, /* ACH 1 */
@@ -1375,18 +1380,19 @@ static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
- u8 pri_ch = chan->primary_channel;
+ u8 pri_ch = chan->pri_ch_idx;
bool mask_5m_low;
bool mask_5m_en;
switch (chan->band_width) {
case RTW89_CHANNEL_WIDTH_40:
mask_5m_en = true;
- mask_5m_low = pri_ch == 2;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWER;
break;
case RTW89_CHANNEL_WIDTH_80:
- mask_5m_en = ((pri_ch == 3) || (pri_ch == 4));
- mask_5m_low = pri_ch == 4;
+ mask_5m_en = pri_ch == RTW89_SC_20_UPMOST ||
+ pri_ch == RTW89_SC_20_LOWEST;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWEST;
break;
default:
mask_5m_en = false;
@@ -2527,7 +2533,8 @@ do { \
static
s8 rtw8852c_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
{
- return clamp_t(s8, val, -100, 0) + 100;
+ /* +6 for compensate offset */
+ return clamp_t(s8, val + 6, -100, 0) + 100;
}
static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = {
@@ -2536,7 +2543,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = {
{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}, /* the below id is for non-shared-antenna free-run */
{6, 1, 0, 7},
{13, 1, 0, 7},
{13, 1, 0, 7}
@@ -2548,7 +2555,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_dl[] = {
{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}, /* the below id is for non-shared-antenna free-run */
{255, 1, 0, 7},
{255, 1, 0, 7},
{255, 1, 0, 7}
@@ -2570,6 +2577,9 @@ static const struct rtw89_btc_fbtc_mreg rtw89_btc_8852c_mon_reg[] = {
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4aa4),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4778),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x476c),
};
static
@@ -2791,7 +2801,8 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
const struct rtw89_chip_info rtw8852c_chip_info = {
.chip_id = RTL8852C,
.ops = &rtw8852c_chip_ops,
- .fw_name = "rtw89/rtw8852c_fw.bin",
+ .fw_basename = RTW8852C_FW_BASENAME,
+ .fw_format_max = RTW8852C_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
.dle_scc_rsvd_size = 0,
@@ -2811,12 +2822,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
&rtw89_8852c_phy_radioa_table,},
.nctl_table = &rtw89_8852c_phy_nctl_table,
.byr_table = &rtw89_8852c_byr_table,
- .txpwr_lmt_2g = &rtw89_8852c_txpwr_lmt_2g,
- .txpwr_lmt_5g = &rtw89_8852c_txpwr_lmt_5g,
- .txpwr_lmt_6g = &rtw89_8852c_txpwr_lmt_6g,
- .txpwr_lmt_ru_2g = &rtw89_8852c_txpwr_lmt_ru_2g,
- .txpwr_lmt_ru_5g = &rtw89_8852c_txpwr_lmt_ru_5g,
- .txpwr_lmt_ru_6g = &rtw89_8852c_txpwr_lmt_ru_6g,
+ .dflt_parms = &rtw89_8852c_dflt_parms,
+ .rfe_parms_conf = NULL,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -2879,8 +2886,9 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.c2h_regs = rtw8852c_c2h_regs,
.page_regs = &rtw8852c_page_regs,
.cfo_src_fd = false,
+ .cfo_hw_comp = false,
.dcfo_comp = &rtw8852c_dcfo_comp,
- .dcfo_comp_sft = 5,
+ .dcfo_comp_sft = 12,
.imr_info = &rtw8852c_imr_info,
.rrsr_cfgs = &rtw8852c_rrsr_cfgs,
.bss_clr_map_reg = R_BSS_CLR_MAP,
@@ -2892,7 +2900,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
};
EXPORT_SYMBOL(rtw8852c_chip_info);
-MODULE_FIRMWARE("rtw89/rtw8852c_fw.bin");
+MODULE_FIRMWARE(RTW8852C_MODULE_FIRMWARE);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852C driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
index 96c264a057ff..7011e5a6f8fd 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
@@ -28590,6 +28590,7 @@ const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[2][1][RTW89_KCC] = 0,
};
+static
const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
@@ -30107,6 +30108,7 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_UK][13] = 127,
};
+static
const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
@@ -32020,6 +32022,7 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_UK][45] = 127,
};
+static
const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
@@ -33977,6 +33980,7 @@ const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_KCC][112] = 127,
};
+static
const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
[0][0][RTW89_WW][0] = 32,
@@ -34737,6 +34741,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_UK][13] = 127,
};
+static
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] = 16,
@@ -36253,6 +36258,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_UK][52] = 127,
};
+static
const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
[0][0][RTW89_WW][0] = -16,
@@ -37472,3 +37478,18 @@ const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table = {
.data[RTW89_TSSI_BANDEDGE_MID] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.data[RTW89_TSSI_BANDEDGE_HIGH] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
+
+const struct rtw89_rfe_parms rtw89_8852c_dflt_parms = {
+ .rule_2ghz = {
+ .lmt = &rtw89_8852c_txpwr_lmt_2g,
+ .lmt_ru = &rtw89_8852c_txpwr_lmt_ru_2g,
+ },
+ .rule_5ghz = {
+ .lmt = &rtw89_8852c_txpwr_lmt_5g,
+ .lmt_ru = &rtw89_8852c_txpwr_lmt_ru_5g,
+ },
+ .rule_6ghz = {
+ .lmt = &rtw89_8852c_txpwr_lmt_6g,
+ .lmt_ru = &rtw89_8852c_txpwr_lmt_ru_6g,
+ },
+};
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
index 7d71a92e2d27..6da1849fb1fa 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
@@ -17,20 +17,6 @@ extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg;
extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
- [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_2G_CH_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_5G_CH_NUM];
-extern const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms;
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 7cff9c1d8d37..2ca8abb70f11 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -30,7 +30,7 @@ static void rtw89_wow_enter_lps(struct rtw89_dev *rtwdev)
struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
- rtw89_enter_lps(rtwdev, rtwvif);
+ rtw89_enter_lps(rtwdev, rtwvif, false);
}
static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index f446d8f6e1f6..2211fa58fe41 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -3760,6 +3760,9 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info)
int err;
int rem;
+ if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER])
+ return -EINVAL;
+
src = nla_data(info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
data = get_hwsim_data_ref_from_addr(src);
if (!data)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 2463bdd2a382..c4cf296e7eaf 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -9,7 +9,7 @@
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (c) 2018 - 2022 Intel Corporation
+ * Copyright (c) 2018 - 2023 Intel Corporation
*/
#ifndef LINUX_IEEE80211_H
@@ -783,20 +783,6 @@ static inline bool ieee80211_is_any_nullfunc(__le16 fc)
}
/**
- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
- * @fc: frame control field in little-endian byteorder
- */
-static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
-{
- /* IEEE 802.11-2012, definition of "bufferable management frame";
- * note that this ignores the IBSS special case. */
- return ieee80211_is_mgmt(fc) &&
- (ieee80211_is_action(fc) ||
- ieee80211_is_disassoc(fc) ||
- ieee80211_is_deauth(fc));
-}
-
-/**
* ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
* @seq_ctrl: frame sequence control bytes in little-endian byteorder
*/
@@ -3557,11 +3543,6 @@ enum ieee80211_unprotected_wnm_actioncode {
WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE = 1,
};
-/* Public action codes */
-enum ieee80211_public_actioncode {
- WLAN_PUBLIC_ACTION_FTM_RESPONSE = 33,
-};
-
/* Security key length */
enum ieee80211_key_len {
WLAN_KEY_LEN_WEP40 = 5,
@@ -3653,7 +3634,7 @@ enum ieee80211_pub_actioncode {
WLAN_PUB_ACTION_NETWORK_CHANNEL_CONTROL = 30,
WLAN_PUB_ACTION_WHITE_SPACE_MAP_ANN = 31,
WLAN_PUB_ACTION_FTM_REQUEST = 32,
- WLAN_PUB_ACTION_FTM = 33,
+ WLAN_PUB_ACTION_FTM_RESPONSE = 33,
WLAN_PUB_ACTION_FILS_DISCOVERY = 34,
};
@@ -4138,6 +4119,44 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
}
/**
+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
+ * @skb: the skb to check, starting with the 802.11 header
+ */
+static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
+{
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ __le16 fc = mgmt->frame_control;
+
+ /*
+ * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
+ * note that this ignores the IBSS special case.
+ */
+ if (!ieee80211_is_mgmt(fc))
+ return false;
+
+ if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
+ return true;
+
+ if (!ieee80211_is_action(fc))
+ return false;
+
+ if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
+ return true;
+
+ /* action frame - additionally check for non-bufferable FTM */
+
+ if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
+ mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
+ return true;
+
+ if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
+ mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_RESPONSE)
+ return false;
+
+ return true;
+}
+
+/**
* _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
* @hdr: the frame (buffer must include at least the first octet of payload)
*/
@@ -4383,7 +4402,7 @@ static inline bool ieee80211_is_ftm(struct sk_buff *skb)
return false;
if (mgmt->u.action.u.ftm.action_code ==
- WLAN_PUBLIC_ACTION_FTM_RESPONSE &&
+ WLAN_PUB_ACTION_FTM_RESPONSE &&
skb->len >= offsetofend(typeof(*mgmt), u.action.u.ftm))
return true;
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 0e4ef9c5127a..c653accdc7fd 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -74,10 +74,13 @@
#define SDIO_DEVICE_ID_BROADCOM_43362 0xa962
#define SDIO_DEVICE_ID_BROADCOM_43364 0xa9a4
#define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6
-#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xa9af
+#define SDIO_DEVICE_ID_BROADCOM_43439 0xa9af
#define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf
#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 0xaae8
+#define SDIO_VENDOR_ID_CYPRESS 0x04b4
+#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xbd3d
+
#define SDIO_VENDOR_ID_MARVELL 0x02df
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
#define SDIO_DEVICE_ID_MARVELL_8688_WLAN 0x9104
@@ -112,6 +115,15 @@
#define SDIO_VENDOR_ID_MICROCHIP_WILC 0x0296
#define SDIO_DEVICE_ID_MICROCHIP_WILC1000 0x5347
+#define SDIO_VENDOR_ID_REALTEK 0x024c
+#define SDIO_DEVICE_ID_REALTEK_RTW8723BS 0xb723
+#define SDIO_DEVICE_ID_REALTEK_RTW8821BS 0xb821
+#define SDIO_DEVICE_ID_REALTEK_RTW8822BS 0xb822
+#define SDIO_DEVICE_ID_REALTEK_RTW8821CS 0xc821
+#define SDIO_DEVICE_ID_REALTEK_RTW8822CS 0xc822
+#define SDIO_DEVICE_ID_REALTEK_RTW8723DS 0xd723
+#define SDIO_DEVICE_ID_REALTEK_RTW8821DS 0xd821
+
#define SDIO_VENDOR_ID_SIANO 0x039a
#define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201
#define SDIO_DEVICE_ID_SIANO_NICE 0x0202
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 679421d37a42..ac0370e76874 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3950,6 +3950,10 @@ struct ieee80211_prep_tx_info {
* Note that vif can be NULL.
* The callback can sleep.
*
+ * @flush_sta: Flush or drop all pending frames from the hardware queue(s) for
+ * the given station, as it's about to be removed.
+ * The callback can sleep.
+ *
* @channel_switch: Drivers that need (or want) to offload the channel
* switch operation for CSAs received from the AP may implement this
* callback. They must then call ieee80211_chswitch_done() to indicate
@@ -4415,6 +4419,8 @@ struct ieee80211_ops {
#endif
void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
+ void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
void (*channel_switch)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch);
@@ -5210,26 +5216,6 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb);
/**
- * ieee80211_tx_status_8023 - transmit status callback for 802.3 frame format
- *
- * Call this function for all transmitted data frames after their transmit
- * completion. This callback should only be called for data frames which
- * are using driver's (or hardware's) offload capability of encap/decap
- * 802.11 frames.
- *
- * This function may not be called in IRQ context. Calls to this function
- * for a single hardware must be synchronized against each other and all
- * calls in the same tx status family.
- *
- * @hw: the hardware the frame was transmitted by
- * @vif: the interface for which the frame was transmitted
- * @skb: the frame that was transmitted, owned by mac80211 after this call
- */
-void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct sk_buff *skb);
-
-/**
* ieee80211_report_low_ack - report non-responding station
*
* When operating in AP-mode, call this function to report a non-responding
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 473915606715..7317e4a5d1ff 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1342,6 +1342,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
if (params->eht_cap) {
+ if (!link_conf->he_support)
+ return -EOPNOTSUPP;
+
+ link_conf->eht_support = true;
link_conf->eht_puncturing = params->punct_bitmap;
changed |= BSS_CHANGED_EHT_PUNCTURING;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index dfb9f55e2685..207f772bd8ce 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -673,10 +673,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
statsd = debugfs_create_dir("statistics", phyd);
- /* if the dir failed, don't put all the other things into the root! */
- if (!statsd)
- return;
-
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 0bf208f5bbc5..45d3e53c7383 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -649,6 +649,21 @@ static inline void drv_flush(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline void drv_flush_sta(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta)
+{
+ might_sleep();
+
+ if (sdata && !check_sdata_in_driver(sdata))
+ return;
+
+ trace_drv_flush_sta(local, sdata, &sta->sta);
+ if (local->ops->flush_sta)
+ local->ops->flush_sta(&local->hw, &sdata->vif, &sta->sta);
+ trace_drv_return_void(local);
+}
+
static inline void drv_channel_switch(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_switch *ch_switch)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 941bda9141fa..1400512e0dde 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1294,6 +1294,18 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
WARN_ON_ONCE(ret);
}
+ /* Flush queues before removing keys, as that might remove them
+ * from hardware, and then depending on the offload method, any
+ * frames sitting on hardware queues might be sent out without
+ * any encryption at all.
+ */
+ if (local->ops->set_key) {
+ if (local->ops->flush_sta)
+ drv_flush_sta(local, sta->sdata, sta);
+ else
+ ieee80211_flush_queues(local, sta->sdata, false);
+ }
+
/* now keys can no longer be reached */
ieee80211_free_sta_keys(local, sta);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 3f9ddd7f04b6..2b13a52ce96c 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -1244,30 +1244,6 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_tx_rate_update);
-void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct sk_buff *skb)
-{
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_tx_status status = {
- .skb = skb,
- .info = IEEE80211_SKB_CB(skb),
- };
- struct sta_info *sta;
-
- sdata = vif_to_sdata(vif);
-
- rcu_read_lock();
-
- if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta))
- status.sta = &sta->sta;
-
- ieee80211_tx_status_ext(hw, &status);
-
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee80211_tx_status_8023);
-
void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index e0ccf5fe708a..de5d69f21306 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1177,6 +1177,13 @@ TRACE_EVENT(drv_flush,
)
);
+DEFINE_EVENT(sta_event, drv_flush_sta,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta),
+ TP_ARGS(local, sdata, sta)
+);
+
TRACE_EVENT(drv_channel_switch,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index dfe6b9c9b29e..1a3327407552 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -488,7 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
int ac = skb_get_queue_mapping(tx->skb);
if (ieee80211_is_mgmt(hdr->frame_control) &&
- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
+ !ieee80211_is_bufferable_mmpdu(tx->skb)) {
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
return TX_CONTINUE;
}
@@ -1323,7 +1323,7 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
- ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
+ ieee80211_is_bufferable_mmpdu(skb) ||
vif->type == NL80211_IFTYPE_STATION) &&
sta && sta->uploaded) {
/*