From 7dd632ff96dfb76cb0c3632bd8bb5ea20165f8f9 Mon Sep 17 00:00:00 2001 From: Shobek Attupurath Date: Fri, 16 Aug 2024 19:29:47 +0000 Subject: [PATCH] rtl8852ce: Add base driver v1.19.16.1-0-g1fe335ba1.20240815_PC - support Android-14 - support Linux kernel 6.9 - support 6G regulation - support Thermal protection - support TX shortcut to reduce CPU loading - fix some coverity issues - Use RTW regulatory version rtk_8852CE_M.2_2230-67-52 - default enable con-current and MCC Bug 4667769 Bug 4667981 Change-Id: Iee069ecdd1f00a0b78285d0a4ef5778ed9ace478 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195601 Tested-by: Shobek Attupurath Reviewed-by: Revanth Kumar Uppala GVS: buildbot_gerritrpt Reviewed-by: Ashutosh Jha --- .../net/wireless/realtek/rtl8852ce/Kconfig | 6 + .../net/wireless/realtek/rtl8852ce/Makefile | 944 + .../net/wireless/realtek/rtl8852ce/common.mk | 156 + .../realtek/rtl8852ce/core/crypto/aes-ccm.c | 211 + .../realtek/rtl8852ce/core/crypto/aes-ctr.c | 70 + .../realtek/rtl8852ce/core/crypto/aes-gcm.c | 326 + .../rtl8852ce/core/crypto/aes-internal-enc.c | 129 + .../rtl8852ce/core/crypto/aes-internal.c | 843 + .../realtek/rtl8852ce/core/crypto/aes-omac1.c | 172 + .../realtek/rtl8852ce/core/crypto/aes-siv.c | 207 + .../realtek/rtl8852ce/core/crypto/aes.h | 21 + .../realtek/rtl8852ce/core/crypto/aes_i.h | 125 + .../realtek/rtl8852ce/core/crypto/aes_siv.h | 21 + .../realtek/rtl8852ce/core/crypto/aes_wrap.h | 73 + .../realtek/rtl8852ce/core/crypto/ccmp.c | 510 + .../realtek/rtl8852ce/core/crypto/gcmp.c | 194 + .../rtl8852ce/core/crypto/rtw_crypto_wrap.c | 85 + .../rtl8852ce/core/crypto/rtw_crypto_wrap.h | 64 + .../rtl8852ce/core/crypto/sha256-internal.c | 230 + .../rtl8852ce/core/crypto/sha256-prf.c | 109 + .../realtek/rtl8852ce/core/crypto/sha256.c | 104 + .../realtek/rtl8852ce/core/crypto/sha256.h | 30 + .../realtek/rtl8852ce/core/crypto/sha256_i.h | 25 + .../rtl8852ce/core/crypto/wlancrypto_wrap.h | 41 + .../core/def_module_country_chplan.h | 1519 + .../realtek/rtl8852ce/core/mesh/rtw_mesh.c | 4343 + .../realtek/rtl8852ce/core/mesh/rtw_mesh.h | 537 + .../rtl8852ce/core/mesh/rtw_mesh_hwmp.c | 1519 + .../rtl8852ce/core/mesh/rtw_mesh_hwmp.h | 60 + .../rtl8852ce/core/mesh/rtw_mesh_pathtbl.c | 1241 + .../rtl8852ce/core/mesh/rtw_mesh_pathtbl.h | 211 + .../rtl8852ce/core/monitor/rtw_radiotap.c | 806 + .../rtl8852ce/core/monitor/rtw_radiotap.h | 64 + .../core/regdb/rtw_regdb_phl_wrapper.c | 201 + .../core/regdb/rtw_regdb_rtk_58-31.c | 908 + .../core/regdb/rtw_regdb_rtk_59-32.c | 917 + .../core/regdb/rtw_regdb_rtk_60-32.c | 920 + .../core/regdb/rtw_regdb_rtk_60-34.c | 920 + .../core/regdb/rtw_regdb_rtk_61-34.c | 923 + .../core/regdb/rtw_regdb_rtk_62-35.c | 924 + .../core/regdb/rtw_regdb_rtk_63-36.c | 925 + .../core/regdb/rtw_regdb_rtk_63-37.c | 925 + .../core/regdb/rtw_regdb_rtk_63-38.c | 925 + .../core/regdb/rtw_regdb_rtk_63-39.c | 925 + .../core/regdb/rtw_regdb_rtk_63-40.c | 925 + .../core/regdb/rtw_regdb_rtk_64-40.c | 931 + .../core/regdb/rtw_regdb_rtk_64-41.c | 931 + .../core/regdb/rtw_regdb_rtk_64-42.c | 931 + .../core/regdb/rtw_regdb_rtk_65-44.c | 934 + .../core/regdb/rtw_regdb_rtk_66-45.c | 937 + .../core/regdb/rtw_regdb_rtk_67-46.c | 947 + .../core/regdb/rtw_regdb_rtk_68-47.c | 949 + .../rtw_regdb_rtk_8851BE_M.2_2230-67-3.c | 947 + .../rtw_regdb_rtk_8852BE_M.2_2230-67-48.c | 947 + .../rtw_regdb_rtk_8852CE_M.2_2230-67-51.c | 947 + .../rtw_regdb_rtk_8852CE_M.2_2230-67-52.c | 947 + .../wireless/realtek/rtl8852ce/core/rtw_ap.c | 7902 + .../realtek/rtl8852ce/core/rtw_beamforming.c | 2138 + .../realtek/rtl8852ce/core/rtw_br_ext.c | 1582 + .../wireless/realtek/rtl8852ce/core/rtw_btc.c | 20 + .../realtek/rtl8852ce/core/rtw_chplan.c | 4741 + .../realtek/rtl8852ce/core/rtw_chplan.h | 685 + .../realtek/rtl8852ce/core/rtw_chset.c | 382 + .../realtek/rtl8852ce/core/rtw_chset.h | 119 + .../wireless/realtek/rtl8852ce/core/rtw_cmd.c | 5453 + .../wireless/realtek/rtl8852ce/core/rtw_csa.c | 1275 + .../wireless/realtek/rtl8852ce/core/rtw_csi.c | 320 + .../wireless/realtek/rtl8852ce/core/rtw_csi.h | 29 + .../realtek/rtl8852ce/core/rtw_debug.c | 7449 + .../wireless/realtek/rtl8852ce/core/rtw_dfs.c | 1652 + .../wireless/realtek/rtl8852ce/core/rtw_dfs.h | 93 + .../wireless/realtek/rtl8852ce/core/rtw_eht.c | 458 + .../realtek/rtl8852ce/core/rtw_fake_ap.c | 480 + .../wireless/realtek/rtl8852ce/core/rtw_fsm.c | 1983 + .../realtek/rtl8852ce/core/rtw_fsm_rrm.c | 4306 + .../realtek/rtl8852ce/core/rtw_fsm_wnm.c | 945 + .../realtek/rtl8852ce/core/rtw_fsm_xxx.c | 234 + .../wireless/realtek/rtl8852ce/core/rtw_ft.c | 951 + .../wireless/realtek/rtl8852ce/core/rtw_he.c | 1995 + .../realtek/rtl8852ce/core/rtw_ieee80211.c | 3757 + .../wireless/realtek/rtl8852ce/core/rtw_io.c | 75 + .../realtek/rtl8852ce/core/rtw_ioctl_query.c | 19 + .../realtek/rtl8852ce/core/rtw_ioctl_set.c | 870 + .../wireless/realtek/rtl8852ce/core/rtw_mbo.c | 1555 + .../wireless/realtek/rtl8852ce/core/rtw_mem.c | 40 + .../wireless/realtek/rtl8852ce/core/rtw_mi.c | 1624 + .../realtek/rtl8852ce/core/rtw_mlme.c | 7246 + .../realtek/rtl8852ce/core/rtw_mlme_ext.c | 13719 + .../wireless/realtek/rtl8852ce/core/rtw_mp.c | 4161 + .../wireless/realtek/rtl8852ce/core/rtw_p2p.c | 3345 + .../wireless/realtek/rtl8852ce/core/rtw_phl.c | 4687 + .../realtek/rtl8852ce/core/rtw_phl_cmd.c | 461 + .../realtek/rtl8852ce/core/rtw_prealloc.c | 476 + .../realtek/rtl8852ce/core/rtw_pwrctrl.c | 330 + .../realtek/rtl8852ce/core/rtw_recv.c | 5885 + .../rtl8852ce/core/rtw_recv_shortcut.c | 247 + .../wireless/realtek/rtl8852ce/core/rtw_rf.c | 2213 + .../wireless/realtek/rtl8852ce/core/rtw_rm.c | 2986 + .../realtek/rtl8852ce/core/rtw_rm_fsm.c | 1016 + .../realtek/rtl8852ce/core/rtw_rm_util.c | 460 + .../realtek/rtl8852ce/core/rtw_scan.c | 3523 + .../realtek/rtl8852ce/core/rtw_sdio.c | 203 + .../realtek/rtl8852ce/core/rtw_sec_cam.c | 1123 + .../realtek/rtl8852ce/core/rtw_security.c | 2787 + .../realtek/rtl8852ce/core/rtw_sta_mgt.c | 1885 + .../realtek/rtl8852ce/core/rtw_swcrypto.c | 319 + .../realtek/rtl8852ce/core/rtw_tdls.c | 3897 + .../wireless/realtek/rtl8852ce/core/rtw_trx.c | 156 + .../realtek/rtl8852ce/core/rtw_trx_pci.c | 197 + .../realtek/rtl8852ce/core/rtw_trx_usb.c | 50 + .../wireless/realtek/rtl8852ce/core/rtw_twt.c | 1114 + .../realtek/rtl8852ce/core/rtw_txpwr.c | 163 + .../realtek/rtl8852ce/core/rtw_txpwr.h | 64 + .../wireless/realtek/rtl8852ce/core/rtw_vht.c | 1840 + .../realtek/rtl8852ce/core/rtw_wapi.c | 1319 + .../realtek/rtl8852ce/core/rtw_wapi_sms4.c | 922 + .../realtek/rtl8852ce/core/rtw_wlan_util.c | 3748 + .../wireless/realtek/rtl8852ce/core/rtw_wnm.c | 1506 + .../wireless/realtek/rtl8852ce/core/rtw_wow.c | 961 + .../realtek/rtl8852ce/core/rtw_xmit.c | 9995 + .../rtl8852ce/core/rtw_xmit_shortcut.c | 1636 + .../realtek/rtl8852ce/core/wds/rtw_wds.c | 786 + .../realtek/rtl8852ce/core/wds/rtw_wds.h | 65 + .../realtek/rtl8852ce/include/_hal_api_tmp.h | 347 + .../realtek/rtl8852ce/include/_hal_rate.h | 1202 + .../realtek/rtl8852ce/include/autoconf.h | 607 + .../realtek/rtl8852ce/include/autoconf.h.orig | 540 + .../realtek/rtl8852ce/include/basic_types.h | 367 + .../rtl8852ce/include/byteorder/big_endian.h | 82 + .../rtl8852ce/include/byteorder/generic.h | 191 + .../include/byteorder/little_endian.h | 84 + .../rtl8852ce/include/byteorder/swab.h | 136 + .../rtl8852ce/include/byteorder/swabb.h | 151 + .../realtek/rtl8852ce/include/circ_buf.h | 23 + .../realtek/rtl8852ce/include/custom_gpio.h | 34 + .../realtek/rtl8852ce/include/drv_conf.h | 822 + .../realtek/rtl8852ce/include/drv_types.h | 2131 + .../rtl8852ce/include/drv_types_gspi.h | 49 + .../realtek/rtl8852ce/include/drv_types_pci.h | 96 + .../rtl8852ce/include/drv_types_sdio.h | 90 + .../realtek/rtl8852ce/include/drv_types_usb.h | 72 + .../realtek/rtl8852ce/include/ethernet.h | 36 + .../realtek/rtl8852ce/include/gspi_hal.h | 21 + .../realtek/rtl8852ce/include/gspi_ops.h | 144 + .../rtl8852ce/include/gspi_ops_linux.h | 18 + .../realtek/rtl8852ce/include/ieee80211.h | 2063 + .../realtek/rtl8852ce/include/ieee80211_ext.h | 312 + .../realtek/rtl8852ce/include/if_ether.h | 106 + .../wireless/realtek/rtl8852ce/include/ip.h | 135 + .../rtl8852ce/include/linux/wireless.h | 87 + .../realtek/rtl8852ce/include/mlme_osdep.h | 42 + .../realtek/rtl8852ce/include/osdep_intf.h | 100 + .../realtek/rtl8852ce/include/osdep_service.h | 755 + .../rtl8852ce/include/osdep_service.h.orig | 665 + .../rtl8852ce/include/osdep_service_bsd.h | 1044 + .../rtl8852ce/include/osdep_service_linux.h | 1176 + .../realtek/rtl8852ce/include/pci_ops.h | 44 + .../realtek/rtl8852ce/include/pci_ops_linux.h | 24 + .../realtek/rtl8852ce/include/phl_api_tmp.h | 28 + .../realtek/rtl8852ce/include/recv_osdep.h | 74 + .../realtek/rtl8852ce/include/rtw_android.h | 106 + .../realtek/rtl8852ce/include/rtw_ap.h | 184 + .../rtl8852ce/include/rtw_beamforming.h | 48 + .../realtek/rtl8852ce/include/rtw_br_ext.h | 69 + .../realtek/rtl8852ce/include/rtw_btc.h | 22 + .../realtek/rtl8852ce/include/rtw_byteorder.h | 33 + .../realtek/rtl8852ce/include/rtw_cfg.h | 44 + .../realtek/rtl8852ce/include/rtw_cmd.h | 648 + .../realtek/rtl8852ce/include/rtw_csa.h | 148 + .../realtek/rtl8852ce/include/rtw_debug.h | 787 + .../rtl8852ce/include/rtw_debug.h.orig | 631 + .../realtek/rtl8852ce/include/rtw_efuse.h | 139 + .../realtek/rtl8852ce/include/rtw_eht.h | 82 + .../realtek/rtl8852ce/include/rtw_event.h | 75 + .../realtek/rtl8852ce/include/rtw_fsm.h | 338 + .../realtek/rtl8852ce/include/rtw_fsm_rrm.h | 51 + .../realtek/rtl8852ce/include/rtw_fsm_wnm.h | 36 + .../realtek/rtl8852ce/include/rtw_fsm_xxx.h | 33 + .../realtek/rtl8852ce/include/rtw_ft.h | 203 + .../realtek/rtl8852ce/include/rtw_he.h | 1116 + .../realtek/rtl8852ce/include/rtw_he.h.orig | 1095 + .../realtek/rtl8852ce/include/rtw_ht.h | 225 + .../rtl8852ce/include/rtw_hwsim_intf.h | 31 + .../realtek/rtl8852ce/include/rtw_io.h | 40 + .../realtek/rtl8852ce/include/rtw_ioctl.h | 47 + .../rtl8852ce/include/rtw_ioctl_query.h | 19 + .../realtek/rtl8852ce/include/rtw_ioctl_set.h | 41 + .../realtek/rtl8852ce/include/rtw_mbo.h | 210 + .../realtek/rtl8852ce/include/rtw_mcc.h | 14 + .../realtek/rtl8852ce/include/rtw_mem.h | 29 + .../realtek/rtl8852ce/include/rtw_mi.h | 279 + .../realtek/rtl8852ce/include/rtw_mlme.h | 1252 + .../realtek/rtl8852ce/include/rtw_mlme_ext.h | 1127 + .../realtek/rtl8852ce/include/rtw_mp.h | 1755 + .../realtek/rtl8852ce/include/rtw_p2p.h | 94 + .../realtek/rtl8852ce/include/rtw_phl.h | 258 + .../realtek/rtl8852ce/include/rtw_phl_cmd.h | 30 + .../realtek/rtl8852ce/include/rtw_pwrctrl.h | 128 + .../realtek/rtl8852ce/include/rtw_qos.h | 52 + .../realtek/rtl8852ce/include/rtw_recv.h | 659 + .../rtl8852ce/include/rtw_recv_shortcut.h | 60 + .../realtek/rtl8852ce/include/rtw_rf.h | 305 + .../realtek/rtl8852ce/include/rtw_rm.h | 111 + .../realtek/rtl8852ce/include/rtw_rm_fsm.h | 406 + .../realtek/rtl8852ce/include/rtw_rm_util.h | 46 + .../realtek/rtl8852ce/include/rtw_scan.h | 311 + .../realtek/rtl8852ce/include/rtw_sdio.h | 32 + .../realtek/rtl8852ce/include/rtw_sec_cam.h | 210 + .../realtek/rtl8852ce/include/rtw_security.h | 440 + .../realtek/rtl8852ce/include/rtw_swcrypto.h | 54 + .../realtek/rtl8852ce/include/rtw_tdls.h | 190 + .../realtek/rtl8852ce/include/rtw_trx.h | 35 + .../realtek/rtl8852ce/include/rtw_trx_ops.h | 63 + .../realtek/rtl8852ce/include/rtw_trx_pci.h | 35 + .../realtek/rtl8852ce/include/rtw_trx_usb.h | 21 + .../realtek/rtl8852ce/include/rtw_twt.h | 106 + .../realtek/rtl8852ce/include/rtw_version.h | 1 + .../realtek/rtl8852ce/include/rtw_vht.h | 250 + .../realtek/rtl8852ce/include/rtw_wapi.h | 230 + .../realtek/rtl8852ce/include/rtw_wnm.h | 225 + .../realtek/rtl8852ce/include/rtw_wow.h | 191 + .../realtek/rtl8852ce/include/rtw_xmit.h | 1198 + .../realtek/rtl8852ce/include/rtw_xmit.h.orig | 1174 + .../rtl8852ce/include/rtw_xmit_shortcut.h | 137 + .../realtek/rtl8852ce/include/sdio_ops.h | 33 + .../rtl8852ce/include/sdio_ops_linux.h | 20 + .../realtek/rtl8852ce/include/sta_info.h | 899 + .../realtek/rtl8852ce/include/usb_ops.h | 67 + .../realtek/rtl8852ce/include/usb_ops_linux.h | 66 + .../wireless/realtek/rtl8852ce/include/wifi.h | 1311 + .../realtek/rtl8852ce/include/wlan_bssdef.h | 327 + .../realtek/rtl8852ce/include/xmit_osdep.h | 104 + .../os_dep/linux/custom_gpio_linux.c | 245 + .../rtl8852ce/os_dep/linux/ioctl_cfg80211.c | 11568 + .../rtl8852ce/os_dep/linux/ioctl_cfg80211.h | 501 + .../rtl8852ce/os_dep/linux/ioctl_efuse.c | 1625 + .../rtl8852ce/os_dep/linux/ioctl_linux.c | 8252 + .../realtek/rtl8852ce/os_dep/linux/ioctl_mp.c | 4315 + .../rtl8852ce/os_dep/linux/mlme_linux.c | 504 + .../realtek/rtl8852ce/os_dep/linux/nlrtw.c | 596 + .../realtek/rtl8852ce/os_dep/linux/nlrtw.h | 48 + .../rtl8852ce/os_dep/linux/os_ch_utils.c | 444 + .../rtl8852ce/os_dep/linux/os_ch_utils.h | 63 + .../realtek/rtl8852ce/os_dep/linux/os_intfs.c | 3675 + .../realtek/rtl8852ce/os_dep/linux/pci_intf.c | 1194 + .../rtl8852ce/os_dep/linux/pci_ops_linux.c | 327 + .../rtl8852ce/os_dep/linux/recv_linux.c | 643 + .../rtl8852ce/os_dep/linux/rhashtable.c | 844 + .../rtl8852ce/os_dep/linux/rhashtable.h | 827 + .../rtl8852ce/os_dep/linux/rtw_android.c | 1084 + .../realtek/rtl8852ce/os_dep/linux/rtw_cfg.c | 2197 + .../rtl8852ce/os_dep/linux/rtw_cfgvendor.c | 2162 + .../rtl8852ce/os_dep/linux/rtw_cfgvendor.h | 634 + .../realtek/rtl8852ce/os_dep/linux/rtw_proc.c | 6636 + .../realtek/rtl8852ce/os_dep/linux/rtw_proc.h | 77 + .../rtl8852ce/os_dep/linux/rtw_rhashtable.c | 76 + .../rtl8852ce/os_dep/linux/rtw_rhashtable.h | 67 + .../rtl8852ce/os_dep/linux/wifi_regd.c | 1367 + .../rtl8852ce/os_dep/linux/wifi_regd.h | 69 + .../rtl8852ce/os_dep/linux/xmit_linux.c | 750 + .../realtek/rtl8852ce/os_dep/osdep_service.c | 1214 + .../rtl8852ce/os_dep/osdep_service_linux.c | 1095 + .../realtek/rtl8852ce/phl/custom/phl_custom.c | 571 + .../realtek/rtl8852ce/phl/custom/phl_custom.h | 56 + .../rtl8852ce/phl/custom/phl_custom_antenna.c | 288 + .../rtl8852ce/phl/custom/phl_custom_antenna.h | 44 + .../rtl8852ce/phl/custom/phl_custom_api.h | 34 + .../rtl8852ce/phl/custom/phl_custom_def.h | 141 + .../rtl8852ce/phl/custom/phl_custom_vr.c | 1150 + .../rtl8852ce/phl/custom/phl_custom_vr.h | 93 + .../rtl8852ce/phl/custom/phl_custom_vr_csi.c | 268 + .../rtl8852ce/phl/custom/phl_custom_vr_csi.h | 57 + .../realtek/rtl8852ce/phl/hal_g6/btc/btc.mk | 60 + .../phl/hal_g6/btc/btc_8852c/btc_8852c.c | 535 + .../phl/hal_g6/btc/btc_8852c/btc_8852c.h | 58 + .../rtl8852ce/phl/hal_g6/btc/hal_btc.c | 2745 + .../rtl8852ce/phl/hal_g6/btc/hal_btc.h | 1983 + .../rtl8852ce/phl/hal_g6/btc/halbtc_action.c | 2501 + .../rtl8852ce/phl/hal_g6/btc/halbtc_action.h | 316 + .../rtl8852ce/phl/hal_g6/btc/halbtc_dbg_cmd.c | 3719 + .../rtl8852ce/phl/hal_g6/btc/halbtc_dbg_cmd.h | 31 + .../rtl8852ce/phl/hal_g6/btc/halbtc_def.c | 776 + .../rtl8852ce/phl/hal_g6/btc/halbtc_def.h | 21 + .../rtl8852ce/phl/hal_g6/btc/halbtc_fw.c | 1307 + .../rtl8852ce/phl/hal_g6/btc/halbtc_fw.h | 293 + .../rtl8852ce/phl/hal_g6/btc/halbtc_fwdef.h | 609 + .../rtl8852ce/phl/hal_g6/efuse/hal_efuse.c | 1497 + .../rtl8852ce/phl/hal_g6/efuse/hal_efuse.h | 84 + .../phl/hal_g6/efuse/hal_efuse_export.h | 147 + .../realtek/rtl8852ce/phl/hal_g6/hal.mk | 118 + .../realtek/rtl8852ce/phl/hal_g6/hal_acs.c | 33 + .../realtek/rtl8852ce/phl/hal_g6/hal_acs.h | 22 + .../realtek/rtl8852ce/phl/hal_g6/hal_api.c | 658 + .../realtek/rtl8852ce/phl/hal_g6/hal_api.h | 1461 + .../realtek/rtl8852ce/phl/hal_g6/hal_api_bb.c | 3495 + .../realtek/rtl8852ce/phl/hal_g6/hal_api_bb.h | 365 + .../rtl8852ce/phl/hal_g6/hal_api_btc.c | 824 + .../rtl8852ce/phl/hal_g6/hal_api_btc.h | 43 + .../rtl8852ce/phl/hal_g6/hal_api_drv.h | 500 + .../rtl8852ce/phl/hal_g6/hal_api_efuse.c | 639 + .../rtl8852ce/phl/hal_g6/hal_api_efuse.h | 117 + .../rtl8852ce/phl/hal_g6/hal_api_mac.c | 12050 + .../rtl8852ce/phl/hal_g6/hal_api_mac.h | 925 + .../realtek/rtl8852ce/phl/hal_g6/hal_api_rf.c | 1726 + .../realtek/rtl8852ce/phl/hal_g6/hal_api_rf.h | 312 + .../rtl8852ce/phl/hal_g6/hal_beamform.c | 1193 + .../rtl8852ce/phl/hal_g6/hal_beamform.h | 200 + .../realtek/rtl8852ce/phl/hal_g6/hal_c2h.c | 87 + .../realtek/rtl8852ce/phl/hal_g6/hal_c2h.h | 21 + .../realtek/rtl8852ce/phl/hal_g6/hal_cam.c | 72 + .../realtek/rtl8852ce/phl/hal_g6/hal_cap.c | 800 + .../realtek/rtl8852ce/phl/hal_g6/hal_cap.h | 22 + .../realtek/rtl8852ce/phl/hal_g6/hal_chan.c | 226 + .../realtek/rtl8852ce/phl/hal_g6/hal_chan.h | 35 + .../rtl8852ce/phl/hal_g6/hal_chan_info.c | 498 + .../rtl8852ce/phl/hal_g6/hal_chan_info.h | 48 + .../realtek/rtl8852ce/phl/hal_g6/hal_com_i.c | 459 + .../realtek/rtl8852ce/phl/hal_g6/hal_com_i.h | 29 + .../realtek/rtl8852ce/phl/hal_g6/hal_config.h | 132 + .../rtl8852ce/phl/hal_g6/hal_csi_buffer.c | 637 + .../rtl8852ce/phl/hal_g6/hal_csi_buffer.h | 107 + .../realtek/rtl8852ce/phl/hal_g6/hal_custom.c | 178 + .../realtek/rtl8852ce/phl/hal_g6/hal_custom.h | 72 + .../realtek/rtl8852ce/phl/hal_g6/hal_dbcc.c | 348 + .../realtek/rtl8852ce/phl/hal_g6/hal_dbcc.h | 27 + .../realtek/rtl8852ce/phl/hal_g6/hal_def.h | 1299 + .../rtl8852ce/phl/hal_g6/hal_def_btc.h | 18 + .../rtl8852ce/phl/hal_g6/hal_def_mac.h | 18 + .../rtl8852ce/phl/hal_g6/hal_def_phy.h | 18 + .../realtek/rtl8852ce/phl/hal_g6/hal_dfs.c | 46 + .../realtek/rtl8852ce/phl/hal_g6/hal_dfs.h | 18 + .../rtl8852ce/phl/hal_g6/hal_ext_tx_pwr_lmt.c | 103 + .../rtl8852ce/phl/hal_g6/hal_feature.h | 69 + .../realtek/rtl8852ce/phl/hal_g6/hal_fw.c | 339 + .../realtek/rtl8852ce/phl/hal_g6/hal_fw.h | 35 + .../rtl8852ce/phl/hal_g6/hal_general_def.h | 491 + .../rtl8852ce/phl/hal_g6/hal_headers.h | 107 + .../rtl8852ce/phl/hal_g6/hal_headers_le.h | 351 + .../realtek/rtl8852ce/phl/hal_g6/hal_init.c | 1821 + .../realtek/rtl8852ce/phl/hal_g6/hal_io.c | 799 + .../realtek/rtl8852ce/phl/hal_g6/hal_io.h | 123 + .../rtl8852ce/phl/hal_g6/hal_ld_file.c | 2431 + .../rtl8852ce/phl/hal_g6/hal_ld_file.h | 249 + .../realtek/rtl8852ce/phl/hal_g6/hal_led.c | 73 + .../realtek/rtl8852ce/phl/hal_g6/hal_mcc.c | 476 + .../realtek/rtl8852ce/phl/hal_g6/hal_mcc.h | 25 + .../rtl8852ce/phl/hal_g6/hal_mcc_def.h | 19 + .../realtek/rtl8852ce/phl/hal_g6/hal_notify.c | 117 + .../realtek/rtl8852ce/phl/hal_g6/hal_notify.h | 38 + .../realtek/rtl8852ce/phl/hal_g6/hal_p2pps.c | 105 + .../realtek/rtl8852ce/phl/hal_g6/hal_pci.c | 264 + .../realtek/rtl8852ce/phl/hal_g6/hal_pci.h | 126 + .../realtek/rtl8852ce/phl/hal_g6/hal_ps.c | 479 + .../realtek/rtl8852ce/phl/hal_g6/hal_ps.h | 24 + .../rtl8852ce/phl/hal_g6/hal_regulation.c | 23 + .../realtek/rtl8852ce/phl/hal_g6/hal_rx.c | 1156 + .../realtek/rtl8852ce/phl/hal_g6/hal_rx.h | 48 + .../rtl8852ce/phl/hal_g6/hal_scanofld.c | 60 + .../rtl8852ce/phl/hal_g6/hal_scanofld.h | 32 + .../realtek/rtl8852ce/phl/hal_g6/hal_ser.c | 179 + .../realtek/rtl8852ce/phl/hal_g6/hal_ser.h | 18 + .../realtek/rtl8852ce/phl/hal_g6/hal_sound.c | 1059 + .../realtek/rtl8852ce/phl/hal_g6/hal_sound.h | 75 + .../realtek/rtl8852ce/phl/hal_g6/hal_sta.c | 1253 + .../realtek/rtl8852ce/phl/hal_g6/hal_sta.h | 25 + .../rtl8852ce/phl/hal_g6/hal_str_proc.c | 248 + .../rtl8852ce/phl/hal_g6/hal_str_proc.h | 43 + .../realtek/rtl8852ce/phl/hal_g6/hal_struct.h | 434 + .../rtl8852ce/phl/hal_g6/hal_thermal.c | 130 + .../rtl8852ce/phl/hal_g6/hal_trx_mit.c | 118 + .../realtek/rtl8852ce/phl/hal_g6/hal_twt.c | 40 + .../realtek/rtl8852ce/phl/hal_g6/hal_tx.c | 524 + .../realtek/rtl8852ce/phl/hal_g6/hal_tx.h | 45 + .../realtek/rtl8852ce/phl/hal_g6/hal_txpwr.c | 274 + .../realtek/rtl8852ce/phl/hal_g6/hal_txpwr.h | 53 + .../realtek/rtl8852ce/phl/hal_g6/hal_wow.c | 554 + .../realtek/rtl8852ce/phl/hal_g6/hal_wow.h | 23 + .../rtl8852ce/phl/hal_g6/mac/chip_cfg.h | 210 + .../rtl8852ce/phl/hal_g6/mac/chip_cfg_drv.h | 85 + .../realtek/rtl8852ce/phl/hal_g6/mac/errors.h | 261 + .../rtl8852ce/phl/hal_g6/mac/feature_cfg.h | 102 + .../phl/hal_g6/mac/fw_ax/inc_hdr/fwcmd_intf.h | 14287 + .../mac/fw_ax/inc_hdr/wow_h2c_white_list.h | 78 + .../hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw.c | 264386 +++++++++++++++ .../hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw.h | 62 + .../mac/fw_ax/rtl8852c/hal8852c_fw_cap.h | 88 + .../mac/fw_ax/rtl8852c/hal8852c_fw_log.c | 1269 + .../mac/fw_ax/rtl8852c/hal8852c_fw_log.h | 1274 + .../rtl8852ce/phl/hal_g6/mac/halmac_wpp.h | 37 + .../rtl8852ce/phl/hal_g6/mac/hci_reg_ax.h | 4518 + .../rtl8852ce/phl/hal_g6/mac/hci_reg_be.h | 3028 + .../rtl8852ce/phl/hal_g6/mac/hv_type.h | 1136 + .../g6/8852c/err_flag_auto_gen_8852c.c | 42 + .../g6/8852c/err_flag_auto_gen_8852c.h | 39 + .../AutoGen_Func/g6/mac_autogen_func_top_g6.h | 27 + .../phl/hal_g6/mac/include/mac_top.h | 6 + .../realtek/rtl8852ce/phl/hal_g6/mac/mac.mk | 415 + .../rtl8852ce/phl/hal_g6/mac/mac2drv_def.h | 14 + .../realtek/rtl8852ce/phl/hal_g6/mac/mac_ax.c | 608 + .../realtek/rtl8852ce/phl/hal_g6/mac/mac_ax.h | 110 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/_pcie.c | 3114 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/_pcie.h | 1121 + .../phl/hal_g6/mac/mac_ax/addr_cam.c | 910 + .../phl/hal_g6/mac/mac_ax/addr_cam.h | 352 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/beacon.c | 368 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/beacon.h | 79 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/cmac_tx.c | 2424 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/cmac_tx.h | 980 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/coex.c | 115 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/coex.h | 127 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/common.c | 29 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/common.h | 37 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/cpuio.c | 1366 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/cpuio.h | 719 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbcc.c | 671 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbcc.h | 158 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbg_cmd.c | 4167 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbg_cmd.h | 1239 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbgpkg.c | 4098 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dbgpkg.h | 1595 + .../phl/hal_g6/mac/mac_ax/dbgport_hw.c | 954 + .../phl/hal_g6/mac/mac_ax/dbgport_hw.h | 471 + .../phl/hal_g6/mac/mac_ax/diagnosis.c | 3507 + .../phl/hal_g6/mac/mac_ax/diagnosis.h | 33 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dle.c | 4030 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/dle.h | 767 + .../phl/hal_g6/mac/mac_ax/eco_patch_check.c | 5892 + .../phl/hal_g6/mac/mac_ax/eco_patch_check.h | 70 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/efuse.c | 4347 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/efuse.h | 1190 + .../phl/hal_g6/mac/mac_ax/err_flag.c | 134 + .../phl/hal_g6/mac/mac_ax/err_flag.h | 31 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/flash.c | 731 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/flash.h | 52 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd.c | 3880 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd.h | 819 + .../phl/hal_g6/mac/mac_ax/fwcmd_intf_f2p.h | 522 + .../phl/hal_g6/mac/mac_ax/fwcmd_intf_f2p_v1.h | 262 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwdl.c | 2350 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwdl.h | 1404 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwofld.c | 2965 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/fwofld.h | 1411 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/gpio.c | 874 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/gpio.h | 344 + .../phl/hal_g6/mac/mac_ax/gpio_cmd.h | 321 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/h2c_agg.c | 241 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/h2c_agg.h | 32 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hci_fc.c | 2744 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hci_fc.h | 155 + .../phl/hal_g6/mac/mac_ax/hdr_conv.c | 640 + .../phl/hal_g6/mac/mac_ax/hdr_conv.h | 299 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hw.c | 2248 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hw.h | 1157 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hw_seq.c | 338 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hw_seq.h | 175 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hwamsdu.c | 208 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/hwamsdu.h | 171 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/init.c | 952 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/init.h | 226 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/la_mode.c | 244 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/la_mode.h | 139 + .../hal_g6/mac/mac_ax/mac_8852c/_pcie_8852c.c | 2506 + .../hal_g6/mac/mac_ax/mac_8852c/_pcie_8852c.h | 798 + .../hal_g6/mac/mac_ax/mac_8852c/_sdio_8852c.c | 607 + .../hal_g6/mac/mac_ax/mac_8852c/_sdio_8852c.h | 375 + .../hal_g6/mac/mac_ax/mac_8852c/_usb_8852c.c | 567 + .../hal_g6/mac/mac_ax/mac_8852c/_usb_8852c.h | 530 + .../mac/mac_ax/mac_8852c/cmac_tx_8852c.c | 145 + .../mac/mac_ax/mac_8852c/cmac_tx_8852c.h | 29 + .../hal_g6/mac/mac_ax/mac_8852c/coex_8852c.c | 225 + .../hal_g6/mac/mac_ax/mac_8852c/coex_8852c.h | 270 + .../mac/mac_ax/mac_8852c/dbg_cmd_8852c.c | 40 + .../mac/mac_ax/mac_8852c/dbg_cmd_8852c.h | 27 + .../mac/mac_ax/mac_8852c/dbgpkg_8852c.c | 4224 + .../mac/mac_ax/mac_8852c/dbgpkg_8852c.h | 163 + .../hal_g6/mac/mac_ax/mac_8852c/dle_8852c.c | 753 + .../hal_g6/mac/mac_ax/mac_8852c/dle_8852c.h | 333 + .../hal_g6/mac/mac_ax/mac_8852c/efuse_8852c.c | 140 + .../hal_g6/mac/mac_ax/mac_8852c/efuse_8852c.h | 82 + .../hal_g6/mac/mac_ax/mac_8852c/fwcmd_8852c.c | 47 + .../hal_g6/mac/mac_ax/mac_8852c/fwcmd_8852c.h | 30 + .../hal_g6/mac/mac_ax/mac_8852c/gpio_8852c.c | 2586 + .../hal_g6/mac/mac_ax/mac_8852c/gpio_8852c.h | 82 + .../mac/mac_ax/mac_8852c/hci_fc_8852c.c | 382 + .../mac/mac_ax/mac_8852c/hci_fc_8852c.h | 121 + .../mac/mac_ax/mac_8852c/hdr_conv_rx_8852c.c | 185 + .../mac/mac_ax/mac_8852c/hdr_conv_rx_8852c.h | 44 + .../mac/mac_ax/mac_8852c/hwamsdu_8852c.c | 67 + .../mac/mac_ax/mac_8852c/hwamsdu_8852c.h | 52 + .../hal_g6/mac/mac_ax/mac_8852c/init_8852c.c | 983 + .../hal_g6/mac/mac_ax/mac_8852c/init_8852c.h | 32 + .../mac/mac_ax/mac_8852c/mac_priv_8852c.c | 222 + .../mac/mac_ax/mac_8852c/mac_priv_8852c.h | 26 + .../mac/mac_ax/mac_8852c/mac_txccxrpt.h | 185 + .../mac/mac_ax/mac_8852c/phy_rpt_8852c.c | 113 + .../mac/mac_ax/mac_8852c/phy_rpt_8852c.h | 30 + .../mac/mac_ax/mac_8852c/pwr_seq_8852c.c | 1508 + .../mac/mac_ax/mac_8852c/pwr_seq_8852c.h | 30 + .../mac/mac_ax/mac_8852c/pwr_seq_func_8852c.c | 2401 + .../mac/mac_ax/mac_8852c/pwr_seq_func_8852c.h | 46 + .../hal_g6/mac/mac_ax/mac_8852c/rrsr_8852c.c | 143 + .../hal_g6/mac/mac_ax/mac_8852c/rrsr_8852c.h | 109 + .../mac/mac_ax/mac_8852c/security_cam_8852c.c | 1174 + .../mac/mac_ax/mac_8852c/security_cam_8852c.h | 261 + .../hal_g6/mac/mac_ax/mac_8852c/ser_8852c.c | 1249 + .../hal_g6/mac/mac_ax/mac_8852c/ser_8852c.h | 633 + .../mac/mac_ax/mac_8852c/tblupd_8852c.c | 852 + .../mac/mac_ax/mac_8852c/tblupd_8852c.h | 136 + .../mac/mac_ax/mac_8852c/trx_desc_8852c.c | 772 + .../mac/mac_ax/mac_8852c/trx_desc_8852c.h | 181 + .../mac/mac_ax/mac_8852c/wowlan_8852c.c | 28 + .../mac/mac_ax/mac_8852c/wowlan_8852c.h | 27 + .../phl/hal_g6/mac/mac_ax/mac_ax_dfs.h | 28 + .../phl/hal_g6/mac/mac_ax/mac_ax_mac_info.h | 47 + .../phl/hal_g6/mac/mac_ax/mac_priv.c | 98 + .../phl/hal_g6/mac/mac_ax/mac_priv.h | 285 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/mcc.c | 596 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/mcc.h | 413 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/mport.c | 2628 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/mport.h | 298 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/nan.c | 416 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/nan.h | 128 + .../phl/hal_g6/mac/mac_ax/otpkeysinfo.c | 7 + .../phl/hal_g6/mac/mac_ax/otpkeysinfo.h | 22 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/outsrc.c | 891 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/outsrc.h | 67 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/p2p.c | 331 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/p2p.h | 118 + .../phl/hal_g6/mac/mac_ax/phy_misc.c | 89 + .../phl/hal_g6/mac/mac_ax/phy_misc.h | 26 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/phy_rpt.c | 734 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/phy_rpt.h | 144 + .../phl/hal_g6/mac/mac_ax/power_saving.c | 1343 + .../phl/hal_g6/mac/mac_ax/power_saving.h | 588 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/pwr.c | 458 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/pwr.h | 120 + .../phl/hal_g6/mac/mac_ax/pwr_seq_func.c | 108 + .../phl/hal_g6/mac/mac_ax/pwr_seq_func.h | 28 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/role.c | 1358 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/role.h | 381 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/rx.c | 99 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/rx.h | 64 + .../phl/hal_g6/mac/mac_ax/rx_filter.c | 431 + .../phl/hal_g6/mac/mac_ax/rx_filter.h | 169 + .../phl/hal_g6/mac/mac_ax/rx_forwarding.c | 430 + .../phl/hal_g6/mac/mac_ax/rx_forwarding.h | 113 + .../phl/hal_g6/mac/mac_ax/secure_boot.c | 481 + .../phl/hal_g6/mac/mac_ax/secure_boot.h | 102 + .../phl/hal_g6/mac/mac_ax/security_cam.c | 1080 + .../phl/hal_g6/mac/mac_ax/security_cam.h | 353 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/ser.c | 1698 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/ser.h | 826 + .../phl/hal_g6/mac/mac_ax/sounding.c | 3343 + .../phl/hal_g6/mac/mac_ax/sounding.h | 423 + .../phl/hal_g6/mac/mac_ax/spatial_reuse.c | 88 + .../phl/hal_g6/mac/mac_ax/spatial_reuse.h | 29 + .../phl/hal_g6/mac/mac_ax/sta_diag.c | 771 + .../phl/hal_g6/mac/mac_ax/sta_diag.h | 224 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/sta_sch.c | 935 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/sta_sch.h | 174 + .../phl/hal_g6/mac/mac_ax/state_mach.h | 286 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/status.c | 149 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/status.h | 73 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/tblupd.c | 2509 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/tblupd.h | 759 + .../mac/mac_ax/tcpip_checksum_offload.c | 124 + .../mac/mac_ax/tcpip_checksum_offload.h | 101 + .../phl/hal_g6/mac/mac_ax/trx_desc.c | 99 + .../phl/hal_g6/mac/mac_ax/trx_desc.h | 62 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/trxcfg.c | 2346 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/trxcfg.h | 362 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/twt.c | 259 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/twt.h | 176 + .../phl/hal_g6/mac/mac_ax/tx_statistic.c | 247 + .../phl/hal_g6/mac/mac_ax/tx_statistic.h | 188 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/wowlan.c | 2504 + .../rtl8852ce/phl/hal_g6/mac/mac_ax/wowlan.h | 1078 + .../rtl8852ce/phl/hal_g6/mac/mac_def.h | 18329 + .../rtl8852ce/phl/hal_g6/mac/mac_exp_def.h | 1273 + .../rtl8852ce/phl/hal_g6/mac/mac_hw_info.h | 75 + .../rtl8852ce/phl/hal_g6/mac/mac_outsrc_def.h | 186 + .../rtl8852ce/phl/hal_g6/mac/mac_reg.h | 9 + .../rtl8852ce/phl/hal_g6/mac/mac_reg_ax.h | 19563 ++ .../rtl8852ce/phl/hal_g6/mac/mac_reg_be.h | 12110 + .../rtl8852ce/phl/hal_g6/mac/pcie_reg.h | 174 + .../rtl8852ce/phl/hal_g6/mac/plat_reg_ax.h | 1988 + .../rtl8852ce/phl/hal_g6/mac/plat_reg_be.h | 2129 + .../rtl8852ce/phl/hal_g6/mac/pltfm_cfg.h | 186 + .../rtl8852ce/phl/hal_g6/mac/pltfm_cfg_drv.h | 69 + .../realtek/rtl8852ce/phl/hal_g6/mac/rxdesc.h | 152 + .../realtek/rtl8852ce/phl/hal_g6/mac/txdesc.h | 1695 + .../realtek/rtl8852ce/phl/hal_g6/mac/type.h | 1702 + .../realtek/rtl8852ce/phl/hal_g6/phy/bb/bb.mk | 235 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb.c | 1639 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb.h | 624 + .../hal_g6/phy/bb/halbb_8852c/halbb_8852c.c | 457 + .../hal_g6/phy/bb/halbb_8852c/halbb_8852c.h | 57 + .../phy/bb/halbb_8852c/halbb_8852c_api.c | 4341 + .../phy/bb/halbb_8852c/halbb_8852c_api.h | 287 + .../phy/bb/halbb_8852c/halbb_8852c_api_ex.h | 34 + .../phy/bb/halbb_8852c/halbb_8852c_dcra.c | 238 + .../phy/bb/halbb_8852c/halbb_8852c_dcra.h | 78 + .../phy/bb/halbb_8852c/halbb_8852c_dcra_ex.h | 34 + .../bb/halbb_8852c/halbb_8852c_fwofld_api.c | 1764 + .../bb/halbb_8852c/halbb_8852c_fwofld_api.h | 62 + .../phy/bb/halbb_8852c/halbb_cr_info_8852c.h | 18905 ++ .../phy/bb/halbb_8852c/halbb_hwimg_8852c.c | 373 + .../phy/bb/halbb_8852c/halbb_hwimg_8852c.h | 50 + .../halbb_8852c/halbb_hwimg_raw_data_8842a.h | 1896 + .../halbb_8852c/halbb_hwimg_raw_data_8852c.h | 6523 + .../halbb_8852c/halbb_hwimg_raw_data_8852d.h | 6171 + .../phy/bb/halbb_8852c/halbb_reg_cfg_8852c.c | 240 + .../phy/bb/halbb_8852c/halbb_reg_cfg_8852c.h | 36 + .../bb/halbb_8852c/halbb_version_rtl8842a.h | 30 + .../bb/halbb_8852c/halbb_version_rtl8852c.h | 30 + .../bb/halbb_8852c/halbb_version_rtl8852d.h | 30 + .../phl/hal_g6/phy/bb/halbb_ant_div.c | 2940 + .../phl/hal_g6/phy/bb/halbb_ant_div.h | 402 + .../phl/hal_g6/phy/bb/halbb_ant_div_ex.h | 34 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_api.c | 4897 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_api.h | 97 + .../phl/hal_g6/phy/bb/halbb_api_be.c | 86 + .../phl/hal_g6/phy/bb/halbb_api_be.h | 30 + .../phl/hal_g6/phy/bb/halbb_api_be_ex.h | 34 + .../phl/hal_g6/phy/bb/halbb_api_be_hw.c | 135 + .../phl/hal_g6/phy/bb/halbb_api_be_hw.h | 39 + .../phl/hal_g6/phy/bb/halbb_api_be_intg.c | 20 + .../phl/hal_g6/phy/bb/halbb_api_be_intg.h | 27 + .../phl/hal_g6/phy/bb/halbb_api_be_sw.c | 20 + .../phl/hal_g6/phy/bb/halbb_api_be_sw.h | 27 + .../phl/hal_g6/phy/bb/halbb_api_ex.h | 217 + .../phl/hal_g6/phy/bb/halbb_auto_dbg.c | 449 + .../phl/hal_g6/phy/bb/halbb_auto_dbg.h | 56 + .../phl/hal_g6/phy/bb/halbb_auto_dbg_ex.h | 67 + .../phl/hal_g6/phy/bb/halbb_bb_wrapper.c | 1900 + .../phl/hal_g6/phy/bb/halbb_bb_wrapper.h | 33 + .../hal_g6/phy/bb/halbb_bb_wrapper_outsrc.h | 227 + .../phl/hal_g6/phy/bb/halbb_cfg_ic.h | 77 + .../phl/hal_g6/phy/bb/halbb_cfo_trk.c | 1518 + .../phl/hal_g6/phy/bb/halbb_cfo_trk.h | 209 + .../phl/hal_g6/phy/bb/halbb_ch_info.c | 1589 + .../phl/hal_g6/phy/bb/halbb_ch_info.h | 116 + .../phl/hal_g6/phy/bb/halbb_ch_info_ex.h | 173 + .../phl/hal_g6/phy/bb/halbb_cmn_rpt.c | 1802 + .../phl/hal_g6/phy/bb/halbb_cmn_rpt.h | 144 + .../phl/hal_g6/phy/bb/halbb_cmn_rpt_ex.h | 125 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dbcc.c | 540 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dbcc.h | 55 + .../phl/hal_g6/phy/bb/halbb_dbcc_ex.h | 44 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg.c | 3990 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg.h | 444 + .../phl/hal_g6/phy/bb/halbb_dbg_cmd.c | 1026 + .../phl/hal_g6/phy/bb/halbb_dbg_cmd.h | 84 + .../phl/hal_g6/phy/bb/halbb_dbg_cmd_ex.h | 39 + .../phl/hal_g6/phy/bb/halbb_dbg_cmd_table.h | 170 + .../phl/hal_g6/phy/bb/halbb_dbg_cnsl_out.c | 2111 + .../phl/hal_g6/phy/bb/halbb_dbg_cnsl_out.h | 43 + .../phl/hal_g6/phy/bb/halbb_dbg_cnsl_out_ex.h | 75 + .../phl/hal_g6/phy/bb/halbb_dbg_ex.h | 35 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dfs.c | 2734 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dfs.h | 482 + .../phl/hal_g6/phy/bb/halbb_dfs_ex.h | 62 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dig.c | 2642 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_dig.h | 387 + .../phl/hal_g6/phy/bb/halbb_dig_ex.h | 52 + .../phl/hal_g6/phy/bb/halbb_dv_dbg.c | 237 + .../phl/hal_g6/phy/bb/halbb_dv_dbg.h | 52 + .../phl/hal_g6/phy/bb/halbb_dyn_1r_cca.c | 213 + .../phl/hal_g6/phy/bb/halbb_dyn_1r_cca.h | 46 + .../phl/hal_g6/phy/bb/halbb_dyn_1r_cca_ex.h | 37 + .../phl/hal_g6/phy/bb/halbb_dyn_csi_rsp.c | 523 + .../phl/hal_g6/phy/bb/halbb_dyn_csi_rsp.h | 62 + .../phl/hal_g6/phy/bb/halbb_dyn_csi_rsp_ex.h | 40 + .../phl/hal_g6/phy/bb/halbb_dyn_dtr.c | 241 + .../phl/hal_g6/phy/bb/halbb_dyn_dtr.h | 54 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_edcca.c | 1552 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_edcca.h | 277 + .../phl/hal_g6/phy/bb/halbb_edcca_ex.h | 44 + .../phl/hal_g6/phy/bb/halbb_env_mntr.c | 5728 + .../phl/hal_g6/phy/bb/halbb_env_mntr.h | 542 + .../phl/hal_g6/phy/bb/halbb_env_mntr_ex.h | 226 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_ex.h | 200 + .../phl/hal_g6/phy/bb/halbb_export_fun.h | 80 + .../phl/hal_g6/phy/bb/halbb_features.h | 205 + .../phl/hal_g6/phy/bb/halbb_fwofld.c | 1314 + .../phl/hal_g6/phy/bb/halbb_fwofld.h | 74 + .../phl/hal_g6/phy/bb/halbb_fwofld_ex.h | 44 + .../phl/hal_g6/phy/bb/halbb_hw_cfg.c | 1533 + .../phl/hal_g6/phy/bb/halbb_hw_cfg.h | 158 + .../phl/hal_g6/phy/bb/halbb_hw_cfg_ex.h | 42 + .../phl/hal_g6/phy/bb/halbb_ic_hw_info.h | 584 + .../phl/hal_g6/phy/bb/halbb_ic_sw_info.h | 63 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_init.c | 1140 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_init.h | 33 + .../phl/hal_g6/phy/bb/halbb_init_ex.h | 41 + .../phl/hal_g6/phy/bb/halbb_interface.c | 978 + .../phl/hal_g6/phy/bb/halbb_interface.h | 315 + .../phl/hal_g6/phy/bb/halbb_interface_ex.h | 53 + .../phl/hal_g6/phy/bb/halbb_la_mode.c | 3238 + .../phl/hal_g6/phy/bb/halbb_la_mode.h | 561 + .../phl/hal_g6/phy/bb/halbb_la_mode_ex.h | 37 + .../phl/hal_g6/phy/bb/halbb_math_lib.c | 485 + .../phl/hal_g6/phy/bb/halbb_math_lib.h | 132 + .../phl/hal_g6/phy/bb/halbb_math_lib_ex.h | 38 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_mp.c | 1521 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_mp_ex.h | 232 + .../phl/hal_g6/phy/bb/halbb_outsrc_def.h | 365 + .../phl/hal_g6/phy/bb/halbb_path_div.c | 883 + .../phl/hal_g6/phy/bb/halbb_path_div.h | 121 + .../phl/hal_g6/phy/bb/halbb_physts.c | 3326 + .../phl/hal_g6/phy/bb/halbb_physts.h | 793 + .../phl/hal_g6/phy/bb/halbb_physts_7.c | 2126 + .../phl/hal_g6/phy/bb/halbb_physts_7.h | 36 + .../phl/hal_g6/phy/bb/halbb_physts_ex.h | 119 + .../hal_g6/phy/bb/halbb_physts_ie_b_endian.h | 1515 + .../phy/bb/halbb_physts_ie_b_endian_7.h | 209 + .../hal_g6/phy/bb/halbb_physts_ie_l_endian.h | 1515 + .../phy/bb/halbb_physts_ie_l_endian_7.h | 209 + .../phl/hal_g6/phy/bb/halbb_plcp_gen.c | 975 + .../phl/hal_g6/phy/bb/halbb_plcp_gen.h | 253 + .../phl/hal_g6/phy/bb/halbb_plcp_tx.c | 2629 + .../phl/hal_g6/phy/bb/halbb_plcp_tx.h | 773 + .../phl/hal_g6/phy/bb/halbb_plcp_tx_7.c | 3531 + .../phl/hal_g6/phy/bb/halbb_plcp_tx_7.h | 52 + .../hal_g6/phy/bb/halbb_plcp_tx_b_endian.h | 278 + .../hal_g6/phy/bb/halbb_plcp_tx_l_endian.h | 275 + .../phl/hal_g6/phy/bb/halbb_pmac_setting.c | 1277 + .../phl/hal_g6/phy/bb/halbb_pmac_setting.h | 53 + .../phl/hal_g6/phy/bb/halbb_pmac_setting_ex.h | 125 + .../phl/hal_g6/phy/bb/halbb_precomp.h | 218 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_psd.c | 634 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_psd.h | 115 + .../phl/hal_g6/phy/bb/halbb_pwr_ctrl.c | 1554 + .../phl/hal_g6/phy/bb/halbb_pwr_ctrl.h | 129 + .../phl/hal_g6/phy/bb/halbb_pwr_ctrl_ex.h | 45 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_ra.c | 3455 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_ra.h | 331 + .../phl/hal_g6/phy/bb/halbb_ra_b_endian.h | 355 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_ra_ex.h | 40 + .../phl/hal_g6/phy/bb/halbb_ra_l_endian.h | 355 + .../phl/hal_g6/phy/bb/halbb_rua_tbl.c | 3244 + .../phl/hal_g6/phy/bb/halbb_rua_tbl.h | 66 + .../hal_g6/phy/bb/halbb_rua_tbl_b_endian.h | 950 + .../phl/hal_g6/phy/bb/halbb_rua_tbl_ex.h | 927 + .../hal_g6/phy/bb/halbb_rua_tbl_l_endian.h | 963 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_snif.c | 300 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_snif.h | 42 + .../phl/hal_g6/phy/bb/halbb_snif_ex.h | 263 + .../phl/hal_g6/phy/bb/halbb_spatial_reuse.c | 242 + .../phl/hal_g6/phy/bb/halbb_spatial_reuse.h | 70 + .../hal_g6/phy/bb/halbb_spatial_reuse_ex.h | 48 + .../phl/hal_g6/phy/bb/halbb_spur_suppress.c | 570 + .../phl/hal_g6/phy/bb/halbb_spur_suppress.h | 84 + .../phl/hal_g6/phy/bb/halbb_statistics.c | 1952 + .../phl/hal_g6/phy/bb/halbb_statistics.h | 255 + .../phl/hal_g6/phy/bb/halbb_statistics_ex.h | 192 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_types.h | 33 + .../phl/hal_g6/phy/bb/halbb_ul_tb_ctrl.c | 279 + .../phl/hal_g6/phy/bb/halbb_ul_tb_ctrl.h | 59 + .../rtl8852ce/phl/hal_g6/phy/bb/halbb_wpp.h | 64 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf.c | 6704 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf.h | 410 + .../hal_g6/phy/rf/halrf_8852c/halrf_8852c.c | 1486 + .../hal_g6/phy/rf/halrf_8852c/halrf_8852c.h | 70 + .../phy/rf/halrf_8852c/halrf_8852c_api.c | 844 + .../phy/rf/halrf_8852c/halrf_8852c_api.h | 70 + .../phy/rf/halrf_8852c/halrf_dack_8852c.c | 1018 + .../phy/rf/halrf_8852c/halrf_dack_8852c.h | 34 + .../phy/rf/halrf_8852c/halrf_dpk_8852c.c | 1815 + .../phy/rf/halrf_8852c/halrf_dpk_8852c.h | 53 + .../phy/rf/halrf_8852c/halrf_efuse_8852c.c | 1090 + .../phy/rf/halrf_8852c/halrf_efuse_8852c.h | 677 + .../phy/rf/halrf_8852c/halrf_hwimg_8852c.c | 1260 + .../phy/rf/halrf_8852c/halrf_hwimg_8852c.h | 91 + .../halrf_hwimg_nctl_raw_data_8852c.h | 3590 + .../halrf_8852c/halrf_hwimg_raw_data_8852c.h | 87617 +++++ .../halrf_hwimg_raw_data_w_bt_8852c.h | 267 + .../phy/rf/halrf_8852c/halrf_iqk_8852c.c | 2649 + .../phy/rf/halrf_8852c/halrf_iqk_8852c.h | 106 + .../phy/rf/halrf_8852c/halrf_kfree_8852c.c | 379 + .../phy/rf/halrf_8852c/halrf_kfree_8852c.h | 76 + .../phy/rf/halrf_8852c/halrf_ops_rtl8852c.c | 53 + .../phy/rf/halrf_8852c/halrf_ops_rtl8852c.h | 34 + .../phy/rf/halrf_8852c/halrf_psd_8852c.c | 608 + .../phy/rf/halrf_8852c/halrf_psd_8852c.h | 43 + .../phy/rf/halrf_8852c/halrf_reg_cfg_8852c.c | 64 + .../phy/rf/halrf_8852c/halrf_reg_cfg_8852c.h | 35 + .../halrf_8852c/halrf_set_pwr_table_8852c.c | 2550 + .../halrf_8852c/halrf_set_pwr_table_8852c.h | 62 + .../phy/rf/halrf_8852c/halrf_tssi_8852c.c | 5215 + .../phy/rf/halrf_8852c/halrf_tssi_8852c.h | 88 + .../phy/rf/halrf_8852c/halrf_txgapk_8852c.c | 2341 + .../phy/rf/halrf_8852c/halrf_txgapk_8852c.h | 71 + .../rf/halrf_8852c/halrf_version_rtl8852c.h | 26 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_api.c | 2024 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_api.h | 164 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_dack.h | 57 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg.c | 3375 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg.h | 108 + .../phl/hal_g6/phy/rf/halrf_dbg_cmd.c | 397 + .../phl/hal_g6/phy/rf/halrf_dbg_cmd.h | 39 + .../phl/hal_g6/phy/rf/halrf_dbg_cmd_ex.h | 37 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_dpk.h | 119 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_ex.c | 16 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_ex.h | 432 + .../phl/hal_g6/phy/rf/halrf_export_fun.h | 38 + .../phl/hal_g6/phy/rf/halrf_headers.h | 20 + .../phl/hal_g6/phy/rf/halrf_hw_cfg.c | 1489 + .../phl/hal_g6/phy/rf/halrf_hw_cfg.h | 40 + .../phl/hal_g6/phy/rf/halrf_hw_cfg_ex.h | 41 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_hwimg.h | 38 + .../phl/hal_g6/phy/rf/halrf_ic_hw_info.h | 146 + .../phl/hal_g6/phy/rf/halrf_ic_sw_info.h | 42 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_init.c | 804 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_init.h | 32 + .../phl/hal_g6/phy/rf/halrf_init_ex.c | 135 + .../phl/hal_g6/phy/rf/halrf_init_ex.h | 38 + .../phl/hal_g6/phy/rf/halrf_interface.c | 441 + .../phl/hal_g6/phy/rf/halrf_interface.h | 168 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_iqk.c | 1511 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_iqk.h | 136 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_kfree.h | 48 + .../phl/hal_g6/phy/rf/halrf_outsrc_def.h | 77 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_pmac.c | 180 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_pmac.h | 55 + .../phl/hal_g6/phy/rf/halrf_precomp.h | 425 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_psd.h | 41 + .../phl/hal_g6/phy/rf/halrf_pwr_table.c | 3814 + .../phl/hal_g6/phy/rf/halrf_pwr_table.h | 536 + .../phl/hal_g6/phy/rf/halrf_pwr_track.h | 266 + .../phl/hal_g6/phy/rf/halrf_struct.h | 25 + .../phl/hal_g6/phy/rf/halrf_txgapk.h | 54 + .../rtl8852ce/phl/hal_g6/phy/rf/halrf_wpp.h | 52 + .../realtek/rtl8852ce/phl/hal_g6/phy/rf/rf.mk | 311 + .../phl/hal_g6/rtl8852c/hal_trx_8852c.c | 801 + .../phl/hal_g6/rtl8852c/hal_trx_8852c.h | 181 + .../phl/hal_g6/rtl8852c/pci/hal_trx_8852ce.c | 1748 + .../phl/hal_g6/rtl8852c/pci/hal_trx_8852ce.h | 387 + .../phl/hal_g6/rtl8852c/pci/rtl8852ce.h | 20 + .../phl/hal_g6/rtl8852c/pci/rtl8852ce_hal.h | 193 + .../hal_g6/rtl8852c/pci/rtl8852ce_halinit.c | 1236 + .../phl/hal_g6/rtl8852c/pci/rtl8852ce_io.c | 17 + .../phl/hal_g6/rtl8852c/pci/rtl8852ce_ops.c | 59 + .../rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c.h | 40 + .../rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c.mk | 49 + .../phl/hal_g6/rtl8852c/rtl8852c_cmd.c | 17 + .../phl/hal_g6/rtl8852c/rtl8852c_hal.h | 132 + .../phl/hal_g6/rtl8852c/rtl8852c_halinit.c | 831 + .../phl/hal_g6/rtl8852c/rtl8852c_mac.c | 17 + .../phl/hal_g6/rtl8852c/rtl8852c_ops.c | 98 + .../phl/hal_g6/rtl8852c/rtl8852c_phy.c | 16 + .../phl/hal_g6/rtl8852c/rtl8852c_phy.h | 20 + .../phl/hal_g6/rtl8852c/rtl8852c_regulation.c | 595 + .../phl/hal_g6/rtl8852c/rtl8852c_spec.h | 19 + .../phl/hal_g6/test/hal_test_module.c | 18 + .../phl/hal_g6/test/mp/hal_test_mp.c | 34 + .../phl/hal_g6/test/mp/hal_test_mp_api.h | 284 + .../phl/hal_g6/test/mp/hal_test_mp_cal.c | 333 + .../phl/hal_g6/test/mp/hal_test_mp_config.c | 740 + .../phl/hal_g6/test/mp/hal_test_mp_efuse.c | 529 + .../phl/hal_g6/test/mp/hal_test_mp_reg.c | 311 + .../phl/hal_g6/test/mp/hal_test_mp_rx.c | 248 + .../phl/hal_g6/test/mp/hal_test_mp_tx.c | 409 + .../phl/hal_g6/test/mp/hal_test_mp_txpwr.c | 318 + .../rtl8852ce/phl/hci/phl_trx_def_pcie.h | 79 + .../realtek/rtl8852ce/phl/hci/phl_trx_pcie.c | 4805 + .../realtek/rtl8852ce/phl/hci/phl_trx_pcie.h | 127 + .../net/wireless/realtek/rtl8852ce/phl/phl.mk | 120 + .../wireless/realtek/rtl8852ce/phl/phl_acs.c | 243 + .../wireless/realtek/rtl8852ce/phl/phl_acs.h | 39 + .../realtek/rtl8852ce/phl/phl_acs_def.h | 40 + .../wireless/realtek/rtl8852ce/phl/phl_api.h | 1308 + .../realtek/rtl8852ce/phl/phl_api_drv.c | 298 + .../realtek/rtl8852ce/phl/phl_api_drv.h | 132 + .../realtek/rtl8852ce/phl/phl_btc_def.h | 190 + .../wireless/realtek/rtl8852ce/phl/phl_chan.c | 2240 + .../wireless/realtek/rtl8852ce/phl/phl_chan.h | 108 + .../realtek/rtl8852ce/phl/phl_chan_info.c | 461 + .../realtek/rtl8852ce/phl/phl_chan_info.h | 45 + .../realtek/rtl8852ce/phl/phl_chan_info_def.h | 141 + .../realtek/rtl8852ce/phl/phl_cmd_btc.c | 1061 + .../realtek/rtl8852ce/phl/phl_cmd_btc.h | 21 + .../realtek/rtl8852ce/phl/phl_cmd_dispatch.h | 180 + .../rtl8852ce/phl/phl_cmd_dispatch_engine.c | 1031 + .../rtl8852ce/phl/phl_cmd_dispatcher.c | 2666 + .../rtl8852ce/phl/phl_cmd_dispr_controller.c | 684 + .../realtek/rtl8852ce/phl/phl_cmd_fsm.c | 779 + .../realtek/rtl8852ce/phl/phl_cmd_fsm.h | 56 + .../realtek/rtl8852ce/phl/phl_cmd_general.c | 817 + .../realtek/rtl8852ce/phl/phl_cmd_general.h | 61 + .../realtek/rtl8852ce/phl/phl_cmd_job.c | 201 + .../realtek/rtl8852ce/phl/phl_cmd_job.h | 126 + .../realtek/rtl8852ce/phl/phl_cmd_ps.c | 2758 + .../realtek/rtl8852ce/phl/phl_cmd_ps.h | 74 + .../realtek/rtl8852ce/phl/phl_cmd_scan.c | 1611 + .../realtek/rtl8852ce/phl/phl_cmd_ser.c | 1065 + .../realtek/rtl8852ce/phl/phl_cmd_ser.h | 32 + .../realtek/rtl8852ce/phl/phl_config.h | 624 + .../realtek/rtl8852ce/phl/phl_connect.c | 461 + .../realtek/rtl8852ce/phl/phl_connect.h | 123 + .../realtek/rtl8852ce/phl/phl_debug.c | 507 + .../realtek/rtl8852ce/phl/phl_debug.h | 345 + .../wireless/realtek/rtl8852ce/phl/phl_def.h | 4991 + .../wireless/realtek/rtl8852ce/phl/phl_dfs.c | 519 + .../wireless/realtek/rtl8852ce/phl/phl_dfs.h | 42 + .../realtek/rtl8852ce/phl/phl_diagnose.c | 91 + .../realtek/rtl8852ce/phl/phl_diagnose.h | 64 + .../wireless/realtek/rtl8852ce/phl/phl_dm.c | 258 + .../wireless/realtek/rtl8852ce/phl/phl_dm.h | 47 + .../wireless/realtek/rtl8852ce/phl/phl_ecsa.c | 1066 + .../wireless/realtek/rtl8852ce/phl/phl_ecsa.h | 58 + .../realtek/rtl8852ce/phl/phl_ecsa_export.h | 158 + .../rtl8852ce/phl/phl_ext_tx_pwr_lmt.c | 184 + .../rtl8852ce/phl/phl_ext_tx_pwr_lmt_def.h | 56 + .../wireless/realtek/rtl8852ce/phl/phl_fsm.c | 2203 + .../wireless/realtek/rtl8852ce/phl/phl_fsm.h | 282 + .../realtek/rtl8852ce/phl/phl_git_info.h | 43 + .../realtek/rtl8852ce/phl/phl_headers.h | 153 + .../realtek/rtl8852ce/phl/phl_headers_core.h | 68 + .../wireless/realtek/rtl8852ce/phl/phl_ie.c | 1357 + .../wireless/realtek/rtl8852ce/phl/phl_ie.h | 682 + .../wireless/realtek/rtl8852ce/phl/phl_init.c | 3006 + .../wireless/realtek/rtl8852ce/phl/phl_led.c | 1189 + .../wireless/realtek/rtl8852ce/phl/phl_led.h | 22 + .../realtek/rtl8852ce/phl/phl_led_def.h | 101 + .../wireless/realtek/rtl8852ce/phl/phl_list.h | 233 + .../wireless/realtek/rtl8852ce/phl/phl_mcc.c | 4091 + .../wireless/realtek/rtl8852ce/phl/phl_mcc.h | 88 + .../realtek/rtl8852ce/phl/phl_mcc_def.h | 105 + .../wireless/realtek/rtl8852ce/phl/phl_mr.c | 4627 + .../wireless/realtek/rtl8852ce/phl/phl_mr.h | 228 + .../realtek/rtl8852ce/phl/phl_mr_coex.c | 2180 + .../realtek/rtl8852ce/phl/phl_mr_coex.h | 56 + .../realtek/rtl8852ce/phl/phl_msg_hub.c | 459 + .../realtek/rtl8852ce/phl/phl_msg_hub.h | 37 + .../realtek/rtl8852ce/phl/phl_notify.c | 134 + .../realtek/rtl8852ce/phl/phl_notify.h | 30 + .../realtek/rtl8852ce/phl/phl_p2pps.c | 976 + .../realtek/rtl8852ce/phl/phl_p2pps.h | 83 + .../realtek/rtl8852ce/phl/phl_p2pps_def.h | 35 + .../realtek/rtl8852ce/phl/phl_pkt_ofld.c | 1307 + .../realtek/rtl8852ce/phl/phl_pkt_ofld.h | 239 + .../wireless/realtek/rtl8852ce/phl/phl_ps.c | 753 + .../wireless/realtek/rtl8852ce/phl/phl_ps.h | 70 + .../realtek/rtl8852ce/phl/phl_ps_def.h | 25 + .../realtek/rtl8852ce/phl/phl_regulation.c | 1707 + .../realtek/rtl8852ce/phl/phl_regulation.h | 83 + .../rtl8852ce/phl/phl_regulation_def.h | 672 + .../wireless/realtek/rtl8852ce/phl/phl_role.c | 2278 + .../wireless/realtek/rtl8852ce/phl/phl_role.h | 118 + .../wireless/realtek/rtl8852ce/phl/phl_rx.c | 2393 + .../wireless/realtek/rtl8852ce/phl/phl_rx.h | 82 + .../realtek/rtl8852ce/phl/phl_rx_agg.c | 303 + .../realtek/rtl8852ce/phl/phl_rx_agg.h | 33 + .../wireless/realtek/rtl8852ce/phl/phl_scan.h | 246 + .../realtek/rtl8852ce/phl/phl_scanofld.c | 534 + .../realtek/rtl8852ce/phl/phl_scanofld.h | 23 + .../wireless/realtek/rtl8852ce/phl/phl_sec.c | 239 + .../realtek/rtl8852ce/phl/phl_ser_def.h | 46 + .../realtek/rtl8852ce/phl/phl_ser_fsm.c | 1387 + .../realtek/rtl8852ce/phl/phl_ser_fsm.h | 41 + .../realtek/rtl8852ce/phl/phl_sound.c | 1945 + .../realtek/rtl8852ce/phl/phl_sound.h | 282 + .../realtek/rtl8852ce/phl/phl_sound_cmd.c | 1104 + .../realtek/rtl8852ce/phl/phl_sound_cmd.h | 85 + .../wireless/realtek/rtl8852ce/phl/phl_sta.c | 4988 + .../wireless/realtek/rtl8852ce/phl/phl_sta.h | 327 + .../realtek/rtl8852ce/phl/phl_status.h | 50 + .../realtek/rtl8852ce/phl/phl_struct.h | 455 + .../realtek/rtl8852ce/phl/phl_sw_cap.c | 1028 + .../realtek/rtl8852ce/phl/phl_sw_cap.h | 43 + .../wireless/realtek/rtl8852ce/phl/phl_tdls.c | 23 + .../wireless/realtek/rtl8852ce/phl/phl_tdls.h | 19 + .../wireless/realtek/rtl8852ce/phl/phl_test.h | 100 + .../realtek/rtl8852ce/phl/phl_test_def.h | 157 + .../realtek/rtl8852ce/phl/phl_thermal.c | 179 + .../realtek/rtl8852ce/phl/phl_thermal.h | 30 + .../realtek/rtl8852ce/phl/phl_trx_def.h | 746 + .../realtek/rtl8852ce/phl/phl_trx_mit.c | 150 + .../realtek/rtl8852ce/phl/phl_trx_mit.h | 28 + .../wireless/realtek/rtl8852ce/phl/phl_twt.c | 3058 + .../wireless/realtek/rtl8852ce/phl/phl_twt.h | 427 + .../wireless/realtek/rtl8852ce/phl/phl_tx.c | 3478 + .../wireless/realtek/rtl8852ce/phl/phl_tx.h | 132 + .../realtek/rtl8852ce/phl/phl_txpwr.c | 776 + .../realtek/rtl8852ce/phl/phl_txpwr.h | 68 + .../realtek/rtl8852ce/phl/phl_types.h | 328 + .../wireless/realtek/rtl8852ce/phl/phl_util.c | 255 + .../wireless/realtek/rtl8852ce/phl/phl_util.h | 151 + .../realtek/rtl8852ce/phl/phl_version.h | 29 + .../realtek/rtl8852ce/phl/phl_watchdog.c | 386 + .../realtek/rtl8852ce/phl/phl_watchdog.h | 68 + .../wireless/realtek/rtl8852ce/phl/phl_wow.c | 2090 + .../wireless/realtek/rtl8852ce/phl/phl_wow.h | 142 + .../realtek/rtl8852ce/phl/phl_wow_def.h | 269 + .../wireless/realtek/rtl8852ce/phl/phl_wpp.h | 322 + .../realtek/rtl8852ce/phl/pltfm_ops.h | 30 + .../realtek/rtl8852ce/phl/pltfm_ops_linux.h | 1346 + .../realtek/rtl8852ce/phl/pltfm_ops_macos.h | 587 + .../realtek/rtl8852ce/phl/pltfm_ops_none.h | 939 + .../realtek/rtl8852ce/phl/pltfm_ops_uefi.h | 883 + .../realtek/rtl8852ce/phl/pltfm_ops_windows.h | 933 + .../realtek/rtl8852ce/phl/rtw_general_def.h | 679 + .../rtl8852ce/phl/test/cmd_disp_test.c | 1069 + .../rtl8852ce/phl/test/cmd_disp_test.h | 27 + .../rtl8852ce/phl/test/mp/phl_test_mp.c | 535 + .../rtl8852ce/phl/test/mp/phl_test_mp_api.h | 28 + .../rtl8852ce/phl/test/mp/phl_test_mp_cal.c | 398 + .../phl/test/mp/phl_test_mp_config.c | 919 + .../rtl8852ce/phl/test/mp/phl_test_mp_def.h | 625 + .../rtl8852ce/phl/test/mp/phl_test_mp_efuse.c | 861 + .../rtl8852ce/phl/test/mp/phl_test_mp_reg.c | 321 + .../rtl8852ce/phl/test/mp/phl_test_mp_rx.c | 350 + .../rtl8852ce/phl/test/mp/phl_test_mp_tx.c | 620 + .../rtl8852ce/phl/test/mp/phl_test_mp_txpwr.c | 495 + .../phl/test/mp/phl_test_mp_watchdog.c | 101 + .../phl/test/mp/phl_test_mp_watchdog.h | 29 + .../realtek/rtl8852ce/phl/test/phl_dbg_cmd.c | 2726 + .../realtek/rtl8852ce/phl/test/phl_dbg_cmd.h | 199 + .../rtl8852ce/phl/test/phl_ps_dbg_cmd.c | 498 + .../rtl8852ce/phl/test/phl_ps_dbg_cmd.h | 42 + .../rtl8852ce/phl/test/phl_ser_dbg_cmd.c | 124 + .../rtl8852ce/phl/test/phl_ser_dbg_cmd.h | 21 + .../realtek/rtl8852ce/phl/test/test_module.c | 798 + .../realtek/rtl8852ce/phl/test/trx_test.c | 1568 + .../realtek/rtl8852ce/phl/test/trx_test.h | 219 + .../phl/test/verify/dbcc/phl_test_dbcc.c | 189 + .../phl/test/verify/dbcc/phl_test_dbcc_api.h | 23 + .../phl/test/verify/dbcc/phl_test_dbcc_def.h | 114 + .../phl/test/verify/phl_test_verify.c | 397 + .../phl/test/verify/phl_test_verify_api.h | 34 + .../phl/test/verify/phl_test_verify_def.h | 66 + .../realtek/rtl8852ce/platform/aml_s905.mk | 76 + .../rtl8852ce/platform/aml_s905_l3a.mk | 84 + .../realtek/rtl8852ce/platform/aml_s928x.mk | 60 + .../rtl8852ce/platform/android_intel_x86.mk | 11 + .../realtek/rtl8852ce/platform/android_x86.mk | 8 + .../realtek/rtl8852ce/platform/arm_1319.mk | 50 + .../realtek/rtl8852ce/platform/arm_1619b.mk | 50 + .../realtek/rtl8852ce/platform/arm_rk.mk | 38 + .../realtek/rtl8852ce/platform/arm_sunxi.mk | 33 + .../rtl8852ce/platform/autoconf_arm_9617b.h | 8 + .../platform/autoconf_i386_ap_func.h | 19 + .../rtl8852ce/platform/autoconf_mips_98d.h | 35 + .../platform/custom_country_chplan.h | 22 + .../realtek/rtl8852ce/platform/i386_pc.mk | 32 + .../realtek/rtl8852ce/platform/mips_98d.mk | 14 + .../realtek/rtl8852ce/platform/nv_tk1.mk | 17 + .../rtl8852ce/platform/nv_tk1_ubuntu.mk | 14 + .../rtl8852ce/platform/plat_huanglong.mk | 40 + .../rtl8852ce/platform/platform_ARM_RK_pci.c | 53 + .../rtl8852ce/platform/platform_ARM_RK_sdio.c | 54 + .../platform/platform_ARM_SUNnI_sdio.c | 130 + .../platform/platform_ARM_SUNxI_sdio.c | 95 + .../platform/platform_ARM_SUNxI_usb.c | 136 + .../rtl8852ce/platform/platform_RTK_DMP_usb.c | 30 + .../platform/platform_linux_pc_pci.c | 159 + .../platform/platform_mips_98d_pci.c | 171 + .../realtek/rtl8852ce/platform/platform_ops.c | 35 + .../realtek/rtl8852ce/platform/platform_ops.h | 46 + .../rtl8852ce/platform/platform_sprd_sdio.c | 84 + 1061 files changed, 1210881 insertions(+) create mode 100644 drivers/net/wireless/realtek/rtl8852ce/Kconfig create mode 100644 drivers/net/wireless/realtek/rtl8852ce/Makefile create mode 100644 drivers/net/wireless/realtek/rtl8852ce/common.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ccm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ctr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-gcm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal-enc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-omac1.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-siv.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_i.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_siv.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_wrap.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/crypto/ccmp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/gcmp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-internal.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-prf.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256_i.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/crypto/wlancrypto_wrap.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/def_module_country_chplan.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_phl_wrapper.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_58-31.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_59-32.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-32.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-34.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_61-34.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_62-35.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-36.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-37.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-38.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-39.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-40.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-40.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-41.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-42.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_65-44.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_66-45.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_67-46.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_68-47.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8851BE_M.2_2230-67-3.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852BE_M.2_2230-67-48.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-51.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-52.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ap.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_beamforming.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_br_ext.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_btc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_cmd.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_csa.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_debug.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_eht.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_fake_ap.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm_rrm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm_wnm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm_xxx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ft.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_he.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ieee80211.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_io.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ioctl_query.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ioctl_set.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mbo.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mem.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mi.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mlme.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mlme_ext.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_mp.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_p2p.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_phl.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_phl_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_prealloc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_pwrctrl.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_recv.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_recv_shortcut.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_rf.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_rm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_rm_fsm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_rm_util.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_scan.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_sdio.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_sec_cam.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_security.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_sta_mgt.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_swcrypto.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_tdls.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_trx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_trx_pci.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_trx_usb.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_twt.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_txpwr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_txpwr.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_vht.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_wapi.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_wapi_sms4.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_wlan_util.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_wnm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/rtw_wow.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_xmit.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/core/rtw_xmit_shortcut.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/wds/rtw_wds.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/core/wds/rtw_wds.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/_hal_api_tmp.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/_hal_rate.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/autoconf.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/autoconf.h.orig create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/basic_types.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/byteorder/big_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/byteorder/generic.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/byteorder/little_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/byteorder/swab.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/byteorder/swabb.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/circ_buf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/custom_gpio.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/drv_conf.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/drv_types.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/drv_types_gspi.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/drv_types_pci.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/drv_types_sdio.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/drv_types_usb.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/ethernet.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/gspi_hal.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/gspi_ops.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/gspi_ops_linux.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/ieee80211.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/ieee80211_ext.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/if_ether.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/ip.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/linux/wireless.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/mlme_osdep.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/osdep_intf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/osdep_service.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/osdep_service.h.orig create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/osdep_service_bsd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/osdep_service_linux.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/pci_ops.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/pci_ops_linux.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/phl_api_tmp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/recv_osdep.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_android.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ap.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_beamforming.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_br_ext.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_btc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_byteorder.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_cfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_csa.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_debug.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_debug.h.orig create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_efuse.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_eht.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_event.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_fsm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_fsm_rrm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_fsm_wnm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_fsm_xxx.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ft.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_he.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_he.h.orig create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ht.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_hwsim_intf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_io.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ioctl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ioctl_query.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_ioctl_set.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mbo.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mcc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mem.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mi.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mlme.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mlme_ext.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_mp.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_p2p.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_phl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_phl_cmd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_pwrctrl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_qos.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_recv.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_recv_shortcut.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_rf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_rm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_rm_fsm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_rm_util.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_scan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_sdio.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_sec_cam.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_security.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_swcrypto.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_tdls.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_trx.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_trx_ops.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_trx_pci.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_trx_usb.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_twt.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_version.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_vht.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/rtw_wapi.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_wnm.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_wow.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_xmit.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_xmit.h.orig create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/rtw_xmit_shortcut.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/sdio_ops.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/sdio_ops_linux.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/sta_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/include/usb_ops.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/usb_ops_linux.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/wifi.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/wlan_bssdef.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/include/xmit_osdep.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/custom_gpio_linux.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/ioctl_cfg80211.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/ioctl_cfg80211.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/ioctl_efuse.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/ioctl_linux.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/ioctl_mp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/mlme_linux.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/nlrtw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/nlrtw.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/os_ch_utils.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/os_ch_utils.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/os_intfs.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/pci_intf.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/pci_ops_linux.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/recv_linux.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rhashtable.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rhashtable.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_android.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_cfg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_cfgvendor.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_cfgvendor.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_proc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_proc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_rhashtable.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/rtw_rhashtable.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/wifi_regd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/wifi_regd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/xmit_linux.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/osdep_service.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/os_dep/osdep_service_linux.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_antenna.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_antenna.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_vr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_vr.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_vr_csi.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/custom/phl_custom_vr_csi.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/btc.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/btc_8852c/btc_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/btc_8852c/btc_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/hal_btc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/hal_btc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_action.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_action.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_def.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_fw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_fw.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/btc/halbtc_fwdef.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/efuse/hal_efuse.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/efuse/hal_efuse.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/efuse/hal_efuse_export.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_acs.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_acs.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_bb.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_bb.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_btc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_btc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_drv.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_efuse.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_efuse.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_mac.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_mac.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_rf.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_api_rf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_beamform.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_beamform.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_c2h.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_c2h.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_cam.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_cap.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_cap.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_chan.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_chan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_chan_info.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_chan_info.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_com_i.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_com_i.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_config.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_csi_buffer.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_csi_buffer.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_custom.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_custom.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_dbcc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_dbcc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_def_btc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_def_mac.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_def_phy.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_dfs.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_dfs.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ext_tx_pwr_lmt.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_feature.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_fw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_fw.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_general_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_headers.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_headers_le.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_init.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_io.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_io.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ld_file.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ld_file.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_led.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_mcc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_mcc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_mcc_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_notify.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_notify.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_p2pps.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_pci.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_pci.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ps.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ps.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_regulation.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_rx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_rx.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_scanofld.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_scanofld.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ser.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_ser.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_sound.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_sound.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_sta.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_sta.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_str_proc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_str_proc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_struct.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_thermal.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_trx_mit.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_twt.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_tx.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_tx.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_txpwr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_txpwr.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_wow.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/hal_wow.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/chip_cfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/chip_cfg_drv.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/errors.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/feature_cfg.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/inc_hdr/fwcmd_intf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/inc_hdr/wow_h2c_white_list.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw_cap.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw_log.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/fw_ax/rtl8852c/hal8852c_fw_log.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/halmac_wpp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/hci_reg_ax.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/hci_reg_be.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/hv_type.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/include/AutoGen_Func/g6/8852c/err_flag_auto_gen_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/include/AutoGen_Func/g6/8852c/err_flag_auto_gen_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/include/AutoGen_Func/g6/mac_autogen_func_top_g6.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/include/mac_top.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac2drv_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/_pcie.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/_pcie.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/addr_cam.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/addr_cam.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/beacon.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/beacon.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/cmac_tx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/cmac_tx.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/coex.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/coex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/common.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/common.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/cpuio.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/cpuio.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbcc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbcc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbg_cmd.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbg_cmd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbgpkg.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbgpkg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbgport_hw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dbgport_hw.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/diagnosis.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/diagnosis.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dle.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/dle.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/eco_patch_check.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/eco_patch_check.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/efuse.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/efuse.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/err_flag.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/err_flag.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/flash.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/flash.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd_intf_f2p.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwcmd_intf_f2p_v1.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwdl.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwdl.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwofld.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/fwofld.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/gpio.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/gpio.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/gpio_cmd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/h2c_agg.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/h2c_agg.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hci_fc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hci_fc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hdr_conv.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hdr_conv.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hw.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hw.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hw_seq.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hw_seq.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hwamsdu.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/hwamsdu.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/init.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/init.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/la_mode.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/la_mode.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_pcie_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_pcie_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_sdio_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_sdio_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_usb_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/_usb_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/cmac_tx_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/cmac_tx_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/coex_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/coex_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dbg_cmd_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dbg_cmd_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dbgpkg_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dbgpkg_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dle_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/dle_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/efuse_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/efuse_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/fwcmd_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/fwcmd_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/gpio_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/gpio_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hci_fc_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hci_fc_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hdr_conv_rx_8852c.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hdr_conv_rx_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hwamsdu_8852c.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/hwamsdu_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/init_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/init_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/mac_priv_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/mac_priv_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/mac_txccxrpt.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/phy_rpt_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/phy_rpt_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/pwr_seq_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/pwr_seq_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/pwr_seq_func_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/pwr_seq_func_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/rrsr_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/rrsr_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/security_cam_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/security_cam_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/ser_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/ser_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/tblupd_8852c.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/tblupd_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/trx_desc_8852c.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/trx_desc_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/wowlan_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_8852c/wowlan_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_ax_dfs.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_ax_mac_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_priv.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mac_priv.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mcc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mcc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mport.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/mport.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/nan.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/nan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/otpkeysinfo.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/otpkeysinfo.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/outsrc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/outsrc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/p2p.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/p2p.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/phy_misc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/phy_misc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/phy_rpt.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/phy_rpt.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/power_saving.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/power_saving.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/pwr.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/pwr.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/pwr_seq_func.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/pwr_seq_func.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/role.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/role.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx_filter.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx_filter.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx_forwarding.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/rx_forwarding.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/secure_boot.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/secure_boot.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/security_cam.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/security_cam.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/ser.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/ser.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sounding.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sounding.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/spatial_reuse.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/spatial_reuse.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sta_diag.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sta_diag.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sta_sch.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/sta_sch.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/state_mach.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/status.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/status.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tblupd.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tblupd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tcpip_checksum_offload.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tcpip_checksum_offload.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/trx_desc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/trx_desc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/trxcfg.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/trxcfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/twt.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/twt.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tx_statistic.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/tx_statistic.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/wowlan.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_ax/wowlan.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_exp_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_hw_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_outsrc_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_reg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_reg_ax.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/mac_reg_be.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/pcie_reg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/plat_reg_ax.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/plat_reg_be.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/pltfm_cfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/pltfm_cfg_drv.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/rxdesc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/txdesc.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/mac/type.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/bb.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_api.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_api_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_dcra.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_dcra.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_dcra_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_fwofld_api.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_8852c_fwofld_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_cr_info_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_hwimg_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_hwimg_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_hwimg_raw_data_8842a.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_hwimg_raw_data_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_hwimg_raw_data_8852d.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_reg_cfg_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_reg_cfg_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_version_rtl8842a.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_version_rtl8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_8852c/halbb_version_rtl8852d.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ant_div.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ant_div.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ant_div_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_hw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_hw.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_intg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_intg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_sw.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_be_sw.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_api_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_auto_dbg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_auto_dbg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_auto_dbg_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_bb_wrapper.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_bb_wrapper.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_bb_wrapper_outsrc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cfg_ic.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cfo_trk.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cfo_trk.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ch_info.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ch_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ch_info_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cmn_rpt.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cmn_rpt.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_cmn_rpt_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbcc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbcc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbcc_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cmd_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cmd_table.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cnsl_out.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cnsl_out.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_cnsl_out_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dbg_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dfs.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dfs.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dfs_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dig.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dig.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dig_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dv_dbg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dv_dbg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_1r_cca.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_1r_cca.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_1r_cca_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_csi_rsp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_csi_rsp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_csi_rsp_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_dtr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_dyn_dtr.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_edcca.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_edcca.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_edcca_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_env_mntr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_env_mntr.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_env_mntr_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_export_fun.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_features.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_fwofld.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_fwofld.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_fwofld_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_hw_cfg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_hw_cfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_hw_cfg_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ic_hw_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ic_sw_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_init.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_init.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_init_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_interface.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_interface.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_interface_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_la_mode.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_la_mode.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_la_mode_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_math_lib.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_math_lib.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_math_lib_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_mp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_mp_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_outsrc_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_path_div.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_path_div.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_7.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_7.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_ie_b_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_ie_b_endian_7.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_ie_l_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_physts_ie_l_endian_7.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_gen.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_gen.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx_7.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx_7.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx_b_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_plcp_tx_l_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pmac_setting.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pmac_setting.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pmac_setting_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_precomp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_psd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_psd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pwr_ctrl.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pwr_ctrl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_pwr_ctrl_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ra.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ra.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ra_b_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ra_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ra_l_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_rua_tbl.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_rua_tbl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_rua_tbl_b_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_rua_tbl_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_rua_tbl_l_endian.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_snif.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_snif.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_snif_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_spatial_reuse.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_spatial_reuse.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_spatial_reuse_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_spur_suppress.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_spur_suppress.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_statistics.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_statistics.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_statistics_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_types.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ul_tb_ctrl.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_ul_tb_ctrl.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/bb/halbb_wpp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_8852c_api.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_8852c_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_dack_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_dack_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_dpk_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_dpk_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_efuse_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_efuse_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_hwimg_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_hwimg_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_hwimg_nctl_raw_data_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_hwimg_raw_data_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_hwimg_raw_data_w_bt_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_iqk_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_iqk_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_kfree_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_kfree_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_ops_rtl8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_ops_rtl8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_psd_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_psd_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_reg_cfg_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_reg_cfg_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_set_pwr_table_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_set_pwr_table_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_tssi_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_tssi_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_txgapk_8852c.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_txgapk_8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_8852c/halrf_version_rtl8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_api.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dack.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dbg_cmd_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_dpk.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_ex.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_export_fun.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_headers.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_hw_cfg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_hw_cfg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_hw_cfg_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_hwimg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_ic_hw_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_ic_sw_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_init.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_init.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_init_ex.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_init_ex.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_interface.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_interface.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_iqk.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_iqk.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_kfree.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_outsrc_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_pmac.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_pmac.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_precomp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_psd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_pwr_table.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_pwr_table.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_pwr_track.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_struct.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_txgapk.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/halrf_wpp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/phy/rf/rf.mk create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/hal_trx_8852c.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/hal_trx_8852c.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/hal_trx_8852ce.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/hal_trx_8852ce.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/rtl8852ce.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/rtl8852ce_hal.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/rtl8852ce_halinit.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/rtl8852ce_io.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/pci/rtl8852ce_ops.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_hal.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_halinit.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_mac.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_ops.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_phy.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_phy.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_regulation.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/rtl8852c/rtl8852c_spec.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/hal_test_module.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_cal.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_config.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_efuse.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_reg.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_rx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_tx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hal_g6/test/mp/hal_test_mp_txpwr.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hci/phl_trx_def_pcie.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hci/phl_trx_pcie.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/hci/phl_trx_pcie.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_acs.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_acs.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_acs_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_api.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_api_drv.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_api_drv.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_btc_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_chan.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_chan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_chan_info.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_chan_info.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_chan_info_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_btc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_btc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_dispatch.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_dispatch_engine.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_dispatcher.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_dispr_controller.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_fsm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_fsm.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_general.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_general.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_job.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_job.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_ps.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_ps.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_scan.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_ser.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_cmd_ser.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_config.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_connect.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_connect.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_debug.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_debug.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_dfs.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_dfs.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_diagnose.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_diagnose.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_dm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_dm.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ecsa.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ecsa.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ecsa_export.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ext_tx_pwr_lmt.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ext_tx_pwr_lmt_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_fsm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_fsm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_git_info.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_headers.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_headers_core.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ie.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ie.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_init.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_led.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_led.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_led_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_list.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mcc.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mcc.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mcc_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mr.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mr.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mr_coex.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_mr_coex.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_msg_hub.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_msg_hub.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_notify.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_notify.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_p2pps.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_p2pps.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_p2pps_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_pkt_ofld.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_pkt_ofld.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ps.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ps.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ps_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_regulation.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_regulation.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_regulation_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_role.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_role.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_rx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_rx.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_rx_agg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_rx_agg.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_scan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_scanofld.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_scanofld.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sec.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ser_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ser_fsm.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_ser_fsm.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sound.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sound.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sound_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sound_cmd.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sta.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sta.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_status.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_struct.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sw_cap.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sw_cap.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_tdls.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_tdls.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_test.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_test_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_thermal.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_thermal.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_trx_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_trx_mit.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_trx_mit.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_twt.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_twt.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_tx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_tx.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_txpwr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_txpwr.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_types.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_util.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_util.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_version.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_watchdog.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_watchdog.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_wow.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_wow.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/phl_wow_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/phl_wpp.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops_linux.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops_macos.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops_none.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops_uefi.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/pltfm_ops_windows.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/rtw_general_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/cmd_disp_test.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/cmd_disp_test.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_api.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_cal.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_config.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_efuse.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_reg.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_rx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_tx.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_txpwr.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_watchdog.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/mp/phl_test_mp_watchdog.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_ps_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_ps_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_ser_dbg_cmd.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/phl_ser_dbg_cmd.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/test_module.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/trx_test.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/trx_test.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/dbcc/phl_test_dbcc.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/dbcc/phl_test_dbcc_api.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/dbcc/phl_test_dbcc_def.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/phl_test_verify.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/phl_test_verify_api.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/phl/test/verify/phl_test_verify_def.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/aml_s905.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/aml_s905_l3a.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/aml_s928x.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/android_intel_x86.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/android_x86.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/arm_1319.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/arm_1619b.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/arm_rk.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/arm_sunxi.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/autoconf_arm_9617b.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/platform/autoconf_i386_ap_func.h create mode 100755 drivers/net/wireless/realtek/rtl8852ce/platform/autoconf_mips_98d.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/custom_country_chplan.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/i386_pc.mk create mode 100755 drivers/net/wireless/realtek/rtl8852ce/platform/mips_98d.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/nv_tk1.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/nv_tk1_ubuntu.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/plat_huanglong.mk create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ARM_RK_pci.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ARM_RK_sdio.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ARM_SUNnI_sdio.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ARM_SUNxI_sdio.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ARM_SUNxI_usb.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_RTK_DMP_usb.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_linux_pc_pci.c create mode 100755 drivers/net/wireless/realtek/rtl8852ce/platform/platform_mips_98d_pci.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ops.c create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_ops.h create mode 100644 drivers/net/wireless/realtek/rtl8852ce/platform/platform_sprd_sdio.c diff --git a/drivers/net/wireless/realtek/rtl8852ce/Kconfig b/drivers/net/wireless/realtek/rtl8852ce/Kconfig new file mode 100644 index 00000000..4fcf4e60 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/Kconfig @@ -0,0 +1,6 @@ +config RTL8852CE + tristate "Realtek 8852C PCIE WiFi" + depends on PCIE + ---help--- + Help message of RTL8852CE + diff --git a/drivers/net/wireless/realtek/rtl8852ce/Makefile b/drivers/net/wireless/realtek/rtl8852ce/Makefile new file mode 100644 index 00000000..34f8ebf3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/Makefile @@ -0,0 +1,944 @@ +EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS) +EXTRA_CFLAGS += -O1 +#EXTRA_CFLAGS += -O3 +#EXTRA_CFLAGS += -Wall +#EXTRA_CFLAGS += -Wextra +#EXTRA_CFLAGS += -Werror +#EXTRA_CFLAGS += -pedantic +#EXTRA_CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes + +EXTRA_CFLAGS += -Wno-unused-variable +#EXTRA_CFLAGS += -Wno-unused-value +EXTRA_CFLAGS += -Wno-unused-label +#EXTRA_CFLAGS += -Wno-unused-parameter +#EXTRA_CFLAGS += -Wno-unused-function +EXTRA_CFLAGS += -Wno-unused +#EXTRA_CFLAGS += -Wno-uninitialized + +############ ANDROID COMMON KERNEL ############ +# clang +ifeq ($(CC), clang) +EXTRA_CFLAGS += -Wno-uninitialized +EXTRA_CFLAGS += -Wno-enum-conversion +EXTRA_CFLAGS += -Wno-fortify-source +EXTRA_CFLAGS += -Wno-invalid-source-encoding +EXTRA_CFLAGS += -Wno-tautological-pointer-compare +EXTRA_CFLAGS += -Wno-tautological-overlap-compare +EXTRA_CFLAGS += -Wno-pointer-bool-conversion +EXTRA_CFLAGS += -Wno-parentheses-equality +EXTRA_CFLAGS += -Wno-self-assign +EXTRA_CFLAGS += -Wno-header-guard +endif + +GCC_VER_49 := $(shell echo `$(CC) -dumpversion | cut -f1-2 -d.` \>= 4.9 | bc ) +ifeq ($(GCC_VER_49),1) +EXTRA_CFLAGS += -Wno-date-time # Fix compile error && warning on gcc 4.9 and later +endif + +EXTRA_CFLAGS += -I$(src)/include + +EXTRA_LDFLAGS += --strip-debug + +CONFIG_AUTOCFG_CP = n + +########################## WIFI IC ############################ +CONFIG_RTL8852B = n +CONFIG_RTL8852BP = n +CONFIG_RTL8852BT = n +CONFIG_RTL8851B = n +CONFIG_RTL8852C = y +CONFIG_RTL8852D = n +######################### Interface ########################### +CONFIG_USB_HCI = n +CONFIG_PCI_HCI = y +CONFIG_SDIO_HCI = n +CONFIG_GSPI_HCI = n +########################## Features ########################### +CONFIG_MP_INCLUDED = y +CONFIG_CONCURRENT_MODE = y +CONFIG_POWER_SAVE = y +CONFIG_IPS_MODE = default +CONFIG_LPS_MODE = default +CONFIG_BTC = y +CONFIG_WAPI_SUPPORT = n +CONFIG_EFUSE_CONFIG_FILE = y +CONFIG_EXT_CLK = n +CONFIG_TRAFFIC_PROTECT = n +CONFIG_LOAD_PHY_PARA_FROM_FILE = y +# Remember to set CONFIG_FILE_FWIMG when set CONFIG_FILE_FWIMG to y, +# or driver will fail on ifconfig up because can't find firmware file +CONFIG_FILE_FWIMG = n +CONFIG_TXPWR_BY_RATE = y +CONFIG_TXPWR_BY_RATE_EN = y +CONFIG_TXPWR_LIMIT = y +CONFIG_TXPWR_LIMIT_EN = auto +CONFIG_PCI_ASPM = n +CONFIG_PCI_RTW_MSI = y +CONFIG_PCI_64BIT_DMA = n + +####################### RTW regulatory DB selection ###################### +# RTW regulatory database version to select +# *MUST* config to match the certification status of shipping product, +# otherwise regression issue on regulatory may happen. +CONFIG_RTW_REGDB = rtk_8852CE_M.2_2230-67-52 + +########################## Initial Channel Plan ########################## +# XX: unspecified +CONFIG_RTW_COUNTRY_CODE = XX +# 0xFFFF: unspecified +CONFIG_RTW_CHPLAN = 0xFFFF +# 0xFFFF: unspecified +CONFIG_RTW_CHPLAN_6G = 0xFFFF + +########################## 802.11d (country IE slave) ########################## +CONFIG_80211D = y +# 0: disable, 1: enable, 2: enable when INIT/USER set world wide mode +CONFIG_RTW_COUNTRY_IE_SLAVE_EN_MODE = 0 +# BIT0: deprecated BIT +# BIT1: consider all environment BSSs, otherwise associated BSSs only +CONFIG_RTW_COUNTRY_IE_SLAVE_FLAGS = 0x00 + +########################## EDCCA for regulatory ########################## +# NORMAL: Without regulatory consideration +# CS : Force Carrier Sense +# ADAPT : Force Adaptivity +# CBP : Force Contention Based Protocol +# AUTO : According to regulatory +CONFIG_RTW_EDCCA_MODE_SEL = NORMAL + +CONFIG_SIGNAL_SCALE_MAPPING = n +CONFIG_80211W = y +CONFIG_REDUCE_TX_CPU_LOADING = n +CONFIG_BR_EXT = y +CONFIG_TDLS = n +CONFIG_WIFI_MONITOR = n +CONFIG_MCC_MODE = y +CONFIG_APPEND_VENDOR_IE_ENABLE = n +CONFIG_RTW_NAPI = y +CONFIG_RTW_GRO = y +CONFIG_RTW_NETIF_SG = n +CONFIG_RTW_IPCAM_APPLICATION = n +CONFIG_ICMP_VOQ = n +CONFIG_IP_R_MONITOR = n #arp VOQ and high rate +# user priority mapping rule : tos, dscp +CONFIG_RTW_UP_MAPPING_RULE = tos + +CONFIG_PHL_ARCH = y +CONFIG_PHL_FSM = n +CONFIG_RTW_FSM = y +CONFIG_CMD_DISP = y + +CONFIG_HWSIM = n + +CONFIG_PHL_TEST_SUITE = n +CONFIG_WIFI_6 = y + +RTW_PHL_RX = y +RTW_PHL_TX = y +RTW_PHL_BCN = y +DIRTY_FOR_WORK = y + +CONFIG_DRV_FAKE_AP = n + +CONFIG_DBG_AX_CAM = y + +USE_TRUE_PHY = y +CONFIG_I386_BUILD_VERIFY = n +CONFIG_RTW_MBO = y +# CONFIG_RTKM - n/m/y for not support / standalone / built-in +CONFIG_RTKM ?= n +########################## Android ########################### +# CONFIG_RTW_ANDROID - 0: no Android, 4/5/6/7/8/9/10/11/12 : Android version +CONFIG_RTW_ANDROID = 0 + +ifeq ($(shell test $(CONFIG_RTW_ANDROID) -gt 0; echo $$?), 0) +EXTRA_CFLAGS += -DCONFIG_RTW_ANDROID=$(CONFIG_RTW_ANDROID) +endif + +########################## Debug ########################### +CONFIG_RTW_DEBUG = y +# default log level is _DRV_INFO_ = 4, +# please refer to "How_to_set_driver_debug_log_level.doc" to set the available level. +CONFIG_RTW_LOG_LEVEL = 4 +CONFIG_RTW_PHL_LOG_LEVEL = 3 + +# CONFIG_RTW_APPEND_LOGLEVEL decide if append kernel log level to each messages. +# default "n" for don't append. +CONFIG_RTW_APPEND_LOGLEVEL = n + +# Add "RTW_LL_*" define to change default mapping of driver debug log level +# to Linux kernel log level. +# NOTICE: "RTW_LL_*" would be valid only when "CONFIG_RTW_APPEND_LOGLEVEL = y" +#RTW_LL_PRINT = KERN_CRIT +#RTW_LL_ERR = KERN_ERR +#RTW_LL_WARN = KERN_WARNING +#RTW_LL_INFO = KERN_INFO +#RTW_LL_DBG = KERN_DEBUG +#RTW_LL_DEFAULT = KERN_DEFAULT + +# enable /proc/net/rtlxxxx/ debug interfaces +CONFIG_PROC_DEBUG = y +CONFIG_SELF_DIAG_INFO = y +############################# MLO ############################# +CONFIG_80211BE_EHT = n +ifeq ($(CONFIG_80211BE_EHT), y) +EXTRA_CFLAGS += -DCONFIG_80211BE_EHT +endif +CONFIG_MLD_TEST = n # used for test MLD capability +RTW_NETWORK_LINK_MAX = 3 +DTYPE = DEV_TYPE_LEGACY # DEV_TYPE_MLD for MLD device +ifeq ($(CONFIG_MLD_TEST), y) +EXTRA_CFLAGS += -DCONFIG_MLD_TEST +endif +EXTRA_CFLAGS += -DRTW_NETWORK_LINK_MAX=$(RTW_NETWORK_LINK_MAX) +EXTRA_CFLAGS += -DDTYPE=$(DTYPE) +######################## Wake On Lan ########################## +CONFIG_WOWLAN = n +# CONFIG_WAKE_TYPE definition: +# bit0: magic packet +# bit1: unicast packet (default pattern match) +# bit2: disconnect (beacon loss & deauth/dissociation) +# bit3: customized pattern match +# bit4: pairwise key rekey +CONFIG_WAKEUP_TYPE = 0x0f +CONFIG_WOW_IPS_MODE = default +CONFIG_WOW_LPS_MODE = default +#bit0: disBBRF off, #bit1: Wireless remote controller (WRC) +CONFIG_SUSPEND_TYPE = 0 +CONFIG_WOW_STA_MIX = n +CONFIG_GPIO_WAKEUP = n +# Please contact with RTK support team first. After getting the agreement from RTK support team, +# you are just able to modify the CONFIG_WAKEUP_GPIO_IDX with customized requirement. +CONFIG_WAKEUP_GPIO_IDX = default +CONFIG_HIGH_ACTIVE_DEV2HST = n +#0:TOGGLE 1:PULSE +CONFIG_TOGGLE_PULSE = 0 +CONFIG_PULSE_COUNT = 3 +######### only for USB ######### +CONFIG_ONE_PIN_GPIO = n +CONFIG_HIGH_ACTIVE_HST2DEV = n +CONFIG_PNO_SUPPORT = n +CONFIG_AP_WOWLAN = n +######### Notify SDIO Host Keep Power During Syspend ########## +CONFIG_RTW_SDIO_PM_KEEP_POWER = y +###################### MP HW TX MODE FOR VHT ####################### +CONFIG_MP_VHT_HW_TX_MODE = n + +###################### ROAMING ##################################### +CONFIG_LAYER2_ROAMING = y +#bit0: ROAM_ON_EXPIRED, #bit1: ROAM_ON_RESUME, #bit2: ROAM_ACTIVE +CONFIG_ROAMING_FLAG = 0x3 + +###################### Platform Related ####################### +CONFIG_PLATFORM_I386_PC = y +CONFIG_PLATFORM_RTL8198D = n +CONFIG_PLATFORM_ANDROID_X86 = n +CONFIG_PLATFORM_ANDROID_INTEL_X86 = n +CONFIG_PLATFORM_NV_TK1 = n +CONFIG_PLATFORM_NV_TK1_UBUNTU = n +CONFIG_PLATFORM_ARM_SUNxI = n +CONFIG_PLATFORM_RTK1319 = n +CONFIG_PLATFORM_RTK16XXB = n +CONFIG_PLATFORM_AML_S905 = n +CONFIG_PLATFORM_AML_S905_L3A = n +CONFIG_PLATFORM_HUANGLONG = n +CONFIG_PLATFORM_ARM_ROCKCHIP = n +CONFIG_PLATFORM_AML_S928X = n + +########### CUSTOMER ################################ + +CONFIG_DRVEXT_MODULE = n + +export TopDIR ?= $(shell pwd) + +########### COMMON ################################# +ifeq ($(CONFIG_GSPI_HCI), y) +HCI_NAME = gspi +endif + +ifeq ($(CONFIG_SDIO_HCI), y) +HCI_NAME = sdio +endif + +ifeq ($(CONFIG_USB_HCI), y) +HCI_NAME = usb +endif + +ifeq ($(CONFIG_PCI_HCI), y) +HCI_NAME = pci +endif + +ifeq ($(CONFIG_HWSIM), y) + HAL = hal_sim +else + HAL = phl +endif + +ifeq ($(CONFIG_PLATFORM_RTL8198D), y) +DRV_PATH = $(src) +else +DRV_PATH = $(TopDIR) +endif + +########### HAL_RTL8852B ################################# +ifeq ($(CONFIG_RTL8852B), y) +IC_NAME := rtl8852b +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8852bu +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8852be +endif +ifeq ($(CONFIG_SDIO_HCI), y) +MODULE_NAME = 8852bs +endif + +endif + +########### HAL_RTL8852BP ################################# +ifeq ($(CONFIG_RTL8852BP), y) +IC_NAME := rtl8852bp +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8852bpu +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8852bpe +endif +ifeq ($(CONFIG_SDIO_HCI), y) +MODULE_NAME = 8852bps +endif + +endif + +########### HAL_RTL8852BT ################################# +ifeq ($(CONFIG_RTL8852BT), y) +IC_NAME := rtl8852bt +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8852btu +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8852bte +endif +ifeq ($(CONFIG_SDIO_HCI), y) +MODULE_NAME = 8852bts +endif + +endif + +########### HAL_RTL8851B ################################# +ifeq ($(CONFIG_RTL8851B), y) +IC_NAME := rtl8851b +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8851bu +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8851be +endif +ifeq ($(CONFIG_SDIO_HCI), y) +MODULE_NAME = 8851bs +endif + +endif + +########### HAL_RTL8852C ################################# +ifeq ($(CONFIG_RTL8852C), y) +IC_NAME := rtl8852c +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8852cu +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8852ce +endif +endif + +########### HAL_RTL8852D ################################# +ifeq ($(CONFIG_RTL8852D), y) +IC_NAME := rtl8852d +ifeq ($(CONFIG_USB_HCI), y) +MODULE_NAME = 8852du +endif +ifeq ($(CONFIG_PCI_HCI), y) +MODULE_NAME = 8852de +endif +endif + +########### AUTO_CFG ################################# + +ifeq ($(CONFIG_AUTOCFG_CP), y) +$(shell cp $(DRV_PATH)/autoconf_$(IC_NAME)_$(HCI_NAME)_linux.h $(DRV_PATH)/include/autoconf.h) +endif + +########### END OF PATH ################################# +ifeq ($(CONFIG_MP_INCLUDED), y) +#MODULE_NAME := $(MODULE_NAME)_mp +EXTRA_CFLAGS += -DCONFIG_MP_INCLUDED +CONFIG_PHL_TEST_SUITE = y +endif + +ifeq ($(CONFIG_RTW_FSM), y) +EXTRA_CFLAGS += -DCONFIG_RTW_FSM +#EXTRA_CFLAGS += -DCONFIG_RTW_FSM_XXX +EXTRA_CFLAGS += -DCONFIG_RTW_FSM_RRM +#EXTRA_CFLAGS += -DCONFIG_RTW_FSM_BTM +endif + +ifeq ($(CONFIG_PHL_FSM), y) +EXTRA_CFLAGS += -DCONFIG_FSM +endif + +ifeq ($(CONFIG_CMD_DISP), y) +EXTRA_CFLAGS += -DCONFIG_CMD_DISP +endif + +ifeq ($(CONFIG_PHL_TEST_SUITE), y) +EXTRA_CFLAGS += -DCONFIG_PHL_TEST_SUITE +endif + +ifeq ($(CONFIG_CONCURRENT_MODE), y) +EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE +endif + +ifeq ($(CONFIG_POWER_SAVE), y) +EXTRA_CFLAGS += -DCONFIG_POWER_SAVE +ifneq ($(CONFIG_IPS_MODE), default) +EXTRA_CFLAGS += -DRTW_IPS_MODE=$(CONFIG_IPS_MODE) +endif +ifneq ($(CONFIG_LPS_MODE), default) +EXTRA_CFLAGS += -DRTW_LPS_MODE=$(CONFIG_LPS_MODE) +endif +ifneq ($(CONFIG_WOW_IPS_MODE), default) +EXTRA_CFLAGS += -DRTW_WOW_IPS_MODE=$(CONFIG_WOW_IPS_MODE) +endif +ifneq ($(CONFIG_WOW_LPS_MODE), default) +EXTRA_CFLAGS += -DRTW_WOW_LPS_MODE=$(CONFIG_WOW_LPS_MODE) +endif +endif + +ifeq ($(CONFIG_BTC), y) +EXTRA_CFLAGS += -DCONFIG_BTC +endif + +ifeq ($(CONFIG_WAPI_SUPPORT), y) +EXTRA_CFLAGS += -DCONFIG_WAPI_SUPPORT +endif + +ifeq ($(CONFIG_WIFI_6), y) +EXTRA_CFLAGS += -DCONFIG_WIFI_6 +endif + +ifeq ($(CONFIG_EFUSE_CONFIG_FILE), y) +EXTRA_CFLAGS += -DCONFIG_EFUSE_CONFIG_FILE + +#EFUSE_MAP_PATH +USER_EFUSE_MAP_PATH ?= +ifneq ($(USER_EFUSE_MAP_PATH),) +EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"$(USER_EFUSE_MAP_PATH)\" +else +EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"/system/etc/wifi/wifi_efuse_$(MODULE_NAME).map\" +endif + +#WIFIMAC_PATH +USER_WIFIMAC_PATH ?= +ifneq ($(USER_WIFIMAC_PATH),) +EXTRA_CFLAGS += -DWIFIMAC_PATH=\"$(USER_WIFIMAC_PATH)\" +else +EXTRA_CFLAGS += -DWIFIMAC_PATH=\"/data/wifimac.txt\" +endif + +endif + +ifeq ($(CONFIG_EXT_CLK), y) +EXTRA_CFLAGS += -DCONFIG_EXT_CLK +endif + +ifeq ($(CONFIG_TRAFFIC_PROTECT), y) +EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT +endif + +ifeq ($(CONFIG_LOAD_PHY_PARA_FROM_FILE), y) +EXTRA_CFLAGS += -DCONFIG_LOAD_PHY_PARA_FROM_FILE +#EXTRA_CFLAGS += -DREALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER +EXTRA_CFLAGS += -DREALTEK_CONFIG_PATH=\"/lib/firmware/\" +endif + +ifeq ($(CONFIG_FILE_FWIMG), y) +EXTRA_CFLAGS += -DCONFIG_FILE_FWIMG +# default external firmware path is [CONFIG_FIRMWARE_PATH][ic_name]/[fw_name] +# ex. Take 8852AE as example: +# normal firmware is [CONFIG_FIRMWARE_PATH]rtl8852ae/rtl8852afw.bin +# WOW firmware is [CONFIG_FIRMWARE_PATH]rtl8852ae/rtl8852afw_wowlan.bin +EXTRA_CFLAGS += -DCONFIG_FIRMWARE_PATH=\"\" +# EXTRA_CFLAGS += -DCONFIG_FIRMWARE_PATH=\"/lib/firmware/\" +endif + +ifeq ($(CONFIG_TXPWR_BY_RATE), n) +EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE=0 +else ifeq ($(CONFIG_TXPWR_BY_RATE), y) +EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE=1 +endif +ifeq ($(CONFIG_TXPWR_BY_RATE_EN), n) +EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=0 +else ifeq ($(CONFIG_TXPWR_BY_RATE_EN), y) +EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=1 +else ifeq ($(CONFIG_TXPWR_BY_RATE_EN), auto) +EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=2 +endif + +ifeq ($(CONFIG_TXPWR_LIMIT), n) +EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT=0 +else ifeq ($(CONFIG_TXPWR_LIMIT), y) +EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT=1 +endif +ifeq ($(CONFIG_TXPWR_LIMIT_EN), n) +EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=0 +else ifeq ($(CONFIG_TXPWR_LIMIT_EN), y) +EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=1 +else ifeq ($(CONFIG_TXPWR_LIMIT_EN), auto) +EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=2 +endif + +ifeq ($(CONFIG_PCI_ASPM), y) +EXTRA_CFLAGS += -DCONFIG_PCI_ASPM +endif + +ifeq ($(CONFIG_PCI_RTW_MSI), n) +EXTRA_CFLAGS += -DCONFIG_RTW_FORCE_PCI_MSI_DISABLE +endif + +ifeq ($(CONFIG_PCI_64BIT_DMA), y) +EXTRA_CFLAGS += -DCONFIG_64BIT_DMA +endif + +ifneq ($(CONFIG_RTW_COUNTRY_CODE), XX) +EXTRA_CFLAGS += -DCONFIG_RTW_COUNTRY_CODE=\"$(CONFIG_RTW_COUNTRY_CODE)\" +endif +ifneq ($(CONFIG_RTW_CHPLAN), 0xFFFF) +EXTRA_CFLAGS += -DCONFIG_RTW_CHPLAN=$(CONFIG_RTW_CHPLAN) +endif +ifneq ($(CONFIG_RTW_CHPLAN_6G), 0xFFFF) +EXTRA_CFLAGS += -DCONFIG_RTW_CHPLAN_6G=$(CONFIG_RTW_CHPLAN_6G) +endif + +ifeq ($(CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY), y) +EXTRA_CFLAGS += -DCONFIG_CALIBRATE_TX_POWER_BY_REGULATORY +endif + +ifeq ($(CONFIG_CALIBRATE_TX_POWER_TO_MAX), y) +EXTRA_CFLAGS += -DCONFIG_CALIBRATE_TX_POWER_TO_MAX +endif + +ifeq ($(CONFIG_RTW_EDCCA_MODE_SEL), NORMAL) +EXTRA_CFLAGS += -DCONFIG_RTW_EDCCA_MODE_SEL=0 +else ifeq ($(CONFIG_RTW_EDCCA_MODE_SEL), CS) +EXTRA_CFLAGS += -DCONFIG_RTW_EDCCA_MODE_SEL=1 +else ifeq ($(CONFIG_RTW_EDCCA_MODE_SEL), ADAPT) +EXTRA_CFLAGS += -DCONFIG_RTW_EDCCA_MODE_SEL=2 +else ifeq ($(CONFIG_RTW_EDCCA_MODE_SEL), CBP) +EXTRA_CFLAGS += -DCONFIG_RTW_EDCCA_MODE_SEL=3 +else ifeq ($(CONFIG_RTW_EDCCA_MODE_SEL), AUTO) +EXTRA_CFLAGS += -DCONFIG_RTW_EDCCA_MODE_SEL=0xFF +endif + +ifeq ($(CONFIG_RTW_ADAPTIVITY_EN), disable) +EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_EN=0 +else ifeq ($(CONFIG_RTW_ADAPTIVITY_EN), enable) +EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_EN=1 +else ifeq ($(CONFIG_RTW_ADAPTIVITY_EN), auto) +EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_EN=2 +endif + +ifeq ($(CONFIG_RTW_ADAPTIVITY_MODE), normal) +EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_MODE=0 +else ifeq ($(CONFIG_RTW_ADAPTIVITY_MODE), carrier_sense) +EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_MODE=1 +endif + +ifeq ($(CONFIG_80211D), y) +EXTRA_CFLAGS += -DCONFIG_80211D +ifneq ($(CONFIG_RTW_COUNTRY_IE_SLAVE_EN_MODE), ) +EXTRA_CFLAGS += -DCONFIG_RTW_COUNTRY_IE_SLAVE_EN_MODE=$(CONFIG_RTW_COUNTRY_IE_SLAVE_EN_MODE) +endif +ifneq ($(CONFIG_RTW_COUNTRY_IE_SLAVE_FLAGS), ) +EXTRA_CFLAGS += -DCONFIG_RTW_COUNTRY_IE_SLAVE_FLAGS=$(CONFIG_RTW_COUNTRY_IE_SLAVE_FLAGS) +endif +endif + +ifeq ($(CONFIG_SIGNAL_SCALE_MAPPING), y) +EXTRA_CFLAGS += -DCONFIG_SIGNAL_SCALE_MAPPING +endif + +ifeq ($(CONFIG_80211W), y) +EXTRA_CFLAGS += -DCONFIG_IEEE80211W +endif + +ifeq ($(CONFIG_WOWLAN), y) +EXTRA_CFLAGS += -DCONFIG_WOWLAN -DRTW_WAKEUP_EVENT=$(CONFIG_WAKEUP_TYPE) +EXTRA_CFLAGS += -DRTW_SUSPEND_TYPE=$(CONFIG_SUSPEND_TYPE) +ifeq ($(CONFIG_WOW_STA_MIX), y) +EXTRA_CFLAGS += -DRTW_WOW_STA_MIX +endif +ifeq ($(CONFIG_SDIO_HCI), y) +EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER +endif +endif + +ifeq ($(CONFIG_AP_WOWLAN), y) +EXTRA_CFLAGS += -DCONFIG_AP_WOWLAN +ifeq ($(CONFIG_SDIO_HCI), y) +EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER +endif +endif + +ifeq ($(CONFIG_LAYER2_ROAMING), y) + EXTRA_CFLAGS += -DCONFIG_LAYER2_ROAMING -DCONFIG_ROAMING_FLAG=$(CONFIG_ROAMING_FLAG) +endif + +ifeq ($(CONFIG_PNO_SUPPORT), y) +EXTRA_CFLAGS += -DCONFIG_PNO_SUPPORT +endif + +ifeq ($(CONFIG_GPIO_WAKEUP), y) +EXTRA_CFLAGS += -DCONFIG_GPIO_WAKEUP +EXTRA_CFLAGS += -DCONFIG_TOGGLE_PULSE=$(CONFIG_TOGGLE_PULSE) +EXTRA_CFLAGS += -DCONFIG_PULSE_COUNT=$(CONFIG_PULSE_COUNT) +ifeq ($(CONFIG_ONE_PIN_GPIO), y) +EXTRA_CFLAGS += -DCONFIG_RTW_ONE_PIN_GPIO +endif +ifeq ($(CONFIG_HIGH_ACTIVE_DEV2HST), y) +EXTRA_CFLAGS += -DHIGH_ACTIVE_DEV2HST=1 +else +EXTRA_CFLAGS += -DHIGH_ACTIVE_DEV2HST=0 +endif +endif + +ifeq ($(CONFIG_HIGH_ACTIVE_HST2DEV), y) +EXTRA_CFLAGS += -DHIGH_ACTIVE_HST2DEV=1 +else +EXTRA_CFLAGS += -DHIGH_ACTIVE_HST2DEV=0 +endif + +ifneq ($(CONFIG_WAKEUP_GPIO_IDX), default) +EXTRA_CFLAGS += -DWAKEUP_GPIO_IDX=$(CONFIG_WAKEUP_GPIO_IDX) +endif + +ifeq ($(CONFIG_RTW_SDIO_PM_KEEP_POWER), y) +ifeq ($(CONFIG_SDIO_HCI), y) +EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER +endif +endif + +ifeq ($(CONFIG_REDUCE_TX_CPU_LOADING), y) +EXTRA_CFLAGS += -DCONFIG_REDUCE_TX_CPU_LOADING +endif + +ifeq ($(CONFIG_BR_EXT), y) +BR_NAME = br0 +EXTRA_CFLAGS += -DCONFIG_BR_EXT +EXTRA_CFLAGS += '-DCONFIG_BR_EXT_BRNAME="'$(BR_NAME)'"' +endif + + +ifeq ($(CONFIG_TDLS), y) +EXTRA_CFLAGS += -DCONFIG_TDLS +endif + +ifeq ($(CONFIG_WIFI_MONITOR), y) +EXTRA_CFLAGS += -DCONFIG_WIFI_MONITOR +endif + +ifeq ($(CONFIG_MCC_MODE), y) +EXTRA_CFLAGS += -DCONFIG_MCC_MODE +endif + +ifeq ($(CONFIG_RTW_NAPI), y) +EXTRA_CFLAGS += -DCONFIG_RTW_NAPI +endif + +ifeq ($(CONFIG_RTW_GRO), y) +EXTRA_CFLAGS += -DCONFIG_RTW_GRO +endif + +ifeq ($(CONFIG_RTW_IPCAM_APPLICATION), y) +EXTRA_CFLAGS += -DCONFIG_RTW_IPCAM_APPLICATION +ifeq ($(CONFIG_WIFI_MONITOR), n) +EXTRA_CFLAGS += -DCONFIG_WIFI_MONITOR +endif +endif + +ifeq ($(CONFIG_RTW_NETIF_SG), y) +EXTRA_CFLAGS += -DCONFIG_RTW_NETIF_SG +endif + +ifeq ($(CONFIG_ICMP_VOQ), y) +EXTRA_CFLAGS += -DCONFIG_ICMP_VOQ +endif + +ifeq ($(CONFIG_IP_R_MONITOR), y) +EXTRA_CFLAGS += -DCONFIG_IP_R_MONITOR +endif + +ifeq ($(CONFIG_MP_VHT_HW_TX_MODE), y) +EXTRA_CFLAGS += -DCONFIG_MP_VHT_HW_TX_MODE +ifeq ($(CONFIG_PLATFORM_I386_PC), y) +## For I386 X86 ToolChain use Hardware FLOATING +EXTRA_CFLAGS += -mhard-float +else +## For ARM ToolChain use Hardware FLOATING +EXTRA_CFLAGS += -mfloat-abi=hard +endif +endif + +ifeq ($(CONFIG_APPEND_VENDOR_IE_ENABLE), y) +EXTRA_CFLAGS += -DCONFIG_APPEND_VENDOR_IE_ENABLE +endif + +ifeq ($(CONFIG_RTW_DEBUG), y) +EXTRA_CFLAGS += -DCONFIG_RTW_DEBUG +EXTRA_CFLAGS += -DRTW_LOG_LEVEL=$(CONFIG_RTW_LOG_LEVEL) +EXTRA_CFLAGS += -DRTW_PHL_LOG_LEVEL=$(CONFIG_RTW_PHL_LOG_LEVEL) +ifeq ($(CONFIG_RTW_APPEND_LOGLEVEL), y) +EXTRA_CFLAGS += -DRTW_APPEND_LOGLEVEL +ifdef RTW_LL_PRINT +EXTRA_CFLAGS += -DRTW_LL_PRINT=$(RTW_LL_PRINT) +endif +ifdef RTW_LL_ERR +EXTRA_CFLAGS += -DRTW_LL_ERR=$(RTW_LL_ERR) +endif +ifdef RTW_LL_WARN +EXTRA_CFLAGS += -DRTW_LL_WARN=$(RTW_LL_WARN) +endif +ifdef RTW_LL_INFO +EXTRA_CFLAGS += -DRTW_LL_INFO=$(RTW_LL_INFO) +endif +ifdef RTW_LL_DBG +EXTRA_CFLAGS += -DRTW_LL_DBG=$(RTW_LL_DBG) +endif +ifdef RTW_LL_DEFAULT +EXTRA_CFLAGS += -DRTW_LL_DEFAULT=$(RTW_LL_DEFAULT) +endif +endif # CONFIG_RTW_APPEND_LOGLEVEL +endif # CONFIG_RTW_DEBUG + +ifeq ($(CONFIG_PROC_DEBUG), y) +EXTRA_CFLAGS += -DCONFIG_PROC_DEBUG +endif + +ifeq ($(CONFIG_SELF_DIAG_INFO), y) +EXTRA_CFLAGS += -DCONFIG_SELF_DIAG_INFO +endif + +ifeq ($(CONFIG_RTW_UP_MAPPING_RULE), dscp) +EXTRA_CFLAGS += -DCONFIG_RTW_UP_MAPPING_RULE=1 +else +EXTRA_CFLAGS += -DCONFIG_RTW_UP_MAPPING_RULE=0 +endif + +EXTRA_CFLAGS += -DPLATFORM_LINUX + +ifeq ($(USE_TRUE_PHY), y) +EXTRA_CFLAGS += -DUSE_TRUE_PHY +endif + +ifeq ($(CONFIG_HWSIM), y) +EXTRA_CFLAGS += -DCONFIG_HWSIM + +# To use pure sw beacon +EXTRA_CFLAGS += -DCONFIG_SWTIMER_BASED_TXBCN +EXTRA_CFLAGS += -DCONFIG_SUPPORT_MULTI_BCN +endif + +ifeq ($(CONFIG_DRV_FAKE_AP), y) +EXTRA_CFLAGS += -DCONFIG_DRV_FAKE_AP +OBJS += core/rtw_fake_ap.o +endif + +ifeq ($(CONFIG_DBG_AX_CAM), y) +EXTRA_CFLAGS += -DCONFIG_DBG_AX_CAM +endif + +ifeq ($(CONFIG_I386_BUILD_VERIFY), y) +EXTRA_CFLAGS += -DCONFIG_I386_BUILD_VERIFY +endif + +ifeq ($(CONFIG_RTW_MBO), y) +EXTRA_CFLAGS += -DCONFIG_RTW_MBO -DCONFIG_RTW_WNM -DCONFIG_RTW_BTM_ROAM +#EXTRA_CFLAGS += -DCONFIG_RTW_80211K +EXTRA_CFLAGS += -DCONFIG_RTW_80211R +EXTRA_CFLAGS += -DRTW_FT_DBG=0 -DRTW_WNM_DBG=0 -DRTW_MBO_DBG=0 +endif + +########### PLATFORM OPS ########################## +# Import platform assigned KSRC and CROSS_COMPILE +include $(wildcard $(DRV_PATH)/platform/*.mk) + +# Import platform specific compile options +EXTRA_CFLAGS += -I$(src)/platform +#_PLATFORM_FILES := platform/platform_ops.o +OBJS += $(_PLATFORM_FILES) + +########### CUSTOMER ################################ +USER_MODULE_NAME ?= +ifneq ($(USER_MODULE_NAME),) +MODULE_NAME := $(USER_MODULE_NAME) +endif + +############ ANDROID COMMON KERNEL ############ +export M ?= $(shell pwd) +export OUT_DIR ?= $(shell pwd) +ifneq ($(LLVM),) +export CC_STRIP = llvm-strip +else +export CC_STRIP = $(CROSS_COMPILE)strip +endif + +ifneq ($(KERNELRELEASE),) +########### COMMON ################################# +include $(src)/common.mk + +EXTRA_CFLAGS += -DPHL_PLATFORM_LINUX +EXTRA_CFLAGS += -DCONFIG_PHL_ARCH + +ifeq ($(RTW_PHL_RX), y) +EXTRA_CFLAGS += -DRTW_PHL_RX +endif + +ifeq ($(RTW_PHL_TX), y) +EXTRA_CFLAGS += -DRTW_PHL_TX +endif + +ifeq ($(RTW_PHL_BCN), y) +EXTRA_CFLAGS += -DRTW_PHL_BCN +endif + +ifeq ($(DIRTY_FOR_WORK), y) +EXTRA_CFLAGS += -DDIRTY_FOR_WORK +endif + +include $(src)/phl/phl.mk + + +obj-$(CONFIG_RTL8852CE) := $(MODULE_NAME).o +obj-$(CONFIG_RTL8852CE) := $(MODULE_NAME).o +$(MODULE_NAME)-y = $(OBJS) + +############# MEMORY MANAGMENT ############# +ifneq ($(CONFIG_RTKM), n) +_MEMM_FILES = core/rtw_prealloc.o +ifeq ($(CONFIG_RTKM), y) +EXTRA_CFLAGS += -DCONFIG_RTKM -DCONFIG_RTKM_BUILT_IN +$(MODULE_NAME)-y += $(_MEMM_FILES) +else ifeq ($(CONFIG_RTKM), m) +RTKM_MODULE = rtkm +EXTRA_CFLAGS += -DCONFIG_RTKM -DCONFIG_RTKM_STANDALONE +_MEMM_FILES += core/rtw_mem.o +$(RTKM_MODULE)-y += $(_MEMM_FILES) +obj-$(CONFIG_RTL8852CE) += $(RTKM_MODULE).o +endif +endif + +else + +export CONFIG_RTL8852CE = m + +all: modules + +modules: +# rm -f .symvers.$(MODULE_NAME) + + $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KSRC) M=$(M) modules + +# $(CC_STRIP) --strip-unneeded ${OUT_DIR}/$(M)/$(MODULE_NAME).ko +# cp Module.symvers .symvers.$(MODULE_NAME) + +strip: + $(CC_STRIP) $(MODULE_NAME).ko --strip-unneeded + +install: + install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) + /sbin/depmod -a ${KVER} + +uninstall: + rm -f $(MODDESTDIR)/$(MODULE_NAME).ko + /sbin/depmod -a ${KVER} + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 M=$(M) -C $(KSRC) modules_install +# mkdir -p ${OUT_DIR}/../vendor_lib/modules +# cd ${OUT_DIR}/$(M)/; find -name $(MODULE_NAME).ko -exec cp {} ${OUT_DIR}/../vendor_lib/modules/ \; + +backup_rtlwifi: + @echo "Making backup rtlwifi drivers" +ifneq (,$(wildcard $(STAGINGMODDIR)/rtl*)) + @tar cPf $(wildcard $(STAGINGMODDIR))/backup_rtlwifi_driver.tar $(wildcard $(STAGINGMODDIR)/rtl*) + @rm -rf $(wildcard $(STAGINGMODDIR)/rtl*) +endif +ifneq (,$(wildcard $(MODDESTDIR)realtek)) + @tar cPf $(MODDESTDIR)backup_rtlwifi_driver.tar $(MODDESTDIR)realtek + @rm -fr $(MODDESTDIR)realtek +endif +ifneq (,$(wildcard $(MODDESTDIR)rtl*)) + @tar cPf $(MODDESTDIR)../backup_rtlwifi_driver.tar $(wildcard $(MODDESTDIR)rtl*) + @rm -fr $(wildcard $(MODDESTDIR)rtl*) +endif + @/sbin/depmod -a ${KVER} + @echo "Please reboot your system" + +restore_rtlwifi: + @echo "Restoring backups" +ifneq (,$(wildcard $(STAGINGMODDIR)/backup_rtlwifi_driver.tar)) + @tar xPf $(STAGINGMODDIR)/backup_rtlwifi_driver.tar + @rm $(STAGINGMODDIR)/backup_rtlwifi_driver.tar +endif +ifneq (,$(wildcard $(MODDESTDIR)backup_rtlwifi_driver.tar)) + @tar xPf $(MODDESTDIR)backup_rtlwifi_driver.tar + @rm $(MODDESTDIR)backup_rtlwifi_driver.tar +endif +ifneq (,$(wildcard $(MODDESTDIR)../backup_rtlwifi_driver.tar)) + @tar xPf $(MODDESTDIR)../backup_rtlwifi_driver.tar + @rm $(MODDESTDIR)../backup_rtlwifi_driver.tar +endif + @/sbin/depmod -a ${KVER} + @echo "Please reboot your system" + +config_r: + @echo "make config" + /bin/bash script/Configure script/config.in + + +.PHONY: modules clean + +clean: +# $(MAKE) -C $(KSRC) M=$(shell pwd) clean + cd $(HAL) ; rm -fr */*/*/*/*.mod.c */*/*/*/*.mod */*/*/*/*.o */*/*/*/.*.cmd */*/*/*/*.ko + cd $(HAL) ; rm -fr */*/*/*.mod.c */*/*/*.mod */*/*/*.o */*/*/.*.cmd */*/*/*.ko + cd $(HAL) ; rm -fr */*/*.mod.c */*/*.mod */*/*.o */*/.*.cmd */*/*.ko + cd $(HAL) ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko + cd $(HAL) ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + cd core ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko + cd core ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + cd os_dep/linux ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + cd os_dep/linux/hwsim ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + cd os_dep ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + cd platform ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko + rm -fr Module.symvers ; rm -fr Module.markers ; rm -fr modules.order + rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~ + rm -fr .tmp_versions +endif + +############ ANDROID COMMON KERNEL ############ +# Convert to absolute path +ifneq ($(srctree),) +_EXTRA_CFLAGS := +_INC_CFLAGS := +$(foreach flag,$(EXTRA_CFLAGS),\ + $(if $(shell echo $(flag) | grep "\-I"),\ + $(eval _INC_CFLAGS += $(flag)),\ + $(eval _EXTRA_CFLAGS += $(flag))\ + )\ +) +_INC_CFLAGS := \ +$(foreach flag,$(subst -I,,$(_INC_CFLAGS)),\ + $(shell if test -d $(srctree)/$(flag); then echo -I$$(cd $(srctree)/$(flag) && pwd); else echo -I$(flag); fi)\ +) +EXTRA_CFLAGS := $(_EXTRA_CFLAGS) $(_INC_CFLAGS) +endif diff --git a/drivers/net/wireless/realtek/rtl8852ce/common.mk b/drivers/net/wireless/realtek/rtl8852ce/common.mk new file mode 100644 index 00000000..b5cf5649 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/common.mk @@ -0,0 +1,156 @@ +########### OS_DEP PATH ################################# +_OS_INTFS_FILES := os_dep/osdep_service.o \ + os_dep/osdep_service_linux.o \ + os_dep/linux/rtw_cfg.o \ + os_dep/linux/os_intfs.o \ + os_dep/linux/ioctl_linux.o \ + os_dep/linux/xmit_linux.o \ + os_dep/linux/mlme_linux.o \ + os_dep/linux/recv_linux.o \ + os_dep/linux/ioctl_cfg80211.o \ + os_dep/linux/rtw_cfgvendor.o \ + os_dep/linux/os_ch_utils.o \ + os_dep/linux/wifi_regd.o \ + os_dep/linux/rtw_android.o \ + os_dep/linux/rtw_proc.o \ + os_dep/linux/nlrtw.o \ + os_dep/linux/rtw_rhashtable.o + +ifeq ($(CONFIG_HWSIM), y) + _OS_INTFS_FILES += os_dep/linux/hwsim/medium/local.o + _OS_INTFS_FILES += os_dep/linux/hwsim/medium/sock_udp.o + _OS_INTFS_FILES += os_dep/linux/hwsim/medium/loopback.o + _OS_INTFS_FILES += os_dep/linux/hwsim/core.o + _OS_INTFS_FILES += os_dep/linux/hwsim/txrx.o + _OS_INTFS_FILES += os_dep/linux/hwsim/netdev.o + _OS_INTFS_FILES += os_dep/linux/hwsim/cfg80211.o + _OS_INTFS_FILES += os_dep/linux/hwsim/platform_dev.o + + _OS_INTFS_FILES += os_dep/linux/$(HCI_NAME)_ops_linux.o +else + _OS_INTFS_FILES += os_dep/linux/$(HCI_NAME)_intf.o + _OS_INTFS_FILES += os_dep/linux/$(HCI_NAME)_ops_linux.o +endif + +ifeq ($(CONFIG_MP_INCLUDED), y) +_OS_INTFS_FILES += os_dep/linux/ioctl_mp.o \ + os_dep/linux/ioctl_efuse.o +endif + +ifeq ($(CONFIG_SDIO_HCI), y) +_OS_INTFS_FILES += os_dep/linux/custom_gpio_linux.o +endif + +ifeq ($(CONFIG_GSPI_HCI), y) +_OS_INTFS_FILES += os_dep/linux/custom_gpio_linux.o +endif + +########### CORE PATH ################################# +_CORE_FILES := core/rtw_fsm.o \ + core/rtw_fsm_xxx.o \ + core/rtw_fsm_rrm.o \ + core/rtw_fsm_wnm.o \ + core/rtw_cmd.o \ + core/rtw_security.o \ + core/rtw_debug.o \ + core/rtw_io.o \ + core/rtw_ioctl_query.o \ + core/rtw_ioctl_set.o \ + core/rtw_ieee80211.o \ + core/rtw_mlme.o \ + core/rtw_mlme_ext.o \ + core/rtw_sec_cam.o \ + core/rtw_mi.o \ + core/rtw_wlan_util.o \ + core/rtw_vht.o \ + core/rtw_he.o \ + core/rtw_eht.o \ + core/rtw_pwrctrl.o \ + core/rtw_rf.o \ + core/rtw_chplan.o \ + core/regdb/rtw_regdb_$(CONFIG_RTW_REGDB).o \ + core/rtw_chset.o \ + core/rtw_dfs.o \ + core/rtw_txpwr.o \ + core/monitor/rtw_radiotap.o \ + core/rtw_recv.o \ + core/rtw_recv_shortcut.o \ + core/rtw_sta_mgt.o \ + core/rtw_ap.o \ + core/rtw_csa.o \ + core/wds/rtw_wds.o \ + core/mesh/rtw_mesh.o \ + core/mesh/rtw_mesh_pathtbl.o \ + core/mesh/rtw_mesh_hwmp.o \ + core/rtw_xmit.o \ + core/rtw_xmit_shortcut.o \ + core/rtw_p2p.o \ + core/rtw_tdls.o \ + core/rtw_br_ext.o \ + core/rtw_rm.o \ + core/rtw_rm_fsm.o \ + core/rtw_rm_util.o \ + core/rtw_trx.o \ + core/rtw_beamforming.o \ + core/rtw_scan.o \ + core/rtw_twt.o \ + #core/efuse/rtw_efuse.o + +_CORE_FILES += core/rtw_phl.o \ + core/rtw_phl_cmd.o + +EXTRA_CFLAGS += -I$(src)/core/crypto +_CORE_FILES += core/crypto/aes-internal.o \ + core/crypto/aes-internal-enc.o \ + core/crypto/aes-gcm.o \ + core/crypto/aes-ccm.o \ + core/crypto/aes-omac1.o \ + core/crypto/ccmp.o \ + core/crypto/gcmp.o \ + core/crypto/aes-siv.o \ + core/crypto/aes-ctr.o \ + core/crypto/sha256-internal.o \ + core/crypto/sha256.o \ + core/crypto/sha256-prf.o \ + core/crypto/rtw_crypto_wrap.o \ + core/rtw_swcrypto.o \ + core/rtw_csi.o + +ifeq ($(CONFIG_WOWLAN), y) +_CORE_FILES += core/rtw_wow.o +endif + +ifeq ($(CONFIG_PCI_HCI), y) +_CORE_FILES += core/rtw_trx_pci.o +endif + +ifeq ($(CONFIG_USB_HCI), y) +_CORE_FILES += core/rtw_trx_usb.o +endif + +ifeq ($(CONFIG_SDIO_HCI), y) +_CORE_FILES += core/rtw_sdio.o +endif + +ifeq ($(CONFIG_FPGA_INCLUDED), y) +_CORE_FILES += core/rtw_fpga.o +endif + +ifeq ($(CONFIG_MP_INCLUDED), y) +_CORE_FILES += core/rtw_mp.o +endif + +ifeq ($(CONFIG_WAPI_SUPPORT), y) +_CORE_FILES += core/rtw_wapi.o \ + core/rtw_wapi_sms4.o +endif + +ifeq ($(CONFIG_BTC), y) +_CORE_FILES += core/rtw_btc.o +endif + +ifeq ($(CONFIG_RTW_MBO), y) +_CORE_FILES += core/rtw_mbo.o core/rtw_ft.o core/rtw_wnm.o +endif + +OBJS += $(_OS_INTFS_FILES) $(_CORE_FILES) diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ccm.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ccm.c new file mode 100644 index 00000000..f208eb2f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ccm.c @@ -0,0 +1,211 @@ +/* + * Counter with CBC-MAC (CCM) with AES + * + * Copyright (c) 2010-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" + + +static void xor_aes_block(u8 *dst, const u8 *src) +{ + u32 *d = (u32 *) dst; + u32 *s = (u32 *) src; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; +} + + +static void aes_ccm_auth_start(void *aes, size_t M, size_t L, const u8 *nonce, + const u8 *aad, size_t aad_len, size_t plain_len, + u8 *x) +{ + u8 aad_buf[2 * AES_BLOCK_SIZE]; + u8 b[AES_BLOCK_SIZE]; + + /* Authentication */ + /* B_0: Flags | Nonce N | l(m) */ + b[0] = aad_len ? 0x40 : 0 /* Adata */; + b[0] |= (((M - 2) / 2) /* M' */ << 3); + b[0] |= (L - 1) /* L' */; + os_memcpy(&b[1], nonce, 15 - L); + WPA_PUT_BE16(&b[AES_BLOCK_SIZE - L], plain_len); + + wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM B_0", b, AES_BLOCK_SIZE); + wpa_aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */ + + if (!aad_len) + return; + + WPA_PUT_BE16(aad_buf, aad_len); + os_memcpy(aad_buf + 2, aad, aad_len); + os_memset(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len); + + xor_aes_block(aad_buf, x); + wpa_aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */ + + if (aad_len > AES_BLOCK_SIZE - 2) { + xor_aes_block(&aad_buf[AES_BLOCK_SIZE], x); + /* X_3 = E(K, X_2 XOR B_2) */ + wpa_aes_encrypt(aes, &aad_buf[AES_BLOCK_SIZE], x); + } +} + + +static void aes_ccm_auth(void *aes, const u8 *data, size_t len, u8 *x) +{ + size_t last = len % AES_BLOCK_SIZE; + size_t i; + + for (i = 0; i < len / AES_BLOCK_SIZE; i++) { + /* X_i+1 = E(K, X_i XOR B_i) */ + xor_aes_block(x, data); + data += AES_BLOCK_SIZE; + wpa_aes_encrypt(aes, x, x); + } + if (last) { + /* XOR zero-padded last block */ + for (i = 0; i < last; i++) + x[i] ^= *data++; + wpa_aes_encrypt(aes, x, x); + } +} + + +static void aes_ccm_encr_start(size_t L, const u8 *nonce, u8 *a) +{ + /* A_i = Flags | Nonce N | Counter i */ + a[0] = L - 1; /* Flags = L' */ + os_memcpy(&a[1], nonce, 15 - L); +} + + +static void aes_ccm_encr(void *aes, size_t L, const u8 *in, size_t len, u8 *out, + u8 *a) +{ + size_t last = len % AES_BLOCK_SIZE; + size_t i; + + /* crypt = msg XOR (S_1 | S_2 | ... | S_n) */ + for (i = 1; i <= len / AES_BLOCK_SIZE; i++) { + WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i); + /* S_i = E(K, A_i) */ + wpa_aes_encrypt(aes, a, out); + xor_aes_block(out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + if (last) { + WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i); + wpa_aes_encrypt(aes, a, out); + /* XOR zero-padded last block */ + for (i = 0; i < last; i++) + *out++ ^= *in++; + } +} + + +static void aes_ccm_encr_auth(void *aes, size_t M, u8 *x, u8 *a, u8 *auth) +{ + size_t i; + u8 tmp[AES_BLOCK_SIZE]; + + wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM T", x, M); + /* U = T XOR S_0; S_0 = E(K, A_0) */ + WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0); + wpa_aes_encrypt(aes, a, tmp); + for (i = 0; i < M; i++) + auth[i] = x[i] ^ tmp[i]; + wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM U", auth, M); +} + + +static void aes_ccm_decr_auth(void *aes, size_t M, u8 *a, const u8 *auth, u8 *t) +{ + size_t i; + u8 tmp[AES_BLOCK_SIZE]; + + wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM U", auth, M); + /* U = T XOR S_0; S_0 = E(K, A_0) */ + WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0); + wpa_aes_encrypt(aes, a, tmp); + for (i = 0; i < M; i++) + t[i] = auth[i] ^ tmp[i]; + wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM T", t, M); +} + + +/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */ +int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth) +{ + const size_t L = 2; + void *aes; + u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; + + if (aad_len > 30 || M > AES_BLOCK_SIZE) + return -1; + + aes = aes_encrypt_init(key, key_len); + if (aes == NULL) + return -1; + + aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, plain_len, x); + aes_ccm_auth(aes, plain, plain_len, x); + + /* Encryption */ + aes_ccm_encr_start(L, nonce, a); + aes_ccm_encr(aes, L, plain, plain_len, crypt, a); + aes_ccm_encr_auth(aes, M, x, a, auth); + + aes_encrypt_deinit(aes); + + return 0; +} + + +/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */ +int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain) +{ + const size_t L = 2; + void *aes; + u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; + u8 t[AES_BLOCK_SIZE]; + + if (aad_len > 30 || M > AES_BLOCK_SIZE) + return -1; + + aes = aes_encrypt_init(key, key_len); + if (aes == NULL) + return -1; + + /* Decryption */ + aes_ccm_encr_start(L, nonce, a); + aes_ccm_decr_auth(aes, M, a, auth, t); + + /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */ + aes_ccm_encr(aes, L, crypt, crypt_len, plain, a); + + aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x); + aes_ccm_auth(aes, plain, crypt_len, x); + + aes_encrypt_deinit(aes); + + if (os_memcmp_const(x, t, M) != 0) { + wpa_printf(_MSG_EXCESSIVE_, "CCM: Auth mismatch"); + return -1; + } + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ctr.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ctr.c new file mode 100644 index 00000000..c7e235e4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-ctr.c @@ -0,0 +1,70 @@ +/* + * AES-128/192/256 CTR + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_ctr_encrypt - AES-128/192/256 CTR mode encryption + * @key: Key for encryption (key_len bytes) + * @key_len: Length of the key (16, 24, or 32 bytes) + * @nonce: Nonce for counter mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * Returns: 0 on success, -1 on failure + */ +int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, + u8 *data, size_t data_len) +{ + void *ctx; + size_t j, len, left = data_len; + int i; + u8 *pos = data; + u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; + + ctx = aes_encrypt_init(key, key_len); + if (ctx == NULL) + return -1; + os_memcpy(counter, nonce, AES_BLOCK_SIZE); + + while (left > 0) { + wpa_aes_encrypt(ctx, counter, buf); + + len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; + for (j = 0; j < len; j++) + pos[j] ^= buf[j]; + pos += len; + left -= len; + + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + counter[i]++; + if (counter[i]) + break; + } + } + aes_encrypt_deinit(ctx); + return 0; +} + + +/** + * aes_128_ctr_encrypt - AES-128 CTR mode encryption + * @key: Key for encryption (key_len bytes) + * @nonce: Nonce for counter mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * Returns: 0 on success, -1 on failure + */ +int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, + u8 *data, size_t data_len) +{ + return aes_ctr_encrypt(key, 16, nonce, data, data_len); +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-gcm.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-gcm.c new file mode 100644 index 00000000..27b4bbf0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-gcm.c @@ -0,0 +1,326 @@ +/* + * Galois/Counter Mode (GCM) and GMAC with AES + * + * Copyright (c) 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" + +static void inc32(u8 *block) +{ + u32 val; + val = WPA_GET_BE32(block + AES_BLOCK_SIZE - 4); + val++; + WPA_PUT_BE32(block + AES_BLOCK_SIZE - 4, val); +} + + +static void xor_block(u8 *dst, const u8 *src) +{ + u32 *d = (u32 *) dst; + u32 *s = (u32 *) src; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; +} + + +static void shift_right_block(u8 *v) +{ + u32 val; + + val = WPA_GET_BE32(v + 12); + val >>= 1; + if (v[11] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 12, val); + + val = WPA_GET_BE32(v + 8); + val >>= 1; + if (v[7] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 8, val); + + val = WPA_GET_BE32(v + 4); + val >>= 1; + if (v[3] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 4, val); + + val = WPA_GET_BE32(v); + val >>= 1; + WPA_PUT_BE32(v, val); +} + + +/* Multiplication in GF(2^128) */ +static void gf_mult(const u8 *x, const u8 *y, u8 *z) +{ + u8 v[16]; + int i, j; + + os_memset(z, 0, 16); /* Z_0 = 0^128 */ + os_memcpy(v, y, 16); /* V_0 = Y */ + + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) { + if (x[i] & BIT(7 - j)) { + /* Z_(i + 1) = Z_i XOR V_i */ + xor_block(z, v); + } else { + /* Z_(i + 1) = Z_i */ + } + + if (v[15] & 0x01) { + /* V_(i + 1) = (V_i >> 1) XOR R */ + shift_right_block(v); + /* R = 11100001 || 0^120 */ + v[0] ^= 0xe1; + } else { + /* V_(i + 1) = V_i >> 1 */ + shift_right_block(v); + } + } + } +} + + +static void ghash_start(u8 *y) +{ + /* Y_0 = 0^128 */ + os_memset(y, 0, 16); +} + + +static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y) +{ + size_t m, i; + const u8 *xpos = x; + u8 tmp[16]; + + m = xlen / 16; + + for (i = 0; i < m; i++) { + /* Y_i = (Y^(i-1) XOR X_i) dot H */ + xor_block(y, xpos); + xpos += 16; + + /* dot operation: + * multiplication operation for binary Galois (finite) field of + * 2^128 elements */ + gf_mult(y, h, tmp); + os_memcpy(y, tmp, 16); + } + + if (x + xlen > xpos) { + /* Add zero padded last block */ + size_t last = x + xlen - xpos; + os_memcpy(tmp, xpos, last); + os_memset(tmp + last, 0, sizeof(tmp) - last); + + /* Y_i = (Y^(i-1) XOR X_i) dot H */ + xor_block(y, tmp); + + /* dot operation: + * multiplication operation for binary Galois (finite) field of + * 2^128 elements */ + gf_mult(y, h, tmp); + os_memcpy(y, tmp, 16); + } + + /* Return Y_m */ +} + + +static void aes_gctr(void *aes, const u8 *icb, const u8 *x, size_t xlen, u8 *y) +{ + size_t i, n, last; + u8 cb[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; + const u8 *xpos = x; + u8 *ypos = y; + + if (xlen == 0) + return; + + n = xlen / 16; + + os_memcpy(cb, icb, AES_BLOCK_SIZE); + /* Full blocks */ + for (i = 0; i < n; i++) { + wpa_aes_encrypt(aes, cb, ypos); + xor_block(ypos, xpos); + xpos += AES_BLOCK_SIZE; + ypos += AES_BLOCK_SIZE; + inc32(cb); + } + + last = x + xlen - xpos; + if (last) { + /* Last, partial block */ + wpa_aes_encrypt(aes, cb, tmp); + for (i = 0; i < last; i++) + *ypos++ = *xpos++ ^ tmp[i]; + } +} + + +static void * aes_gcm_init_hash_subkey(const u8 *key, size_t key_len, u8 *H) +{ + void *aes; + + aes = aes_encrypt_init(key, key_len); + if (aes == NULL) + return NULL; + + /* Generate hash subkey H = AES_K(0^128) */ + os_memset(H, 0, AES_BLOCK_SIZE); + wpa_aes_encrypt(aes, H, H); + wpa_hexdump_key(_MSG_EXCESSIVE_, "Hash subkey H for GHASH", + H, AES_BLOCK_SIZE); + return aes; +} + + +static void aes_gcm_prepare_j0(const u8 *iv, size_t iv_len, const u8 *H, u8 *J0) +{ + u8 len_buf[16]; + + if (iv_len == 12) { + /* Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */ + os_memcpy(J0, iv, iv_len); + os_memset(J0 + iv_len, 0, AES_BLOCK_SIZE - iv_len); + J0[AES_BLOCK_SIZE - 1] = 0x01; + } else { + /* + * s = 128 * ceil(len(IV)/128) - len(IV) + * J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64) + */ + ghash_start(J0); + ghash(H, iv, iv_len, J0); + WPA_PUT_BE64(len_buf, 0); + WPA_PUT_BE64(len_buf + 8, iv_len * 8); + ghash(H, len_buf, sizeof(len_buf), J0); + } +} + + +static void aes_gcm_gctr(void *aes, const u8 *J0, const u8 *in, size_t len, + u8 *out) +{ + u8 J0inc[AES_BLOCK_SIZE]; + + if (len == 0) + return; + + os_memcpy(J0inc, J0, AES_BLOCK_SIZE); + inc32(J0inc); + aes_gctr(aes, J0inc, in, len, out); +} + + +static void aes_gcm_ghash(const u8 *H, const u8 *aad, size_t aad_len, + const u8 *crypt, size_t crypt_len, u8 *S) +{ + u8 len_buf[16]; + + /* + * u = 128 * ceil[len(C)/128] - len(C) + * v = 128 * ceil[len(A)/128] - len(A) + * S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64) + * (i.e., zero padded to block size A || C and lengths of each in bits) + */ + ghash_start(S); + ghash(H, aad, aad_len, S); + ghash(H, crypt, crypt_len, S); + WPA_PUT_BE64(len_buf, aad_len * 8); + WPA_PUT_BE64(len_buf + 8, crypt_len * 8); + ghash(H, len_buf, sizeof(len_buf), S); + + wpa_hexdump_key(_MSG_EXCESSIVE_, "S = GHASH_H(...)", S, 16); +} + + +/** + * aes_gcm_ae - GCM-AE_K(IV, P, A) + */ +int aes_gcm_ae(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, u8 *crypt, u8 *tag) +{ + u8 H[AES_BLOCK_SIZE]; + u8 J0[AES_BLOCK_SIZE]; + u8 S[16]; + void *aes; + + aes = aes_gcm_init_hash_subkey(key, key_len, H); + if (aes == NULL) + return -1; + + aes_gcm_prepare_j0(iv, iv_len, H, J0); + + /* C = GCTR_K(inc_32(J_0), P) */ + aes_gcm_gctr(aes, J0, plain, plain_len, crypt); + + aes_gcm_ghash(H, aad, aad_len, crypt, plain_len, S); + + /* T = MSB_t(GCTR_K(J_0, S)) */ + aes_gctr(aes, J0, S, sizeof(S), tag); + + /* Return (C, T) */ + + aes_encrypt_deinit(aes); + + return 0; +} + + +/** + * aes_gcm_ad - GCM-AD_K(IV, C, A, T) + */ +int aes_gcm_ad(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *tag, u8 *plain) +{ + u8 H[AES_BLOCK_SIZE]; + u8 J0[AES_BLOCK_SIZE]; + u8 S[16], T[16]; + void *aes; + + aes = aes_gcm_init_hash_subkey(key, key_len, H); + if (aes == NULL) + return -1; + + aes_gcm_prepare_j0(iv, iv_len, H, J0); + + /* P = GCTR_K(inc_32(J_0), C) */ + aes_gcm_gctr(aes, J0, crypt, crypt_len, plain); + + aes_gcm_ghash(H, aad, aad_len, crypt, crypt_len, S); + + /* T' = MSB_t(GCTR_K(J_0, S)) */ + aes_gctr(aes, J0, S, sizeof(S), T); + + aes_encrypt_deinit(aes); + + if (os_memcmp_const(tag, T, 16) != 0) { + wpa_printf(_MSG_EXCESSIVE_, "GCM: Tag mismatch"); + return -1; + } + + return 0; +} + + +int aes_gmac(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *aad, size_t aad_len, u8 *tag) +{ + return aes_gcm_ae(key, key_len, iv, iv_len, NULL, 0, aad, aad_len, NULL, + tag); +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal-enc.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal-enc.c new file mode 100644 index 00000000..c5521b87 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal-enc.c @@ -0,0 +1,129 @@ +/* + * AES (Rijndael) cipher - encrypt + * + * Modifications to public domain implementation: + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes_i.h" + +static void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; + +#define ROUND(i,d,s) \ +d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ +d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ +d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ +d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] + +#ifdef FULL_UNROLL + + ROUND(1,t,s); + ROUND(2,s,t); + ROUND(3,t,s); + ROUND(4,s,t); + ROUND(5,t,s); + ROUND(6,s,t); + ROUND(7,t,s); + ROUND(8,s,t); + ROUND(9,t,s); + if (Nr > 10) { + ROUND(10,s,t); + ROUND(11,t,s); + if (Nr > 12) { + ROUND(12,s,t); + ROUND(13,t,s); + } + } + + rk += Nr << 2; + +#else /* !FULL_UNROLL */ + + /* Nr - 1 full rounds: */ + r = Nr >> 1; + for (;;) { + ROUND(1,t,s); + rk += 8; + if (--r == 0) + break; + ROUND(0,s,t); + } + +#endif /* ?FULL_UNROLL */ + +#undef ROUND + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; + PUTU32(ct , s0); + s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; + PUTU32(ct + 4, s1); + s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; + PUTU32(ct + 8, s2); + s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; + PUTU32(ct + 12, s3); +} + + +void * aes_encrypt_init(const u8 *key, size_t len) +{ + u32 *rk; + int res; + + if (TEST_FAIL()) + return NULL; + + rk = os_malloc(AES_PRIV_SIZE); + if (rk == NULL) + return NULL; + res = rijndaelKeySetupEnc(rk, key, len * 8); + if (res < 0) { + rtw_mfree(rk, AES_PRIV_SIZE); + return NULL; + } + rk[AES_PRIV_NR_POS] = res; + return rk; +} + + +int wpa_aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + u32 *rk = ctx; + rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); + return 0; +} + + +void aes_encrypt_deinit(void *ctx) +{ + os_memset(ctx, 0, AES_PRIV_SIZE); + rtw_mfree(ctx, AES_PRIV_SIZE); +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal.c new file mode 100644 index 00000000..57d65394 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-internal.c @@ -0,0 +1,843 @@ +/* + * AES (Rijndael) cipher + * + * Modifications to public domain implementation: + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes_i.h" + +/* + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +#ifndef AES_SMALL_TABLES +const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +#endif /* AES_SMALL_TABLES */ +const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +#ifndef AES_SMALL_TABLES +const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; +#else /* AES_SMALL_TABLES */ +const u8 Td4s[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +const u8 rcons[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; +#endif /* AES_SMALL_TABLES */ +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits) +{ + int i; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + + if (keyBits == 128) { + for (i = 0; i < 10; i++) { + temp = rk[3]; + rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + rk += 4; + } + return 10; + } + + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + + if (keyBits == 192) { + for (i = 0; i < 8; i++) { + temp = rk[5]; + rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + if (i == 7) + return 12; + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + rk += 6; + } + } + + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + + if (keyBits == 256) { + for (i = 0; i < 7; i++) { + temp = rk[7]; + rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + if (i == 6) + return 14; + temp = rk[11]; + rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^ + TE433(temp) ^ TE444(temp); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + rk += 8; + } + } + + return -1; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-omac1.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-omac1.c new file mode 100644 index 00000000..c55645fb --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-omac1.c @@ -0,0 +1,172 @@ +/* + * One-key CBC MAC (OMAC1) hash with AES + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" + +static void gf_mulx(u8 *pad) +{ + int i, carry; + + carry = pad[0] & 0x80; + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[AES_BLOCK_SIZE - 1] <<= 1; + if (carry) + pad[AES_BLOCK_SIZE - 1] ^= 0x87; +} + + +/** + * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES + * @key: Key for the hash operation + * @key_len: Key length in octets + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + void *ctx; + u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; + const u8 *pos, *end; + size_t i, e, left, total_len; + + if (TEST_FAIL()) + return -1; + + ctx = aes_encrypt_init(key, key_len); + if (ctx == NULL) + return -1; + os_memset(cbc, 0, AES_BLOCK_SIZE); + + total_len = 0; + for (e = 0; e < num_elem; e++) + total_len += len[e]; + left = total_len; + + e = 0; + pos = addr[0]; + end = pos + len[0]; + + while (left >= AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + /* + * Stop if there are no more bytes to process + * since there are no more entries in the array. + */ + if (i + 1 == AES_BLOCK_SIZE && + left == AES_BLOCK_SIZE) + break; + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + if (left > AES_BLOCK_SIZE) + wpa_aes_encrypt(ctx, cbc, cbc); + left -= AES_BLOCK_SIZE; + } + + os_memset(pad, 0, AES_BLOCK_SIZE); + wpa_aes_encrypt(ctx, pad, pad); + gf_mulx(pad); + + if (left || total_len == 0) { + for (i = 0; i < left; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + /* + * Stop if there are no more bytes to process + * since there are no more entries in the array. + */ + if (i + 1 == left) + break; + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + cbc[left] ^= 0x80; + gf_mulx(pad); + } + + for (i = 0; i < AES_BLOCK_SIZE; i++) + pad[i] ^= cbc[i]; + wpa_aes_encrypt(ctx, pad, mac); + aes_encrypt_deinit(ctx); + return 0; +} + + +/** + * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 + * @key: 128-bit key for the hash operation + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); +} + + +/** + * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) + * @key: 128-bit key for the hash operation + * @data: Data buffer for which a MAC is determined + * @data_len: Length of data buffer in bytes + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_128_vector(key, 1, &data, &data_len, mac); +} + + +/** + * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC) + * @key: 256-bit key for the hash operation + * @data: Data buffer for which a MAC is determined + * @data_len: Length of data buffer in bytes + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-siv.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-siv.c new file mode 100644 index 00000000..58656f2b --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes-siv.c @@ -0,0 +1,207 @@ +/* + * AES SIV (RFC 5297) + * Copyright (c) 2013 Cozybit, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" +#include "aes_siv.h" + + +static const u8 zero[AES_BLOCK_SIZE]; + + +static void dbl(u8 *pad) +{ + int i, carry; + + carry = pad[0] & 0x80; + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[AES_BLOCK_SIZE - 1] <<= 1; + if (carry) + pad[AES_BLOCK_SIZE - 1] ^= 0x87; +} + + +static void xor(u8 *a, const u8 *b) +{ + int i; + + for (i = 0; i < AES_BLOCK_SIZE; i++) + *a++ ^= *b++; +} + + +static void xorend(u8 *a, int alen, const u8 *b, int blen) +{ + int i; + + if (alen < blen) + return; + + for (i = 0; i < blen; i++) + a[alen - blen + i] ^= b[i]; +} + + +static void pad_block(u8 *pad, const u8 *addr, size_t len) +{ + os_memset(pad, 0, AES_BLOCK_SIZE); + os_memcpy(pad, addr, len); + + if (len < AES_BLOCK_SIZE) + pad[len] = 0x80; +} + + +static int aes_s2v(const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], size_t *len, u8 *mac) +{ + u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; + u8 *buf = NULL; + int ret; + size_t i; + const u8 *data[1]; + size_t data_len[1]; + + if (!num_elem) { + os_memcpy(tmp, zero, sizeof(zero)); + tmp[AES_BLOCK_SIZE - 1] = 1; + data[0] = tmp; + data_len[0] = sizeof(tmp); + return omac1_aes_vector(key, key_len, 1, data, data_len, mac); + } + + data[0] = zero; + data_len[0] = sizeof(zero); + ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp); + if (ret) + return ret; + + for (i = 0; i < num_elem - 1; i++) { + ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i], + tmp2); + if (ret) + return ret; + + dbl(tmp); + xor(tmp, tmp2); + } + if (len[i] >= AES_BLOCK_SIZE) { + buf = os_memdup(addr[i], len[i]); + if (!buf) + return -ENOMEM; + + xorend(buf, len[i], tmp, AES_BLOCK_SIZE); + data[0] = buf; + ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac); + bin_clear_free(buf, len[i]); + return ret; + } + + dbl(tmp); + pad_block(tmp2, addr[i], len[i]); + xor(tmp, tmp2); + + data[0] = tmp; + data_len[0] = sizeof(tmp); + return omac1_aes_vector(key, key_len, 1, data, data_len, mac); +} + + +int aes_siv_encrypt(const u8 *key, size_t key_len, + const u8 *pw, size_t pwlen, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out) +{ + const u8 *_addr[6]; + size_t _len[6]; + const u8 *k1, *k2; + u8 v[AES_BLOCK_SIZE]; + size_t i; + u8 *iv, *crypt_pw; + + if (num_elem > ARRAY_SIZE(_addr) - 1 || + (key_len != 32 && key_len != 48 && key_len != 64)) + return -1; + + key_len /= 2; + k1 = key; + k2 = key + key_len; + + for (i = 0; i < num_elem; i++) { + _addr[i] = addr[i]; + _len[i] = len[i]; + } + _addr[num_elem] = pw; + _len[num_elem] = pwlen; + + if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v)) + return -1; + + iv = out; + crypt_pw = out + AES_BLOCK_SIZE; + + os_memcpy(iv, v, AES_BLOCK_SIZE); + os_memcpy(crypt_pw, pw, pwlen); + + /* zero out 63rd and 31st bits of ctr (from right) */ + v[8] &= 0x7f; + v[12] &= 0x7f; + return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen); +} + + +int aes_siv_decrypt(const u8 *key, size_t key_len, + const u8 *iv_crypt, size_t iv_c_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out) +{ + const u8 *_addr[6]; + size_t _len[6]; + const u8 *k1, *k2; + size_t crypt_len; + size_t i; + int ret; + u8 iv[AES_BLOCK_SIZE]; + u8 check[AES_BLOCK_SIZE]; + + if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 || + (key_len != 32 && key_len != 48 && key_len != 64)) + return -1; + crypt_len = iv_c_len - AES_BLOCK_SIZE; + key_len /= 2; + k1 = key; + k2 = key + key_len; + + for (i = 0; i < num_elem; i++) { + _addr[i] = addr[i]; + _len[i] = len[i]; + } + _addr[num_elem] = out; + _len[num_elem] = crypt_len; + + os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE); + os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len); + + iv[8] &= 0x7f; + iv[12] &= 0x7f; + + ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len); + if (ret) + return ret; + + ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check); + if (ret) + return ret; + if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0) + return 0; + + return -1; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes.h new file mode 100644 index 00000000..d105d54d --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes.h @@ -0,0 +1,21 @@ +/* + * AES functions + * Copyright (c) 2003-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_H +#define AES_H + +#define AES_BLOCK_SIZE 16 + +void * aes_encrypt_init(const u8 *key, size_t len); +int wpa_aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); +void aes_encrypt_deinit(void *ctx); +void * aes_decrypt_init(const u8 *key, size_t len); +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); +void aes_decrypt_deinit(void *ctx); + +#endif /* AES_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_i.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_i.h new file mode 100644 index 00000000..54375cf3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_i.h @@ -0,0 +1,125 @@ +/* + * AES (Rijndael) cipher + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_I_H +#define AES_I_H + +#include "aes.h" + +/* #define FULL_UNROLL */ +#define AES_SMALL_TABLES + +extern const u32 Te0[256]; +extern const u32 Te1[256]; +extern const u32 Te2[256]; +extern const u32 Te3[256]; +extern const u32 Te4[256]; +extern const u32 Td0[256]; +extern const u32 Td1[256]; +extern const u32 Td2[256]; +extern const u32 Td3[256]; +extern const u32 Td4[256]; +extern const u32 rcon[10]; +extern const u8 Td4s[256]; +extern const u8 rcons[10]; + +#ifndef AES_SMALL_TABLES + +#define RCON(i) rcon[(i)] + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) Te1[((i) >> 16) & 0xff] +#define TE2(i) Te2[((i) >> 8) & 0xff] +#define TE3(i) Te3[(i) & 0xff] +#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) +#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) +#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) +#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) +#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) +#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) +#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff) +#define TE4(i) (Te4[(i)] & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) Td1[((i) >> 16) & 0xff] +#define TD2(i) Td2[((i) >> 8) & 0xff] +#define TD3(i) Td3[(i) & 0xff] +#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) +#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) Td1[(i) & 0xff] +#define TD2_(i) Td2[(i) & 0xff] +#define TD3_(i) Td3[(i) & 0xff] + +#else /* AES_SMALL_TABLES */ + +#define RCON(i) (rcons[(i)] << 24) + +static inline u32 rotr(u32 val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) +#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) +#define TE3(i) rotr(Te0[(i) & 0xff], 24) +#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) +#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) +#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) +#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) +#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) +#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) +#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) +#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) +#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) +#define TD3(i) rotr(Td0[(i) & 0xff], 24) +#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) +#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) +#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) +#define TD44(i) (Td4s[(i) & 0xff]) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) rotr(Td0[(i) & 0xff], 8) +#define TD2_(i) rotr(Td0[(i) & 0xff], 16) +#define TD3_(i) rotr(Td0[(i) & 0xff], 24) + +#endif /* AES_SMALL_TABLES */ + +#ifdef _MSC_VER +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ +((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { \ +(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ +(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +#define AES_PRIV_SIZE (4 * 4 * 15 + 4) +#define AES_PRIV_NR_POS (4 * 15) + +int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits); + +#endif /* AES_I_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_siv.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_siv.h new file mode 100644 index 00000000..fb05d80c --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_siv.h @@ -0,0 +1,21 @@ +/* + * AES SIV (RFC 5297) + * Copyright (c) 2013 Cozybit, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_SIV_H +#define AES_SIV_H + +int aes_siv_encrypt(const u8 *key, size_t key_len, + const u8 *pw, size_t pwlen, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out); +int aes_siv_decrypt(const u8 *key, size_t key_len, + const u8 *iv_crypt, size_t iv_c_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out); + +#endif /* AES_SIV_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_wrap.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_wrap.h new file mode 100644 index 00000000..b70b1d26 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/aes_wrap.h @@ -0,0 +1,73 @@ +/* + * AES-based functions + * + * - AES Key Wrap Algorithm (RFC3394) + * - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256 + * - AES-128/192/256 CTR mode encryption + * - AES-128 EAX mode encryption/decryption + * - AES-128 CBC + * - AES-GCM + * - AES-CCM + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_WRAP_H +#define AES_WRAP_H + +int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, + u8 *cipher); +int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n, + const u8 *cipher, u8 *plain); +int __must_check omac1_aes_vector(const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, + u8 *mac); +int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, + u8 *mac); +int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, + u8 *mac); +int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); +int __must_check aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, + u8 *data, size_t data_len); +int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, + u8 *data, size_t data_len); +int __must_check aes_128_eax_encrypt(const u8 *key, + const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, u8 *tag); +int __must_check aes_128_eax_decrypt(const u8 *key, + const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, const u8 *tag); +int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +int __must_check aes_gcm_ae(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, + u8 *crypt, u8 *tag); +int __must_check aes_gcm_ad(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *tag, + u8 *plain); +int __must_check aes_gmac(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *aad, size_t aad_len, u8 *tag); +int __must_check aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth); +int __must_check aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *auth, + u8 *plain); + +#endif /* AES_WRAP_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/ccmp.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/ccmp.c new file mode 100755 index 00000000..13975e14 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/ccmp.c @@ -0,0 +1,510 @@ +/* + * CTR with CBC-MAC Protocol (CCMP) + * Copyright (c) 2010-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" +#include "wlancrypto_wrap.h" + + + +static void ccmp_aad_nonce(_adapter *padapter, const struct ieee80211_hdr *hdr, const u8 *data, + u8 *aad, size_t *aad_len, u8 *nonce) +{ + u16 fc, stype, seq; + int qos = 0, addr4 = 0; + u8 *pos; + + nonce[0] = 0; + + fc = le_to_host16(hdr->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == + (WLAN_FC_TODS | WLAN_FC_FROMDS)) + addr4 = 1; + + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { + fc &= ~0x0070; /* Mask subtype bits */ + if (stype & WLAN_FC_STYPE_QOS_DATA) { + const u8 *qc; + qos = 1; + fc &= ~WLAN_FC_ORDER; + qc = (const u8 *)hdr + 24; + if (addr4) + qc += ETH_ALEN; + nonce[0] = qc[0] & 0x0f; + } + } else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) + nonce[0] |= 0x10; /* Management */ + + fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); + fc |= WLAN_FC_ISWEP; + WPA_PUT_LE16(aad, fc); + pos = aad + 2; + os_memcpy(pos, GetAddr1Ptr((u8 *)hdr), 3 * ETH_ALEN); + pos += 3 * ETH_ALEN; + seq = le_to_host16(hdr->seq_ctrl); + seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ + WPA_PUT_LE16(pos, seq); + pos += 2; + + os_memcpy(pos, (u8 *)hdr + 24, addr4 * ETH_ALEN + qos * 2); + pos += addr4 * ETH_ALEN; + if (qos) { + pos[0] &= ~0x70; + /* only spp mode need to refer QoS bit7 */ + if (padapter->registrypriv.amsdu_mode != RTW_AMSDU_MODE_SPP) + pos[0] &= ~0x80; + pos++; + *pos++ = 0x00; + } + + *aad_len = pos - aad; + + os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN); + nonce[7] = data[7]; /* PN5 */ + nonce[8] = data[6]; /* PN4 */ + nonce[9] = data[5]; /* PN3 */ + nonce[10] = data[4]; /* PN2 */ + nonce[11] = data[1]; /* PN1 */ + nonce[12] = data[0]; /* PN0 */ +} + + +static void ccmp_aad_nonce_pv1(const u8 *hdr, const u8 *a1, const u8 *a2, + const u8 *a3, const u8 *pn, + u8 *aad, size_t *aad_len, u8 *nonce) +{ + u16 fc, type; + u8 *pos; + + nonce[0] = BIT(5); /* PV1 */ + /* TODO: Priority for QMF; 0 is used for Data frames */ + + fc = WPA_GET_LE16(hdr); + type = (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2; + + if (type == 1) + nonce[0] |= 0x10; /* Management */ + + fc &= ~(BIT(10) | BIT(11) | BIT(13) | BIT(14) | BIT(15)); + fc |= BIT(12); + WPA_PUT_LE16(aad, fc); + pos = aad + 2; + if (type == 0 || type == 3) { + const u8 *sc; + + os_memcpy(pos, a1, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, a2, ETH_ALEN); + pos += ETH_ALEN; + + if (type == 0) { + /* Either A1 or A2 contains SID */ + sc = hdr + 2 + 2 + ETH_ALEN; + } else { + /* Both A1 and A2 contain full addresses */ + sc = hdr + 2 + 2 * ETH_ALEN; + } + /* SC with Sequence Number subfield (bits 4-15 of the Sequence + * Control field) masked to 0. */ + *pos++ = *sc & 0x0f; + *pos++ = 0; + + if (a3) { + os_memcpy(pos, a3, ETH_ALEN); + pos += ETH_ALEN; + } + } + + *aad_len = pos - aad; + + os_memcpy(nonce + 1, a2, ETH_ALEN); + nonce[7] = pn[5]; /* PN5 */ + nonce[8] = pn[4]; /* PN4 */ + nonce[9] = pn[3]; /* PN3 */ + nonce[10] = pn[2]; /* PN2 */ + nonce[11] = pn[1]; /* PN1 */ + nonce[12] = pn[0]; /* PN0 */ +} + + +u8 * ccmp_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len; + size_t mlen; + u8 *plain; + + if (data_len < 8 + 8) + return NULL; + + plain = os_malloc(data_len + AES_BLOCK_SIZE); + if (plain == NULL) + return NULL; + + mlen = data_len - 8 - 8; + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, 13); + + if (aes_ccm_ad(tk, 16, nonce, 8, data + 8, mlen, aad, aad_len, + data + 8 + mlen, plain) < 0) { + u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); + wpa_printf(_MSG_INFO_, "Invalid CCMP MIC in frame: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", + MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), + MAC2STR(hdr->addr3), + WLAN_GET_SEQ_SEQ(seq_ctrl), + WLAN_GET_SEQ_FRAG(seq_ctrl)); + rtw_mfree(plain, data_len + AES_BLOCK_SIZE); + return NULL; + } + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP decrypted", plain, mlen); + + *decrypted_len = mlen; + return plain; +} + + +void ccmp_get_pn(u8 *pn, const u8 *data) +{ + pn[0] = data[7]; /* PN5 */ + pn[1] = data[6]; /* PN4 */ + pn[2] = data[5]; /* PN3 */ + pn[3] = data[4]; /* PN2 */ + pn[4] = data[1]; /* PN1 */ + pn[5] = data[0]; /* PN0 */ +} + + +u8 * ccmp_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, + u8 *pn, int keyid, size_t *encrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len, plen; + u8 *crypt, *pos, *pdata; + struct ieee80211_hdr *hdr; + + if (len < hdrlen || hdrlen < 24) + return NULL; + plen = len - hdrlen; + + crypt = os_malloc(hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE); + if (crypt == NULL) + return NULL; + + if (pn == NULL) { + os_memcpy(crypt, frame, hdrlen + 8); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen + 8; + pdata = frame + hdrlen + 8; + } else { + os_memcpy(crypt, frame, hdrlen); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen; + *pos++ = pn[5]; /* PN0 */ + *pos++ = pn[4]; /* PN1 */ + *pos++ = 0x00; /* Rsvd */ + *pos++ = 0x20 | (keyid << 6); + *pos++ = pn[3]; /* PN2 */ + *pos++ = pn[2]; /* PN3 */ + *pos++ = pn[1]; /* PN4 */ + *pos++ = pn[0]; /* PN5 */ + pdata = frame + hdrlen; + } + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, 13); + + if (aes_ccm_ae(tk, 16, nonce, 8, pdata, plen, aad, aad_len, + pos, pos + plen) < 0) { + rtw_mfree(crypt, hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE); + return NULL; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP encrypted", crypt + hdrlen + 8, plen); + + *encrypted_len = hdrlen + 8 + plen + 8; + + return crypt; +} + + +u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3, + const u8 *frame, size_t len, + size_t hdrlen, const u8 *pn, int keyid, + size_t *encrypted_len) +{ + u8 aad[24], nonce[13]; + size_t aad_len, plen; + u8 *crypt, *pos; + struct ieee80211_hdr *hdr; + + if (len < hdrlen || hdrlen < 12) + return NULL; + plen = len - hdrlen; + + crypt = os_malloc(hdrlen + plen + 8 + AES_BLOCK_SIZE); + if (crypt == NULL) + return NULL; + + os_memcpy(crypt, frame, hdrlen); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(BIT(12)); /* Protected Frame */ + pos = crypt + hdrlen; + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce_pv1(crypt, a1, a2, a3, pn, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, sizeof(nonce)); + + if (aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, plen, aad, aad_len, + pos, pos + plen) < 0) { + rtw_mfree(crypt, hdrlen + plen + 8 + AES_BLOCK_SIZE); + return NULL; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP encrypted", crypt + hdrlen, plen); + + *encrypted_len = hdrlen + plen + 8; + + return crypt; +} + + +u8 * ccmp_256_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len; + size_t mlen; + u8 *plain; + + if (data_len < 8 + 16) + return NULL; + + plain = os_malloc(data_len + AES_BLOCK_SIZE); + if (plain == NULL) + return NULL; + + mlen = data_len - 8 - 16; + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 nonce", nonce, 13); + + if (aes_ccm_ad(tk, 32, nonce, 16, data + 8, mlen, aad, aad_len, + data + 8 + mlen, plain) < 0) { + u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); + wpa_printf(_MSG_INFO_, "Invalid CCMP-256 MIC in frame: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", + MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), + MAC2STR(hdr->addr3), + WLAN_GET_SEQ_SEQ(seq_ctrl), + WLAN_GET_SEQ_FRAG(seq_ctrl)); + rtw_mfree(plain, data_len + AES_BLOCK_SIZE); + return NULL; + } + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 decrypted", plain, mlen); + + *decrypted_len = mlen; + return plain; +} + + +u8 * ccmp_256_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len, plen; + u8 *crypt, *pos, *pdata; + struct ieee80211_hdr *hdr; + + if (len < hdrlen || hdrlen < 24) + return NULL; + plen = len - hdrlen; + + crypt = os_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE); + if (crypt == NULL) + return NULL; + + if (pn == NULL) { + os_memcpy(crypt, frame, hdrlen + 8); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen + 8; + pdata = frame + hdrlen + 8; + } else { + os_memcpy(crypt, frame, hdrlen); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen; + *pos++ = pn[5]; /* PN0 */ + *pos++ = pn[4]; /* PN1 */ + *pos++ = 0x00; /* Rsvd */ + *pos++ = 0x20 | (keyid << 6); + *pos++ = pn[3]; /* PN2 */ + *pos++ = pn[2]; /* PN3 */ + *pos++ = pn[1]; /* PN4 */ + *pos++ = pn[0]; /* PN5 */ + pdata = frame + hdrlen; + } + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 nonce", nonce, 13); + + if (aes_ccm_ae(tk, 32, nonce, 16, pdata, plen, aad, aad_len, + pos, pos + plen) < 0) { + rtw_mfree(crypt, hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE); + return NULL; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 encrypted", crypt + hdrlen + 8, + plen); + + *encrypted_len = hdrlen + 8 + plen + 16; + + return crypt; +} + +#if 0 //RTW_PHL_TX: mark un-finished codes for reading +void core_ccmp_encrypt(const u8 *tk, uint hdrlen, u8 *phdr, uint datalen, u8 *pdata, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len; + u8 *crypt, *pos; + struct ieee80211_hdr *hdr; + size_t enc_hdrlen, enc_datalen = 0; + + if (hdrlen < 24) + return; + + enc_hdrlen = hdrlen + 8; + enc_datalen = datalen + 8; + + crypt = os_malloc(enc_hdrlen + enc_hdrlen + AES_BLOCK_SIZE); + if (crypt == NULL) + return; + + if (pn == NULL) { + os_memcpy(crypt, phdr, hdrlen + 8); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen + 8; + } else { + os_memcpy(crypt, phdr, hdrlen); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen; + *pos++ = pn[5]; /* PN0 */ + *pos++ = pn[4]; /* PN1 */ + *pos++ = 0x00; /* Rsvd */ + *pos++ = 0x20 | (keyid << 6); + *pos++ = pn[3]; /* PN2 */ + *pos++ = pn[2]; /* PN3 */ + *pos++ = pn[1]; /* PN4 */ + *pos++ = pn[0]; /* PN5 */ + } + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, 13); + + if (aes_ccm_ae(tk, 16, nonce, 8, pdata, datalen, aad, aad_len, + pos, pos + datalen) < 0) { + rtw_mfree(crypt, hdrlen + 8 + datalen + 8 + AES_BLOCK_SIZE); + return; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP encrypted", crypt + enc_hdrlen, datalen); + + /* Copy @enc back to @frame and free @enc */ + _rtw_memcpy(phdr, crypt, enc_hdrlen); + _rtw_memcpy(pdata, crypt + enc_hdrlen, enc_datalen); + + rtw_mfree(crypt, enc_hdrlen+enc_datalen+AES_BLOCK_SIZE); + + return; +} + + +void core_ccmp_256_encrypt(const u8 *tk, uint hdrlen, u8 *phdr, uint datalen, u8 *pdata, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len) +{ + u8 aad[30], nonce[13]; + size_t aad_len; + u8 *crypt, *pos; + struct ieee80211_hdr *hdr; + size_t enc_hdrlen, enc_datalen = 0; + + if (hdrlen < 24) + return; + + enc_hdrlen = hdrlen + 8; + enc_datalen = datalen + 16; + + crypt = os_malloc(enc_hdrlen + enc_hdrlen + AES_BLOCK_SIZE); + + if (crypt == NULL) + return; + + if (pn == NULL) { + os_memcpy(crypt, phdr, hdrlen + 8); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen + 8; + } else { + os_memcpy(crypt, phdr, hdrlen); + hdr = (struct ieee80211_hdr *) crypt; + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); + pos = crypt + hdrlen; + *pos++ = pn[5]; /* PN0 */ + *pos++ = pn[4]; /* PN1 */ + *pos++ = 0x00; /* Rsvd */ + *pos++ = 0x20 | (keyid << 6); + *pos++ = pn[3]; /* PN2 */ + *pos++ = pn[2]; /* PN3 */ + *pos++ = pn[1]; /* PN4 */ + *pos++ = pn[0]; /* PN5 */ + } + + os_memset(aad, 0, sizeof(aad)); + ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 nonce", nonce, 13); + + if (aes_ccm_ae(tk, 32, nonce, 16, pdata, datalen, aad, aad_len, + pos, pos + datalen) < 0) { + rtw_mfree(crypt, enc_hdrlen + enc_datalen + AES_BLOCK_SIZE); + return; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 encrypted", crypt + enc_hdrlen, datalen); + + _rtw_memcpy(phdr, crypt, enc_hdrlen); + _rtw_memcpy(pdata, crypt + enc_hdrlen, enc_datalen); + + rtw_mfree(crypt, enc_hdrlen+enc_datalen+AES_BLOCK_SIZE); +} + + +#endif diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/gcmp.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/gcmp.c new file mode 100644 index 00000000..9141d552 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/gcmp.c @@ -0,0 +1,194 @@ +/* + * GCM with GMAC Protocol (GCMP) + * Copyright (c) 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "aes.h" +#include "aes_wrap.h" +#include "wlancrypto_wrap.h" + + +static void gcmp_aad_nonce(_adapter * padapter, const struct ieee80211_hdr *hdr, const u8 *data, + u8 *aad, size_t *aad_len, u8 *nonce) +{ + u16 fc, stype, seq; + int qos = 0, addr4 = 0; + u8 *pos; + + fc = le_to_host16(hdr->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == + (WLAN_FC_TODS | WLAN_FC_FROMDS)) + addr4 = 1; + + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { + fc &= ~0x0070; /* Mask subtype bits */ + if (stype & WLAN_FC_STYPE_QOS_DATA) { + const u8 *qc; + qos = 1; + fc &= ~WLAN_FC_ORDER; + qc = (const u8 *)hdr + 24; + if (addr4) + qc += ETH_ALEN; + } + } + + fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); + WPA_PUT_LE16(aad, fc); + pos = aad + 2; + os_memcpy(pos, GetAddr1Ptr((u8 *)hdr), 3 * ETH_ALEN); + pos += 3 * ETH_ALEN; + seq = le_to_host16(hdr->seq_ctrl); + seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ + WPA_PUT_LE16(pos, seq); + pos += 2; + + wpa_printf(_MSG_INFO_, "pos - aad = %u, qos(%d)\n", (pos - aad), qos); + + os_memcpy(pos, (u8 *)hdr + 24, addr4 * ETH_ALEN + qos * 2); + pos += addr4 * ETH_ALEN; + if (qos) { + pos[0] &= ~0x70; + /* only spp mode need to refer QoS bit7 */ + if (padapter->registrypriv.amsdu_mode != RTW_AMSDU_MODE_SPP) + pos[0] &= ~0x80; + pos++; + *pos++ = 0x00; + } + + wpa_printf(_MSG_INFO_, "pos - aad = %u\n", (pos - aad)); + *aad_len = pos - aad; + + os_memcpy(nonce, hdr->addr2, ETH_ALEN); + nonce[6] = data[7]; /* PN5 */ + nonce[7] = data[6]; /* PN4 */ + nonce[8] = data[5]; /* PN3 */ + nonce[9] = data[4]; /* PN2 */ + nonce[10] = data[1]; /* PN1 */ + nonce[11] = data[0]; /* PN0 */ +} + +/** + * gcmp_decrypt - + * @tk: the temporal key + * @tk_len: length of @tk + * @hdr: the mac header + * @data: payload after mac header (PN + enc_data + MIC) + * @data_len: length of @data (PN + enc_data + MIC) + * @decrypted_len: length of the data decrypted + */ +u8 * gcmp_decrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len) +{ + u8 aad[30], nonce[12], *plain; + size_t aad_len, mlen; + const u8 *m; + + if (data_len < 8 + 16) + return NULL; + + plain = os_malloc(data_len + AES_BLOCK_SIZE); + if (plain == NULL) + return NULL; + + m = data + 8; + mlen = data_len - 8 - 16; + + os_memset(aad, 0, sizeof(aad)); + gcmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP nonce", nonce, sizeof(nonce)); + + if (aes_gcm_ad(tk, tk_len, nonce, sizeof(nonce), m, mlen, aad, aad_len, + m + mlen, plain) < 0) { + u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); + wpa_printf(_MSG_INFO_, "Invalid GCMP frame: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", + MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), + MAC2STR(hdr->addr3), + WLAN_GET_SEQ_SEQ(seq_ctrl), + WLAN_GET_SEQ_FRAG(seq_ctrl)); + rtw_mfree(plain, data_len + AES_BLOCK_SIZE); + return NULL; + } + + *decrypted_len = mlen; + return plain; +} + +/** + * gcmp_encrypt - + * @tk: the temporal key + * @tk_len: length of @tk + * @frame: the point to mac header, the frame including mac header and payload, + * if @pn is NULL, then the frame including pn + * @len: length of @frame + * length = mac header + payload + * @hdrlen: length of the mac header + * @qos: pointer to the QOS field of the frame + * @pn: packet number + * @keyid: key id + * @encrypted_len: length of the encrypted frame + * including mac header, pn, payload and MIC + */ +u8 * gcmp_encrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const u8 *frame, size_t len, + size_t hdrlen, const u8 *qos, + const u8 *pn, int keyid, size_t *encrypted_len) +{ + u8 aad[30], nonce[12], *crypt, *pos; + const u8 *pdata; + size_t aad_len, plen; + struct ieee80211_hdr *hdr; + + if (len < hdrlen || hdrlen < 24) + return NULL; + plen = len - hdrlen; + + crypt = os_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE); + if (crypt == NULL) + return NULL; + + if (pn == NULL) { + os_memcpy(crypt, frame, hdrlen + 8); + hdr = (struct ieee80211_hdr *)crypt; + pos = crypt + hdrlen + 8; + pdata = frame + hdrlen + 8; + } else { + os_memcpy(crypt, frame, hdrlen); + hdr = (struct ieee80211_hdr *)crypt; + pos = crypt + hdrlen; + + *pos++ = pn[5]; /* PN0 */ + *pos++ = pn[4]; /* PN1 */ + *pos++ = 0x00; /* Rsvd */ + *pos++ = 0x20 | (keyid << 6); + *pos++ = pn[3]; /* PN2 */ + *pos++ = pn[2]; /* PN3 */ + *pos++ = pn[1]; /* PN4 */ + *pos++ = pn[0]; /* PN5 */ + pdata = frame + hdrlen; + } + + os_memset(aad, 0, sizeof(aad)); + gcmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce); + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP AAD", aad, aad_len); + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP nonce", nonce, sizeof(nonce)); + + if (aes_gcm_ae(tk, tk_len, nonce, sizeof(nonce), pdata, plen, + aad, aad_len, pos, pos + plen) < 0) { + rtw_mfree(crypt, hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE); + return NULL; + } + + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP MIC", pos + plen, 16); + wpa_hexdump(_MSG_EXCESSIVE_, "GCMP encrypted", pos, plen); + + *encrypted_len = hdrlen + 8 + plen + 16; + + return crypt; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.c new file mode 100644 index 00000000..8fdb3c90 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.c @@ -0,0 +1,85 @@ +#include "rtw_crypto_wrap.h" + +#ifndef DEBUG_CRYPTO +#define DEBUG_CRYPTO 0 +#endif /* DEBUG_CRYTO */ + +int os_memcmp(const void *s1, const void *s2, size_t n) +{ + return _rtw_memcmp2(s1, s2, n); +} + +int os_memcmp_const(const void *a, const void *b, size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + size_t i; + u8 res; + + for (res = 0, i = 0; i < len; i++) + res |= aa[i] ^ bb[i]; + + return res; +} + +void* os_memdup(const void *src, u32 sz) +{ + void *r = rtw_malloc(sz); + + if (r && src) + _rtw_memcpy(r, src, sz); + return r; +} + +size_t os_strlen(const char *s) +{ + const char *p = s; + while (*p) + p++; + return p - s; +} + + +void forced_memzero(void *ptr, size_t len) +{ + _rtw_memset(ptr, 0, len); +} + +void bin_clear_free(void *bin, size_t len) +{ + if (bin) { + forced_memzero(bin, len); + rtw_mfree(bin, len); + } +} + +void wpa_printf(int level, const char *fmt, ...) +{ +#if DEBUG_CRYPTO +#define MSG_LEN 100 + va_list args; + u8 buf[MSG_LEN] = { 0 }; + int err; + + va_start(args, fmt); + err = vsnprintf(buf, MSG_LEN, fmt, args); + va_end(args); + + RTW_INFO("%s", buf); +#undef MSG_LEN +#endif /* DEBUG_CRYPTO */ +} + +void wpa_hexdump(int level, const char *title, const void *buf, size_t len) +{ +#if DEBUG_CRYPTO + RTW_INFO_DUMP((u8 *)title, buf, len); +#endif /* DEBUG_CRYPTO */ +} + +void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len) +{ +#if DEBUG_CRYPTO + RTW_INFO_DUMP((u8 *)title, buf, len); +#endif /* DEBUG_CRYPTO */ +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.h new file mode 100644 index 00000000..9b64a141 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/rtw_crypto_wrap.h @@ -0,0 +1,64 @@ +#ifndef RTW_CRYTO_WRAP_H +#define RTW_CRYTO_WRAP_H + +#include + +#define TEST_FAIL() 0 + +#define os_memset _rtw_memset +#define os_memcpy _rtw_memcpy +#define os_malloc rtw_malloc + +#define le_to_host16 le16_to_cpu +#define host_to_le16 cpu_to_le16 + +#define WPA_PUT_LE16 RTW_PUT_LE16 +#define WPA_GET_LE16 RTW_GET_LE16 +#define WPA_PUT_LE32 RTW_PUT_LE32 +#define WPA_GET_LE32 RTW_GET_LE32 +#define WPA_PUT_LE64 RTW_PUT_LE64 +#define WPA_GET_LE64 RTW_GET_LE64 +#define WPA_PUT_BE16 RTW_PUT_BE16 +#define WPA_GET_BE16 RTW_GET_BE16 +#define WPA_PUT_BE32 RTW_PUT_BE32 +#define WPA_GET_BE32 RTW_GET_BE32 +#define WPA_PUT_BE64 RTW_PUT_BE64 +#define WPA_GET_BE64 RTW_GET_BE64 + +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +#define WLAN_FC_PVER 0x0003 +#define WLAN_FC_TODS 0x0100 +#define WLAN_FC_FROMDS 0x0200 +#define WLAN_FC_MOREFRAG 0x0400 +#define WLAN_FC_RETRY 0x0800 +#define WLAN_FC_PWRMGT 0x1000 +#define WLAN_FC_MOREDATA 0x2000 +#define WLAN_FC_ISWEP 0x4000 +#define WLAN_FC_ORDER 0x8000 + +#define WLAN_FC_TYPE_DATA RTW_IEEE80211_FTYPE_DATA +#define WLAN_FC_TYPE_MGMT RTW_IEEE80211_FTYPE_MGMT + +#define WLAN_FC_STYPE_QOS_DATA RTW_IEEE80211_STYPE_QOS_DATA + +enum { + _MSG_EXCESSIVE_, _MSG_MSGDUMP_, _MSG_DEBUG_, _MSG_INFO_, _MSG_WARNING_, _MSG_ERROR_ +}; + +int os_memcmp(const void *s1, const void *s2, size_t n); +int os_memcmp_const(const void *a, const void *b, size_t len); +void* os_memdup(const void *src, u32 sz); +size_t os_strlen(const char *s); + +void forced_memzero(void *ptr, size_t len); +void bin_clear_free(void *bin, size_t len); + +void wpa_printf(int level, const char *fmt, ...); +void wpa_hexdump(int level, const char *title, const void *buf, size_t len); +void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len); + +#endif /* RTW_CRYTO_WRAP_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-internal.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-internal.c new file mode 100644 index 00000000..98228ea3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-internal.c @@ -0,0 +1,230 @@ +/* + * SHA-256 hash implementation and interface functions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +//#include "common.h" +#include "sha256.h" +#include "sha256_i.h" +//#include "crypto.h" +#include "wlancrypto_wrap.h" + + +/** + * sha256_vector - SHA256 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + struct _sha256_state ctx; + size_t i; + + if (TEST_FAIL()) + return -1; + + _sha256_init(&ctx); + for (i = 0; i < num_elem; i++) + if (sha256_process(&ctx, addr[i], len[i])) + return -1; + if (sha256_done(&ctx, mac)) + return -1; + return 0; +} + + +/* ===== start - public domain SHA256 implementation ===== */ + +/* This is based on SHA256 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. */ + +/* the K array */ +static const unsigned long K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + + +/* Various logical functions */ +#define RORc(x, y) \ +( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ + ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x), (n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif + +/* compress 512-bits */ +static int sha256_compress(struct _sha256_state *md, unsigned char *buf) +{ + u32 S[8], W[64], t0, t1; + u32 t; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) + W[i] = WPA_GET_BE32(buf + (4 * i)); + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + + /* Compress */ +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} + + +/* Initialize the hash state */ +void _sha256_init(struct _sha256_state *md) +{ + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int sha256_process(struct _sha256_state *md, const unsigned char *in, + unsigned long inlen) +{ + unsigned long n; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + while (inlen > 0) { + if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) { + if (sha256_compress(md, (unsigned char *) in) < 0) + return -1; + md->length += SHA256_BLOCK_SIZE * 8; + in += SHA256_BLOCK_SIZE; + inlen -= SHA256_BLOCK_SIZE; + } else { + n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen)); + os_memcpy(md->buf + md->curlen, in, n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == SHA256_BLOCK_SIZE) { + if (sha256_compress(md, md->buf) < 0) + return -1; + md->length += 8 * SHA256_BLOCK_SIZE; + md->curlen = 0; + } + } + } + + return 0; +} + + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sha256_done(struct _sha256_state *md, unsigned char *out) +{ + int i; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char) 0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < SHA256_BLOCK_SIZE) { + md->buf[md->curlen++] = (unsigned char) 0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + + /* pad up to 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char) 0; + } + + /* store length */ + WPA_PUT_BE64(md->buf + 56, md->length); + sha256_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 8; i++) + WPA_PUT_BE32(out + (4 * i), md->state[i]); + + return 0; +} + +/* ===== end - public domain SHA256 implementation ===== */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-prf.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-prf.c new file mode 100644 index 00000000..642b38ff --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256-prf.c @@ -0,0 +1,109 @@ +/* + * SHA256-based PRF (IEEE 802.11r) + * Copyright (c) 2003-2016, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +//#include "common.h" +#include "sha256.h" +//#include "crypto.h" +#include "wlancrypto_wrap.h" + + +/** + * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) + * @key: Key for PRF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bytes of key to generate + * Returns: 0 on success, -1 on failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key. + */ +int sha256_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) +{ + return sha256_prf_bits(key, key_len, label, data, data_len, buf, + buf_len * 8); +} + + +/** + * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function + * @key: Key for KDF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bits of key to generate + * Returns: 0 on success, -1 on failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key. If the requested buf_len is not divisible by eight, the least + * significant 1-7 bits of the last octet in the output are not part of the + * requested output. + */ +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits) +{ + u16 counter = 1; + size_t pos, plen; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + u8 counter_le[2], length_le[2]; + size_t buf_len = (buf_len_bits + 7) / 8; + + addr[0] = counter_le; + len[0] = 2; + addr[1] = (u8 *) label; + len[1] = os_strlen(label); + addr[2] = data; + len[2] = data_len; + addr[3] = length_le; + len[3] = sizeof(length_le); + + WPA_PUT_LE16(length_le, buf_len_bits); + pos = 0; + while (pos < buf_len) { + plen = buf_len - pos; + WPA_PUT_LE16(counter_le, counter); + if (plen >= SHA256_MAC_LEN) { + if (hmac_sha256_vector(key, key_len, 4, addr, len, + &buf[pos]) < 0) + return -1; + pos += SHA256_MAC_LEN; + } else { + if (hmac_sha256_vector(key, key_len, 4, addr, len, + hash) < 0) + return -1; + os_memcpy(&buf[pos], hash, plen); + pos += plen; + break; + } + counter++; + } + + /* + * Mask out unused bits in the last octet if it does not use all the + * bits. + */ + if (buf_len_bits % 8) { + u8 mask = 0xff << (8 - buf_len_bits % 8); + buf[pos - 1] &= mask; + } + + forced_memzero(hash, sizeof(hash)); + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.c b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.c new file mode 100644 index 00000000..ea5d9e3f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.c @@ -0,0 +1,104 @@ +/* + * SHA-256 hash implementation and interface functions + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rtw_crypto_wrap.h" + +#include "sha256.h" +//#include "crypto.h" +#include "wlancrypto_wrap.h" + + +/** + * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (32 bytes) + * Returns: 0 on success, -1 on failure + */ +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ + unsigned char tk[32]; + const u8 *_addr[6]; + size_t _len[6], i; + + if (num_elem > 5) { + /* + * Fixed limit on the number of fragments to avoid having to + * allocate memory (which could fail). + */ + return -1; + } + + /* if key is longer than 64 bytes reset it to key = SHA256(key) */ + if (key_len > 64) { + if (sha256_vector(1, &key, &key_len, tk) < 0) + return -1; + key = tk; + key_len = 32; + } + + /* the HMAC_SHA256 transform looks like: + * + * SHA256(K XOR opad, SHA256(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected */ + + /* start out by storing key in ipad */ + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with ipad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x36; + + /* perform inner SHA256 */ + _addr[0] = k_pad; + _len[0] = 64; + for (i = 0; i < num_elem; i++) { + _addr[i + 1] = addr[i]; + _len[i + 1] = len[i]; + } + if (sha256_vector(1 + num_elem, _addr, _len, mac) < 0) + return -1; + + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with opad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x5c; + + /* perform outer SHA256 */ + _addr[0] = k_pad; + _len[0] = 64; + _addr[1] = mac; + _len[1] = SHA256_MAC_LEN; + return sha256_vector(2, _addr, _len, mac); +} + + +/** + * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (32 bytes) + * Returns: 0 on success, -1 on failure + */ +int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac) +{ + return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.h new file mode 100644 index 00000000..5219022e --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256.h @@ -0,0 +1,30 @@ +/* + * SHA256 hash implementation and interface functions + * Copyright (c) 2003-2016, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA256_H +#define SHA256_H + +#define SHA256_MAC_LEN 32 + +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +int sha256_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); +void tls_prf_sha256(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); +int hmac_sha256_kdf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); + +#endif /* SHA256_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256_i.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256_i.h new file mode 100644 index 00000000..11ddd6b1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/sha256_i.h @@ -0,0 +1,25 @@ +/* + * SHA-256 internal definitions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA256_I_H +#define SHA256_I_H + +#define SHA256_BLOCK_SIZE 64 + +struct _sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +void _sha256_init(struct _sha256_state *md); +int sha256_process(struct _sha256_state *md, const unsigned char *in, + unsigned long inlen); +int sha256_done(struct _sha256_state *md, unsigned char *out); + +#endif /* SHA256_I_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/crypto/wlancrypto_wrap.h b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/wlancrypto_wrap.h new file mode 100755 index 00000000..d39ce99e --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/crypto/wlancrypto_wrap.h @@ -0,0 +1,41 @@ +/* + * wlantest - IEEE 802.11 protocol monitoring and testing tool + * Copyright (c) 2010-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WLANCRYPTO_WRAP_H +#define WLANCRYPTO_WRAP_H + +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +u8* ccmp_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len); +u8* ccmp_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, + u8 *pn, int keyid, size_t *encrypted_len); +u8* ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3, + const u8 *frame, size_t len, + size_t hdrlen, const u8 *pn, int keyid, + size_t *encrypted_len); +u8* ccmp_256_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len); +u8* ccmp_256_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len); + +u8* gcmp_decrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len); +u8* gcmp_encrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const u8 *frame, size_t len, + size_t hdrlen, const u8 *qos, + const u8 *pn, int keyid, size_t *encrypted_len); + +#if 0 //RTW_PHL_TX: mark un-finished codes for reading +void core_ccmp_encrypt(const u8 *tk, uint hdrlen, u8 *phdr, uint datalen, u8 *pdata, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len); + +void core_ccmp_256_encrypt(const u8 *tk, uint hdrlen, u8 *phdr, uint datalen, u8 *pdata, + u8 *qos, u8 *pn, int keyid, size_t *encrypted_len); +#endif +#endif /* WLANCRYPTO_WRAP_H */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/def_module_country_chplan.h b/drivers/net/wireless/realtek/rtl8852ce/core/def_module_country_chplan.h new file mode 100644 index 00000000..b993d9e4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/def_module_country_chplan.h @@ -0,0 +1,1519 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ + +#define RTW_MODULE_RTL8821AE_HMC_M2 BIT0 /* RTL8821AE(HMC + M.2) */ +#define RTW_MODULE_RTL8821AU BIT1 /* RTL8821AU */ +#define RTW_MODULE_RTL8812AENF_NGFF BIT2 /* RTL8812AENF(8812AE+8761)_NGFF */ +#define RTW_MODULE_RTL8812AEBT_HMC BIT3 /* RTL8812AEBT(8812AE+8761)_HMC */ +#define RTW_MODULE_RTL8188EE_HMC_M2 BIT4 /* RTL8188EE(HMC + M.2) */ +#define RTW_MODULE_RTL8723BE_HMC_M2 BIT5 /* RTL8723BE(HMC + M.2) */ +#define RTW_MODULE_RTL8723BS_NGFF1216 BIT6 /* RTL8723BS(NGFF1216) */ +#define RTW_MODULE_RTL8192EEBT_HMC_M2 BIT7 /* RTL8192EEBT(8192EE+8761AU)_(HMC + M.2) */ +#define RTW_MODULE_RTL8723DE_NGFF1630 BIT8 /* RTL8723DE(NGFF1630) */ +#define RTW_MODULE_RTL8822BE BIT9 /* RTL8822BE */ +#define RTW_MODULE_RTL8821CE BIT10 /* RTL8821CE */ +#define RTW_MODULE_RTL8822CE BIT11 /* RTL8822CE */ + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8821AE_HMC_M2) /* 2013 certify */ +static const struct country_chplan RTL8821AE_HMC_M2_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8821AU) /* 2014 certify */ +static const struct country_chplan RTL8821AU_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8812AENF_NGFF) /* 2014 certify */ +static const struct country_chplan RTL8812AENF_NGFF_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8812AEBT_HMC) /* 2013 certify */ +static const struct country_chplan RTL8812AEBT_HMC_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8188EE_HMC_M2) /* 2012 certify */ +static const struct country_chplan RTL8188EE_HMC_M2_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BB", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8723BE_HMC_M2) /* 2013 certify */ +static const struct country_chplan RTL8723BE_HMC_M2_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BS", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8723BS_NGFF1216) /* 2014 certify */ +static const struct country_chplan RTL8723BS_NGFF1216_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BB", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("YE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8192EEBT_HMC_M2) /* 2013 certify */ +static const struct country_chplan RTL8192EEBT_HMC_M2_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SC", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ST", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8723DE_NGFF1630) /* 2016 certify */ +static const struct country_chplan RTL8723DE_NGFF1630_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2A, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8822BE) /* 2016 certify */ +static const struct country_chplan RTL8822BE_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, UKRAINE, 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8821CE) /* 2016 certify */ +static const struct country_chplan RTL8821CE_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0x00, DEF , 0, 0, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, UKRAINE, 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +#if (RTW_DEF_MODULE_REGULATORY_CERT & RTW_MODULE_RTL8822CE) /* 2018 certify */ +static const struct country_chplan RTL8822CE_country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AE", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 0x00, CN , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("SZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 0x00, UKRAINE, 0, 1, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 0x00, DEF , 0, 1, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 0x00, DEF , 0, 1, 1), +}; +#endif + +/** + * rtw_def_module_country_chplan_map - + * @hal_map: returned map + * @return: size of map + */ +static u16 rtw_def_module_country_chplan_map(const struct country_chplan **hal_map) +{ + u16 hal_map_sz = 0; + + /* TODO: runtime selection for multi driver */ +#if (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8821AE_HMC_M2) + *hal_map = RTL8821AE_HMC_M2_country_chplan_map; + hal_map_sz = sizeof(RTL8821AE_HMC_M2_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8821AU) + *hal_map = RTL8821AU_country_chplan_map; + hal_map_sz = sizeof(RTL8821AU_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8812AENF_NGFF) + *hal_map = RTL8812AENF_NGFF_country_chplan_map; + hal_map_sz = sizeof(RTL8812AENF_NGFF_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8812AEBT_HMC) + *hal_map = RTL8812AEBT_HMC_country_chplan_map; + hal_map_sz = sizeof(RTL8812AEBT_HMC_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8188EE_HMC_M2) + *hal_map = RTL8188EE_HMC_M2_country_chplan_map; + hal_map_sz = sizeof(RTL8188EE_HMC_M2_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8723BE_HMC_M2) + *hal_map = RTL8723BE_HMC_M2_country_chplan_map; + hal_map_sz = sizeof(RTL8723BE_HMC_M2_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8723BS_NGFF1216) + *hal_map = RTL8723BS_NGFF1216_country_chplan_map; + hal_map_sz = sizeof(RTL8723BS_NGFF1216_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8192EEBT_HMC_M2) + *hal_map = RTL8192EEBT_HMC_M2_country_chplan_map; + hal_map_sz = sizeof(RTL8192EEBT_HMC_M2_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8723DE_NGFF1630) + *hal_map = RTL8723DE_NGFF1630_country_chplan_map; + hal_map_sz = sizeof(RTL8723DE_NGFF1630_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8822BE) + *hal_map = RTL8822BE_country_chplan_map; + hal_map_sz = sizeof(RTL8822BE_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8821CE) + *hal_map = RTL8821CE_country_chplan_map; + hal_map_sz = sizeof(RTL8821CE_country_chplan_map) / sizeof(struct country_chplan); +#elif (RTW_DEF_MODULE_REGULATORY_CERT == RTW_MODULE_RTL8822CE) + *hal_map = RTL8822CE_country_chplan_map; + hal_map_sz = sizeof(RTL8822CE_country_chplan_map) / sizeof(struct country_chplan); +#endif + + return hal_map_sz; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.c b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.c new file mode 100755 index 00000000..e8243bca --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.c @@ -0,0 +1,4343 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_MESH_C_ + +#ifdef CONFIG_RTW_MESH +#include + +const char *_rtw_mesh_plink_str[] = { + "UNKNOWN", + "LISTEN", + "OPN_SNT", + "OPN_RCVD", + "CNF_RCVD", + "ESTAB", + "HOLDING", + "BLOCKED", +}; + +const char *_rtw_mesh_ps_str[] = { + "UNKNOWN", + "ACTIVE", + "LSLEEP", + "DSLEEP", +}; + +const char *_action_self_protected_str[] = { + "ACT_SELF_PROTECTED_RSVD", + "MESH_OPEN", + "MESH_CONF", + "MESH_CLOSE", + "MESH_GK_INFORM", + "MESH_GK_ACK", +}; + +inline u8 *rtw_set_ie_mesh_id(u8 *buf, u32 *buf_len, const char *mesh_id, u8 id_len) +{ + return rtw_set_ie(buf, WLAN_EID_MESH_ID, id_len, mesh_id, buf_len); +} + +inline u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len + , u8 path_sel_proto, u8 path_sel_metric, u8 congest_ctl_mode, u8 sync_method, u8 auth_proto + , u8 num_of_peerings, bool cto_mgate, bool cto_as + , bool accept_peerings, bool mcca_sup, bool mcca_en, bool forwarding + , bool mbca_en, bool tbtt_adj, bool ps_level) +{ + + u8 conf[7] = {0}; + + SET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(conf, path_sel_proto); + SET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(conf, path_sel_metric); + SET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(conf, congest_ctl_mode); + SET_MESH_CONF_ELE_SYNC_METHOD_ID(conf, sync_method); + SET_MESH_CONF_ELE_AUTH_PROTO_ID(conf, auth_proto); + + SET_MESH_CONF_ELE_CTO_MGATE(conf, cto_mgate); + SET_MESH_CONF_ELE_NUM_OF_PEERINGS(conf, num_of_peerings); + SET_MESH_CONF_ELE_CTO_AS(conf, cto_as); + + SET_MESH_CONF_ELE_ACCEPT_PEERINGS(conf, accept_peerings); + SET_MESH_CONF_ELE_MCCA_SUP(conf, mcca_sup); + SET_MESH_CONF_ELE_MCCA_EN(conf, mcca_en); + SET_MESH_CONF_ELE_FORWARDING(conf, forwarding); + SET_MESH_CONF_ELE_MBCA_EN(conf, mbca_en); + SET_MESH_CONF_ELE_TBTT_ADJ(conf, tbtt_adj); + SET_MESH_CONF_ELE_PS_LEVEL(conf, ps_level); + + return rtw_set_ie(buf, WLAN_EID_MESH_CONFIG, 7, conf, buf_len); +} + +inline u8 *rtw_set_ie_mpm(u8 *buf, u32 *buf_len + , u8 proto_id, u16 llid, u16 *plid, u16 *reason, u8 *chosen_pmk) +{ + u8 data[24] = {0}; + u8 *pos = data; + + RTW_PUT_LE16(pos, proto_id); + pos += 2; + + RTW_PUT_LE16(pos, llid); + pos += 2; + + if (plid) { + RTW_PUT_LE16(pos, *plid); + pos += 2; + } + + if (reason) { + RTW_PUT_LE16(pos, *reason); + pos += 2; + } + + if (chosen_pmk) { + _rtw_memcpy(pos, chosen_pmk, 16); + pos += 16; + } + + return rtw_set_ie(buf, WLAN_EID_MPM, pos - data, data, buf_len); +} + +bool rtw_bss_is_forwarding(WLAN_BSSID_EX *bss) +{ + u8 *ie; + int ie_len; + bool ret = 0; + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, + BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) + goto exit; + + ret = GET_MESH_CONF_ELE_FORWARDING(ie + 2); + +exit: + return ret; +} + +bool rtw_bss_is_cto_mgate(WLAN_BSSID_EX *bss) +{ + u8 *ie; + int ie_len; + bool ret = 0; + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, + BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) + goto exit; + + ret = GET_MESH_CONF_ELE_CTO_MGATE(ie + 2); + +exit: + return ret; +} + +int _rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b, u8 **a_mconf_ie_r, u8 **b_mconf_ie_r) +{ + int ret = 0; + u8 *a_mconf_ie, *b_mconf_ie; + sint a_mconf_ie_len, b_mconf_ie_len; + + if (a->InfrastructureMode != Ndis802_11_mesh) + goto exit; + a_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(a), WLAN_EID_MESH_CONFIG, &a_mconf_ie_len, BSS_EX_TLV_IES_LEN(a)); + if (!a_mconf_ie || a_mconf_ie_len != 7) + goto exit; + if (a_mconf_ie_r) + *a_mconf_ie_r = a_mconf_ie; + + if (b->InfrastructureMode != Ndis802_11_mesh) + goto exit; + b_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(b), WLAN_EID_MESH_CONFIG, &b_mconf_ie_len, BSS_EX_TLV_IES_LEN(b)); + if (!b_mconf_ie || b_mconf_ie_len != 7) + goto exit; + if (b_mconf_ie_r) + *b_mconf_ie_r = b_mconf_ie; + + if (a->mesh_id.SsidLength != b->mesh_id.SsidLength + || _rtw_memcmp(a->mesh_id.Ssid, b->mesh_id.Ssid, a->mesh_id.SsidLength) == _FALSE) + goto exit; + + if (_rtw_memcmp(a_mconf_ie + 2, b_mconf_ie + 2, 5) == _FALSE) + goto exit; + + ret = 1; + +exit: + return ret; +} + +int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b) +{ + return _rtw_bss_is_same_mbss(a, b, NULL, NULL); +} + +int rtw_bss_is_candidate_mesh_peer(_adapter *adapter, WLAN_BSSID_EX *target, u8 ch, u8 add_peer) +{ + int ret = 0; + WLAN_BSSID_EX *self = &adapter->mlmepriv.cur_network.network; + u8 *s_mconf_ie, *t_mconf_ie; + u8 auth_pid; + int i, j; + + if (ch && self->Configuration.DSConfig != target->Configuration.DSConfig) + goto exit; + + if (!_rtw_bss_is_same_mbss(self, target, &s_mconf_ie, &t_mconf_ie)) + goto exit; + + if (add_peer) { + /* Accept additional mesh peerings */ + if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(t_mconf_ie + 2) == 0) + goto exit; + } + + /* BSSBasicRateSet */ + for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { + if (target->SupportedRates[i] == 0) + break; + if (target->SupportedRates[i] & 0x80) { + u8 match = 0; + + if (!ch) { + /* off-channel, check target with our hardcode capability */ + if (target->Configuration.DSConfig > 14) + match = rtw_is_basic_rate_ofdm(target->SupportedRates[i]); + else + match = rtw_is_basic_rate_mix(target->SupportedRates[i]); + } else { + for (j = 0; j < NDIS_802_11_LENGTH_RATES_EX; j++) { + if (self->SupportedRates[j] == 0) + break; + if (self->SupportedRates[j] == target->SupportedRates[i]) { + match = 1; + break; + } + } + } + if (!match) + goto exit; + } + } + + /* BSSBasicMCSSet */ + + + auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(s_mconf_ie + 2); + if (auth_pid && auth_pid <= 2) { + struct security_priv *sec = &adapter->securitypriv; + u8 *rsn_ie; + int rsn_ie_len; + int group_cipher = 0, pairwise_cipher = 0, gmcs = 0; + u8 mfp_opt = MFP_NO; + + /* 802.1X connected to AS ? */ + + /* RSN */ + rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(target), &rsn_ie_len, BSS_EX_TLV_IES_LEN(target)); + if (!rsn_ie || rsn_ie_len == 0) + goto exit; + if (rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, NULL, &mfp_opt, NULL) != _SUCCESS) + goto exit; + if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt < MFP_OPTIONAL) + || (mfp_opt == MFP_REQUIRED && sec->mfp_opt < MFP_OPTIONAL)) + goto exit; + if (!(sec->wpa2_group_cipher & group_cipher)) + goto exit; + if (!(sec->wpa2_pairwise_cipher & pairwise_cipher)) + goto exit; + #ifdef CONFIG_IEEE80211W + if ((sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL) + && security_type_bip_to_gmcs(sec->dot11wCipher) != gmcs) + goto exit; + #endif + } + + ret = 1; + +exit: + return ret; +} + +void rtw_mesh_bss_peering_status(WLAN_BSSID_EX *bss, u8 *nop, u8 *accept) +{ + u8 *ie; + int ie_len; + + if (nop) + *nop = 0; + if (accept) + *accept = 0; + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, + BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) + goto exit; + + if (nop) + *nop = GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2); + if (accept) + *accept = GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2); + +exit: + return; +} + +#if CONFIG_RTW_MESH_ACNODE_PREVENT +void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned) +{ + bool acnode; + u8 nop, accept; + + rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept); + + acnode = !nop && accept; + + if (acnode && scanned->acnode_stime == 0) { + scanned->acnode_stime = rtw_get_current_time(); + if (scanned->acnode_stime == 0) + scanned->acnode_stime++; + } else if (!acnode) { + scanned->acnode_stime = 0; + scanned->acnode_notify_etime = 0; + } +} + +bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned) +{ + return scanned->acnode_stime + && rtw_get_passing_time_ms(scanned->acnode_stime) + > adapter->mesh_cfg.peer_sel_policy.acnode_conf_timeout_ms; +} + +static bool rtw_mesh_scanned_is_acnode_allow_notify(_adapter *adapter, struct wlan_network *scanned) +{ + return scanned->acnode_notify_etime + && rtw_time_after(scanned->acnode_notify_etime, rtw_get_current_time()); +} + +bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct sta_priv *stapriv = &adapter->stapriv; + bool allow = 0; + + if (!mcfg->peer_sel_policy.acnode_prevent + || mcfg->max_peer_links <= 1 + || stapriv->asoc_list_cnt < mcfg->max_peer_links) + goto exit; + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + if (rtw_mesh_cto_mgate_required(adapter)) + goto exit; +#endif + + allow = 1; + +exit: + return allow; +} + +static bool rtw_mesh_acnode_candidate_exist(_adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct sta_priv *stapriv = &adapter->stapriv; + struct mlme_priv *mlme = &adapter->mlmepriv; + _queue *queue = &(mlme->scanned_queue); + _list *head, *list; + struct wlan_network *scanned = NULL; + struct sta_info *sta = NULL; + bool need = 0; + + _rtw_spinlock_bh(&(mlme->scanned_queue.lock)); + + head = get_list_head(queue); + list = get_next(head); + while (!rtw_end_of_queue_search(head, list)) { + scanned = LIST_CONTAINOR(list, struct wlan_network, list); + list = get_next(list); + + if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms + && rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned) + && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.PhyInfo.rssi) + #if CONFIG_RTW_MACADDR_ACL + && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE + #endif + && rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1) + #if CONFIG_RTW_MESH_PEER_BLACKLIST + && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress) + #endif + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + && rtw_mesh_cto_mgate_network_filter(adapter, scanned) + #endif + ) { + need = 1; + break; + } + } + + _rtw_spinunlock_bh(&(mlme->scanned_queue.lock)); + + return need; +} + +static int rtw_mesh_acnode_prevent_sacrifice_chk(_adapter *adapter, struct sta_info **sac, struct sta_info *com) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + int updated = 0; + + /* + * TODO: compare next_hop reference cnt of forwarding info + * don't sacrifice working next_hop or choose sta with least cnt + */ + + if (*sac == NULL) { + updated = 1; + goto exit; + } + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + if (mcfg->peer_sel_policy.cto_mgate_require + && !mcfg->dot11MeshGateAnnouncementProtocol + ) { + if (IS_CTO_MGATE_CONF_TIMEOUT(com->plink)) { + if (!IS_CTO_MGATE_CONF_TIMEOUT((*sac)->plink)) { + /* blacklist > not blacklist */ + updated = 1; + goto exit; + } + } else if (!IS_CTO_MGATE_CONF_DISABLED(com->plink)) { + if (IS_CTO_MGATE_CONF_DISABLED((*sac)->plink)) { + /* confirming > disabled */ + updated = 1; + goto exit; + } + } + } +#endif + +exit: + if (updated) + *sac = com; + + return updated; +} + +struct sta_info *_rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter) +{ + struct sta_priv *stapriv = &adapter->stapriv; + _list *head, *list; + struct sta_info *sta, *sacrifice = NULL; + u8 nop; + + head = &stapriv->asoc_list; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + if (!sta->plink || !sta->plink->scanned) { + rtw_warn_on(1); + continue; + } + + rtw_mesh_bss_peering_status(&sta->plink->scanned->network, &nop, NULL); + if (nop < 2) + continue; + + rtw_mesh_acnode_prevent_sacrifice_chk(adapter, &sacrifice, sta); + } + + return sacrifice; +} + +struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct sta_info *sacrifice = NULL; + + rtw_stapriv_asoc_list_lock(stapriv); + + sacrifice = _rtw_mesh_acnode_prevent_pick_sacrifice(adapter); + + rtw_stapriv_asoc_list_unlock(stapriv); + + return sacrifice; +} + +static void rtw_mesh_acnode_rsvd_chk(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + u8 acnode_rsvd = 0; + + if (rtw_mesh_acnode_prevent_allow_sacrifice(adapter) + && rtw_mesh_acnode_prevent_pick_sacrifice(adapter) + && rtw_mesh_acnode_candidate_exist(adapter)) + acnode_rsvd = 1; + + if (plink_ctl->acnode_rsvd != acnode_rsvd) { + plink_ctl->acnode_rsvd = acnode_rsvd; + RTW_INFO(FUNC_ADPT_FMT" acnode_rsvd = %d\n", FUNC_ADPT_ARG(adapter), plink_ctl->acnode_rsvd); + rtw_update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, 1, 0); + } +} + +static void rtw_mesh_acnode_set_notify_etime(_adapter *adapter, u8 *rframe_whdr) +{ + if (adapter->mesh_info.plink_ctl.acnode_rsvd) { + struct wlan_network *scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, get_addr2_ptr(rframe_whdr)); + + if (rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)) { + scanned->acnode_notify_etime = rtw_get_current_time() + + rtw_ms_to_systime(adapter->mesh_cfg.peer_sel_policy.acnode_notify_timeout_ms); + if (scanned->acnode_notify_etime == 0) + scanned->acnode_notify_etime++; + } + } +} + +void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter) +{ + struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy; + + RTW_PRINT_SEL(sel, "%-6s %-12s %-14s\n" + , "enable", "conf_timeout", "nofity_timeout"); + RTW_PRINT_SEL(sel, "%6u %12u %14u\n" + , peer_sel_policy->acnode_prevent + , peer_sel_policy->acnode_conf_timeout_ms + , peer_sel_policy->acnode_notify_timeout_ms); +} +#endif /* CONFIG_RTW_MESH_ACNODE_PREVENT */ + +#if CONFIG_RTW_MESH_PEER_BLACKLIST +int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_add(&plink_ctl->peer_blacklist, addr + , mcfg->peer_sel_policy.peer_blacklist_timeout_ms); +} + +int rtw_mesh_peer_blacklist_del(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_del(&plink_ctl->peer_blacklist, addr); +} + +int rtw_mesh_peer_blacklist_search(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_search(&plink_ctl->peer_blacklist, addr); +} + +void rtw_mesh_peer_blacklist_flush(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + rtw_blacklist_flush(&plink_ctl->peer_blacklist); +} + +void dump_mesh_peer_blacklist(void *sel, _adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + dump_blacklist(sel, &plink_ctl->peer_blacklist, "blacklist"); +} + +void dump_mesh_peer_blacklist_settings(void *sel, _adapter *adapter) +{ + struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy; + + RTW_PRINT_SEL(sel, "%-12s %-17s\n" + , "conf_timeout", "blacklist_timeout"); + RTW_PRINT_SEL(sel, "%12u %17u\n" + , peer_sel_policy->peer_conf_timeout_ms + , peer_sel_policy->peer_blacklist_timeout_ms); +} +#endif /* CONFIG_RTW_MESH_PEER_BLACKLIST */ + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST +u8 rtw_mesh_cto_mgate_required(_adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + + return mcfg->peer_sel_policy.cto_mgate_require + && !rtw_bss_is_cto_mgate(&(mlmeext->mlmext_info.network)); +} + +u8 rtw_mesh_cto_mgate_network_filter(_adapter *adapter, struct wlan_network *scanned) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + + return !rtw_mesh_cto_mgate_required(adapter) + || (rtw_bss_is_cto_mgate(&scanned->network) + && !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress)); +} + +int rtw_mesh_cto_mgate_blacklist_add(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_add(&plink_ctl->cto_mgate_blacklist, addr + , mcfg->peer_sel_policy.cto_mgate_blacklist_timeout_ms); +} + +int rtw_mesh_cto_mgate_blacklist_del(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_del(&plink_ctl->cto_mgate_blacklist, addr); +} + +int rtw_mesh_cto_mgate_blacklist_search(_adapter *adapter, const u8 *addr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + return rtw_blacklist_search(&plink_ctl->cto_mgate_blacklist, addr); +} + +void rtw_mesh_cto_mgate_blacklist_flush(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + rtw_blacklist_flush(&plink_ctl->cto_mgate_blacklist); +} + +void dump_mesh_cto_mgate_blacklist(void *sel, _adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + dump_blacklist(sel, &plink_ctl->cto_mgate_blacklist, "blacklist"); +} + +void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter) +{ + struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy; + + RTW_PRINT_SEL(sel, "%-12s %-17s\n" + , "conf_timeout", "blacklist_timeout"); + RTW_PRINT_SEL(sel, "%12u %17u\n" + , peer_sel_policy->cto_mgate_conf_timeout_ms + , peer_sel_policy->cto_mgate_blacklist_timeout_ms); +} + +static void rtw_mesh_cto_mgate_blacklist_chk(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + _queue *blist = &plink_ctl->cto_mgate_blacklist; + _list *list, *head; + struct blacklist_ent *ent = NULL; + struct wlan_network *scanned = NULL; + + _rtw_spinlock_bh(&blist->lock); + head = &blist->queue; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + ent = LIST_CONTAINOR(list, struct blacklist_ent, list); + list = get_next(list); + + if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) { + rtw_list_delete(&ent->list); + rtw_mfree(ent, sizeof(struct blacklist_ent)); + continue; + } + + scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, ent->addr); + if (!scanned) + continue; + + if (rtw_bss_is_forwarding(&scanned->network)) { + rtw_list_delete(&ent->list); + rtw_mfree(ent, sizeof(struct blacklist_ent)); + } + } + + _rtw_spinunlock_bh(&blist->lock); +} +#endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */ + +void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + struct mlme_priv *mlme = &adapter->mlmepriv; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + bool acnode = 0; + + if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) + goto exit; + + if (plink_ctl->num >= RTW_MESH_MAX_PEER_CANDIDATES) + goto exit; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + if (plink_ctl->acnode_rsvd) { + acnode = rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned); + if (acnode && !rtw_mesh_scanned_is_acnode_allow_notify(adapter, scanned)) + goto exit; + } +#endif + + /* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */ + if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0) + goto exit; + + if (rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms + || (mcfg->rssi_threshold && mcfg->rssi_threshold > scanned->network.PhyInfo.rssi) + || !rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1) + #if CONFIG_RTW_MACADDR_ACL + || rtw_access_ctrl(adapter, scanned->network.MacAddress) == _FALSE + #endif + || rtw_mesh_plink_get(adapter, scanned->network.MacAddress) + #if CONFIG_RTW_MESH_PEER_BLACKLIST + || rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress) + #endif + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + || !rtw_mesh_cto_mgate_network_filter(adapter, scanned) + #endif + ) + goto exit; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + if (acnode) { + scanned->acnode_notify_etime = 0; + RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(scanned->network.MacAddress)); + } +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev + , scanned->network.MacAddress + , BSS_EX_TLV_IES(&scanned->network) + , BSS_EX_TLV_IES_LEN(&scanned->network) + , scanned->network.PhyInfo.rssi + , GFP_ATOMIC + ); +#endif + +exit: + return; +} + +void rtw_mesh_peer_status_chk(_adapter *adapter) +{ + struct mlme_priv *mlme = &adapter->mlmepriv; + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *plink; + _list *head, *list; + struct sta_info *sta = NULL; + struct sta_priv *stapriv = &adapter->stapriv; + int stainfo_offset; +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + u8 cto_mgate, forwarding, mgate; +#endif + u8 flush; + s8 flush_list[NUM_STA]; + u8 flush_num = 0; + int i; + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + if (rtw_mesh_cto_mgate_required(adapter)) { + /* active scan on operating channel */ + issue_probereq_ex(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, NULL, 0, 0, 0, 0); + } +#endif + + _rtw_spinlock_bh(&(plink_ctl->lock)); + + /* check established peers */ + rtw_stapriv_asoc_list_lock(stapriv); + + head = &stapriv->asoc_list; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + if (!sta->plink || !sta->plink->scanned) { + rtw_warn_on(1); + continue; + } + plink = sta->plink; + flush = 0; + + /* remove unsuitable peer */ + if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 0) + #if CONFIG_RTW_MACADDR_ACL + || rtw_access_ctrl(adapter, plink->addr) == _FALSE + #endif + ) { + flush = 1; + goto flush_add; + } + + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + cto_mgate = rtw_bss_is_cto_mgate(&(plink->scanned->network)); + forwarding = rtw_bss_is_forwarding(&(plink->scanned->network)); + mgate = rtw_mesh_gate_search(minfo->mesh_paths, sta->phl_sta->mac_addr); + + /* CTO_MGATE required, remove peer without CTO_MGATE */ + if (rtw_mesh_cto_mgate_required(adapter) && !cto_mgate) { + flush = 1; + goto flush_add; + } + + /* cto_mgate_conf status update */ + if (IS_CTO_MGATE_CONF_DISABLED(plink)) { + if (cto_mgate && !forwarding && !mgate) + SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms); + else + rtw_mesh_cto_mgate_blacklist_del(adapter, sta->phl_sta->mac_addr); + } else { + /* cto_mgate_conf ongoing */ + if (cto_mgate && !forwarding && !mgate) { + if (IS_CTO_MGATE_CONF_TIMEOUT(plink)) { + rtw_mesh_cto_mgate_blacklist_add(adapter, sta->phl_sta->mac_addr); + + /* CTO_MGATE required, remove peering can't achieve CTO_MGATE */ + if (rtw_mesh_cto_mgate_required(adapter)) { + flush = 1; + goto flush_add; + } + } + } else { + SET_CTO_MGATE_CONF_DISABLED(plink); + rtw_mesh_cto_mgate_blacklist_del(adapter, sta->phl_sta->mac_addr); + } + } + #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */ + +flush_add: + if (flush) { + rtw_stapriv_asoc_list_del(stapriv, sta); + stainfo_offset = rtw_stainfo_offset(stapriv, sta); + if (stainfo_offset_valid(stainfo_offset)) + flush_list[flush_num++] = stainfo_offset; + else + rtw_warn_on(1); + } + } + + rtw_stapriv_asoc_list_unlock(stapriv); + + /* check non-established peers */ + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + plink = &plink_ctl->ent[i]; + if (plink->valid != _TRUE || plink->plink_state == RTW_MESH_PLINK_ESTAB) + continue; + + /* remove unsuitable peer */ + if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 1) + #if CONFIG_RTW_MACADDR_ACL + || rtw_access_ctrl(adapter, plink->addr) == _FALSE + #endif + ) { + _rtw_mesh_expire_peer_ent(adapter, plink); + continue; + } + + #if CONFIG_RTW_MESH_PEER_BLACKLIST + /* peer confirm check timeout, add to black list */ + if (IS_PEER_CONF_TIMEOUT(plink)) { + rtw_mesh_peer_blacklist_add(adapter, plink->addr); + _rtw_mesh_expire_peer_ent(adapter, plink); + } + #endif + } + + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + if (flush_num) { + u8 sta_addr[ETH_ALEN]; + u8 updated = _FALSE; + + for (i = 0; i < flush_num; i++) { + sta = rtw_get_stainfo_by_offset(stapriv, flush_list[i]); + _rtw_memcpy(sta_addr, sta->phl_sta->mac_addr, ETH_ALEN); + + updated |= ap_free_sta(adapter, sta, _TRUE, 0, WLAN_REASON_DEAUTH_LEAVING, _FALSE); + rtw_mesh_expire_peer(adapter, sta_addr); + } + + associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL); + } + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + /* loop cto_mgate_blacklist to remove ent according to scan_r */ + rtw_mesh_cto_mgate_blacklist_chk(adapter); +#endif + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + rtw_mesh_acnode_rsvd_chk(adapter); +#endif + + return; +} + +#if CONFIG_RTW_MESH_OFFCH_CAND +static u8 rtw_mesh_offch_cto_mgate_required(_adapter *adapter) +{ +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct mlme_priv *mlme = &adapter->mlmepriv; + _queue *queue = &(mlme->scanned_queue); + _list *head, *pos; + struct wlan_network *scanned = NULL; + u8 ret = 0; + + if (!rtw_mesh_cto_mgate_required(adapter)) + goto exit; + + _rtw_spinlock_bh(&(mlme->scanned_queue.lock)); + + head = get_list_head(queue); + pos = get_next(head); + while (!rtw_end_of_queue_search(head, pos)) { + scanned = LIST_CONTAINOR(pos, struct wlan_network, list); + + if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms + && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.PhyInfo.rssi) + #if CONFIG_RTW_MACADDR_ACL + && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE + #endif + && rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1) + && rtw_bss_is_cto_mgate(&scanned->network) + #if CONFIG_RTW_MESH_PEER_BLACKLIST + && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress) + #endif + && !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress) + ) + break; + + pos = get_next(pos); + } + + if (rtw_end_of_queue_search(head, pos)) + ret = 1; + + _rtw_spinunlock_bh(&(mlme->scanned_queue.lock)); + +exit: + return ret; +#else + return 0; +#endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */ +} + +u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + u8 ret = 0; + + if (!adapter->mesh_cfg.peer_sel_policy.offch_cand) + goto exit; + + ret = MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter) + && (!plink_ctl->num || rtw_mesh_offch_cto_mgate_required(adapter)) + ; + +#ifdef CONFIG_CONCURRENT_MODE + if (ret) { + struct mi_state mstate_no_self; + + rtw_mi_status_no_self(adapter, &mstate_no_self); + if (MSTATE_STA_LD_NUM(&mstate_no_self)) + ret = 0; + } +#endif + +exit: + return ret; +} + +/* + * this function is called under off channel candidate is required + * the channel with maximum candidate count is selected +*/ +u8 rtw_mesh_select_operating_ch(_adapter *adapter) +{ + struct rtw_chset *chset = adapter_to_chset(adapter); + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct mlme_priv *mlme = &adapter->mlmepriv; + _queue *queue = &(mlme->scanned_queue); + _list *head, *pos; + struct wlan_network *scanned = NULL; + int i; + /* statistics for candidate accept peering */ + u8 cand_ap_cnt[MAX_CHANNEL_NUM] = {0}; + u8 max_cand_ap_ch = 0; + u8 max_cand_ap_cnt = 0; + /* statistics for candidate including not accept peering */ + u8 cand_cnt[MAX_CHANNEL_NUM] = {0}; + u8 max_cand_ch = 0; + u8 max_cand_cnt = 0; + + _rtw_spinlock_bh(&(mlme->scanned_queue.lock)); + + head = get_list_head(queue); + pos = get_next(head); + while (!rtw_end_of_queue_search(head, pos)) { + scanned = LIST_CONTAINOR(pos, struct wlan_network, list); + pos = get_next(pos); + + if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms + && (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.PhyInfo.rssi) + #if CONFIG_RTW_MACADDR_ACL + && rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE + #endif + && rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 0, 0) + #if CONFIG_RTW_MESH_PEER_BLACKLIST + && !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress) + #endif + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + && rtw_mesh_cto_mgate_network_filter(adapter, scanned) + #endif + ) { + int ch_set_idx = rtw_chset_search_ch(chset, scanned->network.Configuration.DSConfig); + + if (ch_set_idx >= 0 + && !(chset->chs[ch_set_idx].flags & RTW_CHF_NO_IR) + && !CH_IS_NON_OCP(&chset->chs[ch_set_idx]) + ) { + u8 nop, accept; + + rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept); + cand_cnt[ch_set_idx]++; + if (max_cand_cnt < cand_cnt[ch_set_idx]) { + max_cand_cnt = cand_cnt[ch_set_idx]; + max_cand_ch = chset->chs[ch_set_idx].ChannelNum; + } + if (accept) { + cand_ap_cnt[ch_set_idx]++; + if (max_cand_ap_cnt < cand_ap_cnt[ch_set_idx]) { + max_cand_ap_cnt = cand_ap_cnt[ch_set_idx]; + max_cand_ap_ch = chset->chs[ch_set_idx].ChannelNum; + } + } + } + } + } + + _rtw_spinunlock_bh(&(mlme->scanned_queue.lock)); + + return max_cand_ap_ch ? max_cand_ap_ch : max_cand_ch; +} + +void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter) +{ + struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy; + + RTW_PRINT_SEL(sel, "%-6s %-11s\n" + , "enable", "find_int_ms"); + RTW_PRINT_SEL(sel, "%6u %11u\n" + , peer_sel_policy->offch_cand, peer_sel_policy->offch_find_int_ms); +} +#endif /* CONFIG_RTW_MESH_OFFCH_CAND */ + +void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter) +{ + struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy; + + RTW_PRINT_SEL(sel, "%-12s\n", "scanr_exp_ms"); + RTW_PRINT_SEL(sel, "%12u\n", peer_sel_policy->scanr_exp_ms); +} + +void dump_mesh_networks(void *sel, _adapter *adapter) +{ +#if CONFIG_RTW_MESH_ACNODE_PREVENT +#define NSTATE_TITLE_FMT_ACN " %-5s" +#define NSTATE_VALUE_FMT_ACN " %5d" +#define NSTATE_TITLE_ARG_ACN , "acn" +#define NSTATE_VALUE_ARG_ACN , (acn_ms < 99999 ? acn_ms : 99999) +#else +#define NSTATE_TITLE_FMT_ACN "" +#define NSTATE_VALUE_FMT_ACN "" +#define NSTATE_TITLE_ARG_ACN +#define NSTATE_VALUE_ARG_ACN +#endif + + struct mlme_priv *mlme = &(adapter->mlmepriv); + _queue *queue = &(mlme->scanned_queue); + struct wlan_network *network; + _list *list, *head; + u8 same_mbss; + u8 candidate; + struct mesh_plink_ent *plink; + u8 blocked; + u8 established; + s32 age_ms; +#if CONFIG_RTW_MESH_ACNODE_PREVENT + s32 acn_ms; +#endif + u8 *mesh_conf_ie; + sint mesh_conf_ie_len; + u8 auth_pid; + u8 *rsn_ie; + int rsn_ie_len; + int gcs, pcs, gmcs; + u8 mfp_opt; + struct wlan_network **mesh_networks; + u8 mesh_network_cnt = 0; + int i; + + mesh_networks = rtw_zvmalloc(mlme->max_bss_cnt * sizeof(struct wlan_network *)); + if (!mesh_networks) + return; + + _rtw_spinlock_bh(&queue->lock); + head = get_list_head(queue); + list = get_next(head); + + while (rtw_end_of_queue_search(head, list) == _FALSE) { + network = LIST_CONTAINOR(list, struct wlan_network, list); + list = get_next(list); + + if (network->network.InfrastructureMode != Ndis802_11_mesh) + continue; + + mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG + , &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (!mesh_conf_ie || mesh_conf_ie_len != 7) + continue; + + mesh_networks[mesh_network_cnt++] = network; + } + + _rtw_spinunlock_bh(&queue->lock); + + RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-10s" + " %-3s %-3s %-4s" + " %-3s %-3s %-3s" + NSTATE_TITLE_FMT_ACN + "\n" + , "bssid", "ch", "rssi", "age", "mesh_id", "P M C S A " + , "pcs", "gcs", "gmcs" + , "nop", "fwd", "cto" + NSTATE_TITLE_ARG_ACN + ); + + if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) { + network = &mlme->cur_network; + mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG + , &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (mesh_conf_ie && mesh_conf_ie_len == 7) { + gcs = pcs = gmcs = 0; + mfp_opt = MFP_NO; + auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2); + if (auth_pid && auth_pid <= 2) { + rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network) + , &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (rsn_ie && rsn_ie_len) + rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL); + } + RTW_PRINT_SEL(sel, "* "MAC_FMT" %3d %-32s %2x%2x%2x%2x%2x" + " %03x %03x %c%03x" + " %c%2u %3u %c%c " + "\n" + , MAC_ARG(network->network.MacAddress) + , network->network.Configuration.DSConfig + , network->network.mesh_id.Ssid + , GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2) + , auth_pid + , pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ') + , mfp_opt >= MFP_OPTIONAL ? gmcs : 0 + , GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' ' + , GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' ' + , GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' ' + ); + } + } + + for (i = 0; i < mesh_network_cnt; i++) { + network = mesh_networks[i]; + + if (network->network.InfrastructureMode != Ndis802_11_mesh) + continue; + + mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG + , &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (!mesh_conf_ie || mesh_conf_ie_len != 7) + continue; + + gcs = pcs = gmcs = 0; + mfp_opt = MFP_NO; + auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2); + if (auth_pid && auth_pid <= 2) { + rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network), &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (rsn_ie && rsn_ie_len) + rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL); + } + age_ms = rtw_get_passing_time_ms(network->last_scanned); + #if CONFIG_RTW_MESH_ACNODE_PREVENT + if (network->acnode_stime == 0) + acn_ms = 0; + else + acn_ms = rtw_get_passing_time_ms(network->acnode_stime); + #endif + same_mbss = 0; + candidate = 0; + plink = NULL; + blocked = 0; + established = 0; + + if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) { + plink = rtw_mesh_plink_get(adapter, network->network.MacAddress); + if (plink && plink->plink_state == RTW_MESH_PLINK_ESTAB) + established = 1; + else if (plink && plink->plink_state == RTW_MESH_PLINK_BLOCKED) + blocked = 1; + else if (plink) + ; + else if (rtw_bss_is_candidate_mesh_peer(adapter, &network->network, 0, 1)) + candidate = 1; + else if (rtw_bss_is_same_mbss(&mlme->cur_network.network, &network->network)) + same_mbss = 1; + } + + RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %2x%2x%2x%2x%2x" + " %03x %03x %c%03x" + " %c%2u %3u %c%c " + NSTATE_VALUE_FMT_ACN + "\n" + , established ? 'E' : (blocked ? 'B' : (plink ? 'N' : (candidate ? 'C' : (same_mbss ? 'S' : ' ')))) + , MAC_ARG(network->network.MacAddress) + , network->network.Configuration.DSConfig + , network->network.PhyInfo.rssi + , age_ms < 99999 ? age_ms : 99999 + , network->network.mesh_id.Ssid + , GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2) + , auth_pid + , pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ') + , mfp_opt >= MFP_OPTIONAL ? gmcs : 0 + , GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' ' + , GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2) + , GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' ' + , GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' ' + NSTATE_VALUE_ARG_ACN + ); + } + + rtw_vmfree(mesh_networks, mlme->max_bss_cnt * sizeof(struct wlan_network *)); +} + +void rtw_mesh_adjust_bchbw(enum band_type req_band, u8 req_ch, u8 *req_bw, u8 *req_offset) +{ + if (req_band == BAND_ON_24G && req_ch >= 5 && req_ch <= 9) { + /* prevent secondary channel offset mismatch */ + if (*req_bw > CHANNEL_WIDTH_20) { + *req_bw = CHANNEL_WIDTH_20; + *req_offset = CHAN_OFFSET_NO_EXT; + } + } +} + +void rtw_mesh_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx, u16 alg, u16 seq, u16 status) +{ +#if CONFIG_RTW_MESH_PEER_BLACKLIST + if (tx && seq == 1) + rtw_mesh_plink_set_peer_conf_timeout(adapter, GetAddr1Ptr(buf)); +#endif +} + +#if CONFIG_RTW_MPM_TX_IES_SYNC_BSS +#ifdef CONFIG_RTW_MESH_AEK +static int rtw_mpm_ampe_dec(_adapter *adapter, struct mesh_plink_ent *plink + , u8 *fhead, size_t flen, u8* fbody, u8 *mic_ie, u8 *ampe_buf) +{ + int ret = _FAIL, verify_ret; + const u8 *aad[] = {adapter_mac_addr(adapter), plink->addr, fbody}; + const size_t aad_len[] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody}; + u8 *iv_crypt; + size_t iv_crypt_len = flen - (mic_ie + 2 - fhead); + + iv_crypt = rtw_malloc(iv_crypt_len); + if (!iv_crypt) + goto exit; + + _rtw_memcpy(iv_crypt, mic_ie + 2, iv_crypt_len); + + verify_ret = rtw_aes_siv_decrypt(plink->aek, 32, iv_crypt, iv_crypt_len + , 3, aad, aad_len, ampe_buf); + + rtw_mfree(iv_crypt, iv_crypt_len); + + if (verify_ret) { + RTW_WARN("verify error, aek_valid=%u\n", plink->aek_valid); + goto exit; + } else if (*ampe_buf != WLAN_EID_AMPE) { + RTW_WARN("plaintext is not AMPE IE\n"); + goto exit; + } else if ( 16 /* AES_BLOCK_SIZE*/ + 2 + *(ampe_buf + 1) > iv_crypt_len) { + RTW_WARN("plaintext AMPE IE length is not valid\n"); + goto exit; + } + + ret = _SUCCESS; + +exit: + return ret; +} + +static int rtw_mpm_ampe_enc(_adapter *adapter, struct mesh_plink_ent *plink + , u8* fbody, u8 *mic_ie, u8 *ampe_buf, bool inverse) +{ + int ret = _FAIL, protect_ret; + const u8 *aad[3]; + const size_t aad_len[3] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody}; + u8 *ampe_ie; + size_t ampe_ie_len = *(ampe_buf + 1) + 2; /* including id & len */ + + if (inverse) { + aad[0] = plink->addr; + aad[1] = adapter_mac_addr(adapter); + } else { + aad[0] = adapter_mac_addr(adapter); + aad[1] = plink->addr; + } + aad[2] = fbody; + + ampe_ie = rtw_malloc(ampe_ie_len); + if (!ampe_ie) + goto exit; + + _rtw_memcpy(ampe_ie, ampe_buf, ampe_ie_len); + + protect_ret = rtw_aes_siv_encrypt(plink->aek, 32, ampe_ie, ampe_ie_len + , 3, aad, aad_len, mic_ie + 2); + + rtw_mfree(ampe_ie, ampe_ie_len); + + if (protect_ret) { + RTW_WARN("protect error, aek_valid=%u\n", plink->aek_valid); + goto exit; + } + + ret = _SUCCESS; + +exit: + return ret; +} +#endif /* CONFIG_RTW_MESH_AEK */ + +static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *plink + , u8 *fhead, size_t flen, u8* fbody, u8 tlv_ies_offset, u8 *mpm_ie, u8 *mic_ie + , u8 **nbuf, size_t *nlen) +{ + int ret = _FAIL; + struct mlme_priv *mlme = &(adapter->mlmepriv); + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info); + WLAN_BSSID_EX *network = &(mlmeinfo->network); + uint left; + u8 *pos; + + uint mpm_ielen = *(mpm_ie + 1); + u8 *fpos; + u8 *new_buf = NULL; + size_t new_len = 0; + + u8 *new_fhead; + size_t new_flen; + u8 *new_fbody; + u8 *new_mic_ie; + +#ifdef CONFIG_RTW_MESH_AEK + u8 *ampe_buf = NULL; + size_t ampe_buf_len = 0; + + /* decode */ + if (mic_ie) { + ampe_buf_len = flen - (mic_ie + 2 + 16 /* AES_BLOCK_SIZE */ - fhead); + ampe_buf = rtw_malloc(ampe_buf_len); + if (!ampe_buf) + goto exit; + + if (rtw_mpm_ampe_dec(adapter, plink, fhead, flen, fbody, mic_ie, ampe_buf) != _SUCCESS) + goto exit; + + if (*(ampe_buf + 1) >= 68) { + _rtw_memcpy(plink->sel_pcs, ampe_buf + 2, 4); + _rtw_memcpy(plink->l_nonce, ampe_buf + 6, 32); + _rtw_memcpy(plink->p_nonce, ampe_buf + 38, 32); + } + } +#endif + + /* count for new frame length */ + new_len = sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset; + left = BSS_EX_TLV_IES_LEN(network); + pos = BSS_EX_TLV_IES(network); + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + break; + + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_TIM: + break; + default: + new_len += 2 + elen; + } + + left -= elen; + pos += elen; + } + new_len += mpm_ielen + 2; + if (mic_ie) + new_len += 16 /* AES_BLOCK_SIZE*/ + 2 + ampe_buf_len; + + /* alloc new frame */ + new_buf = rtw_malloc(new_len); + if (!new_buf) { + rtw_warn_on(1); + goto exit; + } + + /* build new frame */ + _rtw_memcpy(new_buf, fhead, sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset); + new_fhead = new_buf; + new_flen = new_len; + new_fbody = new_fhead + sizeof(struct rtw_ieee80211_hdr_3addr); + + fpos = new_fbody + tlv_ies_offset; + left = BSS_EX_TLV_IES_LEN(network); + pos = BSS_EX_TLV_IES(network); + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + break; + + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_TIM: + break; + default: + fpos = rtw_set_ie(fpos, id, elen, pos, NULL); + if (id == WLAN_EID_MESH_CONFIG) + fpos = rtw_set_ie(fpos, WLAN_EID_MPM, mpm_ielen, mpm_ie + 2, NULL); + } + + left -= elen; + pos += elen; + } + if (mic_ie) { + new_mic_ie = fpos; + *fpos++ = WLAN_EID_MIC; + *fpos++ = 16 /* AES_BLOCK_SIZE */; + } + +#ifdef CONFIG_RTW_MESH_AEK + /* encode */ + if (mic_ie) { + int enc_ret = rtw_mpm_ampe_enc(adapter, plink, new_fbody, new_mic_ie, ampe_buf, 0); + if (enc_ret != _SUCCESS) + goto exit; + } +#endif + + *nlen = new_len; + *nbuf = new_buf; + + ret = _SUCCESS; + +exit: + if (ret != _SUCCESS && new_buf) + rtw_mfree(new_buf, new_len); + +#ifdef CONFIG_RTW_MESH_AEK + if (ampe_buf) + rtw_mfree(ampe_buf, ampe_buf_len); +#endif + + return ret; +} +#endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */ + +struct mpm_frame_info { + u8 *aid; + u16 aid_v; + u8 *pid; + u16 pid_v; + u8 *llid; + u16 llid_v; + u8 *plid; + u16 plid_v; + u8 *reason; + u16 reason_v; + u8 *chosen_pmk; +}; + +/* +* pid:00000 llid:00000 chosen_pmk:0x00000000000000000000000000000000 +* aid:00000 pid:00000 llid:00000 plid:00000 chosen_pmk:0x00000000000000000000000000000000 +* pid:00000 llid:00000 plid:00000 reason:00000 chosen_pmk:0x00000000000000000000000000000000 +*/ +#define MPM_LOG_BUF_LEN 92 /* this length is limited for legal combination */ +static void rtw_mpm_info_msg(struct mpm_frame_info *mpm_info, u8 *mpm_log_buf) +{ + int cnt = 0; + + if (mpm_info->aid) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "aid:%u ", mpm_info->aid_v); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + if (mpm_info->pid) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "pid:%u ", mpm_info->pid_v); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + if (mpm_info->llid) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "llid:%u ", mpm_info->llid_v); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + if (mpm_info->plid) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "plid:%u ", mpm_info->plid_v); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + if (mpm_info->reason) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "reason:%u ", mpm_info->reason_v); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + if (mpm_info->chosen_pmk) { + cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "chosen_pmk:0x"KEY_FMT, KEY_ARG(mpm_info->chosen_pmk)); + if (cnt >= MPM_LOG_BUF_LEN - 1) + goto exit; + } + +exit: + return; +} + +static int rtw_mpm_check_frames(_adapter *adapter, u8 action, const u8 **buf, size_t *len, u8 tx) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *plink = NULL; + u8 *nbuf = NULL; + size_t nlen = 0; + u8 *fhead = (u8 *)*buf; + size_t flen = *len; + u8 *peer_addr = tx ? GetAddr1Ptr(fhead) : get_addr2_ptr(fhead); + u8 *frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr); + struct mpm_frame_info mpm_info; + u8 tlv_ies_offset; + u8 *mpm_ie = NULL; + uint mpm_ielen = 0; + u8 *mic_ie = NULL; + uint mic_ielen = 0; + int ret = 0; + u8 mpm_log_buf[MPM_LOG_BUF_LEN] = {0}; + + if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN) + tlv_ies_offset = 4; + else if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) + tlv_ies_offset = 6; + else if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE) + tlv_ies_offset = 2; + else { + rtw_warn_on(1); + goto exit; + } + + plink = rtw_mesh_plink_get(adapter, peer_addr); + if (!plink && (tx == _TRUE || action == RTW_ACT_SELF_PROTECTED_MESH_CONF)) { + /* warning message if no plink when: 1.TX all MPM or 2.RX CONF */ + RTW_WARN("RTW_%s:%s without plink of "MAC_FMT"\n" + , (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action), MAC_ARG(peer_addr)); + goto exit; + } + + _rtw_memset(&mpm_info, 0, sizeof(struct mpm_frame_info)); + + if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) { + mpm_info.aid = (u8 *)frame_body + 4; + mpm_info.aid_v = RTW_GET_LE16(mpm_info.aid); + } + + mpm_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset + , WLAN_EID_MPM, &mpm_ielen + , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset); + if (!mpm_ie || mpm_ielen < 2 + 2) + goto exit; + + mpm_info.pid = mpm_ie + 2; + mpm_info.pid_v = RTW_GET_LE16(mpm_info.pid); + mpm_info.llid = mpm_info.pid + 2; + mpm_info.llid_v = RTW_GET_LE16(mpm_info.llid); + + switch (action) { + case RTW_ACT_SELF_PROTECTED_MESH_OPEN: + /* pid:2, llid:2, (chosen_pmk:16) */ + if (mpm_info.pid_v == 0 && mpm_ielen == 4) + ; + else if (mpm_info.pid_v == 1 && mpm_ielen == 20) + mpm_info.chosen_pmk = mpm_info.llid + 2; + else + goto exit; + break; + case RTW_ACT_SELF_PROTECTED_MESH_CONF: + /* pid:2, llid:2, plid:2, (chosen_pmk:16) */ + mpm_info.plid = mpm_info.llid + 2; + mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid); + if (mpm_info.pid_v == 0 && mpm_ielen == 6) + ; + else if (mpm_info.pid_v == 1 && mpm_ielen == 22) + mpm_info.chosen_pmk = mpm_info.plid + 2; + else + goto exit; + break; + case RTW_ACT_SELF_PROTECTED_MESH_CLOSE: + /* pid:2, llid:2, (plid:2), reason:2, (chosen_pmk:16) */ + if (mpm_info.pid_v == 0 && mpm_ielen == 6) { + /* MPM, without plid */ + mpm_info.reason = mpm_info.llid + 2; + mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason); + } else if (mpm_info.pid_v == 0 && mpm_ielen == 8) { + /* MPM, with plid */ + mpm_info.plid = mpm_info.llid + 2; + mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid); + mpm_info.reason = mpm_info.plid + 2; + mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason); + } else if (mpm_info.pid_v == 1 && mpm_ielen == 22) { + /* AMPE, without plid */ + mpm_info.reason = mpm_info.llid + 2; + mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason); + mpm_info.chosen_pmk = mpm_info.reason + 2; + } else if (mpm_info.pid_v == 1 && mpm_ielen == 24) { + /* AMPE, with plid */ + mpm_info.plid = mpm_info.llid + 2; + mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid); + mpm_info.reason = mpm_info.plid + 2; + mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason); + mpm_info.chosen_pmk = mpm_info.reason + 2; + } else + goto exit; + break; + }; + + if (mpm_info.pid_v == 1) { + mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset + , WLAN_EID_MIC, &mic_ielen + , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset); + if (!mic_ie || mic_ielen != 16 /* AES_BLOCK_SIZE */) + goto exit; + } + +#if CONFIG_RTW_MPM_TX_IES_SYNC_BSS + if ((action == RTW_ACT_SELF_PROTECTED_MESH_OPEN || action == RTW_ACT_SELF_PROTECTED_MESH_CONF) + && tx == _TRUE + ) { +#define DBG_RTW_MPM_TX_IES_SYNC_BSS 0 + + if (mpm_info.pid_v == 1 && (!plink || !MESH_PLINK_AEK_VALID(plink))) { + RTW_WARN("AEK not ready, IEs can't sync with BSS\n"); + goto bypass_sync_bss; + } + + if (DBG_RTW_MPM_TX_IES_SYNC_BSS) { + RTW_INFO(FUNC_ADPT_FMT" before:\n", FUNC_ADPT_ARG(adapter)); + dump_ies(RTW_DBGDUMP + , fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset + , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset); + } + + rtw_mpm_tx_ies_sync_bss(adapter, plink + , fhead, flen, frame_body, tlv_ies_offset, mpm_ie, mic_ie + , &nbuf, &nlen); + if (!nbuf) + goto exit; + + /* update pointer & len for new frame */ + fhead = nbuf; + flen = nlen; + frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr); + if (mpm_info.pid_v == 1) { + mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset + , WLAN_EID_MIC, &mic_ielen + , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset); + } + + if (DBG_RTW_MPM_TX_IES_SYNC_BSS) { + RTW_INFO(FUNC_ADPT_FMT" after:\n", FUNC_ADPT_ARG(adapter)); + dump_ies(RTW_DBGDUMP + , fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset + , flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset); + } + } +bypass_sync_bss: +#endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */ + + if (!plink) + goto mpm_log; + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN) { + if (tx) + rtw_mesh_plink_set_peer_conf_timeout(adapter, peer_addr); + + } else +#endif +#if CONFIG_RTW_MESH_ACNODE_PREVENT + if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE) { + if (tx && mpm_info.reason && mpm_info.reason_v == WLAN_REASON_MESH_MAX_PEERS) { + if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned) + && rtw_mesh_acnode_prevent_allow_sacrifice(adapter) + ) { + struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter); + + if (sac) { + struct sta_priv *stapriv = &adapter->stapriv; + u8 sta_addr[ETH_ALEN]; + u8 updated = _FALSE; + + rtw_stapriv_asoc_list_lock(stapriv); + if (!rtw_is_list_empty(&sac->asoc_list)) + rtw_stapriv_asoc_list_del(stapriv, sac); + rtw_stapriv_asoc_list_unlock(stapriv); + RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sac->phl_sta->mac_addr)); + + _rtw_memcpy(sta_addr, sac->phl_sta->mac_addr, ETH_ALEN); + updated = ap_free_sta(adapter, sac, 0, 0, 0, 1); + rtw_mesh_expire_peer(stapriv->padapter, sta_addr); + + associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL); + } + } + } + } else +#endif + if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) { + u8 *ies = NULL; + u16 ies_len = 0; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + + plink = _rtw_mesh_plink_get(adapter, peer_addr); + if (!plink) + goto release_plink_ctl; + + if (tx == _FALSE) { + ies = plink->rx_conf_ies; + ies_len = plink->rx_conf_ies_len; + plink->rx_conf_ies = NULL; + plink->rx_conf_ies_len = 0; + + plink->llid = mpm_info.plid_v; + plink->plid = mpm_info.llid_v; + plink->peer_aid = mpm_info.aid_v; + if (mpm_info.pid_v == 1) + _rtw_memcpy(plink->chosen_pmk, mpm_info.chosen_pmk, 16); + } + #ifdef CONFIG_RTW_MESH_DRIVER_AID + else { + ies = plink->tx_conf_ies; + ies_len = plink->tx_conf_ies_len; + plink->tx_conf_ies = NULL; + plink->tx_conf_ies_len = 0; + } + #endif + + if (ies && ies_len) + rtw_mfree(ies, ies_len); + + #ifndef CONFIG_RTW_MESH_DRIVER_AID + if (tx == _TRUE) + goto release_plink_ctl; /* no need to copy tx conf ies */ + #endif + + /* copy mesh confirm IEs */ + if (mpm_info.pid_v == 1) /* not include MIC & encrypted AMPE */ + ies_len = (mic_ie - fhead) - sizeof(struct rtw_ieee80211_hdr_3addr) - 2; + else + ies_len = flen - sizeof(struct rtw_ieee80211_hdr_3addr) - 2; + + ies = rtw_zmalloc(ies_len); + if (ies) { + _rtw_memcpy(ies, fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + 2, ies_len); + if (tx == _FALSE) { + plink->rx_conf_ies = ies; + plink->rx_conf_ies_len = ies_len; + } + #ifdef CONFIG_RTW_MESH_DRIVER_AID + else { + plink->tx_conf_ies = ies; + plink->tx_conf_ies_len = ies_len; + } + #endif + } + +release_plink_ctl: + _rtw_spinunlock_bh(&(plink_ctl->lock)); + } + +mpm_log: + rtw_mpm_info_msg(&mpm_info, mpm_log_buf); + RTW_INFO("RTW_%s:%s %s\n" + , (tx == _TRUE) ? "Tx" : "Rx" + , action_self_protected_str(action) + , mpm_log_buf + ); + + ret = 1; + +exit: + if (nbuf) { + if (ret == 1) { + *buf = nbuf; + *len = nlen; + } else + rtw_mfree(nbuf, nlen); + } + + return ret; +} + +static int rtw_mesh_check_frames(_adapter *adapter, const u8 **buf, size_t *len, u8 tx) +{ + int is_mesh_frame = -1; + const u8 *frame_body; + u8 category, action; + + frame_body = *buf + sizeof(struct rtw_ieee80211_hdr_3addr); + category = frame_body[0]; + + if (category == RTW_WLAN_CATEGORY_SELF_PROTECTED) { + action = frame_body[1]; + switch (action) { + case RTW_ACT_SELF_PROTECTED_MESH_OPEN: + case RTW_ACT_SELF_PROTECTED_MESH_CONF: + case RTW_ACT_SELF_PROTECTED_MESH_CLOSE: + rtw_mpm_check_frames(adapter, action, buf, len, tx); + is_mesh_frame = action; + break; + case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM: + case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK: + RTW_INFO("RTW_%s:%s\n", (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action)); + is_mesh_frame = action; + break; + default: + break; + }; + } + + return is_mesh_frame; +} + +int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len) +{ + return rtw_mesh_check_frames(adapter, buf, len, _TRUE); +} + +int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len) +{ + return rtw_mesh_check_frames(adapter, &buf, &len, _FALSE); +} + +int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe) +{ + u8 *whdr = rframe->u.hdr.rx_data; + +#if CONFIG_RTW_MACADDR_ACL + if (rtw_access_ctrl(adapter, get_addr2_ptr(whdr)) == _FALSE) + return _SUCCESS; +#endif + + if (!rtw_mesh_plink_get(adapter, get_addr2_ptr(whdr))) { + #if CONFIG_RTW_MESH_ACNODE_PREVENT + rtw_mesh_acnode_set_notify_etime(adapter, whdr); + #endif + + if (adapter_to_rfctl(adapter)->offch_state == OFFCHS_NONE) + issue_probereq(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, get_addr2_ptr(whdr)); + + /* only peer being added (checked by notify conditions) is allowed */ + return _SUCCESS; + } + + rtw_cfg80211_rx_mframe(adapter, rframe, NULL); + return _SUCCESS; +} + +unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe) +{ + unsigned int ret = _FAIL; + struct sta_info *sta = NULL; + u8 *pframe = rframe->u.hdr.rx_data; + uint frame_len = rframe->u.hdr.len; + u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + u8 category; + u8 action; + + /* check RA matches or not */ + if (!_rtw_memcmp(adapter_mac_addr(adapter), GetAddr1Ptr(pframe), ETH_ALEN)) + goto exit; + + category = frame_body[0]; + if (category != RTW_WLAN_CATEGORY_SELF_PROTECTED) + goto exit; + + action = frame_body[1]; + switch (action) { + case RTW_ACT_SELF_PROTECTED_MESH_OPEN: + case RTW_ACT_SELF_PROTECTED_MESH_CONF: + case RTW_ACT_SELF_PROTECTED_MESH_CLOSE: + case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM: + case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK: + if (!(MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter))) + goto exit; +#ifdef CONFIG_IOCTL_CFG80211 + #if CONFIG_RTW_MACADDR_ACL + if (rtw_access_ctrl(adapter, get_addr2_ptr(pframe)) == _FALSE) + goto exit; + #endif + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + if (rtw_mesh_cto_mgate_required(adapter) + /* only peer being added (checked by notify conditions) is allowed */ + && !rtw_mesh_plink_get(adapter, get_addr2_ptr(pframe))) + goto exit; + #endif + rtw_cfg80211_rx_action(adapter, rframe, NULL); + ret = _SUCCESS; +#endif /* CONFIG_IOCTL_CFG80211 */ + break; + default: + break; + } + +exit: + return ret; +} + +const u8 ae_to_mesh_ctrl_len[] = { + 6, + 12, /* MESH_FLAGS_AE_A4 */ + 18, /* MESH_FLAGS_AE_A5_A6 */ + 0, +}; + +unsigned int on_action_mesh(_adapter *adapter, union recv_frame *rframe) +{ + unsigned int ret = _FAIL; + struct sta_info *sta = NULL; + struct sta_priv *stapriv = &adapter->stapriv; + u8 *pframe = rframe->u.hdr.rx_data; + uint frame_len = rframe->u.hdr.len; + u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + u8 category; + u8 action; + + if (!MLME_IS_MESH(adapter)) + goto exit; + + /* check stainfo exist? */ + + category = frame_body[0]; + if (category != RTW_WLAN_CATEGORY_MESH) + goto exit; + + action = frame_body[1]; + switch (action) { + case RTW_ACT_MESH_HWMP_PATH_SELECTION: + rtw_mesh_rx_path_sel_frame(adapter, rframe); + ret = _SUCCESS; + break; + default: + break; + } + +exit: + return ret; +} + +bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + u8 num_of_peerings = stapriv->asoc_list_cnt; + bool accept_peerings = stapriv->asoc_list_cnt < mcfg->max_peer_links; + u8 *ie; + int ie_len; + bool updated = 0; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + accept_peerings |= plink_ctl->acnode_rsvd; +#endif + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) { + rtw_warn_on(1); + goto exit; + } + + if (GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2) != num_of_peerings) { + SET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2, num_of_peerings); + updated = 1; + } + + if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2) != accept_peerings) { + SET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2, accept_peerings); + updated = 1; + } + +exit: + return updated; +} + +bool rtw_mesh_update_bss_formation_info(_adapter *adapter, WLAN_BSSID_EX *bss) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + u8 cto_mgate = (minfo->num_gates || mcfg->dot11MeshGateAnnouncementProtocol); + u8 cto_as = 0; + u8 *ie; + int ie_len; + bool updated = 0; + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, + BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) { + rtw_warn_on(1); + goto exit; + } + + if (GET_MESH_CONF_ELE_CTO_MGATE(ie + 2) != cto_mgate) { + SET_MESH_CONF_ELE_CTO_MGATE(ie + 2, cto_mgate); + updated = 1; + } + + if (GET_MESH_CONF_ELE_CTO_AS(ie + 2) != cto_as) { + SET_MESH_CONF_ELE_CTO_AS(ie + 2, cto_as); + updated = 1; + } + +exit: + return updated; +} + +bool rtw_mesh_update_bss_forwarding_state(_adapter *adapter, WLAN_BSSID_EX *bss) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + u8 forward = mcfg->dot11MeshForwarding; + u8 *ie; + int ie_len; + bool updated = 0; + + ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, + BSS_EX_TLV_IES_LEN(bss)); + if (!ie || ie_len != 7) { + rtw_warn_on(1); + goto exit; + } + + if (GET_MESH_CONF_ELE_FORWARDING(ie + 2) != forward) { + SET_MESH_CONF_ELE_FORWARDING(ie + 2, forward); + updated = 1; + } + +exit: + return updated; +} + +struct mesh_plink_ent *_rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + int i; + + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + if (plink_ctl->ent[i].valid == _TRUE + && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE + ) { + ent = &plink_ctl->ent[i]; + break; + } + } + + return ent; +} + +struct mesh_plink_ent *rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + ent = _rtw_mesh_plink_get(adapter, hwaddr); + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ent; +} + +struct mesh_plink_ent *rtw_mesh_plink_get_no_estab_by_idx(_adapter *adapter, u8 idx) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + int i, j = 0; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + if (plink_ctl->ent[i].valid == _TRUE + && plink_ctl->ent[i].plink_state != RTW_MESH_PLINK_ESTAB + ) { + if (j == idx) { + ent = &plink_ctl->ent[i]; + break; + } + j++; + } + } + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ent; +} + +int _rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + u8 exist = _FALSE; + int i; + + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + if (plink_ctl->ent[i].valid == _TRUE + && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE + ) { + ent = &plink_ctl->ent[i]; + exist = _TRUE; + break; + } + + if (ent == NULL && plink_ctl->ent[i].valid == _FALSE) + ent = &plink_ctl->ent[i]; + } + + if (exist == _FALSE && ent) { + _rtw_memcpy(ent->addr, hwaddr, ETH_ALEN); + ent->valid = _TRUE; + #ifdef CONFIG_RTW_MESH_AEK + ent->aek_valid = 0; + #endif + ent->llid = 0; + ent->plid = 0; + _rtw_memset(ent->chosen_pmk, 0, 16); + #ifdef CONFIG_RTW_MESH_AEK + _rtw_memset(ent->sel_pcs, 0, 4); + _rtw_memset(ent->l_nonce, 0, 32); + _rtw_memset(ent->p_nonce, 0, 32); + #endif + ent->plink_state = RTW_MESH_PLINK_LISTEN; + #ifndef CONFIG_RTW_MESH_DRIVER_AID + ent->aid = 0; + #endif + ent->peer_aid = 0; + SET_PEER_CONF_DISABLED(ent); + SET_CTO_MGATE_CONF_DISABLED(ent); + plink_ctl->num++; + } + + return exist == _TRUE ? RTW_ALREADY : (ent ? _SUCCESS : _FAIL); +} + +int rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + int ret; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + ret = _rtw_mesh_plink_add(adapter, hwaddr); + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ret; +} + +int rtw_mesh_plink_set_state(_adapter *adapter, const u8 *hwaddr, u8 state) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + ent = _rtw_mesh_plink_get(adapter, hwaddr); + if (ent) + ent->plink_state = state; + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ent ? _SUCCESS : _FAIL; +} + +#ifdef CONFIG_RTW_MESH_AEK +int rtw_mesh_plink_set_aek(_adapter *adapter, const u8 *hwaddr, const u8 *aek) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + ent = _rtw_mesh_plink_get(adapter, hwaddr); + if (ent) { + _rtw_memcpy(ent->aek, aek, 32); + ent->aek_valid = 1; + } + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ent ? _SUCCESS : _FAIL; +} +#endif + +#if CONFIG_RTW_MESH_PEER_BLACKLIST +int rtw_mesh_plink_set_peer_conf_timeout(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + ent = _rtw_mesh_plink_get(adapter, hwaddr); + if (ent) { + if (IS_PEER_CONF_DISABLED(ent)) + SET_PEER_CONF_END_TIME(ent, mcfg->peer_sel_policy.peer_conf_timeout_ms); + } + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return ent ? _SUCCESS : _FAIL; +} +#endif + +void _rtw_mesh_plink_del_ent(_adapter *adapter, struct mesh_plink_ent *ent) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + + ent->valid = _FALSE; + #ifdef CONFIG_RTW_MESH_DRIVER_AID + if (ent->tx_conf_ies && ent->tx_conf_ies_len) + rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len); + ent->tx_conf_ies = NULL; + ent->tx_conf_ies_len = 0; + #endif + if (ent->rx_conf_ies && ent->rx_conf_ies_len) + rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len); + ent->rx_conf_ies = NULL; + ent->rx_conf_ies_len = 0; + if (ent->scanned) + ent->scanned = NULL; + plink_ctl->num--; +} + +int rtw_mesh_plink_del(_adapter *adapter, const u8 *hwaddr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent = NULL; + u8 exist = _FALSE; + int i; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + if (plink_ctl->ent[i].valid == _TRUE + && _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE + ) { + ent = &plink_ctl->ent[i]; + exist = _TRUE; + break; + } + } + + if (exist == _TRUE) + _rtw_mesh_plink_del_ent(adapter, ent); + + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + return exist == _TRUE ? _SUCCESS : RTW_ALREADY; +} + +void rtw_mesh_plink_ctl_init(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + int i; + + _rtw_spinlock_init(&plink_ctl->lock); + plink_ctl->num = 0; + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) + plink_ctl->ent[i].valid = _FALSE; + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + _rtw_init_queue(&plink_ctl->peer_blacklist); +#endif +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + _rtw_init_queue(&plink_ctl->cto_mgate_blacklist); +#endif +} + +void rtw_mesh_plink_ctl_deinit(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent; + int i; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + ent = &plink_ctl->ent[i]; + #ifdef CONFIG_RTW_MESH_DRIVER_AID + if (ent->tx_conf_ies && ent->tx_conf_ies_len) + rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len); + #endif + if (ent->rx_conf_ies && ent->rx_conf_ies_len) + rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len); + } + _rtw_spinunlock_bh(&(plink_ctl->lock)); + + _rtw_spinlock_free(&plink_ctl->lock); + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + rtw_mesh_peer_blacklist_flush(adapter); + _rtw_deinit_queue(&plink_ctl->peer_blacklist); +#endif +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + rtw_mesh_cto_mgate_blacklist_flush(adapter); + _rtw_deinit_queue(&plink_ctl->cto_mgate_blacklist); +#endif +} + +void dump_mesh_plink_ctl(void *sel, _adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *ent; + int i; + + RTW_PRINT_SEL(sel, "num:%u\n", plink_ctl->num); + #if CONFIG_RTW_MESH_ACNODE_PREVENT + RTW_PRINT_SEL(sel, "acnode_rsvd:%u\n", plink_ctl->acnode_rsvd); + #endif + + for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) { + ent = &plink_ctl->ent[i]; + if (!ent->valid) + continue; + + RTW_PRINT_SEL(sel, "\n"); + RTW_PRINT_SEL(sel, "peer:"MAC_FMT"\n", MAC_ARG(ent->addr)); + RTW_PRINT_SEL(sel, "plink_state:%s\n", rtw_mesh_plink_str(ent->plink_state)); + + #ifdef CONFIG_RTW_MESH_AEK + if (ent->aek_valid) + RTW_PRINT_SEL(sel, "aek:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->aek), KEY_ARG(ent->aek + 16)); + #endif + + RTW_PRINT_SEL(sel, "llid:%u, plid:%u\n", ent->llid, ent->plid); + #ifndef CONFIG_RTW_MESH_DRIVER_AID + RTW_PRINT_SEL(sel, "aid:%u\n", ent->aid); + #endif + RTW_PRINT_SEL(sel, "peer_aid:%u\n", ent->peer_aid); + + RTW_PRINT_SEL(sel, "chosen_pmk:"KEY_FMT"\n", KEY_ARG(ent->chosen_pmk)); + + #ifdef CONFIG_RTW_MESH_AEK + RTW_PRINT_SEL(sel, "sel_pcs:%02x%02x%02x%02x\n" + , ent->sel_pcs[0], ent->sel_pcs[1], ent->sel_pcs[2], ent->sel_pcs[3]); + RTW_PRINT_SEL(sel, "l_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->l_nonce), KEY_ARG(ent->l_nonce + 16)); + RTW_PRINT_SEL(sel, "p_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->p_nonce), KEY_ARG(ent->p_nonce + 16)); + #endif + + #ifdef CONFIG_RTW_MESH_DRIVER_AID + RTW_PRINT_SEL(sel, "tx_conf_ies:%p, len:%u\n", ent->tx_conf_ies, ent->tx_conf_ies_len); + #endif + RTW_PRINT_SEL(sel, "rx_conf_ies:%p, len:%u\n", ent->rx_conf_ies, ent->rx_conf_ies_len); + RTW_PRINT_SEL(sel, "scanned:%p\n", ent->scanned); + + #if CONFIG_RTW_MESH_PEER_BLACKLIST + if (!IS_PEER_CONF_DISABLED(ent)) { + if (!IS_PEER_CONF_TIMEOUT(ent)) + RTW_PRINT_SEL(sel, "peer_conf:%d\n", rtw_systime_to_ms(ent->peer_conf_end_time - rtw_get_current_time())); + else + RTW_PRINT_SEL(sel, "peer_conf:TIMEOUT\n"); + } + #endif + + #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + if (!IS_CTO_MGATE_CONF_DISABLED(ent)) { + if (!IS_CTO_MGATE_CONF_TIMEOUT(ent)) + RTW_PRINT_SEL(sel, "cto_mgate_conf:%d\n", rtw_systime_to_ms(ent->cto_mgate_conf_end_time - rtw_get_current_time())); + else + RTW_PRINT_SEL(sel, "cto_mgate_conf:TIMEOUT\n"); + } + #endif + } +} + +/* this function is called with plink_ctl being locked */ +static int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta) +{ +#ifndef DBG_RTW_MESH_PEER_ESTABLISH +#define DBG_RTW_MESH_PEER_ESTABLISH 0 +#endif + + struct sta_priv *stapriv = &adapter->stapriv; + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + u8 *tlv_ies; + u16 tlv_ieslen; + struct rtw_ieee802_11_elems elems; + int i; + u16 status = 0; + int ret = _FAIL; + + if (!plink->rx_conf_ies || !plink->rx_conf_ies_len) { + RTW_INFO(FUNC_ADPT_FMT" no rx confirm from sta "MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + goto exit; + } + + if (plink->rx_conf_ies_len < 4) { + RTW_INFO(FUNC_ADPT_FMT" confirm from sta "MAC_FMT" too short\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + goto exit; + } + +#ifdef CONFIG_RTW_MESH_DRIVER_AID + if (!plink->tx_conf_ies || !plink->tx_conf_ies_len) { + RTW_INFO(FUNC_ADPT_FMT" no tx confirm to sta "MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + goto exit; + } + + if (plink->tx_conf_ies_len < 4) { + RTW_INFO(FUNC_ADPT_FMT" confirm to sta "MAC_FMT" too short\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + goto exit; + } +#endif + + tlv_ies = plink->rx_conf_ies + 4; + tlv_ieslen = plink->rx_conf_ies_len - 4; + + if (DBG_RTW_MESH_PEER_ESTABLISH) + dump_ies(RTW_DBGDUMP, tlv_ies, tlv_ieslen); + + if (rtw_ieee802_11_parse_elems(tlv_ies, tlv_ieslen, &elems, 1) == ParseFailed) { + RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" sent invalid confirm\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + goto exit; + } + + SET_PEER_CONF_DISABLED(plink); + if (rtw_bss_is_cto_mgate(&plink->scanned->network) + && !rtw_bss_is_forwarding(&plink->scanned->network)) + SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms); + else + SET_CTO_MGATE_CONF_DISABLED(plink); + + sta->state &= (~WIFI_FW_AUTH_SUCCESS); + sta->state |= WIFI_FW_ASSOC_STATE; + + rtw_ap_parse_sta_capability(adapter, sta, plink->rx_conf_ies); + + status = rtw_ap_parse_sta_supported_rates(adapter, sta, tlv_ies, tlv_ieslen); + if (status != _STATS_SUCCESSFUL_) + goto exit; + + status = rtw_ap_parse_sta_security_ie(adapter, sta, &elems); + if (status != _STATS_SUCCESSFUL_) { + RTW_INFO(FUNC_ADPT_FMT" security check fail, status=%u\n", FUNC_ADPT_ARG(adapter), status); + goto exit; + } + + rtw_ap_parse_sta_wmm_ie(adapter, sta, tlv_ies, tlv_ieslen); +#ifdef CONFIG_RTS_FULL_BW + /*check vendor IE*/ + rtw_parse_sta_vendor_ie_8812(adapter, sta, tlv_ies, tlv_ieslen); +#endif/*CONFIG_RTS_FULL_BW*/ + +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT + if (elems.tbtx_cap && elems.tbtx_cap_len != 0) { + if(rtw_is_tbtx_capabilty(elems.tbtx_cap, elems.tbtx_cap_len)) + sta->tbtx_enable = _TRUE; + } +#endif + + rtw_ap_parse_sta_ht_ie(adapter, sta, &elems); + rtw_ap_parse_sta_vht_ie(adapter, sta, &elems); + + /* AID */ +#ifdef CONFIG_RTW_MESH_DRIVER_AID + sta->phl_sta->aid = RTW_GET_LE16(plink->tx_conf_ies + 2); +#else + sta->phl_sta->aid = plink->aid; +#endif + stapriv->sta_aid[sta->phl_sta->aid - 1] = sta; + RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" aid:%u\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr), sta->phl_sta->aid); + + sta->state &= (~WIFI_FW_ASSOC_STATE); + sta->state |= WIFI_FW_ASSOC_SUCCESS; + + sta->local_mps = RTW_MESH_PS_ACTIVE; + + rtw_ewma_err_rate_init(&sta->metrics.err_rate); + rtw_ewma_err_rate_add(&sta->metrics.err_rate, 1); + /* init data_rate to 1M */ + sta->metrics.data_rate = 10; + sta->alive = _TRUE; + + rtw_stapriv_asoc_list_lock(stapriv); + if (rtw_is_list_empty(&sta->asoc_list)) { + STA_SET_MESH_PLINK(sta, plink); + /* TBD: up layer timeout mechanism */ + /* sta->expire_to = mcfg->plink_timeout / 2; */ + rtw_stapriv_asoc_list_add(stapriv, sta); + } + rtw_stapriv_asoc_list_unlock(stapriv); + + bss_cap_update_on_sta_join(adapter, sta); + sta_info_update(adapter, sta); + report_add_sta_event(adapter, sta->phl_sta->mac_addr); + + ret = _SUCCESS; + +exit: + return ret; +} + +int rtw_mesh_set_plink_state(_adapter *adapter, const u8 *mac, u8 plink_state) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *plink = NULL; + _irqL irqL2; + struct sta_priv *stapriv = &adapter->stapriv; + struct sta_info *sta = NULL; + struct sta_info *del_sta = NULL; + int ret = _SUCCESS; + + _rtw_spinlock_bh(&(plink_ctl->lock), &irqL2); + + plink = _rtw_mesh_plink_get(adapter, mac); + if (!plink) { + ret = _FAIL; + goto release_plink_ctl; + } + + plink->plink_state = plink_state; + + #if CONFIG_RTW_MESH_ACNODE_PREVENT + if (plink_state == RTW_MESH_PLINK_OPN_SNT) { + if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned) + && rtw_mesh_acnode_prevent_allow_sacrifice(adapter) + ) { + struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter); + + if (sac) { + del_sta = sac; + rtw_stapriv_asoc_list_lock(stapriv); + if (!rtw_is_list_empty(&del_sta->asoc_list)) + rtw_stapriv_asoc_list_del(stapriv, del_sta); + rtw_stapriv_asoc_list_unlock(stapriv); + RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(del_sta->phl_sta->mac_addr)); + } + } + } else + #endif + if (plink_state == RTW_MESH_PLINK_OPN_RCVD + || plink_state == RTW_MESH_PLINK_CNF_RCVD + || plink_state == RTW_MESH_PLINK_ESTAB + ) { + sta = rtw_get_stainfo(stapriv, mac); + if (!sta) { + sta = rtw_alloc_stainfo(stapriv, mac, PHL_CMD_DIRECTLY); + if (!sta) + goto release_plink_ctl; + } + + if (plink_state == RTW_MESH_PLINK_ESTAB) { + if (rtw_mesh_peer_establish(adapter, plink, sta) != _SUCCESS) { + del_sta = sta; + ret = _FAIL; + goto release_plink_ctl; + } + } + } + else if (plink_state == RTW_MESH_PLINK_HOLDING) { + del_sta = rtw_get_stainfo(stapriv, mac); + if (!del_sta) + goto release_plink_ctl; + + rtw_stapriv_asoc_list_lock(stapriv); + if (!rtw_is_list_empty(&del_sta->asoc_list)) + rtw_stapriv_asoc_list_del(stapriv, del_sta); + rtw_stapriv_asoc_list_unlock(stapriv); + } + +release_plink_ctl: + _rtw_spinunlock_bh(&(plink_ctl->lock), &irqL2); + + if (del_sta) { + u8 sta_addr[ETH_ALEN]; + u8 updated = _FALSE; + + _rtw_memcpy(sta_addr, del_sta->phl_sta->mac_addr, ETH_ALEN); + updated = ap_free_sta(adapter, del_sta, 0, 0, 0, 1); + rtw_mesh_expire_peer(stapriv->padapter, sta_addr); + + associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL); + } + + return ret; +} + +struct mesh_set_plink_cmd_parm { + const u8 *mac; + u8 plink_state; +}; + +u8 rtw_mesh_set_plink_state_cmd_hdl(_adapter *adapter, u8 *parmbuf) +{ + struct mesh_set_plink_cmd_parm *parm = (struct mesh_set_plink_cmd_parm *)parmbuf; + + if (rtw_mesh_set_plink_state(adapter, parm->mac, parm->plink_state) == _SUCCESS) + return H2C_SUCCESS; + + return H2C_CMD_FAIL; +} + +u8 rtw_mesh_set_plink_state_cmd(_adapter *adapter, const u8 *mac, u8 plink_state) +{ + struct cmd_obj *cmdobj; + struct mesh_set_plink_cmd_parm *parm; + struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + /* prepare cmd parameter */ + parm = rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + parm->mac = mac; + parm->plink_state = plink_state; + + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree(parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_MESH_PLINK_STATE); + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + if (res == _SUCCESS) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&cmdpriv->sctx_mutex, NULL); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&cmdpriv->sctx_mutex, NULL); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + +exit: + return res; +} + +void rtw_mesh_expire_peer_notify(_adapter *adapter, const u8 *peer_addr) +{ + u8 null_ssid[2] = {0, 0}; + +#ifdef CONFIG_IOCTL_CFG80211 + rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev + , peer_addr + , null_ssid + , 2 + , 0 + , GFP_ATOMIC + ); +#endif + + return; +} + +static u8 *rtw_mesh_construct_peer_mesh_close(_adapter *adapter, struct mesh_plink_ent *plink, u16 reason, u32 *len) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + u8 *frame = NULL, *pos; + u32 flen; + struct rtw_ieee80211_hdr *whdr; + + if (minfo->mesh_auth_id && !MESH_PLINK_AEK_VALID(plink)) + goto exit; + + flen = sizeof(struct rtw_ieee80211_hdr_3addr) + + 2 /* category, action */ + + 2 + minfo->mesh_id_len /* mesh id */ + + 2 + 8 + (minfo->mesh_auth_id ? 16 : 0) /* mpm */ + + (minfo->mesh_auth_id ? 2 + 16 /* AES_BLOCK_SIZE */ : 0) /* mic */ + + (minfo->mesh_auth_id ? 70 : 0) /* ampe */ + ; + + pos = frame = rtw_zmalloc(flen); + if (!frame) + goto exit; + + whdr = (struct rtw_ieee80211_hdr *)frame; + _rtw_memcpy(whdr->addr1, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(whdr->addr2, plink->addr, ETH_ALEN); + _rtw_memcpy(whdr->addr3, adapter_mac_addr(adapter), ETH_ALEN); + + set_frame_sub_type(frame, WIFI_ACTION); + + pos += sizeof(struct rtw_ieee80211_hdr_3addr); + *(pos++) = RTW_WLAN_CATEGORY_SELF_PROTECTED; + *(pos++) = RTW_ACT_SELF_PROTECTED_MESH_CLOSE; + + pos = rtw_set_ie_mesh_id(pos, NULL, minfo->mesh_id, minfo->mesh_id_len); + + pos = rtw_set_ie_mpm(pos, NULL + , minfo->mesh_auth_id ? 1 : 0 + , plink->plid + , &plink->llid + , &reason + , minfo->mesh_auth_id ? plink->chosen_pmk : NULL); + +#ifdef CONFIG_RTW_MESH_AEK + if (minfo->mesh_auth_id) { + u8 ampe_buf[70]; + int enc_ret; + + *pos = WLAN_EID_MIC; + *(pos + 1) = 16 /* AES_BLOCK_SIZE */; + + ampe_buf[0] = WLAN_EID_AMPE; + ampe_buf[1] = 68; + _rtw_memcpy(ampe_buf + 2, plink->sel_pcs, 4); + _rtw_memcpy(ampe_buf + 6, plink->p_nonce, 32); + _rtw_memcpy(ampe_buf + 38, plink->l_nonce, 32); + + enc_ret = rtw_mpm_ampe_enc(adapter, plink + , frame + sizeof(struct rtw_ieee80211_hdr_3addr) + , pos, ampe_buf, 1); + if (enc_ret != _SUCCESS) { + rtw_mfree(frame, flen); + frame = NULL; + goto exit; + } + } +#endif + + *len = flen; + +exit: + return frame; +} + +void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink) +{ +#if defined(CONFIG_RTW_MESH_STA_DEL_DISASOC) + _rtw_mesh_plink_del_ent(adapter, plink); + rtw_cfg80211_indicate_sta_disassoc(adapter, plink->addr, 0); +#else + u8 *frame = NULL; + u32 flen; + + if (plink->plink_state == RTW_MESH_PLINK_ESTAB) + frame = rtw_mesh_construct_peer_mesh_close(adapter, plink, WLAN_REASON_MESH_CLOSE, &flen); + + if (frame) { + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + struct wireless_dev *wdev = adapter->rtw_wdev; + s32 freq = rtw_ch2freq(mlmeext->chandef.chan); + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE) + rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, flen, GFP_ATOMIC); + #else + cfg80211_rx_action(adapter->pnetdev, freq, frame, flen, GFP_ATOMIC); + #endif + + rtw_mfree(frame, flen); + } else { + rtw_mesh_expire_peer_notify(adapter, plink->addr); + RTW_INFO(FUNC_ADPT_FMT" set "MAC_FMT" plink unknown\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(plink->addr)); + plink->plink_state = RTW_MESH_PLINK_UNKNOWN; + } +#endif +} + +void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl; + struct mesh_plink_ent *plink; + + _rtw_spinlock_bh(&(plink_ctl->lock)); + + plink = _rtw_mesh_plink_get(adapter, peer_addr); + if (!plink) + goto exit; + + _rtw_mesh_expire_peer_ent(adapter, plink); + +exit: + _rtw_spinunlock_bh(&(plink_ctl->lock)); +} + +u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps) +{ + _list *head, *list; + struct sta_info *sta; + struct sta_priv *stapriv = &adapter->stapriv; + u8 sta_alive_num = 0, i; + char sta_alive_list[NUM_STA]; + u8 annc_cnt = 0; + + if (rtw_linked_check(adapter) == _FALSE) + goto exit; + + rtw_stapriv_asoc_list_lock(stapriv); + + head = &stapriv->asoc_list; + list = get_next(head); + while ((rtw_end_of_queue_search(head, list)) == _FALSE) { + int stainfo_offset; + + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + stainfo_offset = rtw_stainfo_offset(stapriv, sta); + if (stainfo_offset_valid(stainfo_offset)) + sta_alive_list[sta_alive_num++] = stainfo_offset; + } + rtw_stapriv_asoc_list_unlock(stapriv); + + for (i = 0; i < sta_alive_num; i++) { + sta = rtw_get_stainfo_by_offset(stapriv, sta_alive_list[i]); + if (!sta) + continue; + + issue_qos_nulldata(adapter, sta->phl_sta->mac_addr, 7, ps, 3, PS_ANNC_DRV_RETRY_INT_MS, _FALSE); + annc_cnt++; + } + +exit: + return annc_cnt; +} + +static void mpath_tx_tasklet_hdl(void *priv) +{ + _adapter *adapter = (_adapter *)priv; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct xmit_frame *xframe; + _list *list, *head; + _list tmp; + u32 tmp_len; + s32 res; + + _rtw_init_listhead(&tmp); + + while (1) { + tmp_len = 0; + _rtw_spinlock_bh(&minfo->mpath_tx_queue.lock); + if (minfo->mpath_tx_queue_len) { + rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp); + tmp_len = minfo->mpath_tx_queue_len; + minfo->mpath_tx_queue_len = 0; + } + _rtw_spinunlock_bh(&minfo->mpath_tx_queue.lock); + + if (!tmp_len) + break; + + head = &tmp; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + xframe = LIST_CONTAINOR(list, struct xmit_frame, list); + list = get_next(list); + rtw_list_delete(&xframe->list); + res = rtw_xmit_posthandle(adapter, xframe, xframe->pkt); + if (res < 0) { + #ifdef DBG_TX_DROP_FRAME + RTW_INFO("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__); + #endif + adapter->xmitpriv.tx_drop++; + } + } + } +} + +static void rtw_mpath_tx_queue_flush(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct xmit_frame *xframe; + _list *list, *head; + _list tmp; + + _rtw_init_listhead(&tmp); + + _rtw_spinlock_bh(&minfo->mpath_tx_queue.lock); + rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp); + minfo->mpath_tx_queue_len = 0; + _rtw_spinunlock_bh(&minfo->mpath_tx_queue.lock); + + head = &tmp; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + xframe = LIST_CONTAINOR(list, struct xmit_frame, list); + list = get_next(list); + rtw_list_delete(&xframe->list); + rtw_free_xmitframe(&adapter->xmitpriv, xframe); + } +} + +#ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */ +#if defined(CONFIG_SLUB) +#include +#elif defined(CONFIG_SLAB) +#include +#endif +typedef struct kmem_cache rtw_mcache; +#endif + +rtw_mcache *rtw_mcache_create(const char *name, size_t size) +{ +#ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */ + return kmem_cache_create(name, size, 0, 0, NULL); +#else + #error "TBD\n"; +#endif +} + +void rtw_mcache_destroy(rtw_mcache *s) +{ +#ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */ + kmem_cache_destroy(s); +#else + #error "TBD\n"; +#endif +} + +void *_rtw_mcache_alloc(rtw_mcache *cachep) +{ +#ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */ + return kmem_cache_alloc(cachep, GFP_ATOMIC); +#else + #error "TBD\n"; +#endif +} + +void _rtw_mcache_free(rtw_mcache *cachep, void *objp) +{ +#ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */ + kmem_cache_free(cachep, objp); +#else + #error "TBD\n"; +#endif +} + +#ifdef DBG_MEM_ALLOC +inline void *dbg_rtw_mcache_alloc(rtw_mcache *cachep, const enum mstat_f flags, const char *func, const int line) +{ + void *p; + u32 sz = cachep->size; + + if (match_mstat_sniff_rules(flags, sz)) + RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz); + + p = _rtw_mcache_alloc(cachep); + + rtw_mstat_update( + flags + , p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL + , sz + ); + + return p; +} + +inline void dbg_rtw_mcache_free(rtw_mcache *cachep, void *pbuf, const enum mstat_f flags, const char *func, const int line) +{ + u32 sz = cachep->size; + + if (match_mstat_sniff_rules(flags, sz)) + RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz); + + _rtw_mcache_free(cachep, pbuf); + + rtw_mstat_update( + flags + , MSTAT_FREE + , sz + ); +} + +#define rtw_mcache_alloc(cachep) dbg_rtw_mcache_alloc(cachep, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__) +#define rtw_mcache_free(cachep, objp) dbg_rtw_mcache_free(cachep, objp, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__) +#else +#define rtw_mcache_alloc(cachep) _rtw_mcache_alloc(cachep) +#define rtw_mcache_free(cachep, objp) _rtw_mcache_free(cachep, objp) +#endif /* DBG_MEM_ALLOC */ + +/* Mesh Received Cache */ +#define RTW_MRC_BUCKETS 256 /* must be a power of 2 */ +#define RTW_MRC_QUEUE_MAX_LEN 4 +#define RTW_MRC_TIMEOUT_MS (3 * 1000) + +/** + * struct rtw_mrc_entry - entry in the Mesh Received Cache + * + * @seqnum: mesh sequence number of the frame + * @exp_time: expiration time of the entry + * @msa: mesh source address of the frame + * @list: hashtable list pointer + * + * The Mesh Received Cache keeps track of the latest received frames that + * have been received by a mesh interface and discards received frames + * that are found in the cache. + */ +struct rtw_mrc_entry { + rtw_hlist_node list; + systime exp_time; + u32 seqnum; + u8 msa[ETH_ALEN]; +}; + +struct rtw_mrc { + rtw_hlist_head bucket[RTW_MRC_BUCKETS]; + u32 idx_mask; + rtw_mcache *cache; +}; + +static int rtw_mrc_init(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + char cache_name[IFNAMSIZ + 8 + 1]; + int i; + + minfo->mrc = rtw_malloc(sizeof(struct rtw_mrc)); + if (!minfo->mrc) + return -ENOMEM; + minfo->mrc->idx_mask = RTW_MRC_BUCKETS - 1; + for (i = 0; i < RTW_MRC_BUCKETS; i++) + rtw_hlist_head_init(&minfo->mrc->bucket[i]); + + sprintf(cache_name, "rtw_mrc_%s", ADPT_ARG(adapter)); + minfo->mrc->cache = rtw_mcache_create(cache_name, sizeof(struct rtw_mrc_entry)); + + return 0; +} + +static void rtw_mrc_free(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mrc *mrc = minfo->mrc; + struct rtw_mrc_entry *p; + rtw_hlist_node *np, *n; + int i; + + if (!mrc) + return; + + for (i = 0; i < RTW_MRC_BUCKETS; i++) { + rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[i], list) { + rtw_hlist_del(&p->list); + rtw_mcache_free(mrc->cache, p); + } + } + + rtw_mcache_destroy(mrc->cache); + + rtw_mfree(mrc, sizeof(struct rtw_mrc)); + minfo->mrc = NULL; +} + +/** + * rtw_mrc_check - Check frame in mesh received cache and add if absent. + * + * @adapter: interface + * @msa: mesh source address + * @seq: mesh seq number + * + * Returns: 0 if the frame is not in the cache, nonzero otherwise. + * + * Checks using the mesh source address and the mesh sequence number if we have + * received this frame lately. If the frame is not in the cache, it is added to + * it. + */ +static int rtw_mrc_check(_adapter *adapter, const u8 *msa, u32 seq) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mrc *mrc = minfo->mrc; + int entries = 0; + u8 idx; + struct rtw_mrc_entry *p; + rtw_hlist_node *np, *n; + u8 timeout; + + if (!mrc) + return -1; + + idx = seq & mrc->idx_mask; + rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[idx], list) { + ++entries; + timeout = rtw_time_after(rtw_get_current_time(), p->exp_time); + if (timeout || entries == RTW_MRC_QUEUE_MAX_LEN) { + if (!timeout) + minfo->mshstats.mrc_del_qlen++; + + rtw_hlist_del(&p->list); + rtw_mcache_free(mrc->cache, p); + --entries; + } else if ((seq == p->seqnum) && _rtw_memcmp(msa, p->msa, ETH_ALEN) == _TRUE) + return -1; + } + + p = rtw_mcache_alloc(mrc->cache); + if (!p) + return 0; + + p->seqnum = seq; + p->exp_time = rtw_get_current_time() + rtw_ms_to_systime(RTW_MRC_TIMEOUT_MS); + _rtw_memcpy(p->msa, msa, ETH_ALEN); + rtw_hlist_add_head(&p->list, &mrc->bucket[idx]); + return 0; +} + +static int rtw_mesh_decache(_adapter *adapter, const u8 *msa, u32 seq) +{ + return rtw_mrc_check(adapter, msa, seq); +} + +#ifndef RTW_MESH_SCAN_RESULT_EXP_MS +#define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000) +#endif + +#ifndef RTW_MESH_ACNODE_PREVENT +#define RTW_MESH_ACNODE_PREVENT 0 +#endif +#ifndef RTW_MESH_ACNODE_CONF_TIMEOUT_MS +#define RTW_MESH_ACNODE_CONF_TIMEOUT_MS (20 * 1000) +#endif +#ifndef RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS +#define RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS (2 * 1000) +#endif + +#ifndef RTW_MESH_OFFCH_CAND +#define RTW_MESH_OFFCH_CAND 1 +#endif +#ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS +#define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000) +#endif + +#ifndef RTW_MESH_PEER_CONF_TIMEOUT_MS +#define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000) +#endif +#ifndef RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS +#define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000) +#endif + +#ifndef RTW_MESH_CTO_MGATE_REQUIRE +#define RTW_MESH_CTO_MGATE_REQUIRE 0 +#endif +#ifndef RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS +#define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000) +#endif +#ifndef RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS +#define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000) +#endif + +void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg) +{ + struct mesh_peer_sel_policy *sel_policy = &mcfg->peer_sel_policy; + + sel_policy->scanr_exp_ms = RTW_MESH_SCAN_RESULT_EXP_MS; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + sel_policy->acnode_prevent = RTW_MESH_ACNODE_PREVENT; + sel_policy->acnode_conf_timeout_ms = RTW_MESH_ACNODE_CONF_TIMEOUT_MS; + sel_policy->acnode_notify_timeout_ms = RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS; +#endif + +#if CONFIG_RTW_MESH_OFFCH_CAND + sel_policy->offch_cand = RTW_MESH_OFFCH_CAND; + sel_policy->offch_find_int_ms = RTW_MESH_OFFCH_CAND_FIND_INT_MS; +#endif + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + sel_policy->peer_conf_timeout_ms = RTW_MESH_PEER_CONF_TIMEOUT_MS; + sel_policy->peer_blacklist_timeout_ms = RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS; +#endif + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + sel_policy->cto_mgate_require = RTW_MESH_CTO_MGATE_REQUIRE; + sel_policy->cto_mgate_conf_timeout_ms = RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS; + sel_policy->cto_mgate_blacklist_timeout_ms = RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS; +#endif +} + +void rtw_mesh_cfg_init(_adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + + mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS; + mcfg->plink_timeout = RTW_MESH_PEER_LINK_TIMEOUT; + + mcfg->dot11MeshTTL = RTW_MESH_TTL; + mcfg->element_ttl = RTW_MESH_DEFAULT_ELEMENT_TTL; + mcfg->dot11MeshHWMPmaxPREQretries = RTW_MESH_MAX_PREQ_RETRIES; + mcfg->path_refresh_time = RTW_MESH_PATH_REFRESH_TIME; + mcfg->min_discovery_timeout = RTW_MESH_MIN_DISCOVERY_TIMEOUT; + mcfg->dot11MeshHWMPactivePathTimeout = RTW_MESH_PATH_TIMEOUT; + mcfg->dot11MeshHWMPpreqMinInterval = RTW_MESH_PREQ_MIN_INT; + mcfg->dot11MeshHWMPperrMinInterval = RTW_MESH_PERR_MIN_INT; + mcfg->dot11MeshHWMPnetDiameterTraversalTime = RTW_MESH_DIAM_TRAVERSAL_TIME; + mcfg->dot11MeshHWMPRootMode = RTW_IEEE80211_ROOTMODE_NO_ROOT; + mcfg->dot11MeshHWMPRannInterval = RTW_MESH_RANN_INTERVAL; + mcfg->dot11MeshGateAnnouncementProtocol = _FALSE; + mcfg->dot11MeshForwarding = _TRUE; + mcfg->rssi_threshold = 0; + mcfg->dot11MeshHWMPactivePathToRootTimeout = RTW_MESH_PATH_TO_ROOT_TIMEOUT; + mcfg->dot11MeshHWMProotInterval = RTW_MESH_ROOT_INTERVAL; + mcfg->dot11MeshHWMPconfirmationInterval = RTW_MESH_ROOT_CONFIRMATION_INTERVAL; + mcfg->path_gate_timeout_factor = 3; + rtw_mesh_cfg_init_peer_sel_policy(mcfg); +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + mcfg->sane_metric_delta = RTW_MESH_SANE_METRIC_DELTA; + mcfg->max_root_add_chk_cnt = RTW_MESH_MAX_ROOT_ADD_CHK_CNT; +#endif + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + mcfg->b2u_flags_msrc = 0; + mcfg->b2u_flags_mfwd = RTW_MESH_B2U_GA_UCAST; +#endif +} + +void rtw_mesh_cfg_init_max_peer_links(_adapter *adapter, u8 stack_conf) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + + mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS; + + if (mcfg->max_peer_links > stack_conf) + mcfg->max_peer_links = stack_conf; +} + +void rtw_mesh_cfg_init_plink_timeout(_adapter *adapter, u32 stack_conf) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + + mcfg->plink_timeout = stack_conf; +} + +void rtw_mesh_init_mesh_info(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + + _rtw_memset(minfo, 0, sizeof(struct rtw_mesh_info)); + + rtw_mesh_plink_ctl_init(adapter); + + minfo->last_preq = rtw_get_current_time(); + /* minfo->last_sn_update = rtw_get_current_time(); */ + minfo->next_perr = rtw_get_current_time(); + + ATOMIC_SET(&minfo->mpaths, 0); + rtw_mesh_pathtbl_init(adapter); + + _rtw_init_queue(&minfo->mpath_tx_queue); + tasklet_init(&minfo->mpath_tx_tasklet + , (void(*)(unsigned long))mpath_tx_tasklet_hdl + , (unsigned long)adapter); + + rtw_mrc_init(adapter); + + _rtw_init_listhead(&minfo->preq_queue.list); + _rtw_spinlock_init(&minfo->mesh_preq_queue_lock); + + rtw_init_timer(&adapter->mesh_path_timer, rtw_ieee80211_mesh_path_timer, adapter); + rtw_init_timer(&adapter->mesh_path_root_timer, rtw_ieee80211_mesh_path_root_timer, adapter); + rtw_init_timer(&adapter->mesh_atlm_param_req_timer, rtw_mesh_atlm_param_req_timer, adapter); + _init_workitem(&adapter->mesh_work, rtw_mesh_work_hdl, NULL); +} + +void rtw_mesh_deinit_mesh_info(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + + tasklet_kill(&minfo->mpath_tx_tasklet); + rtw_mpath_tx_queue_flush(adapter); + _rtw_deinit_queue(&adapter->mesh_info.mpath_tx_queue); + + rtw_mrc_free(adapter); + + rtw_mesh_pathtbl_unregister(adapter); + + rtw_mesh_plink_ctl_deinit(adapter); + + _cancel_workitem_sync(&adapter->mesh_work); + _cancel_timer_ex(&adapter->mesh_path_timer); + _cancel_timer_ex(&adapter->mesh_path_root_timer); + _cancel_timer_ex(&adapter->mesh_atlm_param_req_timer); +} + +/** + * rtw_mesh_nexthop_resolve - lookup next hop; conditionally start path discovery + * + * @skb: 802.11 frame to be sent + * @sdata: network subif the frame will be sent through + * + * Lookup next hop for given skb and start path discovery if no + * forwarding information is found. + * + * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. + * skb is freeed here if no mpath could be allocated. + */ +int rtw_mesh_nexthop_resolve(_adapter *adapter, + struct xmit_frame *xframe) +{ + struct pkt_attrib *attrib = &xframe->attrib; + struct rtw_mesh_path *mpath; + struct xmit_frame *xframe_to_free = NULL; + u8 *target_addr = attrib->mda; + int err = 0; + int ret = _SUCCESS; + + rtw_rcu_read_lock(); + err = rtw_mesh_nexthop_lookup(adapter, target_addr, attrib->msa, attrib->ra); + if (!err) + goto endlookup; + + /* no nexthop found, start resolving */ + mpath = rtw_mesh_path_lookup(adapter, target_addr); + if (!mpath) { + mpath = rtw_mesh_path_add(adapter, target_addr); + if (IS_ERR(mpath)) { + xframe->pkt = NULL; /* free pkt outside */ + rtw_mesh_path_discard_frame(adapter, xframe); + err = PTR_ERR(mpath); + ret = _FAIL; + goto endlookup; + } + } + + if (!(mpath->flags & RTW_MESH_PATH_RESOLVING)) + rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START); + + _rtw_spinlock_bh(&mpath->frame_queue.lock); + + if (mpath->frame_queue_len >= RTW_MESH_FRAME_QUEUE_LEN) { + xframe_to_free = LIST_CONTAINOR(get_next(get_list_head(&mpath->frame_queue)), struct xmit_frame, list); + rtw_list_delete(&(xframe_to_free->list)); + mpath->frame_queue_len--; + } + + rtw_list_insert_tail(&xframe->list, get_list_head(&mpath->frame_queue)); + mpath->frame_queue_len++; + + _rtw_spinunlock_bh(&mpath->frame_queue.lock); + + ret = RTW_RA_RESOLVING; + if (xframe_to_free) + rtw_mesh_path_discard_frame(adapter, xframe_to_free); + +endlookup: + rtw_rcu_read_unlock(); + return ret; +} + +/** + * rtw_mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling + * this function is considered "using" the associated mpath, so preempt a path + * refresh if this mpath expires soon. + * + * @skb: 802.11 frame to be sent + * @sdata: network subif the frame will be sent through + * + * Returns: 0 if the next hop was found. Nonzero otherwise. + */ +int rtw_mesh_nexthop_lookup(_adapter *adapter, + const u8 *mda, const u8 *msa, u8 *ra) +{ + struct rtw_mesh_path *mpath; + struct sta_info *next_hop; + const u8 *target_addr = mda; + int err = -ENOENT; + struct registry_priv *registry_par = &adapter->registrypriv; + u8 peer_alive_based_preq = registry_par->peer_alive_based_preq; + BOOLEAN nexthop_alive = _TRUE; + + rtw_rcu_read_lock(); + mpath = rtw_mesh_path_lookup(adapter, target_addr); + + if (!mpath || !(mpath->flags & RTW_MESH_PATH_ACTIVE)) + goto endlookup; + + next_hop = rtw_rcu_dereference(mpath->next_hop); + if (next_hop) { + _rtw_memcpy(ra, next_hop->phl_sta->mac_addr, ETH_ALEN); + err = 0; + } + + if (peer_alive_based_preq && next_hop) + nexthop_alive = next_hop->alive; + + if (_rtw_memcmp(adapter_mac_addr(adapter), msa, ETH_ALEN) == _TRUE && + !(mpath->flags & RTW_MESH_PATH_RESOLVING) && + !(mpath->flags & RTW_MESH_PATH_FIXED)) { + u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH; + + if (peer_alive_based_preq && nexthop_alive == _FALSE) { + flags |= RTW_PREQ_Q_F_BCAST_PREQ; + rtw_mesh_queue_preq(mpath, flags); + } else if (rtw_time_after(rtw_get_current_time(), + mpath->exp_time - + rtw_ms_to_systime(adapter->mesh_cfg.path_refresh_time))) { + rtw_mesh_queue_preq(mpath, flags); + } + /* Avoid keeping trying unicast PREQ toward root, + when next_hop leaves */ + } else if (peer_alive_based_preq && + _rtw_memcmp(adapter_mac_addr(adapter), msa, ETH_ALEN) == _TRUE && + (mpath->flags & RTW_MESH_PATH_RESOLVING) && + !(mpath->flags & RTW_MESH_PATH_FIXED) && + !(mpath->flags & RTW_MESH_PATH_BCAST_PREQ) && + mpath->is_root && nexthop_alive == _FALSE) { + _rtw_spinlock_bh(&mpath->state_lock); + mpath->flags |= RTW_MESH_PATH_BCAST_PREQ; + _rtw_spinunlock_bh(&mpath->state_lock); + } + +endlookup: + rtw_rcu_read_unlock(); + return err; +} + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC +static bool rtw_mesh_data_bmc_to_uc(_adapter *adapter + , const u8 *da, const u8 *sa, const u8 *mda, const u8 *msa + , u8 ae_need, const u8 *ori_ta, u8 mfwd_ttl + , u16 os_qid, _list *b2u_list, u8 *b2u_num, u32 *b2u_mseq) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct xmit_priv *xmitpriv = &adapter->xmitpriv; + _list *head, *list; + struct sta_info *sta; + char b2u_sta_id[NUM_STA]; + u8 b2u_sta_num = 0; + bool bmc_need = _FALSE; + int i; + + rtw_stapriv_asoc_list_lock(stapriv); + head = &stapriv->asoc_list; + list = get_next(head); + + while ((rtw_end_of_queue_search(head, list)) == _FALSE) { + int stainfo_offset; + + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + stainfo_offset = rtw_stainfo_offset(stapriv, sta); + if (stainfo_offset_valid(stainfo_offset)) + b2u_sta_id[b2u_sta_num++] = stainfo_offset; + } + rtw_stapriv_asoc_list_unlock(stapriv); + + if (!b2u_sta_num) + goto exit; + + for (i = 0; i < b2u_sta_num; i++) { + struct xmit_frame *b2uframe; + struct pkt_attrib *attrib; + + sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]); + if (!(sta->state & WIFI_ASOC_STATE) + || _rtw_memcmp(sta->phl_sta->mac_addr, msa, ETH_ALEN) == _TRUE + || (ori_ta && _rtw_memcmp(sta->phl_sta->mac_addr, ori_ta, ETH_ALEN) == _TRUE) + || is_broadcast_mac_addr(sta->phl_sta->mac_addr) + || is_zero_mac_addr(sta->phl_sta->mac_addr)) + continue; + + b2uframe = rtw_alloc_xmitframe(xmitpriv, os_qid); + if (!b2uframe) { + bmc_need = _TRUE; + break; + } + + if ((*b2u_num)++ == 0 && !ori_ta) { + *b2u_mseq = (cpu_to_le32(adapter->mesh_info.mesh_seqnum)); + adapter->mesh_info.mesh_seqnum++; + } + + attrib = &b2uframe->attrib; + + attrib->mb2u = 1; + attrib->mseq = *b2u_mseq; + attrib->mfwd_ttl = ori_ta ? mfwd_ttl : 0; + _rtw_memcpy(attrib->ra, sta->phl_sta->mac_addr, ETH_ALEN); + _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(attrib->mda, mda, ETH_ALEN); + _rtw_memcpy(attrib->msa, msa, ETH_ALEN); + _rtw_memcpy(attrib->dst, da, ETH_ALEN); + _rtw_memcpy(attrib->src, sa, ETH_ALEN); + attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA; + + rtw_list_insert_tail(&b2uframe->list, b2u_list); + } + +exit: + return bmc_need; +} + +void dump_mesh_b2u_flags(void *sel, _adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + + RTW_PRINT_SEL(sel, "%4s %4s\n", "msrc", "mfwd"); + RTW_PRINT_SEL(sel, "0x%02x 0x%02x\n", mcfg->b2u_flags_msrc, mcfg->b2u_flags_mfwd); +} +#endif /* CONFIG_RTW_MESH_DATA_BMC_TO_UC */ + +int rtw_mesh_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list) +{ + struct pkt_file pktfile; + struct ethhdr etherhdr; + struct pkt_attrib *attrib; + struct rtw_mesh_path *mpath = NULL, *mppath = NULL; + u8 is_da_mcast; + u8 ae_need; +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + bool bmc_need = _TRUE; + u8 b2u_num = 0; + u32 b2u_mseq = 0; +#endif + int res = _SUCCESS; + + _rtw_open_pktfile(pkt, &pktfile); + if (_rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN) != ETH_HLEN) { + res = _FAIL; + goto exit; + } + + xframe->pkt = pkt; +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + _rtw_init_listhead(b2u_list); +#endif + + is_da_mcast = IS_MCAST(etherhdr.h_dest); + if (!is_da_mcast) { + struct sta_info *next_hop; + bool mpp_lookup = 1; + + mpath = rtw_mesh_path_lookup(adapter, etherhdr.h_dest); + if (mpath) { + mpp_lookup = 0; + next_hop = rtw_rcu_dereference(mpath->next_hop); + if (!next_hop + || !(mpath->flags & (RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVING)) + ) { + /* mpath is not valid, search mppath */ + mpp_lookup = 1; + } + } + + if (mpp_lookup) { + mppath = rtw_mpp_path_lookup(adapter, etherhdr.h_dest); + if (mppath) + mppath->exp_time = rtw_get_current_time(); + } + + if (mppath && mpath) + rtw_mesh_path_del(adapter, mpath->dst); + + ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE + || (mppath && _rtw_memcmp(mppath->mpp, etherhdr.h_dest, ETH_ALEN) == _FALSE); + } else { + ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE; + + #if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (rtw_msrc_b2u_policy_chk(adapter->mesh_cfg.b2u_flags_msrc, etherhdr.h_dest)) { + bmc_need = rtw_mesh_data_bmc_to_uc(adapter + , etherhdr.h_dest, etherhdr.h_source + , etherhdr.h_dest, adapter_mac_addr(adapter), ae_need, NULL, 0 + , os_qid, b2u_list, &b2u_num, &b2u_mseq); + if (bmc_need == _FALSE) { + res = RTW_ORI_NO_NEED; + goto exit; + } + } + #endif + } + + attrib = &xframe->attrib; + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (b2u_num) { + attrib->mb2u = 1; + attrib->mseq = b2u_mseq; + } else + attrib->mb2u = 0; +#endif + + attrib->mfwd_ttl = 0; + _rtw_memcpy(attrib->dst, etherhdr.h_dest, ETH_ALEN); + _rtw_memcpy(attrib->src, etherhdr.h_source, ETH_ALEN); + _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + + if (is_da_mcast) { + attrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA; + _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN); + _rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN); + } else { + attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA; + _rtw_memcpy(attrib->mda, (mppath && ae_need) ? mppath->mpp : attrib->dst, ETH_ALEN); + _rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN); + /* RA needs to be resolved */ + res = rtw_mesh_nexthop_resolve(adapter, xframe); + } + +exit: + return res; +} + +s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib) +{ + u8 ret = 0; + switch (mesh_frame_mode) { + case MESH_UCAST_DATA: + attrib->hdrlen = WLAN_HDR_A4_QOS_LEN; + attrib->a4_hdr = 1; + /* mesh flag + mesh TTL + Mesh SN. no ext addr. */ + attrib->meshctrl_len = 6; + break; + case MESH_BMCAST_DATA: + attrib->hdrlen = WLAN_HDR_A3_QOS_LEN; + /* mesh flag + mesh TTL + Mesh SN. no ext addr. */ + attrib->meshctrl_len = 6; + break; + case MESH_UCAST_PX_DATA: + attrib->hdrlen = WLAN_HDR_A4_QOS_LEN; + attrib->a4_hdr = 1; + /* mesh flag + mesh TTL + Mesh SN + extaddr1 + extaddr2. */ + attrib->meshctrl_len = 18; + break; + case MESH_BMCAST_PX_DATA: + attrib->hdrlen = WLAN_HDR_A3_QOS_LEN; + /* mesh flag + mesh TTL + Mesh SN + extaddr1 */ + attrib->meshctrl_len = 12; + break; + default: + RTW_WARN("Invalid mesh frame mode:%u\n", mesh_frame_mode); + ret = -1; + break; + } + + return ret; +} + +void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf) +{ + struct rtw_ieee80211s_hdr *mctrl = (struct rtw_ieee80211s_hdr *)buf; + + _rtw_memset(mctrl, 0, XATTRIB_GET_MCTRL_LEN(attrib)); + + if (attrib->mfwd_ttl + #if CONFIG_RTW_MESH_DATA_BMC_TO_UC + || attrib->mb2u + #endif + ) { + #if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (!attrib->mfwd_ttl) + mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL; + else + #endif + mctrl->ttl = attrib->mfwd_ttl; + + mctrl->seqnum = (cpu_to_le32(attrib->mseq)); + } else { + mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL; + mctrl->seqnum = (cpu_to_le32(adapter->mesh_info.mesh_seqnum)); + adapter->mesh_info.mesh_seqnum++; + } + + switch (attrib->mesh_frame_mode){ + case MESH_UCAST_DATA: + case MESH_BMCAST_DATA: + break; + case MESH_UCAST_PX_DATA: + mctrl->flags |= MESH_FLAGS_AE_A5_A6; + _rtw_memcpy(mctrl->eaddr1, attrib->dst, ETH_ALEN); + _rtw_memcpy(mctrl->eaddr2, attrib->src, ETH_ALEN); + break; + case MESH_BMCAST_PX_DATA: + mctrl->flags |= MESH_FLAGS_AE_A4; + _rtw_memcpy(mctrl->eaddr1, attrib->src, ETH_ALEN); + break; + case MESH_MHOP_UCAST_ACT: + /* TBD */ + break; + case MESH_MHOP_BMCAST_ACT: + /* TBD */ + break; + default: + break; + } +} + +u8 rtw_mesh_tx_build_whdr(_adapter *adapter, struct pkt_attrib *attrib + , u16 *fctrl, struct rtw_ieee80211_hdr *whdr) +{ + switch (attrib->mesh_frame_mode) { + case MESH_UCAST_DATA: /* 1, 1, RA, TA, mDA(=DA), mSA(=SA) */ + case MESH_UCAST_PX_DATA: /* 1, 1, RA, TA, mDA, mSA, [DA, SA] */ + SetToDs(fctrl); + SetFrDs(fctrl); + _rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN); + _rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN); + _rtw_memcpy(whdr->addr3, attrib->mda, ETH_ALEN); + _rtw_memcpy(whdr->addr4, attrib->msa, ETH_ALEN); + break; + case MESH_BMCAST_DATA: /* 0, 1, RA(DA), TA, mSA(SA) */ + case MESH_BMCAST_PX_DATA: /* 0, 1, RA(DA), TA, mSA, [SA] */ + SetFrDs(fctrl); + _rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN); + _rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN); + _rtw_memcpy(whdr->addr3, attrib->msa, ETH_ALEN); + break; + case MESH_MHOP_UCAST_ACT: + /* TBD */ + RTW_INFO("MESH_MHOP_UCAST_ACT\n"); + break; + case MESH_MHOP_BMCAST_ACT: + /* TBD */ + RTW_INFO("MESH_MHOP_BMCAST_ACT\n"); + break; + default: + RTW_WARN("Invalid mesh frame mode\n"); + break; + } + + return 0; +} + +int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + u8 *whdr = get_recvframe_data(rframe); + u8 is_ra_bmc = 0; + u8 a4_shift = 0; + u8 ps; + u8 *qc; + u8 mps_mode = RTW_MESH_PS_UNKNOWN; + sint ret = _FAIL; + + if (!(MLME_STATE(adapter) & WIFI_ASOC_STATE)) + goto exit; + + if (!rattrib->qos) + goto exit; + + switch (rattrib->to_fr_ds) { + case 1: + if (!IS_MCAST(GetAddr1Ptr(whdr))) + goto exit; + *sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr)); + if (*sta == NULL) { + ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */ + goto exit; + } + _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->mda, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->msa, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + _rtw_memcpy(rattrib->dst, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->src, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */ + _rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN); + is_ra_bmc = 1; + break; + case 3: + if (IS_MCAST(GetAddr1Ptr(whdr))) + goto exit; + *sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr)); + if (*sta == NULL) { + ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */ + goto exit; + } + _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->mda, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + _rtw_memcpy(rattrib->msa, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */ + _rtw_memcpy(rattrib->src, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */ + _rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN); + a4_shift = ETH_ALEN; + break; + default: + goto exit; + } + + qc = whdr + WLAN_HDR_A3_LEN + a4_shift; + ps = GetPwrMgt(whdr); + mps_mode = ps ? (is_ra_bmc || (get_mps_lv(qc)) ? RTW_MESH_PS_DSLEEP : RTW_MESH_PS_LSLEEP) : RTW_MESH_PS_ACTIVE; + + if (ps) { + if (!((*sta)->state & WIFI_SLEEP_STATE)) + stop_sta_xmit(adapter, *sta); + } else { + if ((*sta)->state & WIFI_SLEEP_STATE) + wakeup_sta_to_xmit(adapter, *sta); + } + + if (is_ra_bmc) + (*sta)->nonpeer_mps = mps_mode; + else { + (*sta)->peer_mps = mps_mode; + if (mps_mode != RTW_MESH_PS_ACTIVE && (*sta)->nonpeer_mps == RTW_MESH_PS_ACTIVE) + (*sta)->nonpeer_mps = RTW_MESH_PS_DSLEEP; + } + + if (get_frame_sub_type(whdr) & BIT(6)) { + /* No data, will not indicate to upper layer, temporily count it here */ + count_rx_stats(adapter, rframe, *sta); + ret = RTW_RX_HANDLED; + goto exit; + } + + rattrib->mesh_ctrl_present = get_mctrl_present(qc) ? 1 : 0; + if (!rattrib->mesh_ctrl_present) + goto exit; + + ret = _SUCCESS; + +exit: + return ret; +} + +int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe + , const struct rtw_ieee80211s_hdr *mctrl, const u8 *mda, const u8 *msa + , u8 *mctrl_len + , const u8 **da, const u8 **sa) +{ + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + u8 mlen; + u8 ae; + int ret = _SUCCESS; + + ae = mctrl->flags & MESH_FLAGS_AE; + mlen = ae_to_mesh_ctrl_len[ae]; + switch (rattrib->to_fr_ds) { + case 1: + *da = mda; + if (ae == MESH_FLAGS_AE_A4) + *sa = mctrl->eaddr1; + else if (ae == 0) + *sa = msa; + else + ret = _FAIL; + break; + case 3: + if (ae == MESH_FLAGS_AE_A5_A6) { + *da = mctrl->eaddr1; + *sa = mctrl->eaddr2; + } else if (ae == 0) { + *da = mda; + *sa = msa; + } else + ret = _FAIL; + break; + default: + ret = _FAIL; + } + + if (ret == _FAIL) { + #ifdef DBG_RX_DROP_FRAME + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" invalid tfDS:%u AE:%u combination ra="MAC_FMT" ta="MAC_FMT"\n" + , FUNC_ADPT_ARG(adapter), rattrib->to_fr_ds, ae, MAC_ARG(rattrib->ra), MAC_ARG(rattrib->ta)); + #endif + *mctrl_len = 0; + } else + *mctrl_len = mlen; + + return ret; +} + +inline int rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter *adapter, union recv_frame *rframe) +{ + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + const u8 *da, *sa; + int ret; + + ret = rtw_mesh_rx_data_validate_mctrl(adapter, rframe + , (struct rtw_ieee80211s_hdr *)(get_recvframe_data(rframe) + rattrib->hdrlen + rattrib->iv_len) + , rattrib->mda, rattrib->msa + , &rattrib->mesh_ctrl_len + , &da, &sa); + + if (ret == _SUCCESS) { + _rtw_memcpy(rattrib->dst, da, ETH_ALEN); + _rtw_memcpy(rattrib->src, sa, ETH_ALEN); + } + + return ret; +} + +/** + * rtw_mesh_rx_nexthop_resolve - lookup next hop; conditionally start path discovery + * + * @skb: 802.11 frame to be sent + * @sdata: network subif the frame will be sent through + * + * Lookup next hop for given skb and start path discovery if no + * forwarding information is found. + * + * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. + * skb is freeed here if no mpath could be allocated. + */ +static int rtw_mesh_rx_nexthop_resolve(_adapter *adapter, + const u8 *mda, const u8 *msa, u8 *ra) +{ + struct rtw_mesh_path *mpath; + struct xmit_frame *xframe_to_free = NULL; + int err = 0; + int ret = _SUCCESS; + + rtw_rcu_read_lock(); + err = rtw_mesh_nexthop_lookup(adapter, mda, msa, ra); + if (!err) + goto endlookup; + + /* no nexthop found, start resolving */ + mpath = rtw_mesh_path_lookup(adapter, mda); + if (!mpath) { + mpath = rtw_mesh_path_add(adapter, mda); + if (IS_ERR(mpath)) { + err = PTR_ERR(mpath); + ret = _FAIL; + goto endlookup; + } + } + + if (!(mpath->flags & RTW_MESH_PATH_RESOLVING)) + rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START); + + ret = _FAIL; + +endlookup: + rtw_rcu_read_unlock(); + return ret; +} + +#define RTW_MESH_DECACHE_BMC 1 +#define RTW_MESH_DECACHE_UC 0 + +#define RTW_MESH_FORWARD_MDA_SELF_COND 0 +#define DBG_RTW_MESH_FORWARD_MDA_SELF_COND 0 +int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe + , const u8 *mda, const u8 *msa + , const u8 *da, const u8 *sa + , struct rtw_ieee80211s_hdr *mctrl + , u8 *msdu, enum rtw_rx_llc_hdl llc_hdl + , struct xmit_frame **fwd_frame, _list *b2u_list) +{ + _adapter *adapter = rframe->u.hdr.adapter; + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + struct rtw_mesh_path *mppath; + u8 is_mda_bmc = IS_MCAST(mda); + u8 is_mda_self = !is_mda_bmc && _rtw_memcmp(mda, adapter_mac_addr(adapter), ETH_ALEN); + u16 os_qid; + struct xmit_frame *xframe; + struct pkt_attrib *xattrib; + u8 fwd_ra[ETH_ALEN] = {0}; + u8 fwd_mpp[ETH_ALEN] = {0}; /* forward to other gate */ + u32 fwd_mseq; + int act = 0; + u8 ae_need; +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + bool ori_need = _TRUE; + u8 b2u_num = 0; +#endif + + /* fwd info lifetime update */ + #if 0 + if (!is_mda_self) + mDA(A3) fwinfo.lifetime + mSA(A4) fwinfo.lifetime + Precursor-to-mDA(A2) fwinfo.lifetime + #endif + + /* update/create pxoxy info for SA, mSA */ + if ((mctrl->flags & MESH_FLAGS_AE) + && sa != msa && _rtw_memcmp(sa, msa, ETH_ALEN) == _FALSE + ) { + const u8 *proxied_addr = sa; + const u8 *mpp_addr = msa; + + rtw_rcu_read_lock(); + mppath = rtw_mpp_path_lookup(adapter, proxied_addr); + if (!mppath) + rtw_mpp_path_add(adapter, proxied_addr, mpp_addr); + else { + _rtw_spinlock_bh(&mppath->state_lock); + if (_rtw_memcmp(mppath->mpp, mpp_addr, ETH_ALEN) == _FALSE) + _rtw_memcpy(mppath->mpp, mpp_addr, ETH_ALEN); + mppath->exp_time = rtw_get_current_time(); + _rtw_spinunlock_bh(&mppath->state_lock); + } + rtw_rcu_read_unlock(); + } + + /* mSA is self, need no further process */ + if (_rtw_memcmp(msa, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE) + goto exit; + + fwd_mseq = le32_to_cpu(mctrl->seqnum); + + /* check duplicate MSDU from mSA */ + if (((RTW_MESH_DECACHE_BMC && is_mda_bmc) + || (RTW_MESH_DECACHE_UC && !is_mda_bmc)) + && rtw_mesh_decache(adapter, msa, fwd_mseq) + ) { + minfo->mshstats.dropped_frames_duplicate++; + goto exit; + } + + if (is_mda_bmc) { + /* mDA is bmc addr */ + act |= RTW_RX_MSDU_ACT_INDICATE; + if (!mcfg->dot11MeshForwarding) + goto exit; + goto fwd_chk; + + } else if (!is_mda_self) { + /* mDA is unicast but not self */ + if (!mcfg->dot11MeshForwarding) { + rtw_mesh_path_error_tx(adapter + , adapter->mesh_cfg.element_ttl + , mda, 0 + , WLAN_REASON_MESH_PATH_NOFORWARD + , rattrib->ta + ); + #ifdef DBG_RX_DROP_FRAME + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") not self, !dot11MeshForwarding\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(mda)); + #endif + goto exit; + } + + if (rtw_mesh_rx_nexthop_resolve(adapter, mda, msa, fwd_ra) != _SUCCESS) { + /* mDA is unknown */ + rtw_mesh_path_error_tx(adapter + , adapter->mesh_cfg.element_ttl + , mda, 0 + , WLAN_REASON_MESH_PATH_NOFORWARD + , rattrib->ta + ); + #ifdef DBG_RX_DROP_FRAME + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") unknown\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(mda)); + #endif + minfo->mshstats.dropped_frames_no_route++; + goto exit; + + } else { + /* mDA is known in fwd info */ + #if 0 + if (TA is not in precursors) + goto exit; + #endif + goto fwd_chk; + } + + } else { + /* mDA is self */ + #if RTW_MESH_FORWARD_MDA_SELF_COND + if (da == mda + || _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN) + ) { + /* DA is self, indicate */ + act |= RTW_RX_MSDU_ACT_INDICATE; + goto exit; + } + + if (rtw_get_iface_by_macddr(adapter, da)) { + /* DA is buddy, indicate */ + act |= RTW_RX_MSDU_ACT_INDICATE; + #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is buddy("ADPT_FMT")\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da), ADPT_ARG(rtw_get_iface_by_macddr(adapter, da))); + #endif + goto exit; + } + + /* DA is not self or buddy */ + if (rtw_mesh_nexthop_lookup(adapter, da, msa, fwd_ra) == 0) { + /* DA is known in fwd info */ + if (!mcfg->dot11MeshForwarding) { + /* path error to? */ + #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") not self, !dot11MeshForwarding\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da)); + #endif + goto exit; + } + mda = da; + #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO(FUNC_ADPT_FMT" fwd to DA("MAC_FMT"), fwd_RA("MAC_FMT")\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(fwd_ra)); + #endif + goto fwd_chk; + } + + rtw_rcu_read_lock(); + mppath = rtw_mpp_path_lookup(adapter, da); + if (mppath) { + if (_rtw_memcmp(mppath->mpp, adapter_mac_addr(adapter), ETH_ALEN) == _FALSE) { + /* DA is proxied by others */ + if (!mcfg->dot11MeshForwarding) { + /* path error to? */ + #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), !dot11MeshForwarding\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp)); + #endif + rtw_rcu_read_unlock(); + goto exit; + } + _rtw_memcpy(fwd_mpp, mppath->mpp, ETH_ALEN); + mda = fwd_mpp; + msa = adapter_mac_addr(adapter); + rtw_rcu_read_unlock(); + + /* resolve RA */ + if (rtw_mesh_nexthop_lookup(adapter, mda, msa, fwd_ra) != 0) { + minfo->mshstats.dropped_frames_no_route++; + #if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), RA resolve fail\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp)); + #endif + goto exit; + } + #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), fwd_RA("MAC_FMT")\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp), MAC_ARG(fwd_ra)); + #endif + goto fwd_chk; /* forward to other gate */ + } else { + #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by self\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da)); + #endif + } + } + rtw_rcu_read_unlock(); + + if (!mppath) { + #if DBG_RTW_MESH_FORWARD_MDA_SELF_COND + RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") unknown\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da)); + #endif + /* DA is unknown */ + #if 0 /* TODO: flags with AE bit */ + rtw_mesh_path_error_tx(adapter + , adapter->mesh_cfg.element_ttl + , mda, adapter->mesh_info.last_sn_update + , WLAN_REASON_MESH_PATH_NOPROXY + , msa + ); + #endif + } + + /* + * indicate to DS for both cases: + * 1.) DA is proxied by self + * 2.) DA is unknown + */ + #endif /* RTW_MESH_FORWARD_MDA_SELF_COND */ + act |= RTW_RX_MSDU_ACT_INDICATE; + goto exit; + } + +fwd_chk: + + if (adapter->stapriv.asoc_list_cnt <= 1) + goto exit; + + if (mctrl->ttl == 1) { + minfo->mshstats.dropped_frames_ttl++; + if (!act) { + #ifdef DBG_RX_DROP_FRAME + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" ttl reaches 0, not forwarding\n" + , FUNC_ADPT_ARG(adapter)); + #endif + } + goto exit; + } + + os_qid = rtw_os_recv_select_queue(msdu, llc_hdl); + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + _rtw_init_listhead(b2u_list); +#endif + + ae_need = _rtw_memcmp(da , mda, ETH_ALEN) == _FALSE + || _rtw_memcmp(sa , msa, ETH_ALEN) == _FALSE; + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (is_mda_bmc + && rtw_mfwd_b2u_policy_chk(mcfg->b2u_flags_mfwd, mda, rattrib->to_fr_ds == 3) + ) { + ori_need = rtw_mesh_data_bmc_to_uc(adapter + , da, sa, mda, msa, ae_need, rframe->u.hdr.psta->phl_sta->mac_addr, mctrl->ttl - 1 + , os_qid, b2u_list, &b2u_num, &fwd_mseq); + } + + if (ori_need == _TRUE) +#endif + { + xframe = rtw_alloc_xmitframe(&adapter->xmitpriv, os_qid); + if (!xframe) { + #ifdef DBG_TX_DROP_FRAME + RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" rtw_alloc_xmitframe fail\n" + , FUNC_ADPT_ARG(adapter)); + #endif + goto exit; + } + + xattrib = &xframe->attrib; + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (b2u_num) + xattrib->mb2u = 1; + else + xattrib->mb2u = 0; +#endif + xattrib->mfwd_ttl = mctrl->ttl - 1; + xattrib->mseq = fwd_mseq; + _rtw_memcpy(xattrib->dst, da, ETH_ALEN); + _rtw_memcpy(xattrib->src, sa, ETH_ALEN); + _rtw_memcpy(xattrib->mda, mda, ETH_ALEN); + _rtw_memcpy(xattrib->msa, msa, ETH_ALEN); + _rtw_memcpy(xattrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + + if (is_mda_bmc) { + xattrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA; + _rtw_memcpy(xattrib->ra, mda, ETH_ALEN); + } else { + xattrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA; + _rtw_memcpy(xattrib->ra, fwd_ra, ETH_ALEN); + } + + *fwd_frame = xframe; + } + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + if (ori_need || b2u_num) +#endif + { + act |= RTW_RX_MSDU_ACT_FORWARD; + if (is_mda_bmc) + minfo->mshstats.fwded_mcast++; + else + minfo->mshstats.fwded_unicast++; + minfo->mshstats.fwded_frames++; + } + +exit: + return act; +} + +void dump_mesh_stats(void *sel, _adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_stats *stats = &minfo->mshstats; + + RTW_PRINT_SEL(sel, "fwd_bmc:%u\n", stats->fwded_mcast); + RTW_PRINT_SEL(sel, "fwd_uc:%u\n", stats->fwded_unicast); + + RTW_PRINT_SEL(sel, "drop_ttl:%u\n", stats->dropped_frames_ttl); + RTW_PRINT_SEL(sel, "drop_no_route:%u\n", stats->dropped_frames_no_route); + RTW_PRINT_SEL(sel, "drop_congestion:%u\n", stats->dropped_frames_congestion); + RTW_PRINT_SEL(sel, "drop_dup:%u\n", stats->dropped_frames_duplicate); + + RTW_PRINT_SEL(sel, "mrc_del_qlen:%u\n", stats->mrc_del_qlen); +} +#endif /* CONFIG_RTW_MESH */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.h b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.h new file mode 100644 index 00000000..56d1f4b9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh.h @@ -0,0 +1,537 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_MESH_H_ +#define __RTW_MESH_H_ + +#ifndef CONFIG_AP_MODE + #error "CONFIG_RTW_MESH can't be enabled when CONFIG_AP_MODE is not defined\n" +#endif + +#define RTW_MESH_TTL 31 +#define RTW_MESH_PERR_MIN_INT 100 +#define RTW_MESH_DEFAULT_ELEMENT_TTL 31 +#define RTW_MESH_RANN_INTERVAL 5000 +#define RTW_MESH_PATH_TO_ROOT_TIMEOUT 6000 +#define RTW_MESH_DIAM_TRAVERSAL_TIME 50 +#define RTW_MESH_PATH_TIMEOUT 5000 +#define RTW_MESH_PREQ_MIN_INT 10 +#define RTW_MESH_MAX_PREQ_RETRIES 4 +#define RTW_MESH_MIN_DISCOVERY_TIMEOUT (2 * RTW_MESH_DIAM_TRAVERSAL_TIME) +#define RTW_MESH_ROOT_CONFIRMATION_INTERVAL 2000 +#define RTW_MESH_PATH_REFRESH_TIME 1000 +#define RTW_MESH_ROOT_INTERVAL 5000 + +#define RTW_MESH_SANE_METRIC_DELTA 100 +#define RTW_MESH_MAX_ROOT_ADD_CHK_CNT 2 + +#define RTW_MESH_PLINK_UNKNOWN 0 +#define RTW_MESH_PLINK_LISTEN 1 +#define RTW_MESH_PLINK_OPN_SNT 2 +#define RTW_MESH_PLINK_OPN_RCVD 3 +#define RTW_MESH_PLINK_CNF_RCVD 4 +#define RTW_MESH_PLINK_ESTAB 5 +#define RTW_MESH_PLINK_HOLDING 6 +#define RTW_MESH_PLINK_BLOCKED 7 + +extern const char *_rtw_mesh_plink_str[]; +#define rtw_mesh_plink_str(s) ((s <= RTW_MESH_PLINK_BLOCKED) ? _rtw_mesh_plink_str[s] : _rtw_mesh_plink_str[RTW_MESH_PLINK_UNKNOWN]) + +#define RTW_MESH_PS_UNKNOWN 0 +#define RTW_MESH_PS_ACTIVE 1 +#define RTW_MESH_PS_LSLEEP 2 +#define RTW_MESH_PS_DSLEEP 3 + +extern const char *_rtw_mesh_ps_str[]; +#define rtw_mesh_ps_str(mps) ((mps <= RTW_MESH_PS_DSLEEP) ? _rtw_mesh_ps_str[mps] : _rtw_mesh_ps_str[RTW_MESH_PS_UNKNOWN]) + +#define GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 0, 0, 8) +#define GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 1, 0, 8) +#define GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 2, 0, 8) +#define GET_MESH_CONF_ELE_SYNC_METHOD_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 3, 0, 8) +#define GET_MESH_CONF_ELE_AUTH_PROTO_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 4, 0, 8) + +#define GET_MESH_CONF_ELE_MESH_FORMATION(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 0, 8) +#define GET_MESH_CONF_ELE_CTO_MGATE(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 0, 1) +#define GET_MESH_CONF_ELE_NUM_OF_PEERINGS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 1, 6) +#define GET_MESH_CONF_ELE_CTO_AS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 7, 1) + +#define GET_MESH_CONF_ELE_MESH_CAP(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 0, 8) +#define GET_MESH_CONF_ELE_ACCEPT_PEERINGS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 0, 1) +#define GET_MESH_CONF_ELE_MCCA_SUP(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 1, 1) +#define GET_MESH_CONF_ELE_MCCA_EN(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 2, 1) +#define GET_MESH_CONF_ELE_FORWARDING(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 3, 1) +#define GET_MESH_CONF_ELE_MBCA_EN(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 4, 1) +#define GET_MESH_CONF_ELE_TBTT_ADJ(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 5, 1) +#define GET_MESH_CONF_ELE_PS_LEVEL(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 6, 1) + +#define SET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 0, 0, 8, _val) +#define SET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 1, 0, 8, _val) +#define SET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 2, 0, 8, _val) +#define SET_MESH_CONF_ELE_SYNC_METHOD_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 3, 0, 8, _val) +#define SET_MESH_CONF_ELE_AUTH_PROTO_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 4, 0, 8, _val) + +#define SET_MESH_CONF_ELE_CTO_MGATE(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 0, 1, _val) +#define SET_MESH_CONF_ELE_NUM_OF_PEERINGS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 1, 6, _val) +#define SET_MESH_CONF_ELE_CTO_AS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 7, 1, _val) + +#define SET_MESH_CONF_ELE_ACCEPT_PEERINGS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 0, 1, _val) +#define SET_MESH_CONF_ELE_MCCA_SUP(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 1, 1, _val) +#define SET_MESH_CONF_ELE_MCCA_EN(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 2, 1, _val) +#define SET_MESH_CONF_ELE_FORWARDING(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 3, 1, _val) +#define SET_MESH_CONF_ELE_MBCA_EN(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 4, 1, _val) +#define SET_MESH_CONF_ELE_TBTT_ADJ(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 5, 1, _val) +#define SET_MESH_CONF_ELE_PS_LEVEL(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 6, 1, _val) + +/* Mesh flags */ +#define MESH_FLAGS_AE 0x3 /* mask */ +#define MESH_FLAGS_AE_A4 0x1 +#define MESH_FLAGS_AE_A5_A6 0x2 + +/* Max number of paths */ +#define RTW_MESH_MAX_PATHS 1024 + +#define RTW_PREQ_Q_F_START 0x1 +#define RTW_PREQ_Q_F_REFRESH 0x2 +#define RTW_PREQ_Q_F_CHK 0x4 +#define RTW_PREQ_Q_F_PEER_AKA 0x8 +#define RTW_PREQ_Q_F_BCAST_PREQ 0x10 /* force path_dicover using broadcast */ +struct rtw_mesh_preq_queue { + _list list; + u8 dst[ETH_ALEN]; + u8 flags; +}; + +extern const u8 ae_to_mesh_ctrl_len[]; + +enum mesh_frame_type { + MESH_UCAST_DATA = 0x0, + MESH_BMCAST_DATA = 0x1, + MESH_UCAST_PX_DATA = 0x2, + MESH_BMCAST_PX_DATA = 0x3, + MESH_MHOP_UCAST_ACT = 0x4, + MESH_MHOP_BMCAST_ACT = 0x5, +}; + +enum mpath_sel_frame_type { + MPATH_PREQ = 0, + MPATH_PREP, + MPATH_PERR, + MPATH_RANN +}; + +/** + * enum rtw_mesh_deferred_task_flags - mesh deferred tasks + * + * + * + * @RTW_MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks + * @RTW_MESH_WORK_ROOT: the mesh root station needs to send a frame + * @RTW_MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other + * mesh nodes + * @RTW_MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes + */ +enum rtw_mesh_deferred_task_flags { + RTW_MESH_WORK_HOUSEKEEPING, + RTW_MESH_WORK_ROOT, + RTW_MESH_WORK_DRIFT_ADJUST, + RTW_MESH_WORK_MBSS_CHANGED, +}; + +#define RTW_MESH_MAX_PEER_CANDIDATES 15 /* aid consideration */ +#define RTW_MESH_MAX_PEER_LINKS 8 +#define RTW_MESH_PEER_LINK_TIMEOUT 20 + +#define RTW_MESH_PEER_CONF_DISABLED 0 /* special time value means no confirmation ongoing */ +#if CONFIG_RTW_MESH_PEER_BLACKLIST +#define IS_PEER_CONF_DISABLED(plink) ((plink)->peer_conf_end_time == RTW_MESH_PEER_CONF_DISABLED) +#define IS_PEER_CONF_TIMEOUT(plink)(!IS_PEER_CONF_DISABLED(plink) && rtw_time_after(rtw_get_current_time(), (plink)->peer_conf_end_time)) +#define SET_PEER_CONF_DISABLED(plink) (plink)->peer_conf_end_time = RTW_MESH_PEER_CONF_DISABLED +#define SET_PEER_CONF_END_TIME(plink, timeout_ms) \ + do { \ + (plink)->peer_conf_end_time = rtw_get_current_time() + rtw_ms_to_systime(timeout_ms); \ + if ((plink)->peer_conf_end_time == RTW_MESH_PEER_CONF_DISABLED) \ + (plink)->peer_conf_end_time++; \ + } while (0) +#else +#define IS_PEER_CONF_DISABLED(plink) 1 +#define IS_PEER_CONF_TIMEOUT(plink) 0 +#define SET_PEER_CONF_DISABLED(plink) do {} while (0) +#define SET_PEER_CONF_END_TIME(plink, timeout_ms) do {} while (0) +#endif /* CONFIG_RTW_MESH_PEER_BLACKLIST */ + +#define RTW_MESH_CTO_MGATE_CONF_DISABLED 0 /* special time value means no confirmation ongoing */ +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST +#define IS_CTO_MGATE_CONF_DISABLED(plink) ((plink)->cto_mgate_conf_end_time == RTW_MESH_CTO_MGATE_CONF_DISABLED) +#define IS_CTO_MGATE_CONF_TIMEOUT(plink)(!IS_CTO_MGATE_CONF_DISABLED(plink) && rtw_time_after(rtw_get_current_time(), (plink)->cto_mgate_conf_end_time)) +#define SET_CTO_MGATE_CONF_DISABLED(plink) (plink)->cto_mgate_conf_end_time = RTW_MESH_CTO_MGATE_CONF_DISABLED +#define SET_CTO_MGATE_CONF_END_TIME(plink, timeout_ms) \ + do { \ + (plink)->cto_mgate_conf_end_time = rtw_get_current_time() + rtw_ms_to_systime(timeout_ms); \ + if ((plink)->cto_mgate_conf_end_time == RTW_MESH_CTO_MGATE_CONF_DISABLED) \ + (plink)->cto_mgate_conf_end_time++; \ + } while (0) +#else +#define IS_CTO_MGATE_CONF_DISABLED(plink) 1 +#define IS_CTO_MGATE_CONF_TIMEOUT(plink) 0 +#define SET_CTO_MGATE_CONF_DISABLED(plink) do {} while (0) +#define SET_CTO_MGATE_CONF_END_TIME(plink, timeout_ms) do {} while (0) +#endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */ + +struct mesh_plink_ent { + u8 valid; + u8 addr[ETH_ALEN]; + u8 plink_state; + +#ifdef CONFIG_RTW_MESH_AEK + u8 aek_valid; + u8 aek[32]; +#endif + + u16 llid; + u16 plid; +#ifndef CONFIG_RTW_MESH_DRIVER_AID + u16 aid; /* aid assigned from upper layer */ +#endif + u16 peer_aid; /* aid assigned from peer */ + + u8 chosen_pmk[16]; + +#ifdef CONFIG_RTW_MESH_AEK + u8 sel_pcs[4]; + u8 l_nonce[32]; + u8 p_nonce[32]; +#endif + +#ifdef CONFIG_RTW_MESH_DRIVER_AID + u8 *tx_conf_ies; + u16 tx_conf_ies_len; +#endif + u8 *rx_conf_ies; + u16 rx_conf_ies_len; + + struct wlan_network *scanned; + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + systime peer_conf_end_time; +#endif +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + systime cto_mgate_conf_end_time; +#endif +}; + +#ifdef CONFIG_RTW_MESH_AEK +#define MESH_PLINK_AEK_VALID(ent) ent->aek_valid +#else +#define MESH_PLINK_AEK_VALID(ent) 0 +#endif + +struct mesh_plink_pool { + _lock lock; + u8 num; /* current ent being used */ + struct mesh_plink_ent ent[RTW_MESH_MAX_PEER_CANDIDATES]; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + u8 acnode_rsvd; +#endif + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + _queue peer_blacklist; +#endif +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + _queue cto_mgate_blacklist; +#endif +}; + +struct mesh_peer_sel_policy { + u32 scanr_exp_ms; + +#if CONFIG_RTW_MESH_ACNODE_PREVENT + u8 acnode_prevent; + u32 acnode_conf_timeout_ms; + u32 acnode_notify_timeout_ms; +#endif + +#if CONFIG_RTW_MESH_OFFCH_CAND + u8 offch_cand; + u32 offch_find_int_ms; /* 0 means no offch find triggerred by driver self*/ +#endif + +#if CONFIG_RTW_MESH_PEER_BLACKLIST + u32 peer_conf_timeout_ms; + u32 peer_blacklist_timeout_ms; +#endif + +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST + u8 cto_mgate_require; + u32 cto_mgate_conf_timeout_ms; + u32 cto_mgate_blacklist_timeout_ms; +#endif +}; + +/* b2u flags */ +#define RTW_MESH_B2U_ALL BIT0 +#define RTW_MESH_B2U_GA_UCAST BIT1 /* Group addressed unicast frame, forward only */ +#define RTW_MESH_B2U_BCAST BIT2 +#define RTW_MESH_B2U_IP_MCAST BIT3 + +#define rtw_msrc_b2u_policy_chk(flags, mda) ( \ + (flags & RTW_MESH_B2U_ALL) \ + || ((flags & RTW_MESH_B2U_BCAST) && is_broadcast_mac_addr(mda)) \ + || ((flags & RTW_MESH_B2U_IP_MCAST) && (IP_MCAST_MAC(mda) || ICMPV6_MCAST_MAC(mda))) \ + ) + +#define rtw_mfwd_b2u_policy_chk(flags, mda, ucst) ( \ + (flags & RTW_MESH_B2U_ALL) \ + || ((flags & RTW_MESH_B2U_GA_UCAST) && ucst) \ + || ((flags & RTW_MESH_B2U_BCAST) && is_broadcast_mac_addr(mda)) \ + || ((flags & RTW_MESH_B2U_IP_MCAST) && (IP_MCAST_MAC(mda) || ICMPV6_MCAST_MAC(mda))) \ + ) + +/** + * @sane_metric_delta: Controlling if trigger additional path check mechanism + * @max_root_add_chk_cnt: The retry cnt to send additional root confirmation + * PREQ through old(last) path + */ +struct rtw_mesh_cfg { + u8 max_peer_links; /* peering limit */ + u32 plink_timeout; /* seconds */ + + u8 dot11MeshTTL; + u8 element_ttl; + u32 path_refresh_time; + u16 dot11MeshHWMPpreqMinInterval; + u16 dot11MeshHWMPnetDiameterTraversalTime; + u32 dot11MeshHWMPactivePathTimeout; + u8 dot11MeshHWMPmaxPREQretries; + u16 min_discovery_timeout; + u16 dot11MeshHWMPconfirmationInterval; + u16 dot11MeshHWMPperrMinInterval; + u8 dot11MeshHWMPRootMode; + BOOLEAN dot11MeshForwarding; + s32 rssi_threshold; /* in dBm, 0: no specified */ + u16 dot11MeshHWMPRannInterval; + BOOLEAN dot11MeshGateAnnouncementProtocol; + u32 dot11MeshHWMPactivePathToRootTimeout; + u16 dot11MeshHWMProotInterval; + u8 path_gate_timeout_factor; +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + u16 sane_metric_delta; + u8 max_root_add_chk_cnt; +#endif + + struct mesh_peer_sel_policy peer_sel_policy; + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC + u8 b2u_flags_msrc; + u8 b2u_flags_mfwd; +#endif +}; + +struct rtw_mesh_stats { + u32 fwded_mcast; /* Mesh forwarded multicast frames */ + u32 fwded_unicast; /* Mesh forwarded unicast frames */ + u32 fwded_frames; /* Mesh total forwarded frames */ + u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ + u32 dropped_frames_no_route; /* Not transmitted, no route found */ + u32 dropped_frames_congestion;/* Not forwarded due to congestion */ + u32 dropped_frames_duplicate; + + u32 mrc_del_qlen; /* MRC entry deleted cause by queue length limit */ +}; + +struct rtw_mrc; + +struct rtw_mesh_info { + u8 mesh_id[NDIS_802_11_LENGTH_SSID]; + size_t mesh_id_len; + /* Active Path Selection Protocol Identifier */ + u8 mesh_pp_id; + /* Active Path Selection Metric Identifier */ + u8 mesh_pm_id; + /* Congestion Control Mode Identifier */ + u8 mesh_cc_id; + /* Synchronization Protocol Identifier */ + u8 mesh_sp_id; + /* Authentication Protocol Identifier */ + u8 mesh_auth_id; + + struct mesh_plink_pool plink_ctl; + + u32 mesh_seqnum; + /* MSTA's own hwmp sequence number */ + u32 sn; + systime last_preq; + systime last_sn_update; + systime next_perr; + /* Last used Path Discovery ID */ + u32 preq_id; + + ATOMIC_T mpaths; + struct rtw_mesh_table *mesh_paths; + struct rtw_mesh_table *mpp_paths; + int mesh_paths_generation; + int mpp_paths_generation; + + int num_gates; + struct rtw_mesh_path *max_addr_gate; + bool max_addr_gate_is_larger_than_self; + + struct rtw_mesh_stats mshstats; + + _queue mpath_tx_queue; + u32 mpath_tx_queue_len; + _tasklet mpath_tx_tasklet; + + struct rtw_mrc *mrc; + + _lock mesh_preq_queue_lock; + struct rtw_mesh_preq_queue preq_queue; + int preq_queue_len; +}; + +extern const char *_action_self_protected_str[]; +#define action_self_protected_str(action) ((action < RTW_ACT_SELF_PROTECTED_NUM) ? _action_self_protected_str[action] : _action_self_protected_str[0]) + +u8 *rtw_set_ie_mesh_id(u8 *buf, u32 *buf_len, const char *mesh_id, u8 id_len); +u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len + , u8 path_sel_proto, u8 path_sel_metric, u8 congest_ctl_mode, u8 sync_method, u8 auth_proto + , u8 num_of_peerings, bool cto_mgate, bool cto_as + , bool accept_peerings, bool mcca_sup, bool mcca_en, bool forwarding + , bool mbca_en, bool tbtt_adj, bool ps_level); + +int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b); +int rtw_bss_is_candidate_mesh_peer(_adapter *adapter, WLAN_BSSID_EX *target, u8 ch, u8 add_peer); + +void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned); + +void rtw_mesh_peer_status_chk(_adapter *adapter); + +#if CONFIG_RTW_MESH_ACNODE_PREVENT +void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned); +bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned); +bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter); +struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter); +void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter); +#endif + +#if CONFIG_RTW_MESH_OFFCH_CAND +u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter); +u8 rtw_mesh_select_operating_ch(_adapter *adapter); +void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter); +#endif + +#if CONFIG_RTW_MESH_PEER_BLACKLIST +int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr); +int rtw_mesh_peer_blacklist_del(_adapter *adapter, const u8 *addr); +int rtw_mesh_peer_blacklist_search(_adapter *adapter, const u8 *addr); +void rtw_mesh_peer_blacklist_flush(_adapter *adapter); +void dump_mesh_peer_blacklist(void *sel, _adapter *adapter); +void dump_mesh_peer_blacklist_settings(void *sel, _adapter *adapter); +#endif +#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST +u8 rtw_mesh_cto_mgate_required(_adapter *adapter); +u8 rtw_mesh_cto_mgate_network_filter(_adapter *adapter, struct wlan_network *scanned); +int rtw_mesh_cto_mgate_blacklist_add(_adapter *adapter, const u8 *addr); +int rtw_mesh_cto_mgate_blacklist_del(_adapter *adapter, const u8 *addr); +int rtw_mesh_cto_mgate_blacklist_search(_adapter *adapter, const u8 *addr); +void rtw_mesh_cto_mgate_blacklist_flush(_adapter *adapter); +void dump_mesh_cto_mgate_blacklist(void *sel, _adapter *adapter); +void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter); +#endif +void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter); +void dump_mesh_networks(void *sel, _adapter *adapter); + +void rtw_mesh_adjust_bchbw(enum band_type req_band, u8 req_ch, u8 *req_bw, u8 *req_offset); + +void rtw_mesh_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx, u16 alg, u16 seq, u16 status); +int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len); +int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len); + +int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe); +unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe); + +bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss); +bool rtw_mesh_update_bss_formation_info(_adapter *adapter, WLAN_BSSID_EX *bss); +bool rtw_mesh_update_bss_forwarding_state(_adapter *adapter, WLAN_BSSID_EX *bss); + +struct mesh_plink_ent *_rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr); +struct mesh_plink_ent *rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr); +struct mesh_plink_ent *rtw_mesh_plink_get_no_estab_by_idx(_adapter *adapter, u8 idx); +int _rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr); +int rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr); +int rtw_mesh_plink_set_state(_adapter *adapter, const u8 *hwaddr, u8 state); +#ifdef CONFIG_RTW_MESH_AEK +int rtw_mesh_plink_set_aek(_adapter *adapter, const u8 *hwaddr, const u8 *aek); +#endif +#if CONFIG_RTW_MESH_PEER_BLACKLIST +int rtw_mesh_plink_set_peer_conf_timeout(_adapter *adapter, const u8 *hwaddr); +#endif +void _rtw_mesh_plink_del_ent(_adapter *adapter, struct mesh_plink_ent *ent); +int rtw_mesh_plink_del(_adapter *adapter, const u8 *hwaddr); +void rtw_mesh_plink_ctl_init(_adapter *adapter); +void rtw_mesh_plink_ctl_deinit(_adapter *adapter); +void dump_mesh_plink_ctl(void *sel, _adapter *adapter); + +u8 rtw_mesh_set_plink_state_cmd(_adapter *adapter, const u8 *mac, u8 plink_state); + +void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink); +void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr); +u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps); + +unsigned int on_action_mesh(_adapter *adapter, union recv_frame *rframe); + +void rtw_mesh_cfg_init(_adapter *adapter); +void rtw_mesh_cfg_init_max_peer_links(_adapter *adapter, u8 stack_conf); +void rtw_mesh_cfg_init_plink_timeout(_adapter *adapter, u32 stack_conf); +void rtw_mesh_init_mesh_info(_adapter *adapter); +void rtw_mesh_deinit_mesh_info(_adapter *adapter); + +#if CONFIG_RTW_MESH_DATA_BMC_TO_UC +void dump_mesh_b2u_flags(void *sel, _adapter *adapter); +#endif + +int rtw_mesh_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list); + +s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib); +void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf); +u8 rtw_mesh_tx_build_whdr(_adapter *adapter, struct pkt_attrib *attrib + , u16 *fctrl, struct rtw_ieee80211_hdr *whdr); + +int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta); +int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe + , const struct rtw_ieee80211s_hdr *mctrl, const u8 *mda, const u8 *msa + , u8 *mctrl_len, const u8 **da, const u8 **sa); +int rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter *adapter, union recv_frame *rframe); + +int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe + , const u8 *mda, const u8 *msa + , const u8 *da, const u8 *sa + , struct rtw_ieee80211s_hdr *mctrl + , u8 *msdu, enum rtw_rx_llc_hdl llc_hdl + , struct xmit_frame **fwd_frame, _list *b2u_list); + +void dump_mesh_stats(void *sel, _adapter *adapter); + +#if defined(PLATFORM_LINUX) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)) +#define rtw_lockdep_assert_held(l) lockdep_assert_held(l) +#define rtw_lockdep_is_held(l) lockdep_is_held(l) +#else +#error "TBD\n" +#endif + +#include "rtw_mesh_pathtbl.h" +#include "rtw_mesh_hwmp.h" +#endif /* __RTW_MESH_H_ */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.c b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.c new file mode 100644 index 00000000..cfff06d3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.c @@ -0,0 +1,1519 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_HWMP_C_ + +#ifdef CONFIG_RTW_MESH +#include + +#define RTW_TEST_FRAME_LEN 8192 +#define RTW_MAX_METRIC 0xffffffff +#define RTW_ARITH_SHIFT 8 +#define RTW_LINK_FAIL_THRESH 95 +#define RTW_MAX_PREQ_QUEUE_LEN 64 +#define RTW_ATLM_REQ_CYCLE 1000 + +#define rtw_ilog2(n) \ +( \ + (n) < 2 ? 0 : \ + (n) & (1ULL << 63) ? 63 : \ + (n) & (1ULL << 62) ? 62 : \ + (n) & (1ULL << 61) ? 61 : \ + (n) & (1ULL << 60) ? 60 : \ + (n) & (1ULL << 59) ? 59 : \ + (n) & (1ULL << 58) ? 58 : \ + (n) & (1ULL << 57) ? 57 : \ + (n) & (1ULL << 56) ? 56 : \ + (n) & (1ULL << 55) ? 55 : \ + (n) & (1ULL << 54) ? 54 : \ + (n) & (1ULL << 53) ? 53 : \ + (n) & (1ULL << 52) ? 52 : \ + (n) & (1ULL << 51) ? 51 : \ + (n) & (1ULL << 50) ? 50 : \ + (n) & (1ULL << 49) ? 49 : \ + (n) & (1ULL << 48) ? 48 : \ + (n) & (1ULL << 47) ? 47 : \ + (n) & (1ULL << 46) ? 46 : \ + (n) & (1ULL << 45) ? 45 : \ + (n) & (1ULL << 44) ? 44 : \ + (n) & (1ULL << 43) ? 43 : \ + (n) & (1ULL << 42) ? 42 : \ + (n) & (1ULL << 41) ? 41 : \ + (n) & (1ULL << 40) ? 40 : \ + (n) & (1ULL << 39) ? 39 : \ + (n) & (1ULL << 38) ? 38 : \ + (n) & (1ULL << 37) ? 37 : \ + (n) & (1ULL << 36) ? 36 : \ + (n) & (1ULL << 35) ? 35 : \ + (n) & (1ULL << 34) ? 34 : \ + (n) & (1ULL << 33) ? 33 : \ + (n) & (1ULL << 32) ? 32 : \ + (n) & (1ULL << 31) ? 31 : \ + (n) & (1ULL << 30) ? 30 : \ + (n) & (1ULL << 29) ? 29 : \ + (n) & (1ULL << 28) ? 28 : \ + (n) & (1ULL << 27) ? 27 : \ + (n) & (1ULL << 26) ? 26 : \ + (n) & (1ULL << 25) ? 25 : \ + (n) & (1ULL << 24) ? 24 : \ + (n) & (1ULL << 23) ? 23 : \ + (n) & (1ULL << 22) ? 22 : \ + (n) & (1ULL << 21) ? 21 : \ + (n) & (1ULL << 20) ? 20 : \ + (n) & (1ULL << 19) ? 19 : \ + (n) & (1ULL << 18) ? 18 : \ + (n) & (1ULL << 17) ? 17 : \ + (n) & (1ULL << 16) ? 16 : \ + (n) & (1ULL << 15) ? 15 : \ + (n) & (1ULL << 14) ? 14 : \ + (n) & (1ULL << 13) ? 13 : \ + (n) & (1ULL << 12) ? 12 : \ + (n) & (1ULL << 11) ? 11 : \ + (n) & (1ULL << 10) ? 10 : \ + (n) & (1ULL << 9) ? 9 : \ + (n) & (1ULL << 8) ? 8 : \ + (n) & (1ULL << 7) ? 7 : \ + (n) & (1ULL << 6) ? 6 : \ + (n) & (1ULL << 5) ? 5 : \ + (n) & (1ULL << 4) ? 4 : \ + (n) & (1ULL << 3) ? 3 : \ + (n) & (1ULL << 2) ? 2 : \ + 1 \ +) + +enum rtw_mpath_frame_type { + RTW_MPATH_PREQ = 0, + RTW_MPATH_PREP, + RTW_MPATH_PERR, + RTW_MPATH_RANN +}; + +static inline u32 rtw_u32_field_get(const u8 *preq_elem, int shift, BOOLEAN ae) +{ + if (ae) + shift += 6; + return LE_BITS_TO_4BYTE(preq_elem + shift, 0, 32); +} + +static inline u16 rtw_u16_field_get(const u8 *preq_elem, int shift, BOOLEAN ae) +{ + if (ae) + shift += 6; + return LE_BITS_TO_2BYTE(preq_elem + shift, 0, 16); +} + +/* HWMP IE processing macros */ +#define RTW_AE_F (1<<6) +#define RTW_AE_F_SET(x) (*x & RTW_AE_F) +#define RTW_PREQ_IE_FLAGS(x) (*(x)) +#define RTW_PREQ_IE_HOPCOUNT(x) (*(x + 1)) +#define RTW_PREQ_IE_TTL(x) (*(x + 2)) +#define RTW_PREQ_IE_PREQ_ID(x) rtw_u32_field_get(x, 3, 0) +#define RTW_PREQ_IE_ORIG_ADDR(x) (x + 7) +#define RTW_PREQ_IE_ORIG_SN(x) rtw_u32_field_get(x, 13, 0) +#define RTW_PREQ_IE_LIFETIME(x) rtw_u32_field_get(x, 17, RTW_AE_F_SET(x)) +#define RTW_PREQ_IE_METRIC(x) rtw_u32_field_get(x, 21, RTW_AE_F_SET(x)) +#define RTW_PREQ_IE_TARGET_F(x) (*(RTW_AE_F_SET(x) ? x + 32 : x + 26)) +#define RTW_PREQ_IE_TARGET_ADDR(x) (RTW_AE_F_SET(x) ? x + 33 : x + 27) +#define RTW_PREQ_IE_TARGET_SN(x) rtw_u32_field_get(x, 33, RTW_AE_F_SET(x)) + +#define RTW_PREP_IE_FLAGS(x) RTW_PREQ_IE_FLAGS(x) +#define RTW_PREP_IE_HOPCOUNT(x) RTW_PREQ_IE_HOPCOUNT(x) +#define RTW_PREP_IE_TTL(x) RTW_PREQ_IE_TTL(x) +#define RTW_PREP_IE_ORIG_ADDR(x) (RTW_AE_F_SET(x) ? x + 27 : x + 21) +#define RTW_PREP_IE_ORIG_SN(x) rtw_u32_field_get(x, 27, RTW_AE_F_SET(x)) +#define RTW_PREP_IE_LIFETIME(x) rtw_u32_field_get(x, 13, RTW_AE_F_SET(x)) +#define RTW_PREP_IE_METRIC(x) rtw_u32_field_get(x, 17, RTW_AE_F_SET(x)) +#define RTW_PREP_IE_TARGET_ADDR(x) (x + 3) +#define RTW_PREP_IE_TARGET_SN(x) rtw_u32_field_get(x, 9, 0) + +#define RTW_PERR_IE_TTL(x) (*(x)) +#define RTW_PERR_IE_TARGET_FLAGS(x) (*(x + 2)) +#define RTW_PERR_IE_TARGET_ADDR(x) (x + 3) +#define RTW_PERR_IE_TARGET_SN(x) rtw_u32_field_get(x, 9, 0) +#define RTW_PERR_IE_TARGET_RCODE(x) rtw_u16_field_get(x, 13, 0) + +#define RTW_TU_TO_SYSTIME(x) (rtw_us_to_systime((x) * 1024)) +#define RTW_TU_TO_EXP_TIME(x) (rtw_get_current_time() + RTW_TU_TO_SYSTIME(x)) +#define RTW_MSEC_TO_TU(x) (x*1000/1024) +#define RTW_SN_GT(x, y) ((s32)(y - x) < 0) +#define RTW_SN_LT(x, y) ((s32)(x - y) < 0) +#define RTW_MAX_SANE_SN_DELTA 32 + +static inline u32 RTW_SN_DELTA(u32 x, u32 y) +{ + return x >= y ? x - y : y - x; +} + +#define rtw_net_traversal_jiffies(adapter) \ + rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPnetDiameterTraversalTime) +#define rtw_default_lifetime(adapter) \ + RTW_MSEC_TO_TU(adapter->mesh_cfg.dot11MeshHWMPactivePathTimeout) +#define rtw_min_preq_int_jiff(adapter) \ + (rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPpreqMinInterval)) +#define rtw_max_preq_retries(adapter) (adapter->mesh_cfg.dot11MeshHWMPmaxPREQretries) +#define rtw_disc_timeout_jiff(adapter) \ + rtw_ms_to_systime(adapter->mesh_cfg.min_discovery_timeout) +#define rtw_root_path_confirmation_jiffies(adapter) \ + rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPconfirmationInterval) + +static inline BOOLEAN rtw_ether_addr_equal(const u8 *addr1, const u8 *addr2) +{ + return _rtw_memcmp(addr1, addr2, ETH_ALEN); +} + +#ifdef PLATFORM_LINUX +#define rtw_print_ratelimit() printk_ratelimit() +#define rtw_mod_timer(ptimer, expires) mod_timer(&(ptimer)->timer, expires) +#else + +#endif + +#define RTW_MESH_EWMA_PRECISION 20 +#define RTW_MESH_EWMA_WEIGHT_RCP 8 +#define RTW_TOTAL_PKT_MIN_THRESHOLD 1 +inline void rtw_ewma_err_rate_init(struct rtw_ewma_err_rate *e) +{ + e->internal = 0; +} +inline unsigned long rtw_ewma_err_rate_read(struct rtw_ewma_err_rate *e) +{ + return e->internal >> (RTW_MESH_EWMA_PRECISION); +} +inline void rtw_ewma_err_rate_add(struct rtw_ewma_err_rate *e, + unsigned long val) +{ + unsigned long internal = e->internal; + unsigned long weight_rcp = rtw_ilog2(RTW_MESH_EWMA_WEIGHT_RCP); + unsigned long precision = RTW_MESH_EWMA_PRECISION; + + (e->internal) = internal ? (((internal << weight_rcp) - internal) + + (val << precision)) >> weight_rcp : + (val << precision); +} + +static const u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +static int rtw_mesh_path_sel_frame_tx(enum rtw_mpath_frame_type mpath_action, u8 flags, + const u8 *originator_addr, u32 originator_sn, + u8 target_flags, const u8 *target, + u32 target_sn, const u8 *da, u8 hopcount, u8 ttl, + u32 lifetime, u32 metric, u32 preq_id, + _adapter *adapter) +{ + struct xmit_priv *pxmitpriv = &(adapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct xmit_frame *pmgntframe = NULL; + struct rtw_ieee80211_hdr *pwlanhdr = NULL; + struct pkt_attrib *pattrib = NULL; + u8 category = RTW_WLAN_CATEGORY_MESH; + u8 action = RTW_ACT_MESH_HWMP_PATH_SELECTION; + u16 *fctrl = NULL; + u8 *pos, ie_len; + + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (pmgntframe == NULL) + return -1; + + pattrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, pattrib); + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + + pos = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pos; + + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN); + + SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); + pmlmeext->mgnt_seq++; + set_frame_sub_type(pos, WIFI_ACTION); + + pos += sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pos = rtw_set_fixed_ie(pos, 1, &(category), &(pattrib->pktlen)); + pos = rtw_set_fixed_ie(pos, 1, &(action), &(pattrib->pktlen)); + + switch (mpath_action) { + case RTW_MPATH_PREQ: + RTW_HWMP_DBG("sending PREQ to "MAC_FMT"\n", MAC_ARG(target)); + ie_len = 37; + pattrib->pktlen += (ie_len + 2); + *pos++ = WLAN_EID_PREQ; + break; + case RTW_MPATH_PREP: + RTW_HWMP_DBG("sending PREP to "MAC_FMT"\n", MAC_ARG(originator_addr)); + ie_len = 31; + pattrib->pktlen += (ie_len + 2); + *pos++ = WLAN_EID_PREP; + break; + case RTW_MPATH_RANN: + RTW_HWMP_DBG("sending RANN from "MAC_FMT"\n", MAC_ARG(originator_addr)); + ie_len = sizeof(struct rtw_ieee80211_rann_ie); + pattrib->pktlen += (ie_len + 2); + *pos++ = WLAN_EID_RANN; + break; + default: + #if 0 /*CONFIG_CORE_XMITBUF*/ + rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); + #endif + rtw_free_xmitframe(pxmitpriv, pmgntframe); + return _FAIL; + } + *pos++ = ie_len; + *pos++ = flags; + *pos++ = hopcount; + *pos++ = ttl; + if (mpath_action == RTW_MPATH_PREP) { + _rtw_memcpy(pos, target, ETH_ALEN); + pos += ETH_ALEN; + *(u32 *)pos = cpu_to_le32(target_sn); + pos += 4; + } else { + if (mpath_action == RTW_MPATH_PREQ) { + *(u32 *)pos = cpu_to_le32(preq_id); + pos += 4; + } + _rtw_memcpy(pos, originator_addr, ETH_ALEN); + pos += ETH_ALEN; + *(u32 *)pos = cpu_to_le32(originator_sn); + pos += 4; + } + *(u32 *)pos = cpu_to_le32(lifetime); + pos += 4; + *(u32 *)pos = cpu_to_le32(metric); + pos += 4; + if (mpath_action == RTW_MPATH_PREQ) { + *pos++ = 1; /* support only 1 destination now */ + *pos++ = target_flags; + _rtw_memcpy(pos, target, ETH_ALEN); + pos += ETH_ALEN; + *(u32 *)pos = cpu_to_le32(target_sn); + pos += 4; + } else if (mpath_action == RTW_MPATH_PREP) { + _rtw_memcpy(pos, originator_addr, ETH_ALEN); + pos += ETH_ALEN; + *(u32 *)pos = cpu_to_le32(originator_sn); + pos += 4; + } + + pattrib->last_txcmdsz = pattrib->pktlen; + dump_mgntframe(adapter, pmgntframe); + return 0; +} + +int rtw_mesh_path_error_tx(_adapter *adapter, + u8 ttl, const u8 *target, u32 target_sn, + u16 perr_reason_code, const u8 *ra) +{ + + struct xmit_priv *pxmitpriv = &(adapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct xmit_frame *pmgntframe = NULL; + struct rtw_ieee80211_hdr *pwlanhdr = NULL; + struct pkt_attrib *pattrib = NULL; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + u8 category = RTW_WLAN_CATEGORY_MESH; + u8 action = RTW_ACT_MESH_HWMP_PATH_SELECTION; + u8 *pos, ie_len; + u16 *fctrl = NULL; + + if (rtw_time_before(rtw_get_current_time(), minfo->next_perr)) + return -1; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (pmgntframe == NULL) + return -1; + + pattrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, pattrib); + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + + pos = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pos; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN); + + SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); + pmlmeext->mgnt_seq++; + set_frame_sub_type(pos, WIFI_ACTION); + + pos += sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pos = rtw_set_fixed_ie(pos, 1, &(category), &(pattrib->pktlen)); + pos = rtw_set_fixed_ie(pos, 1, &(action), &(pattrib->pktlen)); + + ie_len = 15; + pattrib->pktlen += (2 + ie_len); + *pos++ = WLAN_EID_PERR; + *pos++ = ie_len; + /* ttl */ + *pos++ = ttl; + /* The Number of Destinations N */ + *pos++ = 1; + /* Flags format | B7 | B6 | B5:B0 | = | rsvd | AE | rsvd | */ + *pos = 0; + pos++; + _rtw_memcpy(pos, target, ETH_ALEN); + pos += ETH_ALEN; + *(u32 *)pos = cpu_to_le32(target_sn); + pos += 4; + *(u16 *)pos = cpu_to_le16(perr_reason_code); + + adapter->mesh_info.next_perr = RTW_TU_TO_EXP_TIME( + adapter->mesh_cfg.dot11MeshHWMPperrMinInterval); + pattrib->last_txcmdsz = pattrib->pktlen; + /* Send directly. Rewrite it if deferred tx is needed */ + dump_mgntframe(adapter, pmgntframe); + + RTW_HWMP_DBG("TX PERR toward "MAC_FMT", ra = "MAC_FMT"\n", MAC_ARG(target), MAC_ARG(ra)); + + return 0; +} + +static u32 rtw_airtime_link_metric_get(_adapter *adapter, struct sta_info *sta) +{ + int device_constant = rtw_hal_phydm_get_plcp(adapter, sta->phl_sta->macid) << RTW_ARITH_SHIFT; + u32 test_frame_len = RTW_TEST_FRAME_LEN << RTW_ARITH_SHIFT; + u32 s_unit = 1 << RTW_ARITH_SHIFT; + u32 err; + u16 rate; + u32 tx_time, estimated_retx; + u64 result; + /* The fail_avg should <= 100 here */ + u32 fail_avg = (u32)rtw_ewma_err_rate_read(&sta->metrics.err_rate); + + if (fail_avg > RTW_LINK_FAIL_THRESH) + return RTW_MAX_METRIC; + + rate = sta->metrics.data_rate; + /* rate unit is 100Kbps, min rate = 10 */ + if (rate < 10) { + RTW_HWMP_INFO("rate = %d\n", rate); + return RTW_MAX_METRIC; + } + + err = (fail_avg << RTW_ARITH_SHIFT) / 100; + + /* test_frame_len*10 to adjust the unit of rate(100kbps/unit) */ + tx_time = (device_constant + 10 * test_frame_len / rate); + estimated_retx = ((1 << (2 * RTW_ARITH_SHIFT)) / (s_unit - err)); + result = (tx_time * estimated_retx) >> (2 * RTW_ARITH_SHIFT); + /* Convert us to 0.01 TU(10.24us). x/10.24 = x*100/1024 */ + result = (result * 100) >> 10; + + return (u32)result; +} + +void rtw_ieee80211s_update_metric(_adapter *adapter, u8 mac_id, + u8 per, u8 rate, + u8 bw, u8 total_pkt) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + struct sta_info *sta; + u8 rate_idx; + u8 sgi; + + sta = macid_ctl->sta[mac_id]; + if (!sta) + return; + + /* if RA, use reported rate */ + if (adapter->fix_rate == 0xff) { + rate_idx = rate & 0x7f; + sgi = rate >> 7; + } else { + rate_idx = adapter->fix_rate & 0x7f; + sgi = adapter->fix_rate >> 7; + } + sta->metrics.data_rate = rtw_desc_rate_to_bitrate(bw, rate_idx, sgi); + + if (total_pkt < RTW_TOTAL_PKT_MIN_THRESHOLD) + return; + + /* TBD: sta->metrics.overhead = phydm_get_plcp(void *dm_void, u16 macid); */ + sta->metrics.total_pkt = total_pkt; + + rtw_ewma_err_rate_add(&sta->metrics.err_rate, per); + if (rtw_ewma_err_rate_read(&sta->metrics.err_rate) > + RTW_LINK_FAIL_THRESH) + rtw_mesh_plink_broken(sta); +} + +static void rtw_hwmp_preq_frame_process(_adapter *adapter, + struct rtw_ieee80211_hdr_3addr *mgmt, + const u8 *preq_elem, u32 originator_metric) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_path *path = NULL; + const u8 *target_addr, *originator_addr; + const u8 *da; + u8 target_flags, ttl, flags, to_gate_ask = 0; + u32 originator_sn, target_sn, lifetime, target_metric = 0; + BOOLEAN reply = _FALSE; + BOOLEAN forward = _TRUE; + BOOLEAN preq_is_gate; + + /* Update target SN, if present */ + target_addr = RTW_PREQ_IE_TARGET_ADDR(preq_elem); + originator_addr = RTW_PREQ_IE_ORIG_ADDR(preq_elem); + target_sn = RTW_PREQ_IE_TARGET_SN(preq_elem); + originator_sn = RTW_PREQ_IE_ORIG_SN(preq_elem); + target_flags = RTW_PREQ_IE_TARGET_F(preq_elem); + /* PREQ gate announcements */ + flags = RTW_PREQ_IE_FLAGS(preq_elem); + preq_is_gate = !!(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG); + + RTW_HWMP_DBG("received PREQ from "MAC_FMT"\n", MAC_ARG(originator_addr)); + + if (rtw_ether_addr_equal(target_addr, adapter_mac_addr(adapter))) { + RTW_HWMP_DBG("PREQ is for us\n"); +#ifdef CONFIG_RTW_MESH_ON_DMD_GANN + rtw_rcu_read_lock(); + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (path) { + if (preq_is_gate) + rtw_mesh_path_add_gate(path); + else if (path->is_gate) { + _rtw_spinlock_bh(&path->state_lock); + rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path); + _rtw_spinunlock_bh(&path->state_lock); + } + } + path = NULL; + rtw_rcu_read_unlock(); +#endif + forward = _FALSE; + reply = _TRUE; + to_gate_ask = 1; + target_metric = 0; + if (rtw_time_after(rtw_get_current_time(), minfo->last_sn_update + + rtw_net_traversal_jiffies(adapter)) || + rtw_time_before(rtw_get_current_time(), minfo->last_sn_update)) { + ++minfo->sn; + minfo->last_sn_update = rtw_get_current_time(); + } + target_sn = minfo->sn; + } else if (is_broadcast_mac_addr(target_addr) && + (target_flags & RTW_IEEE80211_PREQ_TO_FLAG)) { + rtw_rcu_read_lock(); + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (path) { + if (flags & RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { + reply = _TRUE; + target_addr = adapter_mac_addr(adapter); + target_sn = ++minfo->sn; + target_metric = 0; + minfo->last_sn_update = rtw_get_current_time(); + } + + if (preq_is_gate) { + lifetime = RTW_PREQ_IE_LIFETIME(preq_elem); + path->gate_ann_int = lifetime; + path->gate_asked = false; + rtw_mesh_path_add_gate(path); + } else if (path->is_gate) { + _rtw_spinlock_bh(&path->state_lock); + rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path); + _rtw_spinunlock_bh(&path->state_lock); + } + } + rtw_rcu_read_unlock(); + } else { + rtw_rcu_read_lock(); +#ifdef CONFIG_RTW_MESH_ON_DMD_GANN + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (path) { + if (preq_is_gate) + rtw_mesh_path_add_gate(path); + else if (path->is_gate) { + _rtw_spinlock_bh(&path->state_lock); + rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path); + _rtw_spinunlock_bh(&path->state_lock); + } + } + path = NULL; +#endif + path = rtw_mesh_path_lookup(adapter, target_addr); + if (path) { + if ((!(path->flags & RTW_MESH_PATH_SN_VALID)) || + RTW_SN_LT(path->sn, target_sn)) { + path->sn = target_sn; + path->flags |= RTW_MESH_PATH_SN_VALID; + } else if ((!(target_flags & RTW_IEEE80211_PREQ_TO_FLAG)) && + (path->flags & RTW_MESH_PATH_ACTIVE)) { + reply = _TRUE; + target_metric = path->metric; + target_sn = path->sn; + /* Case E2 of sec 13.10.9.3 IEEE 802.11-2012*/ + target_flags |= RTW_IEEE80211_PREQ_TO_FLAG; + } + } + rtw_rcu_read_unlock(); + } + + if (reply) { + lifetime = RTW_PREQ_IE_LIFETIME(preq_elem); + ttl = mshcfg->element_ttl; + if (ttl != 0 && !to_gate_ask) { + RTW_HWMP_DBG("replying to the PREQ\n"); + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, 0, originator_addr, + originator_sn, 0, target_addr, + target_sn, mgmt->addr2, 0, ttl, + lifetime, target_metric, 0, + adapter); + } else if (ttl != 0 && to_gate_ask) { + RTW_HWMP_DBG("replying to the PREQ (PREQ for us)\n"); + if (mshcfg->dot11MeshGateAnnouncementProtocol) { + /* BIT 7 is used to identify the prep is from mesh gate */ + to_gate_ask = RTW_IEEE80211_PREQ_IS_GATE_FLAG | BIT(7); + } else { + to_gate_ask = 0; + } + + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, to_gate_ask, originator_addr, + originator_sn, 0, target_addr, + target_sn, mgmt->addr2, 0, ttl, + lifetime, target_metric, 0, + adapter); + } else { + minfo->mshstats.dropped_frames_ttl++; + } + } + + if (forward && mshcfg->dot11MeshForwarding) { + u32 preq_id; + u8 hopcount; + + ttl = RTW_PREQ_IE_TTL(preq_elem); + lifetime = RTW_PREQ_IE_LIFETIME(preq_elem); + if (ttl <= 1) { + minfo->mshstats.dropped_frames_ttl++; + return; + } + RTW_HWMP_DBG("forwarding the PREQ from "MAC_FMT"\n", MAC_ARG(originator_addr)); + --ttl; + preq_id = RTW_PREQ_IE_PREQ_ID(preq_elem); + hopcount = RTW_PREQ_IE_HOPCOUNT(preq_elem) + 1; + da = (path && path->is_root) ? + path->rann_snd_addr : bcast_addr; + + if (flags & RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { + target_addr = RTW_PREQ_IE_TARGET_ADDR(preq_elem); + target_sn = RTW_PREQ_IE_TARGET_SN(preq_elem); + } + + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, originator_addr, + originator_sn, target_flags, target_addr, + target_sn, da, hopcount, ttl, lifetime, + originator_metric, preq_id, adapter); + if (!is_multicast_mac_addr(da)) + minfo->mshstats.fwded_unicast++; + else + minfo->mshstats.fwded_mcast++; + minfo->mshstats.fwded_frames++; + } +} + +static inline struct sta_info * +rtw_next_hop_deref_protected(struct rtw_mesh_path *path) +{ + return rtw_rcu_dereference_protected(path->next_hop, + rtw_lockdep_is_held(&path->state_lock)); +} + +static void rtw_hwmp_prep_frame_process(_adapter *adapter, + struct rtw_ieee80211_hdr_3addr *mgmt, + const u8 *prep_elem, u32 metric) +{ + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats; + struct rtw_mesh_path *path; + const u8 *target_addr, *originator_addr; + u8 ttl, hopcount, flags; + u8 next_hop[ETH_ALEN]; + u32 target_sn, originator_sn, lifetime; + + RTW_HWMP_DBG("received PREP from "MAC_FMT"\n", + MAC_ARG(RTW_PREP_IE_TARGET_ADDR(prep_elem))); + + originator_addr = RTW_PREP_IE_ORIG_ADDR(prep_elem); + if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter))) { + /* destination, no forwarding required */ + rtw_rcu_read_lock(); + target_addr = RTW_PREP_IE_TARGET_ADDR(prep_elem); + path = rtw_mesh_path_lookup(adapter, target_addr); + if (path && path->gate_asked) { + flags = RTW_PREP_IE_FLAGS(prep_elem); + if (flags & BIT(7)) { + _rtw_spinlock_bh(&path->state_lock); + path->gate_asked = false; + _rtw_spinunlock_bh(&path->state_lock); + if (!(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG)) { + _rtw_spinlock_bh(&path->state_lock); + rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path); + _rtw_spinunlock_bh(&path->state_lock); + } + } + } + + rtw_rcu_read_unlock(); + return; + } + + if (!mshcfg->dot11MeshForwarding) + return; + + ttl = RTW_PREP_IE_TTL(prep_elem); + if (ttl <= 1) { + mshstats->dropped_frames_ttl++; + return; + } + + rtw_rcu_read_lock(); + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (path) + _rtw_spinlock_bh(&path->state_lock); + else + goto fail; + if (!(path->flags & RTW_MESH_PATH_ACTIVE)) { + _rtw_spinunlock_bh(&path->state_lock); + goto fail; + } + _rtw_memcpy(next_hop, rtw_next_hop_deref_protected(path)->phl_sta->mac_addr, ETH_ALEN); + _rtw_spinunlock_bh(&path->state_lock); + --ttl; + flags = RTW_PREP_IE_FLAGS(prep_elem); + lifetime = RTW_PREP_IE_LIFETIME(prep_elem); + hopcount = RTW_PREP_IE_HOPCOUNT(prep_elem) + 1; + target_addr = RTW_PREP_IE_TARGET_ADDR(prep_elem); + target_sn = RTW_PREP_IE_TARGET_SN(prep_elem); + originator_sn = RTW_PREP_IE_ORIG_SN(prep_elem); + + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, flags, originator_addr, originator_sn, 0, + target_addr, target_sn, next_hop, hopcount, + ttl, lifetime, metric, 0, adapter); + rtw_rcu_read_unlock(); + + mshstats->fwded_unicast++; + mshstats->fwded_frames++; + return; + +fail: + rtw_rcu_read_unlock(); + mshstats->dropped_frames_no_route++; +} + +static void rtw_hwmp_perr_frame_process(_adapter *adapter, + struct rtw_ieee80211_hdr_3addr *mgmt, + const u8 *perr_elem) +{ + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats; + struct rtw_mesh_path *path; + u8 ttl; + const u8 *ta, *target_addr; + u32 target_sn; + u16 perr_reason_code; + + ta = mgmt->addr2; + ttl = RTW_PERR_IE_TTL(perr_elem); + if (ttl <= 1) { + mshstats->dropped_frames_ttl++; + return; + } + ttl--; + target_addr = RTW_PERR_IE_TARGET_ADDR(perr_elem); + target_sn = RTW_PERR_IE_TARGET_SN(perr_elem); + perr_reason_code = RTW_PERR_IE_TARGET_RCODE(perr_elem); + + RTW_HWMP_DBG("received PERR toward target "MAC_FMT"\n", MAC_ARG(target_addr)); + + rtw_rcu_read_lock(); + path = rtw_mesh_path_lookup(adapter, target_addr); + if (path) { + struct sta_info *sta; + + _rtw_spinlock_bh(&path->state_lock); + sta = rtw_next_hop_deref_protected(path); + if (path->flags & RTW_MESH_PATH_ACTIVE && + rtw_ether_addr_equal(ta, sta->phl_sta->mac_addr) && + !(path->flags & RTW_MESH_PATH_FIXED) && + (!(path->flags & RTW_MESH_PATH_SN_VALID) || + RTW_SN_GT(target_sn, path->sn) || target_sn == 0)) { + path->flags &= ~RTW_MESH_PATH_ACTIVE; + if (target_sn != 0) + path->sn = target_sn; + else + path->sn += 1; + _rtw_spinunlock_bh(&path->state_lock); + if (!mshcfg->dot11MeshForwarding) + goto endperr; + rtw_mesh_path_error_tx(adapter, ttl, target_addr, + target_sn, perr_reason_code, + bcast_addr); + } else + _rtw_spinunlock_bh(&path->state_lock); + } +endperr: + rtw_rcu_read_unlock(); +} + +static void rtw_hwmp_rann_frame_process(_adapter *adapter, + struct rtw_ieee80211_hdr_3addr *mgmt, + const struct rtw_ieee80211_rann_ie *rann) +{ + struct sta_info *sta; + struct sta_priv *pstapriv = &adapter->stapriv; + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats; + struct rtw_mesh_path *path; + u8 ttl, flags, hopcount; + const u8 *originator_addr; + u32 originator_sn, metric, metric_txsta, interval; + BOOLEAN root_is_gate; + + ttl = rann->rann_ttl; + flags = rann->rann_flags; + root_is_gate = !!(flags & RTW_RANN_FLAG_IS_GATE); + originator_addr = rann->rann_addr; + originator_sn = le32_to_cpu(rann->rann_seq); + interval = le32_to_cpu(rann->rann_interval); + hopcount = rann->rann_hopcount; + hopcount++; + metric = le32_to_cpu(rann->rann_metric); + + /* Ignore our own RANNs */ + if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter))) + return; + + RTW_HWMP_DBG("received RANN from "MAC_FMT" via neighbour "MAC_FMT" (is_gate=%d)\n", + MAC_ARG(originator_addr), MAC_ARG(mgmt->addr2), root_is_gate); + + rtw_rcu_read_lock(); + sta = rtw_get_stainfo(pstapriv, mgmt->addr2); + if (!sta) { + rtw_rcu_read_unlock(); + return; + } + + metric_txsta = rtw_airtime_link_metric_get(adapter, sta); + + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (!path) { + path = rtw_mesh_path_add(adapter, originator_addr); + if (IS_ERR(path)) { + rtw_rcu_read_unlock(); + mshstats->dropped_frames_no_route++; + return; + } + } + + if (!(RTW_SN_LT(path->sn, originator_sn)) && + !(path->sn == originator_sn && metric < path->rann_metric)) { + rtw_rcu_read_unlock(); + return; + } + + if ((!(path->flags & (RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVING)) || + (rtw_time_after(rtw_get_current_time(), path->last_preq_to_root + + rtw_root_path_confirmation_jiffies(adapter)) || + rtw_time_before(rtw_get_current_time(), path->last_preq_to_root))) && + !(path->flags & RTW_MESH_PATH_FIXED) && (ttl != 0)) { + u8 preq_node_flag = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH; + + RTW_HWMP_DBG("time to refresh root path "MAC_FMT"\n", + MAC_ARG(originator_addr)); +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + if (RTW_SN_LT(path->sn, originator_sn) && + (path->rann_metric + mshcfg->sane_metric_delta < metric) && + _rtw_memcmp(bcast_addr, path->rann_snd_addr, ETH_ALEN) == _FALSE) { + RTW_HWMP_DBG("Trigger additional check for root " + "confirm PREQ. rann_snd_addr = "MAC_FMT + "add_chk_rann_snd_addr= "MAC_FMT"\n", + MAC_ARG(mgmt->addr2), + MAC_ARG(path->rann_snd_addr)); + _rtw_memcpy(path->add_chk_rann_snd_addr, + path->rann_snd_addr, ETH_ALEN); + preq_node_flag |= RTW_PREQ_Q_F_CHK; + + } +#endif + rtw_mesh_queue_preq(path, preq_node_flag); + path->last_preq_to_root = rtw_get_current_time(); + } + + path->sn = originator_sn; + path->rann_metric = metric + metric_txsta; + path->is_root = _TRUE; + /* Recording RANNs sender address to send individually + * addressed PREQs destined for root mesh STA */ + _rtw_memcpy(path->rann_snd_addr, mgmt->addr2, ETH_ALEN); + + if (root_is_gate) { + path->gate_ann_int = interval; + path->gate_asked = false; + rtw_mesh_path_add_gate(path); + } else if (path->is_gate) { + _rtw_spinlock_bh(&path->state_lock); + rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path); + _rtw_spinunlock_bh(&path->state_lock); + } + + if (ttl <= 1) { + mshstats->dropped_frames_ttl++; + rtw_rcu_read_unlock(); + return; + } + ttl--; + + if (mshcfg->dot11MeshForwarding) { + rtw_mesh_path_sel_frame_tx(RTW_MPATH_RANN, flags, originator_addr, + originator_sn, 0, NULL, 0, bcast_addr, + hopcount, ttl, interval, + metric + metric_txsta, 0, adapter); + } + + rtw_rcu_read_unlock(); +} + +static u32 rtw_hwmp_route_info_get(_adapter *adapter, + struct rtw_ieee80211_hdr_3addr *mgmt, + const u8 *hwmp_ie, enum rtw_mpath_frame_type action) +{ + struct rtw_mesh_path *path; + struct sta_priv *pstapriv = &adapter->stapriv; + struct sta_info *sta; + BOOLEAN fresh_info; + const u8 *originator_addr, *ta; + u32 originator_sn, originator_metric; + unsigned long originator_lifetime, exp_time; + u32 last_hop_metric, new_metric; + BOOLEAN process = _TRUE; + + rtw_rcu_read_lock(); + sta = rtw_get_stainfo(pstapriv, mgmt->addr2); + if (!sta) { + rtw_rcu_read_unlock(); + return 0; + } + + last_hop_metric = rtw_airtime_link_metric_get(adapter, sta); + /* Update and check originator routing info */ + fresh_info = _TRUE; + + switch (action) { + case RTW_MPATH_PREQ: + originator_addr = RTW_PREQ_IE_ORIG_ADDR(hwmp_ie); + originator_sn = RTW_PREQ_IE_ORIG_SN(hwmp_ie); + originator_lifetime = RTW_PREQ_IE_LIFETIME(hwmp_ie); + originator_metric = RTW_PREQ_IE_METRIC(hwmp_ie); + break; + case RTW_MPATH_PREP: + /* Note: For coding, the naming is not consist with spec */ + originator_addr = RTW_PREP_IE_TARGET_ADDR(hwmp_ie); + originator_sn = RTW_PREP_IE_TARGET_SN(hwmp_ie); + originator_lifetime = RTW_PREP_IE_LIFETIME(hwmp_ie); + originator_metric = RTW_PREP_IE_METRIC(hwmp_ie); + break; + default: + rtw_rcu_read_unlock(); + return 0; + } + new_metric = originator_metric + last_hop_metric; + if (new_metric < originator_metric) + new_metric = RTW_MAX_METRIC; + exp_time = RTW_TU_TO_EXP_TIME(originator_lifetime); + + if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter))) { + process = _FALSE; + fresh_info = _FALSE; + } else { + path = rtw_mesh_path_lookup(adapter, originator_addr); + if (path) { + _rtw_spinlock_bh(&path->state_lock); + if (path->flags & RTW_MESH_PATH_FIXED) + fresh_info = _FALSE; + else if ((path->flags & RTW_MESH_PATH_ACTIVE) && + (path->flags & RTW_MESH_PATH_SN_VALID)) { + if (RTW_SN_GT(path->sn, originator_sn) || + (path->sn == originator_sn && + new_metric >= path->metric)) { + process = _FALSE; + fresh_info = _FALSE; + } + } else if (!(path->flags & RTW_MESH_PATH_ACTIVE)) { + BOOLEAN have_sn, newer_sn, bounced; + + have_sn = path->flags & RTW_MESH_PATH_SN_VALID; + newer_sn = have_sn && RTW_SN_GT(originator_sn, path->sn); + bounced = have_sn && + (RTW_SN_DELTA(originator_sn, path->sn) > + RTW_MAX_SANE_SN_DELTA); + + if (!have_sn || newer_sn) { + } else if (bounced) { + } else { + process = _FALSE; + fresh_info = _FALSE; + } + } + } else { + path = rtw_mesh_path_add(adapter, originator_addr); + if (IS_ERR(path)) { + rtw_rcu_read_unlock(); + return 0; + } + _rtw_spinlock_bh(&path->state_lock); + } + + if (fresh_info) { + rtw_mesh_path_assign_nexthop(path, sta); + path->flags |= RTW_MESH_PATH_SN_VALID; + path->metric = new_metric; + path->sn = originator_sn; + path->exp_time = rtw_time_after(path->exp_time, exp_time) + ? path->exp_time : exp_time; + rtw_mesh_path_activate(path); +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + if (path->is_root && (action == RTW_MPATH_PREP)) { + _rtw_memcpy(path->rann_snd_addr, + mgmt->addr2, ETH_ALEN); + path->rann_metric = new_metric; + } +#endif + _rtw_spinunlock_bh(&path->state_lock); + rtw_mesh_path_tx_pending(path); + } else + _rtw_spinunlock_bh(&path->state_lock); + } + + /* Update and check transmitter routing info */ + ta = mgmt->addr2; + if (rtw_ether_addr_equal(originator_addr, ta)) + fresh_info = _FALSE; + else { + fresh_info = _TRUE; + + path = rtw_mesh_path_lookup(adapter, ta); + if (path) { + _rtw_spinlock_bh(&path->state_lock); + if ((path->flags & RTW_MESH_PATH_FIXED) || + ((path->flags & RTW_MESH_PATH_ACTIVE) && + (last_hop_metric > path->metric))) + fresh_info = _FALSE; + } else { + path = rtw_mesh_path_add(adapter, ta); + if (IS_ERR(path)) { + rtw_rcu_read_unlock(); + return 0; + } + _rtw_spinlock_bh(&path->state_lock); + } + + if (fresh_info) { + rtw_mesh_path_assign_nexthop(path, sta); + path->metric = last_hop_metric; + path->exp_time = rtw_time_after(path->exp_time, exp_time) + ? path->exp_time : exp_time; + rtw_mesh_path_activate(path); + _rtw_spinunlock_bh(&path->state_lock); + rtw_mesh_path_tx_pending(path); + } else + _rtw_spinunlock_bh(&path->state_lock); + } + + rtw_rcu_read_unlock(); + + return process ? new_metric : 0; +} + +static void rtw_mesh_rx_hwmp_frame_cnts(_adapter *adapter, u8 *addr) +{ + struct sta_info *sta; + + sta = rtw_get_stainfo(&adapter->stapriv, addr); + if (sta) + sta->sta_stats.rx_hwmp_pkts++; +} + +void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe) +{ + struct mesh_plink_ent *plink = NULL; + struct rtw_ieee802_11_elems elems; + u32 path_metric; + struct rx_pkt_attrib *attrib = &rframe->u.hdr.attrib; + u8 *pframe = rframe->u.hdr.rx_data, *start; + uint frame_len = rframe->u.hdr.len, left; + struct rtw_ieee80211_hdr_3addr *frame_hdr = (struct rtw_ieee80211_hdr_3addr *)pframe; + u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + ParseRes parse_res; + + plink = rtw_mesh_plink_get(adapter, get_addr2_ptr(pframe)); + if (!plink || plink->plink_state != RTW_MESH_PLINK_ESTAB) + return; + + rtw_mesh_rx_hwmp_frame_cnts(adapter, get_addr2_ptr(pframe)); + + /* Mesh action frame IE offset = 2 */ + attrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + left = frame_len - attrib->hdrlen - attrib->iv_len - attrib->icv_len - 2; + start = pframe + attrib->hdrlen + 2; + + parse_res = rtw_ieee802_11_parse_elems(start, left, &elems, 1); + if (parse_res == ParseFailed) + RTW_HWMP_INFO(FUNC_ADPT_FMT" Path Select Frame ParseFailed\n" + , FUNC_ADPT_ARG(adapter)); + else if (parse_res == ParseUnknown) + RTW_HWMP_INFO(FUNC_ADPT_FMT" Path Select Frame ParseUnknown\n" + , FUNC_ADPT_ARG(adapter)); + + if (elems.preq) { + if (elems.preq_len != 37) + /* Right now we support just 1 destination and no AE */ + return; + path_metric = rtw_hwmp_route_info_get(adapter, frame_hdr, elems.preq, + MPATH_PREQ); + if (path_metric) + rtw_hwmp_preq_frame_process(adapter, frame_hdr, elems.preq, + path_metric); + } + if (elems.prep) { + if (elems.prep_len != 31) + /* Right now we support no AE */ + return; + path_metric = rtw_hwmp_route_info_get(adapter, frame_hdr, elems.prep, + MPATH_PREP); + if (path_metric) + rtw_hwmp_prep_frame_process(adapter, frame_hdr, elems.prep, + path_metric); + } + if (elems.perr) { + if (elems.perr_len != 15) + /* Right now we support only one destination per PERR */ + return; + rtw_hwmp_perr_frame_process(adapter, frame_hdr, elems.perr); + } + if (elems.rann) + rtw_hwmp_rann_frame_process(adapter, frame_hdr, (struct rtw_ieee80211_rann_ie *)elems.rann); +} + +void rtw_mesh_queue_preq(struct rtw_mesh_path *path, u8 flags) +{ + _adapter *adapter = path->adapter; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_preq_queue *preq_node; + + preq_node = rtw_malloc(sizeof(struct rtw_mesh_preq_queue)); + if (!preq_node) { + RTW_HWMP_INFO("could not allocate PREQ node\n"); + return; + } + + _rtw_spinlock_bh(&minfo->mesh_preq_queue_lock); + if (minfo->preq_queue_len == RTW_MAX_PREQ_QUEUE_LEN) { + _rtw_spinunlock_bh(&minfo->mesh_preq_queue_lock); + rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue)); + if (rtw_print_ratelimit()) + RTW_HWMP_INFO("PREQ node queue full\n"); + return; + } + + _rtw_spinlock(&path->state_lock); + if (path->flags & RTW_MESH_PATH_REQ_QUEUED) { + _rtw_spinunlock(&path->state_lock); + _rtw_spinunlock_bh(&minfo->mesh_preq_queue_lock); + rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue)); + return; + } + + _rtw_memcpy(preq_node->dst, path->dst, ETH_ALEN); + preq_node->flags = flags; + + path->flags |= RTW_MESH_PATH_REQ_QUEUED; +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + if (flags & RTW_PREQ_Q_F_CHK) + path->flags |= RTW_MESH_PATH_ROOT_ADD_CHK; +#endif + if (flags & RTW_PREQ_Q_F_PEER_AKA) + path->flags |= RTW_MESH_PATH_PEER_AKA; + if (flags & RTW_PREQ_Q_F_BCAST_PREQ) + path->flags |= RTW_MESH_PATH_BCAST_PREQ; + _rtw_spinunlock(&path->state_lock); + + rtw_list_insert_tail(&preq_node->list, &minfo->preq_queue.list); + ++minfo->preq_queue_len; + _rtw_spinunlock_bh(&minfo->mesh_preq_queue_lock); + + if (rtw_time_after(rtw_get_current_time(), minfo->last_preq + rtw_min_preq_int_jiff(adapter))) + rtw_mesh_work(&adapter->mesh_work); + + else if (rtw_time_before(rtw_get_current_time(), minfo->last_preq)) { + /* systime wrapped around issue */ + minfo->last_preq = rtw_get_current_time() - rtw_min_preq_int_jiff(adapter) - 1; + rtw_mesh_work(&adapter->mesh_work); + } else + rtw_mod_timer(&adapter->mesh_path_timer, minfo->last_preq + + rtw_min_preq_int_jiff(adapter) + 1); +} + +static const u8 *rtw_hwmp_preq_da(struct rtw_mesh_path *path, + BOOLEAN is_root_add_chk, BOOLEAN da_is_peer, + BOOLEAN force_preq_bcast) +{ + const u8 *da; + + if (da_is_peer) + da = path->dst; + else if (force_preq_bcast) + da = bcast_addr; + else if (path->is_root) +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + da = is_root_add_chk ? path->add_chk_rann_snd_addr: + path->rann_snd_addr; +#else + da = path->rann_snd_addr; +#endif + else + da = bcast_addr; + + return da; +} + +void rtw_mesh_path_start_discovery(_adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_preq_queue *preq_node; + struct rtw_mesh_path *path; + u8 ttl, target_flags = 0; + const u8 *da; + u32 lifetime; + u8 flags = 0; + BOOLEAN is_root_add_chk = _FALSE; + BOOLEAN da_is_peer, force_preq_bcast; + + _rtw_spinlock_bh(&minfo->mesh_preq_queue_lock); + if (!minfo->preq_queue_len || + rtw_time_before(rtw_get_current_time(), minfo->last_preq + + rtw_min_preq_int_jiff(adapter))) { + _rtw_spinunlock_bh(&minfo->mesh_preq_queue_lock); + return; + } + + preq_node = rtw_list_first_entry(&minfo->preq_queue.list, + struct rtw_mesh_preq_queue, list); + rtw_list_delete(&preq_node->list); /* list_del_init(&preq_node->list); */ + --minfo->preq_queue_len; + _rtw_spinunlock_bh(&minfo->mesh_preq_queue_lock); + + rtw_rcu_read_lock(); + path = rtw_mesh_path_lookup(adapter, preq_node->dst); + if (!path) + goto enddiscovery; + + _rtw_spinlock_bh(&path->state_lock); + if (path->flags & (RTW_MESH_PATH_DELETED | RTW_MESH_PATH_FIXED)) { + _rtw_spinunlock_bh(&path->state_lock); + goto enddiscovery; + } + path->flags &= ~RTW_MESH_PATH_REQ_QUEUED; + if (preq_node->flags & RTW_PREQ_Q_F_START) { + if (path->flags & RTW_MESH_PATH_RESOLVING) { + _rtw_spinunlock_bh(&path->state_lock); + goto enddiscovery; + } else { + path->flags &= ~RTW_MESH_PATH_RESOLVED; + path->flags |= RTW_MESH_PATH_RESOLVING; + path->discovery_retries = 0; + path->discovery_timeout = rtw_disc_timeout_jiff(adapter); + } + } else if (!(path->flags & RTW_MESH_PATH_RESOLVING) || + path->flags & RTW_MESH_PATH_RESOLVED) { + path->flags &= ~RTW_MESH_PATH_RESOLVING; + _rtw_spinunlock_bh(&path->state_lock); + goto enddiscovery; + } + + minfo->last_preq = rtw_get_current_time(); + + if (rtw_time_after(rtw_get_current_time(), minfo->last_sn_update + + rtw_net_traversal_jiffies(adapter)) || + rtw_time_before(rtw_get_current_time(), minfo->last_sn_update)) { + ++minfo->sn; + minfo->last_sn_update = rtw_get_current_time(); + } + lifetime = rtw_default_lifetime(adapter); + ttl = mshcfg->element_ttl; + if (ttl == 0) { + minfo->mshstats.dropped_frames_ttl++; + _rtw_spinunlock_bh(&path->state_lock); + goto enddiscovery; + } + + if (preq_node->flags & RTW_PREQ_Q_F_REFRESH) + target_flags |= RTW_IEEE80211_PREQ_TO_FLAG; + else + target_flags &= ~RTW_IEEE80211_PREQ_TO_FLAG; + +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + is_root_add_chk = !!(path->flags & RTW_MESH_PATH_ROOT_ADD_CHK); +#endif + da_is_peer = !!(path->flags & RTW_MESH_PATH_PEER_AKA); + force_preq_bcast = !!(path->flags & RTW_MESH_PATH_BCAST_PREQ); + _rtw_spinunlock_bh(&path->state_lock); + + da = rtw_hwmp_preq_da(path, is_root_add_chk, + da_is_peer, force_preq_bcast); + +#ifdef CONFIG_RTW_MESH_ON_DMD_GANN + flags = (mshcfg->dot11MeshGateAnnouncementProtocol) + ? RTW_IEEE80211_PREQ_IS_GATE_FLAG : 0; +#endif + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, adapter_mac_addr(adapter), minfo->sn, + target_flags, path->dst, path->sn, da, 0, + ttl, lifetime, 0, minfo->preq_id++, adapter); + rtw_mod_timer(&path->timer, rtw_get_current_time() + path->discovery_timeout); + +enddiscovery: + rtw_rcu_read_unlock(); + rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue)); +} + +void rtw_mesh_path_timer(void *ctx) +{ + struct rtw_mesh_path *path = (void *) ctx; + _adapter *adapter = path->adapter; + int ret; + u8 retry = 0; +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; +#endif + /* TBD: Proctect for suspend */ +#if 0 + if (suspending) + return; +#endif + _rtw_spinlock_bh(&path->state_lock); + if (path->flags & RTW_MESH_PATH_RESOLVED || + (!(path->flags & RTW_MESH_PATH_RESOLVING))) { + path->flags &= ~(RTW_MESH_PATH_RESOLVING | + RTW_MESH_PATH_RESOLVED | + RTW_MESH_PATH_ROOT_ADD_CHK | + RTW_MESH_PATH_PEER_AKA | + RTW_MESH_PATH_BCAST_PREQ); + _rtw_spinunlock_bh(&path->state_lock); + } else if (path->discovery_retries < rtw_max_preq_retries(adapter)) { + ++path->discovery_retries; + path->discovery_timeout *= 2; + path->flags &= ~RTW_MESH_PATH_REQ_QUEUED; +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + if (path->discovery_retries > mshcfg->max_root_add_chk_cnt) + path->flags &= ~RTW_MESH_PATH_ROOT_ADD_CHK; +#endif + if (path->gate_asked) + retry |= RTW_PREQ_Q_F_REFRESH; + + _rtw_spinunlock_bh(&path->state_lock); + rtw_mesh_queue_preq(path, retry); + } else { + path->flags &= ~(RTW_MESH_PATH_RESOLVING | + RTW_MESH_PATH_RESOLVED | + RTW_MESH_PATH_REQ_QUEUED | + RTW_MESH_PATH_ROOT_ADD_CHK | + RTW_MESH_PATH_PEER_AKA | + RTW_MESH_PATH_BCAST_PREQ); + path->exp_time = rtw_get_current_time(); + _rtw_spinunlock_bh(&path->state_lock); + if (!path->is_gate && rtw_mesh_gate_num(adapter) > 0) { + ret = rtw_mesh_path_send_to_gates(path); + if (ret) + RTW_HWMP_DBG("no gate was reachable\n"); + } else + rtw_mesh_path_flush_pending(path); + } +} + + +void rtw_mesh_path_tx_root_frame(_adapter *adapter) +{ + struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + u32 interval = mshcfg->dot11MeshHWMPRannInterval; + u8 flags, target_flags = 0; + + flags = (mshcfg->dot11MeshGateAnnouncementProtocol) + ? RTW_RANN_FLAG_IS_GATE : 0; + + switch (mshcfg->dot11MeshHWMPRootMode) { + case RTW_IEEE80211_PROACTIVE_RANN: + rtw_mesh_path_sel_frame_tx(RTW_MPATH_RANN, flags, adapter_mac_addr(adapter), + ++minfo->sn, 0, NULL, 0, bcast_addr, + 0, mshcfg->element_ttl, + interval, 0, 0, adapter); + break; + case RTW_IEEE80211_PROACTIVE_PREQ_WITH_PREP: + flags |= RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG; + case RTW_IEEE80211_PROACTIVE_PREQ_NO_PREP: + interval = mshcfg->dot11MeshHWMPactivePathToRootTimeout; + target_flags |= RTW_IEEE80211_PREQ_TO_FLAG | + RTW_IEEE80211_PREQ_USN_FLAG; + rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, adapter_mac_addr(adapter), + ++minfo->sn, target_flags, + (u8 *) bcast_addr, 0, bcast_addr, + 0, mshcfg->element_ttl, interval, + 0, minfo->preq_id++, adapter); + break; + default: + RTW_HWMP_INFO("Proactive mechanism not supported\n"); + return; + } +} + +void rtw_mesh_work(_workitem *work) +{ + /* use kernel global workqueue */ + _set_workitem(work); +} + +void rtw_ieee80211_mesh_path_timer(void *ctx) +{ + _adapter *adapter = (_adapter *)ctx; + rtw_mesh_work(&adapter->mesh_work); +} + +void rtw_ieee80211_mesh_path_root_timer(void *ctx) +{ + _adapter *adapter = (_adapter *)ctx; + + rtw_set_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags); + + rtw_mesh_work(&adapter->mesh_work); +} + +static void rtw_ieee80211_mesh_rootpath(_adapter *adapter) +{ + u32 interval; + + rtw_mesh_path_tx_root_frame(adapter); + + if (adapter->mesh_cfg.dot11MeshHWMPRootMode == RTW_IEEE80211_PROACTIVE_RANN) + interval = adapter->mesh_cfg.dot11MeshHWMPRannInterval; + else + interval = adapter->mesh_cfg.dot11MeshHWMProotInterval; + + rtw_mod_timer(&adapter->mesh_path_root_timer, + RTW_TU_TO_EXP_TIME(interval)); +} + +BOOLEAN rtw_ieee80211_mesh_root_setup(_adapter *adapter) +{ + BOOLEAN root_enabled = _FALSE; + + if (adapter->mesh_cfg.dot11MeshHWMPRootMode > RTW_IEEE80211_ROOTMODE_ROOT) { + rtw_set_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags); + root_enabled = _TRUE; + } + else { + rtw_clear_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags); + /* stop running timer */ + _cancel_timer_ex(&adapter->mesh_path_root_timer); + root_enabled = _FALSE; + } + + return root_enabled; +} + +void rtw_mesh_work_hdl(_workitem *work) +{ + _adapter *adapter = container_of(work, _adapter, mesh_work); + + while(adapter->mesh_info.preq_queue_len) { + if (rtw_time_after(rtw_get_current_time(), + adapter->mesh_info.last_preq + rtw_min_preq_int_jiff(adapter))) + /* It will consume preq_queue_len */ + rtw_mesh_path_start_discovery(adapter); + else { + struct rtw_mesh_info *minfo = &adapter->mesh_info; + + rtw_mod_timer(&adapter->mesh_path_timer, + minfo->last_preq + rtw_min_preq_int_jiff(adapter) + 1); + break; + } + } + + if (rtw_test_and_clear_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags)) + rtw_ieee80211_mesh_rootpath(adapter); +} + +#ifndef RTW_PER_CMD_SUPPORT_FW +static void rtw_update_metric_directly(_adapter *adapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + u8 i; + + for (i = 0; i < macid_ctl->num; i++) { + u8 role; + role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]); + if (role == H2C_MSR_ROLE_MESH) { + struct sta_info *sta = macid_ctl->sta[i]; + u8 sgi, bw; + u16 rate_idx; + u32 rate; + + if (!sta) + continue; + rate_idx = rtw_get_current_tx_rate(adapter, sta); + sgi = rtw_get_current_tx_sgi(adapter, sta); + bw = sta->phl_sta->chandef.bw; + rate = rtw_desc_rate_to_bitrate(bw, rate_idx, sgi); + sta->metrics.data_rate = rate; + } + } +} +#endif + +void rtw_mesh_atlm_param_req_timer(void *ctx) +{ + _adapter *adapter = (_adapter *)ctx; + u8 ret = _FAIL; + +#ifdef RTW_PER_CMD_SUPPORT_FW + ret = rtw_req_per_cmd(adapter); + if (ret == _FAIL) + RTW_HWMP_INFO("rtw_req_per_cmd fail\n"); +#else + rtw_update_metric_directly(adapter); +#endif + _set_timer(&adapter->mesh_atlm_param_req_timer, RTW_ATLM_REQ_CYCLE); +} + +#endif /* CONFIG_RTW_MESH */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.h b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.h new file mode 100644 index 00000000..466570e3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_hwmp.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_MESH_HWMP_H_ +#define __RTW_MESH_HWMP_H_ + +#ifndef DBG_RTW_HWMP +#define DBG_RTW_HWMP 0 +#endif +#if DBG_RTW_HWMP +#define RTW_HWMP_DBG(fmt, arg...) RTW_PRINT(fmt, ##arg) +#else +#define RTW_HWMP_DBG(fmt, arg...) RTW_DBG(fmt, ##arg) +#endif + +#ifndef INFO_RTW_HWMP +#define INFO_RTW_HWMP 0 +#endif +#if INFO_RTW_HWMP +#define RTW_HWMP_INFO(fmt, arg...) RTW_PRINT(fmt, ##arg) +#else +#define RTW_HWMP_INFO(fmt, arg...) RTW_INFO(fmt, ##arg) +#endif + + +void rtw_ewma_err_rate_init(struct rtw_ewma_err_rate *e); +unsigned long rtw_ewma_err_rate_read(struct rtw_ewma_err_rate *e); +void rtw_ewma_err_rate_add(struct rtw_ewma_err_rate *e, unsigned long val); +int rtw_mesh_path_error_tx(_adapter *adapter, + u8 ttl, const u8 *target, u32 target_sn, + u16 target_rcode, const u8 *ra); +void rtw_ieee80211s_update_metric(_adapter *adapter, u8 mac_id, + u8 per, u8 rate, + u8 bw, u8 total_pkt); +void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe); +void rtw_mesh_queue_preq(struct rtw_mesh_path *mpath, u8 flags); +void rtw_mesh_path_start_discovery(_adapter *adapter); +void rtw_mesh_path_timer(void *ctx); +void rtw_mesh_path_tx_root_frame(_adapter *adapter); +void rtw_mesh_work_hdl(_workitem *work); +void rtw_ieee80211_mesh_path_timer(void *ctx); +void rtw_ieee80211_mesh_path_root_timer(void *ctx); +BOOLEAN rtw_ieee80211_mesh_root_setup(_adapter *adapter); +void rtw_mesh_work(_workitem *work); +void rtw_mesh_atlm_param_req_timer(void *ctx); + +#endif /* __RTW_MESH_HWMP_H_ */ + + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.c b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.c new file mode 100644 index 00000000..97840a66 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.c @@ -0,0 +1,1241 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_MESH_PATHTBL_C_ + +#ifdef CONFIG_RTW_MESH +#include +#include + +#ifdef PLATFORM_LINUX +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +static void rtw_mpath_free_rcu(struct rtw_mesh_path *mpath) +{ + kfree_rcu(mpath, rcu); + rtw_mstat_update(MSTAT_TYPE_PHY, MSTAT_FREE, sizeof(struct rtw_mesh_path)); +} +#else +static void rtw_mpath_free_rcu_callback(rtw_rcu_head *head) +{ + struct rtw_mesh_path *mpath; + + mpath = container_of(head, struct rtw_mesh_path, rcu); + rtw_mfree(mpath, sizeof(struct rtw_mesh_path)); +} + +static void rtw_mpath_free_rcu(struct rtw_mesh_path *mpath) +{ + call_rcu(&mpath->rcu, rtw_mpath_free_rcu_callback); +} +#endif +#endif /* PLATFORM_LINUX */ + +static void rtw_mesh_path_free_rcu(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath); + +static u32 rtw_mesh_table_hash(const void *addr, u32 len, u32 seed) +{ + /* Use last four bytes of hw addr as hash index */ + return jhash_1word(*(u32 *)(addr+2), seed); +} + +static const rtw_rhashtable_params rtw_mesh_rht_params = { + .nelem_hint = 2, + .automatic_shrinking = true, + .key_len = ETH_ALEN, + .key_offset = offsetof(struct rtw_mesh_path, dst), + .head_offset = offsetof(struct rtw_mesh_path, rhash), + .hashfn = rtw_mesh_table_hash, +}; + +static inline bool rtw_mpath_expired(struct rtw_mesh_path *mpath) +{ + return (mpath->flags & RTW_MESH_PATH_ACTIVE) && + rtw_time_after(rtw_get_current_time(), mpath->exp_time) && + !(mpath->flags & RTW_MESH_PATH_FIXED); +} + +static void rtw_mesh_path_rht_free(void *ptr, void *tblptr) +{ + struct rtw_mesh_path *mpath = ptr; + struct rtw_mesh_table *tbl = tblptr; + + rtw_mesh_path_free_rcu(tbl, mpath); +} + +static struct rtw_mesh_table *rtw_mesh_table_alloc(void) +{ + struct rtw_mesh_table *newtbl; + + newtbl = rtw_malloc(sizeof(struct rtw_mesh_table)); + if (!newtbl) + return NULL; + + rtw_hlist_head_init(&newtbl->known_gates); + ATOMIC_SET(&newtbl->entries, 0); + _rtw_spinlock_init(&newtbl->gates_lock); + + return newtbl; +} + +static void rtw_mesh_table_free(struct rtw_mesh_table *tbl) +{ + rtw_rhashtable_free_and_destroy(&tbl->rhead, + rtw_mesh_path_rht_free, tbl); + rtw_mfree(tbl, sizeof(struct rtw_mesh_table)); +} + +/** + * + * rtw_mesh_path_assign_nexthop - update mesh path next hop + * + * @mpath: mesh path to update + * @sta: next hop to assign + * + * Locking: mpath->state_lock must be held when calling this function + */ +void rtw_mesh_path_assign_nexthop(struct rtw_mesh_path *mpath, struct sta_info *sta) +{ + struct xmit_frame *xframe; + _list *list, *head; + + rtw_rcu_assign_pointer(mpath->next_hop, sta); + + _rtw_spinlock_bh(&mpath->frame_queue.lock); + head = &mpath->frame_queue.queue; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + xframe = LIST_CONTAINOR(list, struct xmit_frame, list); + list = get_next(list); + _rtw_memcpy(xframe->attrib.ra, sta->phl_sta->mac_addr, ETH_ALEN); + } + + _rtw_spinunlock_bh(&mpath->frame_queue.lock); +} + +static void rtw_prepare_for_gate(struct xmit_frame *xframe, char *dst_addr, + struct rtw_mesh_path *gate_mpath) +{ + struct pkt_attrib *attrib = &xframe->attrib; + char *next_hop; + + if (attrib->mesh_frame_mode == MESH_UCAST_DATA) + attrib->mesh_frame_mode = MESH_UCAST_PX_DATA; + + /* update next hop */ + rtw_rcu_read_lock(); + next_hop = rtw_rcu_dereference(gate_mpath->next_hop)->phl_sta->mac_addr; + _rtw_memcpy(attrib->ra, next_hop, ETH_ALEN); + rtw_rcu_read_unlock(); + _rtw_memcpy(attrib->mda, dst_addr, ETH_ALEN); +} + +/** + * + * rtw_mesh_path_move_to_queue - Move or copy frames from one mpath queue to another + * + * This function is used to transfer or copy frames from an unresolved mpath to + * a gate mpath. The function also adds the Address Extension field and + * updates the next hop. + * + * If a frame already has an Address Extension field, only the next hop and + * destination addresses are updated. + * + * The gate mpath must be an active mpath with a valid mpath->next_hop. + * + * @mpath: An active mpath the frames will be sent to (i.e. the gate) + * @from_mpath: The failed mpath + * @copy: When true, copy all the frames to the new mpath queue. When false, + * move them. + */ +static void rtw_mesh_path_move_to_queue(struct rtw_mesh_path *gate_mpath, + struct rtw_mesh_path *from_mpath, + bool copy) +{ + struct xmit_frame *fskb; + _list *list, *head; + _list failq; + u32 failq_len; + + if (rtw_warn_on(gate_mpath == from_mpath)) + return; + if (rtw_warn_on(!gate_mpath->next_hop)) + return; + + _rtw_init_listhead(&failq); + + _rtw_spinlock_bh(&from_mpath->frame_queue.lock); + rtw_list_splice_init(&from_mpath->frame_queue.queue, &failq); + failq_len = from_mpath->frame_queue_len; + from_mpath->frame_queue_len = 0; + _rtw_spinunlock_bh(&from_mpath->frame_queue.lock); + + head = &failq; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + if (gate_mpath->frame_queue_len >= RTW_MESH_FRAME_QUEUE_LEN) { + RTW_MPATH_DBG(FUNC_ADPT_FMT" mpath queue for gate %pM is full!\n" + , FUNC_ADPT_ARG(gate_mpath->adapter), gate_mpath->dst); + break; + } + + fskb = LIST_CONTAINOR(list, struct xmit_frame, list); + list = get_next(list); + + rtw_list_delete(&fskb->list); + failq_len--; + rtw_prepare_for_gate(fskb, gate_mpath->dst, gate_mpath); + _rtw_spinlock_bh(&gate_mpath->frame_queue.lock); + rtw_list_insert_tail(&fskb->list, get_list_head(&gate_mpath->frame_queue)); + gate_mpath->frame_queue_len++; + _rtw_spinunlock_bh(&gate_mpath->frame_queue.lock); + + #if 0 /* TODO: copy */ + skb = rtw_skb_copy(fskb); + if (rtw_warn_on(!skb)) + break; + + rtw_prepare_for_gate(skb, gate_mpath->dst, gate_mpath); + skb_queue_tail(&gate_mpath->frame_queue, skb); + + if (copy) + continue; + + __skb_unlink(fskb, &failq); + rtw_skb_free(fskb); + #endif + } + + RTW_MPATH_DBG(FUNC_ADPT_FMT" mpath queue for gate %pM has %d frames\n" + , FUNC_ADPT_ARG(gate_mpath->adapter), gate_mpath->dst, gate_mpath->frame_queue_len); + + if (!copy) + return; + + _rtw_spinlock_bh(&from_mpath->frame_queue.lock); + rtw_list_splice(&failq, &from_mpath->frame_queue.queue); + from_mpath->frame_queue_len += failq_len; + _rtw_spinunlock_bh(&from_mpath->frame_queue.lock); +} + + +static struct rtw_mesh_path *rtw_mpath_lookup(struct rtw_mesh_table *tbl, const u8 *dst) +{ + struct rtw_mesh_path *mpath; + + if (!tbl) + return NULL; + + mpath = rtw_rhashtable_lookup_fast(&tbl->rhead, dst, rtw_mesh_rht_params); + + if (mpath && rtw_mpath_expired(mpath)) { + _rtw_spinlock_bh(&mpath->state_lock); + mpath->flags &= ~RTW_MESH_PATH_ACTIVE; + _rtw_spinunlock_bh(&mpath->state_lock); + } + return mpath; +} + +/** + * rtw_mesh_path_lookup - look up a path in the mesh path table + * @sdata: local subif + * @dst: hardware address (ETH_ALEN length) of destination + * + * Returns: pointer to the mesh path structure, or NULL if not found + * + * Locking: must be called within a read rcu section. + */ +struct rtw_mesh_path * +rtw_mesh_path_lookup(_adapter *adapter, const u8 *dst) +{ + return rtw_mpath_lookup(adapter->mesh_info.mesh_paths, dst); +} + +struct rtw_mesh_path * +rtw_mpp_path_lookup(_adapter *adapter, const u8 *dst) +{ + return rtw_mpath_lookup(adapter->mesh_info.mpp_paths, dst); +} + +static struct rtw_mesh_path * +__rtw_mesh_path_lookup_by_idx(struct rtw_mesh_table *tbl, int idx) +{ + int i = 0, ret; + struct rtw_mesh_path *mpath = NULL; + rtw_rhashtable_iter iter; + + if (!tbl) + return NULL; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return NULL; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto err; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + if (i++ == idx) + break; + } +err: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); + + if (IS_ERR(mpath) || !mpath) + return NULL; + + if (rtw_mpath_expired(mpath)) { + _rtw_spinlock_bh(&mpath->state_lock); + mpath->flags &= ~RTW_MESH_PATH_ACTIVE; + _rtw_spinunlock_bh(&mpath->state_lock); + } + return mpath; +} + +/** + * rtw_mesh_path_lookup_by_idx - look up a path in the mesh path table by its index + * @idx: index + * @sdata: local subif, or NULL for all entries + * + * Returns: pointer to the mesh path structure, or NULL if not found. + * + * Locking: must be called within a read rcu section. + */ +struct rtw_mesh_path * +rtw_mesh_path_lookup_by_idx(_adapter *adapter, int idx) +{ + return __rtw_mesh_path_lookup_by_idx(adapter->mesh_info.mesh_paths, idx); +} + +void dump_mpath(void *sel, _adapter *adapter) +{ + struct rtw_mesh_path *mpath; + int idx = 0; + char dst[ETH_ALEN]; + char next_hop[ETH_ALEN]; + u32 sn, metric, qlen; + u32 exp_ms = 0, dto_ms; + u8 drty; + enum rtw_mesh_path_flags flags; + + RTW_PRINT_SEL(sel, "%-17s %-17s %-10s %-10s %-4s %-6s %-6s %-4s flags\n" + , "dst", "next_hop", "sn", "metric", "qlen", "exp_ms", "dto_ms", "drty" + ); + + do { + rtw_rcu_read_lock(); + + mpath = rtw_mesh_path_lookup_by_idx(adapter, idx); + if (mpath) { + _rtw_memcpy(dst, mpath->dst, ETH_ALEN); + _rtw_memcpy(next_hop, mpath->next_hop->phl_sta->mac_addr, ETH_ALEN); + sn = mpath->sn; + metric = mpath->metric; + qlen = mpath->frame_queue_len; + if (rtw_time_after(mpath->exp_time, rtw_get_current_time())) + exp_ms = rtw_get_remaining_time_ms(mpath->exp_time); + dto_ms = rtw_systime_to_ms(mpath->discovery_timeout); + drty = mpath->discovery_retries; + flags = mpath->flags; + } + + rtw_rcu_read_unlock(); + + if (mpath) { + RTW_PRINT_SEL(sel, MAC_FMT" "MAC_FMT" %10u %10u %4u %6u %6u %4u%s%s%s%s%s%s%s%s%s%s\n" + , MAC_ARG(dst), MAC_ARG(next_hop), sn, metric, qlen + , exp_ms < 999999 ? exp_ms : 999999 + , dto_ms < 999999 ? dto_ms : 999999 + , drty + , (flags & RTW_MESH_PATH_ACTIVE) ? " ACT" : "" + , (flags & RTW_MESH_PATH_RESOLVING) ? " RSVING" : "" + , (flags & RTW_MESH_PATH_SN_VALID) ? " SN_VALID" : "" + , (flags & RTW_MESH_PATH_FIXED) ? " FIXED" : "" + , (flags & RTW_MESH_PATH_RESOLVED) ? " RSVED" : "" + , (flags & RTW_MESH_PATH_REQ_QUEUED) ? " REQ_IN_Q" : "" + , (flags & RTW_MESH_PATH_DELETED) ? " DELETED" : "" + , (flags & RTW_MESH_PATH_ROOT_ADD_CHK) ? " R_ADD_CHK" : "" + , (flags & RTW_MESH_PATH_PEER_AKA) ? " PEER_AKA" : "" + , (flags & RTW_MESH_PATH_BCAST_PREQ) ? " BC_PREQ" : "" + ); + } + + idx++; + } while (mpath); +} + +/** + * rtw_mpp_path_lookup_by_idx - look up a path in the proxy path table by its index + * @idx: index + * @sdata: local subif, or NULL for all entries + * + * Returns: pointer to the proxy path structure, or NULL if not found. + * + * Locking: must be called within a read rcu section. + */ +struct rtw_mesh_path * +rtw_mpp_path_lookup_by_idx(_adapter *adapter, int idx) +{ + return __rtw_mesh_path_lookup_by_idx(adapter->mesh_info.mpp_paths, idx); +} + +/** + * rtw_mesh_path_add_gate - add the given mpath to a mesh gate to our path table + * @mpath: gate path to add to table + */ +int rtw_mesh_path_add_gate(struct rtw_mesh_path *mpath) +{ + struct rtw_mesh_cfg *mcfg; + struct rtw_mesh_info *minfo; + struct rtw_mesh_table *tbl; + int err, ori_num_gates; + + rtw_rcu_read_lock(); + tbl = mpath->adapter->mesh_info.mesh_paths; + if (!tbl) { + err = -ENOENT; + goto err_rcu; + } + + _rtw_spinlock_bh(&mpath->state_lock); + mcfg = &mpath->adapter->mesh_cfg; + mpath->gate_timeout = rtw_get_current_time() + + rtw_ms_to_systime(mcfg->path_gate_timeout_factor * + mpath->gate_ann_int); + if (mpath->is_gate) { + err = -EEXIST; + _rtw_spinunlock_bh(&mpath->state_lock); + goto err_rcu; + } + + minfo = &mpath->adapter->mesh_info; + mpath->is_gate = true; + _rtw_spinlock(&tbl->gates_lock); + ori_num_gates = minfo->num_gates; + minfo->num_gates++; + rtw_hlist_add_head_rcu(&mpath->gate_list, &tbl->known_gates); + + if (ori_num_gates == 0 + || rtw_macaddr_is_larger(mpath->dst, minfo->max_addr_gate->dst) + ) { + minfo->max_addr_gate = mpath; + minfo->max_addr_gate_is_larger_than_self = + rtw_macaddr_is_larger(mpath->dst, adapter_mac_addr(mpath->adapter)); + } + + _rtw_spinunlock(&tbl->gates_lock); + + _rtw_spinunlock_bh(&mpath->state_lock); + + if (ori_num_gates == 0) { + rtw_update_beacon(mpath->adapter, WLAN_EID_MESH_CONFIG, NULL, _TRUE, 0); + #if CONFIG_RTW_MESH_CTO_MGATE_CARRIER + if (!rtw_mesh_cto_mgate_required(mpath->adapter)) + rtw_netif_carrier_on(mpath->adapter->pnetdev); + #endif + } + + RTW_MPATH_DBG( + FUNC_ADPT_FMT" Mesh path: Recorded new gate: %pM. %d known gates\n", + FUNC_ADPT_ARG(mpath->adapter), + mpath->dst, mpath->adapter->mesh_info.num_gates); + err = 0; +err_rcu: + rtw_rcu_read_unlock(); + return err; +} + +/** + * rtw_mesh_gate_del - remove a mesh gate from the list of known gates + * @tbl: table which holds our list of known gates + * @mpath: gate mpath + */ +void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath) +{ + struct rtw_mesh_cfg *mcfg; + struct rtw_mesh_info *minfo; + int ori_num_gates; + + rtw_lockdep_assert_held(&mpath->state_lock); + if (!mpath->is_gate) + return; + + mcfg = &mpath->adapter->mesh_cfg; + minfo = &mpath->adapter->mesh_info; + + mpath->is_gate = false; + _rtw_spinlock_bh(&tbl->gates_lock); + rtw_hlist_del_rcu(&mpath->gate_list); + ori_num_gates = minfo->num_gates; + minfo->num_gates--; + + if (ori_num_gates == 1) { + minfo->max_addr_gate = NULL; + minfo->max_addr_gate_is_larger_than_self = 0; + } else if (minfo->max_addr_gate == mpath) { + struct rtw_mesh_path *gate, *max_addr_gate = NULL; + rtw_hlist_node *node; + + rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) { + if (!max_addr_gate || rtw_macaddr_is_larger(gate->dst, max_addr_gate->dst)) + max_addr_gate = gate; + } + minfo->max_addr_gate = max_addr_gate; + minfo->max_addr_gate_is_larger_than_self = + rtw_macaddr_is_larger(max_addr_gate->dst, adapter_mac_addr(mpath->adapter)); + } + + _rtw_spinunlock_bh(&tbl->gates_lock); + + if (ori_num_gates == 1) { + rtw_update_beacon(mpath->adapter, WLAN_EID_MESH_CONFIG, NULL, _TRUE, 0); + #if CONFIG_RTW_MESH_CTO_MGATE_CARRIER + if (rtw_mesh_cto_mgate_required(mpath->adapter)) + rtw_netif_carrier_off(mpath->adapter->pnetdev); + #endif + } + + RTW_MPATH_DBG( + FUNC_ADPT_FMT" Mesh path: Deleted gate: %pM. %d known gates\n", + FUNC_ADPT_ARG(mpath->adapter), + mpath->dst, mpath->adapter->mesh_info.num_gates); +} + +/** + * rtw_mesh_gate_search - search a mesh gate from the list of known gates + * @tbl: table which holds our list of known gates + * @addr: address of gate + */ +bool rtw_mesh_gate_search(struct rtw_mesh_table *tbl, const u8 *addr) +{ + struct rtw_mesh_path *gate; + rtw_hlist_node *node; + bool exist = 0; + + rtw_rcu_read_lock(); + rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) { + if (_rtw_memcmp(gate->dst, addr, ETH_ALEN) == _TRUE) { + exist = 1; + break; + } + } + + rtw_rcu_read_unlock(); + + return exist; +} + +/** + * rtw_mesh_gate_num - number of gates known to this interface + * @sdata: subif data + */ +int rtw_mesh_gate_num(_adapter *adapter) +{ + return adapter->mesh_info.num_gates; +} + +bool rtw_mesh_is_primary_gate(_adapter *adapter) +{ + struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg; + struct rtw_mesh_info *minfo = &adapter->mesh_info; + + return mcfg->dot11MeshGateAnnouncementProtocol + && !minfo->max_addr_gate_is_larger_than_self; +} + +void dump_known_gates(void *sel, _adapter *adapter) +{ + struct rtw_mesh_info *minfo = &adapter->mesh_info; + struct rtw_mesh_table *tbl; + struct rtw_mesh_path *gate; + rtw_hlist_node *node; + + if (!rtw_mesh_gate_num(adapter)) + goto exit; + + rtw_rcu_read_lock(); + + tbl = minfo->mesh_paths; + if (!tbl) + goto unlock; + + RTW_PRINT_SEL(sel, "num:%d\n", rtw_mesh_gate_num(adapter)); + + rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) { + RTW_PRINT_SEL(sel, "%c"MAC_FMT"\n" + , gate == minfo->max_addr_gate ? '*' : ' ' + , MAC_ARG(gate->dst)); + } + +unlock: + rtw_rcu_read_unlock(); +exit: + return; +} + +static +struct rtw_mesh_path *rtw_mesh_path_new(_adapter *adapter, + const u8 *dst) +{ + struct rtw_mesh_path *new_mpath; + + new_mpath = rtw_zmalloc(sizeof(struct rtw_mesh_path)); + if (!new_mpath) + return NULL; + + _rtw_memcpy(new_mpath->dst, dst, ETH_ALEN); + _rtw_memset(new_mpath->rann_snd_addr, 0xFF, ETH_ALEN); + new_mpath->is_root = false; + new_mpath->adapter = adapter; + new_mpath->flags = 0; + new_mpath->gate_asked = false; + _rtw_init_queue(&new_mpath->frame_queue); + new_mpath->frame_queue_len = 0; + new_mpath->exp_time = rtw_get_current_time(); + _rtw_spinlock_init(&new_mpath->state_lock); + rtw_init_timer(&new_mpath->timer, rtw_mesh_path_timer, new_mpath); + + return new_mpath; +} + +/** + * rtw_mesh_path_add - allocate and add a new path to the mesh path table + * @dst: destination address of the path (ETH_ALEN length) + * @sdata: local subif + * + * Returns: 0 on success + * + * State: the initial state of the new path is set to 0 + */ +struct rtw_mesh_path *rtw_mesh_path_add(_adapter *adapter, + const u8 *dst) +{ + struct rtw_mesh_table *tbl = adapter->mesh_info.mesh_paths; + struct rtw_mesh_path *mpath, *new_mpath; + int ret; + + if (!tbl) + return ERR_PTR(-ENOTSUPP); + + if (_rtw_memcmp(dst, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE) + /* never add ourselves as neighbours */ + return ERR_PTR(-ENOTSUPP); + + if (is_multicast_mac_addr(dst)) + return ERR_PTR(-ENOTSUPP); + + if (ATOMIC_INC_UNLESS(&adapter->mesh_info.mpaths, RTW_MESH_MAX_MPATHS) == 0) + return ERR_PTR(-ENOSPC); + + new_mpath = rtw_mesh_path_new(adapter, dst); + if (!new_mpath) + return ERR_PTR(-ENOMEM); + + do { + ret = rtw_rhashtable_lookup_insert_fast(&tbl->rhead, + &new_mpath->rhash, + rtw_mesh_rht_params); + + if (ret == -EEXIST) + mpath = rtw_rhashtable_lookup_fast(&tbl->rhead, + dst, + rtw_mesh_rht_params); + + } while (unlikely(ret == -EEXIST && !mpath)); + + if (ret && ret != -EEXIST) + return ERR_PTR(ret); + + /* At this point either new_mpath was added, or we found a + * matching entry already in the table; in the latter case + * free the unnecessary new entry. + */ + if (ret == -EEXIST) { + rtw_mfree(new_mpath, sizeof(struct rtw_mesh_path)); + new_mpath = mpath; + } + adapter->mesh_info.mesh_paths_generation++; + return new_mpath; +} + +int rtw_mpp_path_add(_adapter *adapter, + const u8 *dst, const u8 *mpp) +{ + struct rtw_mesh_table *tbl = adapter->mesh_info.mpp_paths; + struct rtw_mesh_path *new_mpath; + int ret; + + if (!tbl) + return -ENOTSUPP; + + if (_rtw_memcmp(dst, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE) + /* never add ourselves as neighbours */ + return -ENOTSUPP; + + if (is_multicast_mac_addr(dst)) + return -ENOTSUPP; + + new_mpath = rtw_mesh_path_new(adapter, dst); + + if (!new_mpath) + return -ENOMEM; + + _rtw_memcpy(new_mpath->mpp, mpp, ETH_ALEN); + ret = rtw_rhashtable_lookup_insert_fast(&tbl->rhead, + &new_mpath->rhash, + rtw_mesh_rht_params); + + adapter->mesh_info.mpp_paths_generation++; + return ret; +} + +void dump_mpp(void *sel, _adapter *adapter) +{ + struct rtw_mesh_path *mpath; + int idx = 0; + char dst[ETH_ALEN]; + char mpp[ETH_ALEN]; + + RTW_PRINT_SEL(sel, "%-17s %-17s\n", "dst", "mpp"); + + do { + rtw_rcu_read_lock(); + + mpath = rtw_mpp_path_lookup_by_idx(adapter, idx); + if (mpath) { + _rtw_memcpy(dst, mpath->dst, ETH_ALEN); + _rtw_memcpy(mpp, mpath->mpp, ETH_ALEN); + } + + rtw_rcu_read_unlock(); + + if (mpath) { + RTW_PRINT_SEL(sel, MAC_FMT" "MAC_FMT"\n" + , MAC_ARG(dst), MAC_ARG(mpp)); + } + + idx++; + } while (mpath); +} + +/** + * rtw_mesh_plink_broken - deactivates paths and sends perr when a link breaks + * + * @sta: broken peer link + * + * This function must be called from the rate control algorithm if enough + * delivery errors suggest that a peer link is no longer usable. + */ +void rtw_mesh_plink_broken(struct sta_info *sta) +{ + _adapter *adapter = sta->padapter; + struct rtw_mesh_table *tbl = adapter->mesh_info.mesh_paths; + static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct rtw_mesh_path *mpath; + rtw_rhashtable_iter iter; + int ret; + + if (!tbl) + return; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + if (rtw_rcu_access_pointer(mpath->next_hop) == sta && + mpath->flags & RTW_MESH_PATH_ACTIVE && + !(mpath->flags & RTW_MESH_PATH_FIXED)) { + _rtw_spinlock_bh(&mpath->state_lock); + mpath->flags &= ~RTW_MESH_PATH_ACTIVE; + ++mpath->sn; + _rtw_spinunlock_bh(&mpath->state_lock); + rtw_mesh_path_error_tx(adapter, + adapter->mesh_cfg.element_ttl, + mpath->dst, mpath->sn, + WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast); + } + } +out: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); +} + +static void rtw_mesh_path_free_rcu(struct rtw_mesh_table *tbl, + struct rtw_mesh_path *mpath) +{ + _adapter *adapter = mpath->adapter; + + _rtw_spinlock_bh(&mpath->state_lock); + mpath->flags |= RTW_MESH_PATH_RESOLVING | RTW_MESH_PATH_DELETED; + rtw_mesh_gate_del(tbl, mpath); + _rtw_spinunlock_bh(&mpath->state_lock); + _cancel_timer_ex(&mpath->timer); + ATOMIC_DEC(&adapter->mesh_info.mpaths); + ATOMIC_DEC(&tbl->entries); + _rtw_spinlock_free(&mpath->state_lock); + + rtw_mesh_path_flush_pending(mpath); + + rtw_mpath_free_rcu(mpath); +} + +static void __rtw_mesh_path_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath) +{ + rtw_rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, rtw_mesh_rht_params); + rtw_mesh_path_free_rcu(tbl, mpath); +} + +/** + * rtw_mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches + * + * @sta: mesh peer to match + * + * RCU notes: this function is called when a mesh plink transitions from + * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that + * allows path creation. This will happen before the sta can be freed (because + * sta_info_destroy() calls this) so any reader in a rcu read block will be + * protected against the plink disappearing. + */ +void rtw_mesh_path_flush_by_nexthop(struct sta_info *sta) +{ + _adapter *adapter = sta->padapter; + struct rtw_mesh_table *tbl = adapter->mesh_info.mesh_paths; + struct rtw_mesh_path *mpath; + rtw_rhashtable_iter iter; + int ret; + + if (!tbl) + return; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + + if (rtw_rcu_access_pointer(mpath->next_hop) == sta) + __rtw_mesh_path_del(tbl, mpath); + } +out: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); +} + +static void rtw_mpp_flush_by_proxy(_adapter *adapter, + const u8 *proxy) +{ + struct rtw_mesh_table *tbl = adapter->mesh_info.mpp_paths; + struct rtw_mesh_path *mpath; + rtw_rhashtable_iter iter; + int ret; + + if (!tbl) + return; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + + if (_rtw_memcmp(mpath->mpp, proxy, ETH_ALEN) == _TRUE) + __rtw_mesh_path_del(tbl, mpath); + } +out: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); +} + +static void rtw_table_flush_by_iface(struct rtw_mesh_table *tbl) +{ + struct rtw_mesh_path *mpath; + rtw_rhashtable_iter iter; + int ret; + + if (!tbl) + return; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + __rtw_mesh_path_del(tbl, mpath); + } +out: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); +} + +/** + * rtw_mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface + * + * This function deletes both mesh paths as well as mesh portal paths. + * + * @sdata: interface data to match + * + */ +void rtw_mesh_path_flush_by_iface(_adapter *adapter) +{ + rtw_table_flush_by_iface(adapter->mesh_info.mesh_paths); + rtw_table_flush_by_iface(adapter->mesh_info.mpp_paths); +} + +/** + * rtw_table_path_del - delete a path from the mesh or mpp table + * + * @tbl: mesh or mpp path table + * @sdata: local subif + * @addr: dst address (ETH_ALEN length) + * + * Returns: 0 if successful + */ +static int rtw_table_path_del(struct rtw_mesh_table *tbl, + const u8 *addr) +{ + struct rtw_mesh_path *mpath; + + if (!tbl) + return -ENXIO; + + rtw_rcu_read_lock(); + mpath = rtw_rhashtable_lookup_fast(&tbl->rhead, addr, rtw_mesh_rht_params); + if (!mpath) { + rtw_rcu_read_unlock(); + return -ENXIO; + } + + __rtw_mesh_path_del(tbl, mpath); + rtw_rcu_read_unlock(); + return 0; +} + + +/** + * rtw_mesh_path_del - delete a mesh path from the table + * + * @addr: dst address (ETH_ALEN length) + * @sdata: local subif + * + * Returns: 0 if successful + */ +int rtw_mesh_path_del(_adapter *adapter, const u8 *addr) +{ + int err; + + /* flush relevant mpp entries first */ + rtw_mpp_flush_by_proxy(adapter, addr); + + err = rtw_table_path_del(adapter->mesh_info.mesh_paths, addr); + adapter->mesh_info.mesh_paths_generation++; + return err; +} + +/** + * rtw_mesh_path_tx_pending - sends pending frames in a mesh path queue + * + * @mpath: mesh path to activate + * + * Locking: the state_lock of the mpath structure must NOT be held when calling + * this function. + */ +void rtw_mesh_path_tx_pending(struct rtw_mesh_path *mpath) +{ + if (mpath->flags & RTW_MESH_PATH_ACTIVE) { + struct rtw_mesh_info *minfo = &mpath->adapter->mesh_info; + _list q; + u32 q_len = 0; + + _rtw_init_listhead(&q); + + /* move to local queue */ + _rtw_spinlock_bh(&mpath->frame_queue.lock); + if (mpath->frame_queue_len) { + rtw_list_splice_init(&mpath->frame_queue.queue, &q); + q_len = mpath->frame_queue_len; + mpath->frame_queue_len = 0; + } + _rtw_spinunlock_bh(&mpath->frame_queue.lock); + + if (q_len) { + /* move to mpath_tx_queue */ + _rtw_spinlock_bh(&minfo->mpath_tx_queue.lock); + rtw_list_splice_tail(&q, &minfo->mpath_tx_queue.queue); + minfo->mpath_tx_queue_len += q_len; + _rtw_spinunlock_bh(&minfo->mpath_tx_queue.lock); + + /* schedule mpath_tx_tasklet */ + tasklet_hi_schedule(&minfo->mpath_tx_tasklet); + } + } +} + +/** + * rtw_mesh_path_send_to_gates - sends pending frames to all known mesh gates + * + * @mpath: mesh path whose queue will be emptied + * + * If there is only one gate, the frames are transferred from the failed mpath + * queue to that gate's queue. If there are more than one gates, the frames + * are copied from each gate to the next. After frames are copied, the + * mpath queues are emptied onto the transmission queue. + */ +int rtw_mesh_path_send_to_gates(struct rtw_mesh_path *mpath) +{ + _adapter *adapter = mpath->adapter; + struct rtw_mesh_table *tbl; + struct rtw_mesh_path *from_mpath = mpath; + struct rtw_mesh_path *gate; + bool copy = false; + rtw_hlist_node *node; + + tbl = adapter->mesh_info.mesh_paths; + if (!tbl) + return 0; + + rtw_rcu_read_lock(); + rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) { + if (gate->flags & RTW_MESH_PATH_ACTIVE) { + RTW_MPATH_DBG(FUNC_ADPT_FMT" Forwarding to %pM\n", + FUNC_ADPT_ARG(adapter), gate->dst); + rtw_mesh_path_move_to_queue(gate, from_mpath, copy); + from_mpath = gate; + copy = true; + } else { + RTW_MPATH_DBG( + FUNC_ADPT_FMT" Not forwarding to %pM (flags %#x)\n", + FUNC_ADPT_ARG(adapter), gate->dst, gate->flags); + } + } + + rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) { + RTW_MPATH_DBG(FUNC_ADPT_FMT" Sending to %pM\n", + FUNC_ADPT_ARG(adapter), gate->dst); + rtw_mesh_path_tx_pending(gate); + } + rtw_rcu_read_unlock(); + + return (from_mpath == mpath) ? -EHOSTUNREACH : 0; +} + +/** + * rtw_mesh_path_discard_frame - discard a frame whose path could not be resolved + * + * @skb: frame to discard + * @sdata: network subif the frame was to be sent through + * + * Locking: the function must me called within a rcu_read_lock region + */ +void rtw_mesh_path_discard_frame(_adapter *adapter, + struct xmit_frame *xframe) +{ + rtw_free_xmitframe(&adapter->xmitpriv, xframe); + adapter->mesh_info.mshstats.dropped_frames_no_route++; +} + +/** + * rtw_mesh_path_flush_pending - free the pending queue of a mesh path + * + * @mpath: mesh path whose queue has to be freed + * + * Locking: the function must me called within a rcu_read_lock region + */ +void rtw_mesh_path_flush_pending(struct rtw_mesh_path *mpath) +{ + struct xmit_frame *xframe; + _list *list, *head; + _list tmp; + + _rtw_init_listhead(&tmp); + + _rtw_spinlock_bh(&mpath->frame_queue.lock); + rtw_list_splice_init(&mpath->frame_queue.queue, &tmp); + mpath->frame_queue_len = 0; + _rtw_spinunlock_bh(&mpath->frame_queue.lock); + + head = &tmp; + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + xframe = LIST_CONTAINOR(list, struct xmit_frame, list); + list = get_next(list); + rtw_list_delete(&xframe->list); + rtw_mesh_path_discard_frame(mpath->adapter, xframe); + } +} + +/** + * rtw_mesh_path_fix_nexthop - force a specific next hop for a mesh path + * + * @mpath: the mesh path to modify + * @next_hop: the next hop to force + * + * Locking: this function must be called holding mpath->state_lock + */ +void rtw_mesh_path_fix_nexthop(struct rtw_mesh_path *mpath, struct sta_info *next_hop) +{ + _rtw_spinlock_bh(&mpath->state_lock); + rtw_mesh_path_assign_nexthop(mpath, next_hop); + mpath->sn = 0xffff; + mpath->metric = 0; + mpath->hop_count = 0; + mpath->exp_time = 0; + mpath->flags = RTW_MESH_PATH_FIXED | RTW_MESH_PATH_SN_VALID; + rtw_mesh_path_activate(mpath); + _rtw_spinunlock_bh(&mpath->state_lock); + rtw_ewma_err_rate_init(&next_hop->metrics.err_rate); + /* init it at a low value - 0 start is tricky */ + rtw_ewma_err_rate_add(&next_hop->metrics.err_rate, 1); + rtw_mesh_path_tx_pending(mpath); +} + +int rtw_mesh_pathtbl_init(_adapter *adapter) +{ + struct rtw_mesh_table *tbl_path, *tbl_mpp; + int ret; + + tbl_path = rtw_mesh_table_alloc(); + if (!tbl_path) + return -ENOMEM; + + tbl_mpp = rtw_mesh_table_alloc(); + if (!tbl_mpp) { + ret = -ENOMEM; + goto free_path; + } + + rtw_rhashtable_init(&tbl_path->rhead, &rtw_mesh_rht_params); + rtw_rhashtable_init(&tbl_mpp->rhead, &rtw_mesh_rht_params); + + adapter->mesh_info.mesh_paths = tbl_path; + adapter->mesh_info.mpp_paths = tbl_mpp; + + return 0; + +free_path: + rtw_mesh_table_free(tbl_path); + return ret; +} + +static +void rtw_mesh_path_tbl_expire(_adapter *adapter, + struct rtw_mesh_table *tbl) +{ + struct rtw_mesh_path *mpath; + rtw_rhashtable_iter iter; + int ret; + + if (!tbl) + return; + + ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter); + if (ret) + return; + + ret = rtw_rhashtable_walk_start(&iter); + if (ret && ret != -EAGAIN) + goto out; + + while ((mpath = rtw_rhashtable_walk_next(&iter))) { + if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN) + continue; + if (IS_ERR(mpath)) + break; + if ((!(mpath->flags & RTW_MESH_PATH_RESOLVING)) && + (!(mpath->flags & RTW_MESH_PATH_FIXED)) && + rtw_time_after(rtw_get_current_time(), mpath->exp_time + RTW_MESH_PATH_EXPIRE)) + __rtw_mesh_path_del(tbl, mpath); + + if (mpath->is_gate && /* need not to deal with non-gate case */ + rtw_time_after(rtw_get_current_time(), mpath->gate_timeout)) { + RTW_MPATH_DBG(FUNC_ADPT_FMT"mpath [%pM] expired systime is %lu systime is %lu\n", + FUNC_ADPT_ARG(adapter), mpath->dst, + mpath->gate_timeout, rtw_get_current_time()); + _rtw_spinlock_bh(&mpath->state_lock); + if (mpath->gate_asked) { /* asked gate before */ + rtw_mesh_gate_del(tbl, mpath); + _rtw_spinunlock_bh(&mpath->state_lock); + } else { + mpath->gate_asked = true; + mpath->gate_timeout = rtw_get_current_time() + rtw_ms_to_systime(mpath->gate_ann_int); + _rtw_spinunlock_bh(&mpath->state_lock); + rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH); + RTW_MPATH_DBG(FUNC_ADPT_FMT"mpath [%pM] ask mesh gate existence (is_root=%d)\n", + FUNC_ADPT_ARG(adapter), mpath->dst, mpath->is_root); + } + } + } + +out: + rtw_rhashtable_walk_stop(&iter); + rtw_rhashtable_walk_exit(&iter); +} + +void rtw_mesh_path_expire(_adapter *adapter) +{ + rtw_mesh_path_tbl_expire(adapter, adapter->mesh_info.mesh_paths); + rtw_mesh_path_tbl_expire(adapter, adapter->mesh_info.mpp_paths); +} + +void rtw_mesh_pathtbl_unregister(_adapter *adapter) +{ + if (adapter->mesh_info.mesh_paths) { + rtw_mesh_table_free(adapter->mesh_info.mesh_paths); + adapter->mesh_info.mesh_paths = NULL; + } + + if (adapter->mesh_info.mpp_paths) { + rtw_mesh_table_free(adapter->mesh_info.mpp_paths); + adapter->mesh_info.mpp_paths = NULL; + } +} +#endif /* CONFIG_RTW_MESH */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.h b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.h new file mode 100644 index 00000000..7ff4d8ba --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/mesh/rtw_mesh_pathtbl.h @@ -0,0 +1,211 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_MESH_PATHTBL_H_ +#define __RTW_MESH_PATHTBL_H_ + +#ifndef DBG_RTW_MPATH +#define DBG_RTW_MPATH 1 +#endif +#if DBG_RTW_MPATH +#define RTW_MPATH_DBG(fmt, arg...) RTW_PRINT(fmt, ##arg) +#else +#define RTW_MPATH_DBG(fmt, arg...) do {} while (0) +#endif + +/** + * enum rtw_mesh_path_flags - mesh path flags + * + * @RTW_MESH_PATH_ACTIVE: the mesh path can be used for forwarding + * @RTW_MESH_PATH_RESOLVING: the discovery process is running for this mesh path + * @RTW_MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence + * number + * @RTW_MESH_PATH_FIXED: the mesh path has been manually set and should not be + * modified + * @RTW_MESH_PATH_RESOLVED: the mesh path can has been resolved + * @RTW_MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination + * already queued up, waiting for the discovery process to start. + * @RTW_MESH_PATH_DELETED: the mesh path has been deleted and should no longer + * be used + * @RTW_MESH_PATH_ROOT_ADD_CHK: root additional check in root mode. + * With this flag, It will try the last used rann_snd_addr + * @RTW_MESH_PATH_PEER_AKA: only used toward a peer, only used in active keep + * alive mechanism. PREQ's da = path dst + * @RTW_MESH_PATH_BCAST_PREQ: for re-checking next hop resolve toward root. + * Use it to force path_discover sending broadcast PREQ for root. + * + * RTW_MESH_PATH_RESOLVED is used by the mesh path timer to + * decide when to stop or cancel the mesh path discovery. + */ +enum rtw_mesh_path_flags { + RTW_MESH_PATH_ACTIVE = BIT(0), + RTW_MESH_PATH_RESOLVING = BIT(1), + RTW_MESH_PATH_SN_VALID = BIT(2), + RTW_MESH_PATH_FIXED = BIT(3), + RTW_MESH_PATH_RESOLVED = BIT(4), + RTW_MESH_PATH_REQ_QUEUED = BIT(5), + RTW_MESH_PATH_DELETED = BIT(6), + RTW_MESH_PATH_ROOT_ADD_CHK = BIT(7), + RTW_MESH_PATH_PEER_AKA = BIT(8), + RTW_MESH_PATH_BCAST_PREQ = BIT(9), +}; + +/** + * struct rtw_mesh_path - mesh path structure + * + * @dst: mesh path destination mac address + * @mpp: mesh proxy mac address + * @rhash: rhashtable list pointer + * @gate_list: list pointer for known gates list + * @sdata: mesh subif + * @next_hop: mesh neighbor to which frames for this destination will be + * forwarded + * @timer: mesh path discovery timer + * @frame_queue: pending queue for frames sent to this destination while the + * path is unresolved + * @rcu: rcu head for freeing mesh path + * @sn: target sequence number + * @metric: current metric to this destination + * @hop_count: hops to destination + * @exp_time: in jiffies, when the path will expire or when it expired + * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery + * retry + * @discovery_retries: number of discovery retries + * @flags: mesh path flags, as specified on &enum rtw_mesh_path_flags + * @state_lock: mesh path state lock used to protect changes to the + * mpath itself. No need to take this lock when adding or removing + * an mpath to a hash bucket on a path table. + * @rann_snd_addr: the RANN sender address + * @rann_metric: the aggregated path metric towards the root node + * @last_preq_to_root: Timestamp of last PREQ sent to root + * @is_root: the destination station of this path is a root node + * @is_gate: the destination station of this path is a mesh gate + * + * + * The dst address is unique in the mesh path table. Since the mesh_path is + * protected by RCU, deleting the next_hop STA must remove / substitute the + * mesh_path structure and wait until that is no longer reachable before + * destroying the STA completely. + */ +struct rtw_mesh_path { + u8 dst[ETH_ALEN]; + u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ + rtw_rhash_head rhash; + rtw_hlist_node gate_list; + _adapter *adapter; + struct sta_info __rcu *next_hop; + _timer timer; + _queue frame_queue; + u32 frame_queue_len; + rtw_rcu_head rcu; + u32 sn; + u32 metric; + u8 hop_count; + systime exp_time; + systime discovery_timeout; + systime gate_timeout; + u32 gate_ann_int; /* gate announce interval */ + u8 discovery_retries; + enum rtw_mesh_path_flags flags; + _lock state_lock; + u8 rann_snd_addr[ETH_ALEN]; +#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK + u8 add_chk_rann_snd_addr[ETH_ALEN]; +#endif + u32 rann_metric; + unsigned long last_preq_to_root; + bool is_root; + bool is_gate; + bool gate_asked; +}; + +/** + * struct rtw_mesh_table + * + * @known_gates: list of known mesh gates and their mpaths by the station. The + * gate's mpath may or may not be resolved and active. + * @gates_lock: protects updates to known_gates + * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr + * @entries: number of entries in the table + */ +struct rtw_mesh_table { + rtw_hlist_head known_gates; + _lock gates_lock; + rtw_rhashtable rhead; + ATOMIC_T entries; +}; + +#define RTW_MESH_PATH_EXPIRE (600 * HZ) + +/* Maximum number of paths per interface */ +#define RTW_MESH_MAX_MPATHS 1024 + +/* Number of frames buffered per destination for unresolved destinations */ +#define RTW_MESH_FRAME_QUEUE_LEN 10 + +int rtw_mesh_nexthop_lookup(_adapter *adapter, + const u8 *mda, const u8 *msa, u8 *ra); +int rtw_mesh_nexthop_resolve(_adapter *adapter, + struct xmit_frame *xframe); + +struct rtw_mesh_path *rtw_mesh_path_lookup(_adapter *adapter, + const u8 *dst); +struct rtw_mesh_path *rtw_mpp_path_lookup(_adapter *adapter, + const u8 *dst); +int rtw_mpp_path_add(_adapter *adapter, + const u8 *dst, const u8 *mpp); +void dump_mpp(void *sel, _adapter *adapter); + +struct rtw_mesh_path * +rtw_mesh_path_lookup_by_idx(_adapter *adapter, int idx); +void dump_mpath(void *sel, _adapter *adapter); + +struct rtw_mesh_path * +rtw_mpp_path_lookup_by_idx(_adapter *adapter, int idx); +void rtw_mesh_path_fix_nexthop(struct rtw_mesh_path *mpath, struct sta_info *next_hop); +void rtw_mesh_path_expire(_adapter *adapter); + +struct rtw_mesh_path * +rtw_mesh_path_add(_adapter *adapter, const u8 *dst); + +int rtw_mesh_path_add_gate(struct rtw_mesh_path *mpath); +void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath); +bool rtw_mesh_gate_search(struct rtw_mesh_table *tbl, const u8 *addr); +int rtw_mesh_path_send_to_gates(struct rtw_mesh_path *mpath); +int rtw_mesh_gate_num(_adapter *adapter); +bool rtw_mesh_is_primary_gate(_adapter *adapter); +void dump_known_gates(void *sel, _adapter *adapter); + +void rtw_mesh_plink_broken(struct sta_info *sta); + +void rtw_mesh_path_assign_nexthop(struct rtw_mesh_path *mpath, struct sta_info *sta); +void rtw_mesh_path_flush_pending(struct rtw_mesh_path *mpath); +void rtw_mesh_path_tx_pending(struct rtw_mesh_path *mpath); +int rtw_mesh_pathtbl_init(_adapter *adapter); +void rtw_mesh_pathtbl_unregister(_adapter *adapter); +int rtw_mesh_path_del(_adapter *adapter, const u8 *addr); + +void rtw_mesh_path_flush_by_nexthop(struct sta_info *sta); +void rtw_mesh_path_discard_frame(_adapter *adapter, + struct xmit_frame *xframe); + +static inline void rtw_mesh_path_activate(struct rtw_mesh_path *mpath) +{ + mpath->flags |= RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVED; +} + +void rtw_mesh_path_flush_by_iface(_adapter *adapter); + +#endif /* __RTW_MESH_PATHTBL_H_ */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.c b/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.c new file mode 100755 index 00000000..c7b523be --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.c @@ -0,0 +1,806 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_RADIOTAP_C_ + +#ifdef CONFIG_WIFI_MONITOR + +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) +#include +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) +#define __bf_shf(x) (__builtin_ffsll(x) - 1) + +/** + * FIELD_PREP() - prepare a bitfield element + * @_mask: shifted mask defining the field's length and position + * @_val: value to put in the field + * + * FIELD_PREP() masks and shifts up the value. The result should + * be combined with other fields of the bitfield using logical OR. + */ +#define FIELD_PREP(_mask, _val) \ + ({ \ + ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ + }) +#endif + +#define __encode_bits(w, v, field) FIELD_PREP((u##w)(field), v) +#define __u16_encode_bits(v, field) __encode_bits(16, v, field) +#define __le16_encode_bits(v, field) cpu_to_le16(__encode_bits(16, v, field)) +#define __be16_encode_bits(v, field) cpu_to_be16(__encode_bits(16, v, field)) +#define __u32_encode_bits(v, field) __encode_bits(32, v, field) +#define __le32_encode_bits(v, field) cpu_to_le32(__encode_bits(32, v, field)) +#define __be32_encode_bits(v, field) cpu_to_be32(__encode_bits(32, v, field)) +#define __u64_encode_bits(v, field) __encode_bits(64, v, field) +#define __le64_encode_bits(v, field) cpu_to_le64(__encode_bits(64, v, field)) +#define __be64_encode_bits(v, field) cpu_to_be64(__encode_bits(64, v, field)) + + +#define CHAN2FREQ(a) ((a < 14) ? (2407+5*a) : (5000+5*a)) + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)) +#define IEEE80211_RADIOTAP_ZERO_LEN_PSDU 26 +#define IEEE80211_RADIOTAP_LSIG 27 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) +#define IEEE80211_RADIOTAP_TIMESTAMP 22 +/* For IEEE80211_RADIOTAP_TIMESTAMP */ +#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK 0x000F +#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS 0x0000 +#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US 0x0001 +#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS 0x0003 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK 0x00F0 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU 0x0000 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0010 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU 0x0020 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0030 +#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN 0x00F0 + +#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT 0x00 +#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT 0x01 +#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY 0x02 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)) +/* for IEEE80211_RADIOTAP_CHANNEL */ +#define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */ +#define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */ +#define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */ +#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */ +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) +#define IEEE80211_RADIOTAP_HE 23 + +struct ieee80211_radiotap_he { + u16 data1, data2, data3, data4, data5, data6; +}; + +enum ieee80211_radiotap_he_bits { + IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3, + IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0, + IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1, + IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2, + IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3, + + IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004, + IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, + IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010, + IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020, + IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040, + IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080, + IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, + IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200, + IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, + IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, + IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, + IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, + IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, + IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000, + + IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001, + IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002, + IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, + IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, + IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010, + IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, + IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040, + IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000, + IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000, + + IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f, + IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040, + IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080, + IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00, + IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000, + IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000, + IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000, + IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000, + + IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f, + IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0, + IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f, + IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0, + IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00, + IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000, + + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9, + IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10, + + IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030, + IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0, + IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1, + IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2, + + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3, + IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700, + IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000, + IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000, + IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000, + + IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, + IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, + IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, + IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, +}; + +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) +#define IEEE80211_RADIOTAP_VHT 21 +/* For IEEE80211_RADIOTAP_VHT */ +#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001 +#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 +#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008 +#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080 +#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100 + +#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 +#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08 +#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 +#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) +#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 +#define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02 +#define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04 +#define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) +#define IEEE80211_RADIOTAP_AMPDU_STATUS 20 +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) +#define IEEE80211_RADIOTAP_AMPDU_EOF 0x0040 +#define IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN 0x0080 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) +#define IEEE80211_RADIOTAP_MCS 19 +/* For IEEE80211_RADIOTAP_MCS */ +#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 +#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 +#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 +#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 +#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 + +#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 +#define IEEE80211_RADIOTAP_MCS_BW_20 0 +#define IEEE80211_RADIOTAP_MCS_BW_40 1 +#define IEEE80211_RADIOTAP_MCS_BW_20L 2 +#define IEEE80211_RADIOTAP_MCS_BW_20U 3 +#define IEEE80211_RADIOTAP_MCS_SGI 0x04 +#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 +#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)) +#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 + +#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 +#define IEEE80211_RADIOTAP_MCS_STBC_1 1 +#define IEEE80211_RADIOTAP_MCS_STBC_2 2 +#define IEEE80211_RADIOTAP_MCS_STBC_3 3 +#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)) +#define IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE 29 +#define IEEE80211_RADIOTAP_VENDOR_NAMESPACE 30 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)) +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 +#endif + +static inline void _rtw_radiotap_fill_flags(struct rx_pkt_attrib *a, u8 *flags) +{ + struct moinfo *moif = (struct moinfo *)&a->moif; + + if (0) + *flags |= IEEE80211_RADIOTAP_F_CFP; + + if (0) + *flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + if ((a->encrypt == 1) || (a->encrypt == 5)) + *flags |= IEEE80211_RADIOTAP_F_WEP; + + if (a->mfrag) + *flags |= IEEE80211_RADIOTAP_F_FRAG; + + if (1) + *flags |= IEEE80211_RADIOTAP_F_FCS; + + if (0) + *flags |= IEEE80211_RADIOTAP_F_DATAPAD; + + if (a->crc_err) + *flags |= IEEE80211_RADIOTAP_F_BADFCS; + + /* Currently unspecified but used + for short guard interval (HT) */ + if (moif->u.snif_info.sgi || a->sgi) + *flags |= 0x80; + +} + +sint rtw_fill_radiotap_hdr(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + struct rx_pkt_attrib *a, struct rtw_recv_pkt *rx_req, u8 *buf) +{ +#define RTAP_HDR_MAX 64 + + sint ret = _SUCCESS; + struct moinfo *moif = (struct moinfo *)&a->moif; + + u8 rx_cnt = 0; + + int i = 0; + u8 tmp_8bit = 0; + u16 tmp_16bit = 0; + u32 tmp_32bit = 0; + u64 tmp_64bit = 0; + + struct sk_buff *pskb = NULL; + + struct ieee80211_radiotap_header *rtap_hdr = NULL; + u8 *ptr = NULL; + + /* + radiotap length (include header 8) + 11G length: 36 (0x0040002f) + 11N length: + 11AC length: 60 (0x0070002b) + */ + u8 hdr_buf[RTAP_HDR_MAX] = { 0 }; + u16 rt_len = 8; + + /* create header */ + rtap_hdr = (struct ieee80211_radiotap_header *)&hdr_buf[0]; + rtap_hdr->it_version = PKTHDR_RADIOTAP_VERSION; + + /* each antenna information */ + rx_cnt = GET_HAL_RFPATH_NUM(padapter->dvobj); +#if 0 + if (rx_cnt > 1) { + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) | + BIT(IEEE80211_RADIOTAP_EXT); + + for (i = 1; i < rx_cnt; i++) { + tmp_32bit = (BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + BIT(IEEE80211_RADIOTAP_LOCK_QUALITY) | + BIT(IEEE80211_RADIOTAP_ANTENNA) | + BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) | + BIT(IEEE80211_RADIOTAP_EXT)); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4); + rt_len += 4; + } + + tmp_32bit = (BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + BIT(IEEE80211_RADIOTAP_LOCK_QUALITY) | + BIT(IEEE80211_RADIOTAP_ANTENNA)); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4); + rt_len += 4; + } +#endif + + /* tsft, Required Alignment: 8 bytes */ + if (0) { //(a->free_cnt) { + /* TSFT + free_cnt */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_TSFT); + if (!IS_ALIGNED(rt_len, 8)) + rt_len = ((rt_len + 7) & 0xFFF8); /* Alignment */ + + tmp_64bit = cpu_to_le64(rx_req->mdata.freerun_cnt); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_64bit, 8); + rt_len += 8; + } + + /* flags */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_FLAGS); + _rtw_radiotap_fill_flags(a, &hdr_buf[rt_len]); + rt_len += 1; + + /* rate */ + if (rx_req->mdata.rx_rate <= RTW_DATA_RATE_OFDM54) { + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RATE); + hdr_buf[rt_len] = hwrate_to_mrate(rx_req->mdata.rx_rate); + rt_len += 1; + } + + /* channel & flags, Required Alignment: 2 bytes */ + if (1) { + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_CHANNEL); + rt_len += (rt_len % 2); /* Alignment */ + + tmp_16bit = CHAN2FREQ(rtw_get_oper_ch(padapter, padapter_link)); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; + + /* channel flags */ + tmp_16bit = 0; + if (WIFI_ROLE_LINK_IS_ON_24G(padapter_link)) + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_2GHZ); + else + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_5GHZ); + + if (rx_req->mdata.rx_rate <= RTW_DATA_RATE_CCK11) { + /* CCK */ + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_CCK); + } else { + /* OFDM */ + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_OFDM); + } + + if (rtw_get_oper_bw(padapter, padapter_link) == CHANNEL_WIDTH_10) { + /* 10Mhz Channel Width */ + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_HALF); + } + + if (rtw_get_oper_bw(padapter, padapter_link) == CHANNEL_WIDTH_5) { + /* 5Mhz Channel Width */ + tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_QUARTER); + } + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; + } + + /* dBm Antenna Signal */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); + hdr_buf[rt_len] = a->phy_info.recv_signal_power; + rt_len += 1; + +#if 0 + /* dBm Antenna Noise */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_DBM_ANTNOISE); + hdr_buf[rt_len] = 0; + rt_len += 1; +#endif +#if 0 + /* Signal Quality, Required Alignment: 2 bytes */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_LOCK_QUALITY); + if (!IS_ALIGNED(rt_len, 2)) + rt_len++; + hdr_buf[rt_len] = a->phy_info.signal_quality; + rt_len += 2; + +#endif + +#if 0 + /* Antenna */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_ANTENNA); + hdr_buf[rt_len] = 0; /* pHalData->rf_type; */ + rt_len += 1; +#endif +#if 0 + /* RX flags, Required Alignment: 2 bytes */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RX_FLAGS); + tmp_16bit = 0; + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; +#endif + + /* MCS information, Required Alignment: 1 bytes */ + if (rx_req->mdata.rx_rate >= RTW_DATA_RATE_MCS0 && rx_req->mdata.rx_rate <= RTW_DATA_RATE_MCS31) { + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_MCS); + /* Structure u8 known, u8 flags, u8 mcs */ + + /* known.bandwidth */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_BW; + if (moif->u.snif_info.ofdm_bw) + hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_40; + if (rx_req->mdata.bw == CHANNEL_WIDTH_40) + hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_40; + else + hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_20; + + + /* known.guard interval */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_GI; + if (moif->u.snif_info.sgi) { + hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_SGI; + } else { + hdr_buf[rt_len + 1] |= ((a->sgi & 0x01) << 2); + } + + /* FEC Type */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_FEC; + if (moif->u.snif_info.ldpc) { + hdr_buf[rt_len + 1] |= ((moif->u.snif_info.ldpc & 0x01) << 4); + } else { + hdr_buf[rt_len + 1] |= ((a->ldpc & 0x01) << 4); + } + + /* STBC */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_STBC; + if (moif->u.snif_info.stbc) { + hdr_buf[rt_len + 1] |= ((moif->u.snif_info.stbc & 0x03) << 5); + } else { + hdr_buf[rt_len + 1] |= ((a->stbc & 0x03) << 5); + } + + /* known.MCS index */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_MCS; + + /* u8 mcs */ + hdr_buf[rt_len + 2] = rx_req->mdata.rx_rate - RTW_DATA_RATE_MCS0; + + rt_len += 3; + } + + /* AMPDU, Required Alignment: 4 bytes */ + if (rx_req->mdata.ampdu) { + static u32 ref_num = 0x10000000; + static u8 ppdu_cnt = 0; + + /* Structure u32 reference number, u16 flags, u8 delimiter CRC value, u8 reserved */ + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_AMPDU_STATUS); + if (!IS_ALIGNED(rt_len, 4)) + rt_len = ((rt_len + 3) & 0xFFFC); /* Alignment */ + + /* u32 reference number */ + if (rx_req->mdata.ppdu_cnt != ppdu_cnt) { + ppdu_cnt = rx_req->mdata.ppdu_cnt; + ref_num += 1; + } + tmp_32bit = cpu_to_le32(ref_num); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4); + rt_len += 4; + + /* u16 flags */ + tmp_16bit = 0; + if (0) { + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN); + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN); + } + + if (0) { + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_IS_LAST); + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN); + } + + if (0) { + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR); + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN); + } + + if (rx_req->mdata.ampdu_end_pkt) { + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN); + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_EOF); + } + + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; + + /* u8 delimiter CRC value, u8 reserved */ + rt_len += 2; + } + + /* VHT, Required Alignment: 2 bytes */ + if (rx_req->mdata.rx_rate >= RTW_DATA_RATE_VHT_NSS1_MCS0 && rx_req->mdata.rx_rate <= RTW_DATA_RATE_VHT_NSS4_MCS9) { + + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_VHT); + + rt_len += (rt_len % 2); /* Alignment */ + + /* Structure + u16 known, u8 flags, u8 bandwidth, u8 mcs_nss[4], + u8 coding, u8 group_id, u16 partial_aid */ + + tmp_16bit = 0; + + /* STBC */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_STBC); + if (moif->u.snif_info.stbc) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; + } else { + hdr_buf[rt_len + 2] |= (a->stbc & 0x01); + } + + /* TXOP_PS_NOT_ALLOWED */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA); + if (moif->u.snif_info.vht_txop_not_allow) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA; + } + + + /* Guard interval */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_GI); + if (moif->u.snif_info.sgi) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; + } else { + hdr_buf[rt_len + 2] |= ((a->sgi & 0x01) << 2); + } + + /* Short GI NSYM */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS); + if (moif->u.snif_info.vht_nsym_dis) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9; + } + + /* LDPC extra OFDM symbol */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM); + if (moif->u.snif_info.vht_ldpc_extra) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM; + } else { + hdr_buf[rt_len + 2] |= ((a->ldpc & 0x01) << 4); + } + + /* Short GI NSYM */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED); + if (moif->u.snif_info.vht_beamformed) { + hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED; + } + + /* know.Bandwidth */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); + + /* Group ID */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID); + + /* Partial AID */ + tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID); + + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 3; + + /* u8 bandwidth */ + if (moif->u.snif_info.ofdm_bw) + tmp_8bit = moif->u.snif_info.ofdm_bw; + else + tmp_8bit = rx_req->mdata.bw; + + switch (tmp_8bit) { + case CHANNEL_WIDTH_20: + hdr_buf[rt_len] |= 0; + break; + case CHANNEL_WIDTH_40: + hdr_buf[rt_len] |= 1; + break; + case CHANNEL_WIDTH_80: + hdr_buf[rt_len] |= 4; + break; + case CHANNEL_WIDTH_160: + hdr_buf[rt_len] |= 11; + break; + default: + hdr_buf[rt_len] |= 0; + } + rt_len += 1; + + /* u8 mcs_nss[4] */ + if ((RTW_DATA_RATE_VHT_NSS1_MCS0 <= rx_req->mdata.rx_rate) && + (rx_req->mdata.rx_rate <= RTW_DATA_RATE_VHT_NSS4_MCS9)) { + /* User 0 */ + /* MCS */ + hdr_buf[rt_len] = cpu_to_le16 (((rx_req->mdata.rx_rate - RTW_DATA_RATE_VHT_NSS1_MCS0) % 10) << 4); + /* NSS */ + hdr_buf[rt_len] |= cpu_to_le16((((rx_req->mdata.rx_rate - RTW_DATA_RATE_VHT_NSS1_MCS0) / 10) + 1)); + } + rt_len += 4; + + /* u8 coding, phystat? */ + hdr_buf[rt_len] = 0; + rt_len += 1; + + /* u8 group_id */ + hdr_buf[rt_len] = moif->u.snif_info.vht_group_id; + rt_len += 1; + + /* u16 partial_aid */ + tmp_16bit = cpu_to_le16(moif->u.snif_info.vht_nsts_aid); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; + } + + /* HE, Required Alignment: 2 bytes */ + if (rx_req->mdata.rx_rate >= RTW_DATA_RATE_HE_NSS1_MCS0 && rx_req->mdata.rx_rate <= RTW_DATA_RATE_HE_NSS4_MCS11) { + + struct ieee80211_radiotap_he he_hdr; + u8 ltf, he_gi, ss; + + _rtw_memset(&he_hdr, 0, sizeof(struct ieee80211_radiotap_he)); + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_HE); + + rt_len += (rt_len % 2); /* Alignment */ + /* Structure + u16 data1, data2, data3, data4, data5, data6 */ + + /* HE PPDU Format: 0=HE_SU, 1=HE_EXT_SU, 2=HE_MU, 3=HE_TRIG */ + he_hdr.data1 |= 0x0000; + he_hdr.data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN); + he_hdr.data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); + + he_hdr.data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN); + he_hdr.data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN); + + he_hdr.data3 |= __le16_encode_bits((rx_req->mdata.rx_rate & 0xf), IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS); + + he_hdr.data5 |= cpu_to_le16((rx_req->mdata.bw)); + + switch (rx_req->mdata.rx_gi_ltf) { + case 0x0: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_3_2; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; + break; + case 0x1: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_0_8; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; + break; + case 0x2: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_1_6; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; + break; + case 0x3: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_0_8; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; + break; + case 0x4: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_1_6; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; + break; + case 0x5: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_0_8; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; + break; + default: + he_gi = IEEE80211_RADIOTAP_HE_DATA5_GI_0_8; + ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; + break; + } + + he_hdr.data5 |= __le16_encode_bits(he_gi, IEEE80211_RADIOTAP_HE_DATA5_GI); + he_hdr.data5 |= __le16_encode_bits(ltf, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); + + ss = cpu_to_le16(((0x70 & rx_req->mdata.rx_rate) >> 4) + 1); + he_hdr.data6 |= __le16_encode_bits(ss, IEEE80211_RADIOTAP_HE_DATA6_NSTS); + + _rtw_memcpy(&hdr_buf[rt_len], &he_hdr, sizeof(struct ieee80211_radiotap_he)); + + rt_len += sizeof(struct ieee80211_radiotap_he); + } + + /* frame timestamp, Required Alignment: 8 bytes */ + if (0) { //(a->free_cnt) { + rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_TIMESTAMP); + if (!IS_ALIGNED(rt_len, 8)) + rt_len = ((rt_len + 7) & 0xFFF8); /* Alignment */ + + /* u64 timestamp */ + tmp_64bit = cpu_to_le64(rx_req->mdata.freerun_cnt); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_64bit, 8); + rt_len += 8; + + /* u16 accuracy */ + tmp_16bit = cpu_to_le16(22); + _rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2); + rt_len += 2; + + /* u8 unit/position */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + rt_len += 1; + + /* u8 flags */ + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT; + hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY; + rt_len += 1; + } + + /* each antenna information */ +#if 0 + if (rx_cnt > 1) { + for (i = 0; i <= rx_cnt; i++) { + /* dBm Antenna Signal */ + hdr_buf[rt_len] = a->phy_info.rx_mimo_signal_strength[i]; + rt_len += 1; + + /* Signal Quality */ + if (!IS_ALIGNED(rt_len, 2)) + rt_len++; + hdr_buf[rt_len] = cpu_to_le16(a->phy_info.rx_mimo_signal_quality[i]); + rt_len += 2; + + /* Antenna */ + hdr_buf[rt_len] = i; /* pHalData->rf_type; */ + rt_len += 1; + } + } +#endif + + /* push to skb */ + pskb = (struct sk_buff *)buf; + if (skb_headroom(pskb) < rt_len) { + RTW_INFO("%s:%d %s headroom is too small.\n", __FILE__, __LINE__, __func__); + ret = _FAIL; + return ret; + } + + ptr = skb_push(pskb, rt_len); + if (ptr) { + rtap_hdr->it_len = cpu_to_le16(rt_len); + rtap_hdr->it_present = cpu_to_le32(rtap_hdr->it_present); + memcpy(ptr, rtap_hdr, rt_len); + } else + ret = _FAIL; + + return ret; + +} + +void rx_query_moinfo(struct rx_pkt_attrib *a, u8 *desc) +{ + switch (a->drvinfo_sz) { + case 40: + _rtw_memcpy(a->moif, &desc[32], 8); + break; + case 48: + _rtw_memcpy(a->moif, &desc[32], 12); + break; + case 32: + /* passthrough */ + default: + break; + } +} + +#endif /* CONFIG_WIFI_MONITOR */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.h b/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.h new file mode 100755 index 00000000..554d73b2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/monitor/rtw_radiotap.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_RADIOTAP_H_ +#define __RTW_RADIOTAP_H_ + +struct mon_reg_backup { + /* flags */ + u8 known_rcr:1; + u8 known_drvinfo:1; + u8 known_rxfilter:1; + u8 known_misc0:1; + /* data */ + u8 drvinfo; + u16 rxfilter0; + u16 rxfilter1; + u16 rxfilter2; + u32 rcr; + u32 misc0; +}; + +struct moinfo { + union { + struct { + u32 sgi:1; + u32 ldpc:1; + u32 stbc:2; + u32 not_sounding:1; + u32 ofdm_bw:2; + u32 vht_group_id:2; + u32 vht_nsts_aid:12; + u32 vht_txop_not_allow:1; + u32 vht_nsym_dis:1; + u32 vht_ldpc_extra:1; + u32 vht_su_mcs:12; + u32 vht_beamformed:1; + }snif_info; + + struct { + u32 A; + u32 B; + u32 C; + }plcp_info; + }u; +}; + +sint rtw_fill_radiotap_hdr(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + struct rx_pkt_attrib *a, struct rtw_recv_pkt *rx_req, u8 *buf); + +void rx_query_moinfo(struct rx_pkt_attrib *a, u8 *desc); + +#endif /* __RTW_RADIOTAP_H_ */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_phl_wrapper.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_phl_wrapper.c new file mode 100644 index 00000000..c2056c59 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_phl_wrapper.c @@ -0,0 +1,201 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_PHL_C_ + +#include + +static enum rtw_regd phl_regulation_to_regd(enum REGULATION reg) +{ + switch (reg) { + case REGULATION_WW: + return RTW_REGD_WW; + case REGULATION_ETSI: + return RTW_REGD_ETSI; + case REGULATION_FCC: + return RTW_REGD_FCC; + case REGULATION_MKK: + return RTW_REGD_MKK; + case REGULATION_KCC: + return RTW_REGD_KCC; + case REGULATION_NCC: + return RTW_REGD_NCC; + case REGULATION_ACMA: + return RTW_REGD_ACMA; + case REGULATION_NA: + return RTW_REGD_NA; + case REGULATION_IC: + return RTW_REGD_IC; + case REGULATION_CHILE: + return RTW_REGD_CHILE; + case REGULATION_MEX: + return RTW_REGD_MEX; + case REGULATION_MAX: + default: + RTW_WARN("unknown reg:%d\n", reg); + rtw_warn_on(1); + return RTW_REGD_NA; + } +}; + +static u8 phl_ch_property_to_flag(enum ch_property prop) +{ + return ((prop & CH_PASSIVE) ? RTW_CHF_NO_IR : 0) + | ((prop & CH_DFS) ? RTW_CHF_DFS : 0) + ; +} + +static u8 phl_regdb_get_default_regd_2g(u8 id) +{ + return phl_regulation_to_regd(rtw_phl_get_domain_regulation_2g(id)); +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 phl_regdb_get_default_regd_5g(u8 id) +{ + return phl_regulation_to_regd(rtw_phl_get_domain_regulation_5g(id)); +} +#endif + +static bool phl_regdb_is_domain_code_valid(u8 id) +{ + return rtw_phl_valid_regulation_domain(id); +} + +static bool phl_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + enum ch_property prop; + + if (rtw_phl_query_domain_channel(id, ch > 14 ? BAND_ON_5G : BAND_ON_24G, ch, &prop)) { + if (flags) + *flags = phl_ch_property_to_flag(prop); + return true; + } + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static u8 phl_regdb_get_default_regd_6g(u8 id) +{ + return phl_regulation_to_regd(rtw_phl_get_domain_regulation_6g(id)); +} + +static bool phl_regdb_is_domain_code_6g_valid(u8 id) +{ + return rtw_phl_valid_regulation_domain_6ghz(id); +} + +static bool phl_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + enum ch_property prop; + + if (rtw_phl_query_domain_6g_channel(id, BAND_ON_6G, ch, &prop)) { + if (flags) + *flags = phl_ch_property_to_flag(prop); + return true; + } + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static REGULATION_TXPWR_LMT phl_tpo_to_txpwr_lmt(enum TP_OVERWRITE tpo) +{ + switch (tpo) { + case TPO_CHILE: + return TXPWR_LMT_CHILE; + case TPO_UK: + return TXPWR_LMT_UK; + case TPO_QATAR: + return TXPWR_LMT_QATAR; + case TPO_UKRAINE: + return TXPWR_LMT_UKRAINE; + case TPO_CN: + return TXPWR_LMT_CN; + case TPO_THAILAND: + return TXPWR_LMT_THAILAND; + case TPO_NA: + return TXPWR_LMT_DEF; + default: + RTW_WARN("unknown tpo:%d\n", tpo); + rtw_warn_on(1); + return TXPWR_LMT_DEF; + } +} + +static bool phl_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + struct rtw_regulation_country_chplan plan; + + _rtw_memset(&plan, 0, sizeof(plan)); + + if (!rtw_phl_query_country_chplan((char *)alpha2, &plan)) /* TODO: PHL use type of 'const char *' for 'country' */ + return false; + + if (ent) { + _rtw_memcpy(ent->alpha2, alpha2, 2); + ent->domain_code = plan.domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + ent->domain_code_6g = plan.domain_code_6g; + #endif + + #if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE + ent->edcca_2g_override = RTW_EDCCA_DEF; + #if CONFIG_IEEE80211_BAND_5GHZ + ent->edcca_5g_override = RTW_EDCCA_DEF; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + ent->edcca_6g_override = RTW_EDCCA_DEF; + #endif + #endif + + ent->txpwr_lmt_override = phl_tpo_to_txpwr_lmt(plan.tpo); + #ifdef CONFIG_CHPLAN_PROTO_EN + ent->proto_en = 0 + /* TODO: SUPPORT_11BE, wait PHL ready */ + | ((plan.support_mode & SUPPORT_11AC) ? CHPLAN_PROTO_EN_AC : 0) + | ((plan.support_mode & SUPPORT_11AX) ? CHPLAN_PROTO_EN_AX : 0) + | ((plan.support_mode & SUPPORT_11A) ? CHPLAN_PROTO_EN_A : 0) + ; + #endif + + /* TODO: cate_6g_map, wait PHL ready */ + } + + return true; +} + +static void phl_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%d-%d", rtw_phl_get_regu_chplan_ver(), rtw_phl_get_regu_country_ver()); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = phl_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = phl_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = phl_regdb_is_domain_code_valid, + .domain_get_ch = phl_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = phl_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = phl_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = phl_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = phl_regdb_get_chplan_from_alpha2, + + .get_ver_str = phl_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_58-31.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_58-31.c new file mode 100644 index 00000000..1165cf75 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_58-31.c @@ -0,0 +1,908 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "58" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "31" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 36), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x00, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x00, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x00, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x00, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x00, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x00, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x00, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x00, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x00, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x00, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x00, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x00, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x00, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x00, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x00, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x5E, 0x00, DEF , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x00, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x00, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x00, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x32, 0x00, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x00, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x00, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x00, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x06, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x00, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x00, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x00, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x00, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x00, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x00, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x00, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x00, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x00, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x00, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x00, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x00, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x00, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x00, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x00, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x00, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x00, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x00, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x00, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x00, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x76, 0x7F, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3C, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_59-32.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_59-32.c new file mode 100644 index 00000000..33f7dbb9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_59-32.c @@ -0,0 +1,917 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "59" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "32" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 36), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x00, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x00, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x05, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x00, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x00, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x00, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x00, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x00, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x00, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x00, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x00, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x00, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x76, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-32.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-32.c new file mode 100644 index 00000000..dc9d40d0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-32.c @@ -0,0 +1,920 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "60" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "32" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 36), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x00, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x00, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x05, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x00, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x00, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x00, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x00, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x00, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x00, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x00, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x00, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x00, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x76, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-34.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-34.c new file mode 100644 index 00000000..70bb2658 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_60-34.c @@ -0,0 +1,920 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "60" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "34" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 36), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x05, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x05, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_61-34.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_61-34.c new file mode 100644 index 00000000..18e21fac --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_61-34.c @@ -0,0 +1,923 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "61" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "34" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x05, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x05, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_62-35.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_62-35.c new file mode 100644 index 00000000..02bf9ce4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_62-35.c @@ -0,0 +1,924 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "62" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "35" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x05, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x05, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-36.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-36.c new file mode 100644 index 00000000..69eb60ff --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-36.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "63" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "36" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x3A, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x3A, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x3A, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x3A, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x3A, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x3A, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x3A, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x3A, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x00, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x3A, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x3A, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x3A, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x00, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x3A, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x3A, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x3A, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x3A, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x3A, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-37.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-37.c new file mode 100644 index 00000000..3c639385 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-37.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "63" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "37" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-38.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-38.c new file mode 100644 index 00000000..412dfbb8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-38.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "63" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "38" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x05, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x05, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-39.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-39.c new file mode 100644 index 00000000..6a53cea9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-39.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "63" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "39" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x05, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x05, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x05, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-40.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-40.c new file mode 100644 index 00000000..2692c47f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_63-40.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "63" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "40" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x05, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x05, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x05, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-40.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-40.c new file mode 100644 index 00000000..ec505725 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-40.c @@ -0,0 +1,931 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "64" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "40" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x05, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x05, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x05, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-41.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-41.c new file mode 100644 index 00000000..e587eabe --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-41.c @@ -0,0 +1,931 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "64" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "41" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x05, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x3A, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-42.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-42.c new file mode 100644 index 00000000..0ae7da23 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_64-42.c @@ -0,0 +1,931 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "64" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "42" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x05, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE, 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_65-44.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_65-44.c new file mode 100644 index 00000000..dc297793 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_65-44.c @@ -0,0 +1,934 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "65" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "44" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x61, 0x05, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_66-45.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_66-45.c new file mode 100644 index 00000000..a19d533a --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_66-45.c @@ -0,0 +1,937 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_DOMAIN_MAP_VER "66" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "45" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x05, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x05, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x05, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x05, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x05, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x05, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x05, DEF , 1, 1, 1), /* Sint Maarten */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x05, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s-%s%s", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_67-46.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_67-46.c new file mode 100644 index 00000000..ea415f9c --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_67-46.c @@ -0,0 +1,947 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "" +#define RTW_DOMAIN_MAP_VER "67" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "46" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 0, 1, 1, 1, _I_), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1, 1, _I_), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 0, 1, 1, 1, ___), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1, 1, _I_), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 0, 1, 1, ___), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1, 1, SI_), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1, 1, _IV), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1, 1, ___), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 0, 1, 1, 1, _I_), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x06, DEF , 0, 1, 1, 1, _IV), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1, 1, _IV), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 1, 0, 1, 1, _I_), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1, 1, ___), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 0, 1, 1, 1, ___), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0, 0, ___), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1, 1, _IV), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 0, 1, 1, 1, _IV), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1, 1, _I_), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1, 1, _I_), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1, 1, _I_), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1, 1, ___), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1, 1, _IV), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 0, 1, 1, 1, ___), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1, 1, _I_), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Sint Maarten */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1, 1, _IV), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 0, 1, 1, 1, ___), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0, 0, ___), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1, 1, _IV), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 0, 1, 1, 1, ___), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_68-47.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_68-47.c new file mode 100644 index 00000000..a8c2c006 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_68-47.c @@ -0,0 +1,949 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "" +#define RTW_DOMAIN_MAP_VER "68" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "47" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x14] = CHPLAN_ENT(ETSI , 02, ETSI , 32), + [0x15] = CHPLAN_ENT(ETSI , 02, ETSI , 09), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 0, 1, 1, 1, _I_), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1, 1, _I_), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 0, 1, 1, 1, ___), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1, 1, _I_), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 0, 1, 1, ___), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1, 1, SI_), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1, 1, _IV), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1, 1, ___), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x06, DEF , 0, 1, 1, 1, _I_), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x06, DEF , 0, 1, 1, 1, _IV), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1, 1, _IV), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 1, 0, 1, 1, _I_), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1, 1, ___), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x05, 0x00, DEF , 0, 1, 1, 1, ___), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x3A, 0x00, DEF , 0, 0, 0, 0, ___), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1, 1, _IV), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x00, DEF , 1, 1, 1, 1, ___), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 0, 1, 1, 1, _IV), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1, 1, _IV), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1, 1, _I_), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1, 1, _I_), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x06, DEF , 0, 1, 1, 1, _IV), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1, 1, _IV), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x09, 0x00, DEF , 0, 1, 1, 1, ___), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1, 1, _I_), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* Sint Maarten */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x06, DEF , 0, 1, 1, 1, _IV), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1, 1, _IV), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 0, 1, 1, 1, ___), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0, 0, ___), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1, 1, _IV), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 0, 1, 1, 1, ___), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 0x05, DEF , 0, 1, 1, 1, _I_), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8851BE_M.2_2230-67-3.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8851BE_M.2_2230-67-3.c new file mode 100644 index 00000000..d9f82618 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8851BE_M.2_2230-67-3.c @@ -0,0 +1,947 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "8851BE_M.2_2230" +#define RTW_DOMAIN_MAP_VER "67" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "3" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x00, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x0A, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x00, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x0A, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x00, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x00, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x00, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x0A, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x0A, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x00, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x00, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x00, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x00, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x00, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x00, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x00, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x0A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x00, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x00, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x00, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x00, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x00, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x00, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x00, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x00, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x00, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x00, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x00, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x0A, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x0A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x00, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x00, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x0A, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x00, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x0A, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x00, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x00, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x00, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x00, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x0A, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x00, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x00, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x00, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x00, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x00, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x00, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x00, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x00, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x00, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x00, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x0A, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x0A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x00, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x0A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x0A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x00, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x0A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x00, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x00, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x0A, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x0A, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x3A, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x0A, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x0A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852BE_M.2_2230-67-48.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852BE_M.2_2230-67-48.c new file mode 100644 index 00000000..14066898 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852BE_M.2_2230-67-48.c @@ -0,0 +1,947 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "8852BE_M.2_2230" +#define RTW_DOMAIN_MAP_VER "67" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "48" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 1, 1, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x00, DEF , 1, 1, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x0A, 0x00, DEF , 1, 1, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x00, DEF , 1, 1, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 1, 1, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 1, 1, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x00, DEF , 1, 1, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x00, DEF , 1, 1, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 1, 1, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 1, 1, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x00, DEF , 1, 1, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x0A, 0x00, DEF , 1, 1, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x00, DEF , 1, 1, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x00, DEF , 1, 1, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 1, 1, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 1, 1, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x00, DEF , 1, 1, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 1, 1, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x00, DEF , 1, 1, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x00, DEF , 1, 1, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x00, DEF , 1, 1, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x00, DEF , 1, 1, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x00, DEF , 1, 1, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 1, 1, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x00, DEF , 1, 1, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 1, 1, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 1, 1, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x00, DEF , 1, 1, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x00, DEF , 1, 1, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x0A, 0x00, DEF , 1, 1, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 1, 1, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x00, DEF , 1, 1, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x08, 0x00, DEF , 0, 1, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 1, 1, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x00, DEF , 1, 1, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 1, 1, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 1, 1, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 1, 1, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x00, DEF , 1, 1, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 1, 1, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 1, 1, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x00, CHILE , 1, 1, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 1, 1, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x00, DEF , 1, 1, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x00, DEF , 1, 1, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 1, 1, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 1, 1, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x00, DEF , 1, 1, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x00, DEF , 1, 1, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x00, DEF , 1, 1, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 1, 1, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 1, 1, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 1, 1, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 1, 1, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x00, DEF , 1, 1, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 1, 1, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 1, 1, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x0A, 0x00, DEF , 1, 1, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x00, DEF , 1, 1, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 1, 1, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x00, DEF , 1, 1, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 1, 1, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 1, 1, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x00, DEF , 1, 1, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 1, 1, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x00, DEF , 1, 1, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 1, 1, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x00, UK , 1, 1, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x00, DEF , 1, 1, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 1, 1, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 1, 1, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x00, DEF , 1, 1, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 1, 1, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 1, 1, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x00, DEF , 1, 1, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 1, 1, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x00, DEF , 1, 1, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x00, DEF , 1, 1, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 1, 1, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x00, DEF , 1, 1, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x00, DEF , 1, 1, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 1, 1, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 1, 1, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x00, DEF , 1, 1, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 1, 1, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x00, DEF , 1, 1, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x00, DEF , 1, 1, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x00, DEF , 0, 1, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x00, DEF , 1, 1, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 1, 1, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x00, DEF , 1, 1, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x00, DEF , 1, 1, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 1, 1, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 1, 1, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 1, 1, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x0A, 0x00, DEF , 1, 1, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x0A, 0x00, DEF , 0, 0, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x00, DEF , 1, 1, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x00, DEF , 1, 1, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 1, 1, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x00, DEF , 1, 1, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x00, DEF , 1, 1, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x00, DEF , 1, 1, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x00, DEF , 1, 1, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x00, DEF , 1, 1, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 1, 1, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x0A, 0x00, DEF , 1, 1, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x00, DEF , 1, 1, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x00, DEF , 1, 1, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x00, DEF , 1, 1, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x0A, 0x00, DEF , 1, 1, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x00, DEF , 1, 1, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x00, DEF , 1, 1, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x00, DEF , 1, 1, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 1, 1, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 1, 1, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 1, 1, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x00, DEF , 1, 1, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x00, DEF , 1, 1, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x00, DEF , 1, 1, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x0A, 0x00, DEF , 1, 1, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x00, DEF , 1, 1, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x00, DEF , 1, 1, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x00, DEF , 1, 1, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 1, 1, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x00, DEF , 1, 1, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x00, DEF , 1, 1, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x00, DEF , 1, 1, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 1, 1, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 1, 1, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 1, 1, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x00, DEF , 1, 1, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 1, 1, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x00, DEF , 1, 1, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 1, 1, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 1, 1, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x00, DEF , 1, 1, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x00, DEF , 1, 1, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 1, 1, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 1, 1, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x00, DEF , 1, 1, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x00, DEF , 1, 1, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 1, 1, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 1, 1, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 1, 1, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 1, 1, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 1, 1, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 1, 1, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x00, DEF , 1, 1, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x00, DEF , 1, 1, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 1, 1, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 1, 1, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 1, 1, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x00, DEF , 1, 1, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 1, 1, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 1, 1, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x00, DEF , 1, 1, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x00, DEF , 1, 1, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 1, 1, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 1, 1, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x00, DEF , 1, 1, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 1, 1, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 1, 1, 1), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x00, DEF , 1, 1, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x00, DEF , 1, 1, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 1, 1, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x00, QATAR , 1, 1, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 1, 1, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x00, DEF , 1, 1, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x00, DEF , 1, 1, 1), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x0A, 0x00, DEF , 1, 1, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 1, 1, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x00, DEF , 1, 1, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x0A, 0x00, DEF , 1, 1, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 1, 1, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x00, DEF , 1, 1, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x00, DEF , 1, 1, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 1, 1, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x00, DEF , 1, 1, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x00, DEF , 1, 1, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 1, 1, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 1, 1, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x0A, 0x00, DEF , 1, 1, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x00, DEF , 1, 1, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 1, 1, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x00, DEF , 1, 1, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x00, DEF , 1, 1, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x0A, 0x00, DEF , 1, 1, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x00, DEF , 1, 1, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 1, 1, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x00, DEF , 1, 1, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x00, DEF , 1, 1, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 1, 1, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 1, 1, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 1, 1, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x0A, 0x00, DEF , 1, 1, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x00, DEF , 1, 1, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 1, 1, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x00, DEF , 1, 1, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 1, 1, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 1, 1, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 1, 1, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x00, DEF , 1, 1, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 1, 1, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x00, DEF , 1, 1, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 1, 1, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x0A, 0x00, DEF , 1, 1, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 1, 1, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x0A, 0x00, DEF , 1, 1, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x00, DEF , 1, 1, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 1, 1, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 1, 1, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 1, 1, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x0A, 0x00, DEF , 1, 1, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x00, DEF , 1, 1, 1), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x0A, 0x00, DEF , 1, 1, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 1, 1, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x00, DEF , 1, 1, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 1, 1, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-51.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-51.c new file mode 100644 index 00000000..e73c0ed1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-51.c @@ -0,0 +1,947 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "8852CE_M.2_2230" +#define RTW_DOMAIN_MAP_VER "67" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "51" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 0, 1, 1, 1, _I_), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1, 1, _I_), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1, 1, _I_), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x0A, 0x00, DEF , 0, 0, 1, 1, ___), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1, 1, SI_), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1, 1, ___), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1, 1, _I_), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 0, 1, 1, 1, ___), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1, 1, ___), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1, 1, _IV), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 1, 0, 1, 1, _I_), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1, 1, ___), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x0A, 0x00, DEF , 0, 0, 0, 0, ___), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1, 1, _IV), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 0, 1, 1, 1, _IV), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1, 1, _I_), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1, 1, _I_), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1, 1, _I_), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1, 1, ___), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1, 1, _IV), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1, 1, _I_), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1, 1, _IV), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 0, 1, 1, 1, ___), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0, 0, ___), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1, 1, _IV), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 0, 1, 1, 1, ___), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1, 1, ___), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-52.c b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-52.c new file mode 100644 index 00000000..741c83e8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/regdb/rtw_regdb_rtk_8852CE_M.2_2230-67-52.c @@ -0,0 +1,947 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_REGDB_RTK_C_ + +#include + +#define RTW_MODULE_NAME "8852CE_M.2_2230" +#define RTW_DOMAIN_MAP_VER "67" +#define RTW_DOMAIN_MAP_M_VER "" +#define RTW_COUNTRY_MAP_VER "52" +#define RTW_COUNTRY_MAP_M_VER "" + +#define rtw_is_5g_band1(ch) ((ch) >= 36 && (ch) <= 48) +#define rtw_is_5g_band2(ch) ((ch) >= 52 && (ch) <= 64) +#define rtw_is_5g_band3(ch) ((ch) >= 100 && (ch) <= 144) +#define rtw_is_5g_band4(ch) ((ch) >= 149 && (ch) <= 177) + +#define rtw_is_6g_band1(ch) ((ch) >= 1 && (ch) <= 93) +#define rtw_is_6g_band2(ch) ((ch) >= 97 && (ch) <= 117) +#define rtw_is_6g_band3(ch) ((ch) >= 121 && (ch) <= 189) +#define rtw_is_6g_band4(ch) ((ch) >= 193 && (ch) <= 237) + +struct ch_list_t { + u8 *len_ch_attr; +}; + +#define CLA_2G_12_14_PASSIVE BIT0 + +#define CLA_5G_B1_PASSIVE BIT0 +#define CLA_5G_B2_PASSIVE BIT1 +#define CLA_5G_B3_PASSIVE BIT2 +#define CLA_5G_B4_PASSIVE BIT3 +#define CLA_5G_B2_DFS BIT4 +#define CLA_5G_B3_DFS BIT5 +#define CLA_5G_B4_DFS BIT6 + +#define CLA_6G_B1_PASSIVE BIT0 +#define CLA_6G_B2_PASSIVE BIT1 +#define CLA_6G_B3_PASSIVE BIT2 +#define CLA_6G_B4_PASSIVE BIT3 + +#define CH_LIST_ENT(_len, arg...) \ + {.len_ch_attr = (u8[_len + 2]) {_len, ##arg}, } + +#define CH_LIST_LEN(_ch_list) (_ch_list.len_ch_attr[0]) +#define CH_LIST_CH(_ch_list, _i) (_ch_list.len_ch_attr[_i + 1]) +#define CH_LIST_ATTRIB(_ch_list) (_ch_list.len_ch_attr[CH_LIST_LEN(_ch_list) + 1]) + +enum rtw_chd_2g { + RTW_CHD_2G_INVALID = 0, + + RTW_CHD_2G_00, + RTW_CHD_2G_01, + RTW_CHD_2G_02, + RTW_CHD_2G_03, + RTW_CHD_2G_04, + RTW_CHD_2G_05, + RTW_CHD_2G_06, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_INVALID = 0, + + RTW_CHD_5G_00, + RTW_CHD_5G_01, + RTW_CHD_5G_02, + RTW_CHD_5G_03, + RTW_CHD_5G_04, + RTW_CHD_5G_05, + RTW_CHD_5G_06, + RTW_CHD_5G_07, + RTW_CHD_5G_08, + RTW_CHD_5G_09, + RTW_CHD_5G_10, + RTW_CHD_5G_11, + RTW_CHD_5G_12, + RTW_CHD_5G_13, + RTW_CHD_5G_14, + RTW_CHD_5G_15, + RTW_CHD_5G_16, + RTW_CHD_5G_17, + RTW_CHD_5G_18, + RTW_CHD_5G_19, + RTW_CHD_5G_20, + RTW_CHD_5G_21, + RTW_CHD_5G_22, + RTW_CHD_5G_23, + RTW_CHD_5G_24, + RTW_CHD_5G_25, + RTW_CHD_5G_26, + RTW_CHD_5G_27, + RTW_CHD_5G_28, + RTW_CHD_5G_29, + RTW_CHD_5G_30, + RTW_CHD_5G_31, + RTW_CHD_5G_32, + RTW_CHD_5G_33, + RTW_CHD_5G_34, + RTW_CHD_5G_35, + RTW_CHD_5G_36, + RTW_CHD_5G_37, + RTW_CHD_5G_38, + RTW_CHD_5G_39, + RTW_CHD_5G_40, + RTW_CHD_5G_41, + RTW_CHD_5G_42, + RTW_CHD_5G_43, + RTW_CHD_5G_44, + RTW_CHD_5G_45, + RTW_CHD_5G_46, + RTW_CHD_5G_47, + RTW_CHD_5G_48, + RTW_CHD_5G_49, + RTW_CHD_5G_50, + RTW_CHD_5G_51, + RTW_CHD_5G_52, + RTW_CHD_5G_53, + RTW_CHD_5G_54, + RTW_CHD_5G_55, + RTW_CHD_5G_56, + RTW_CHD_5G_57, + RTW_CHD_5G_58, + RTW_CHD_5G_59, + RTW_CHD_5G_60, + RTW_CHD_5G_61, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* RTW_CHD_2G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_2G_01 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, CLA_2G_12_14_PASSIVE), + /* RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* RTW_CHD_2G_06 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, CLA_2G_12_14_PASSIVE), +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +static const struct ch_list_t rtw_channel_def_5g[] = { + /* RTW_CHD_5G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_5G_01 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_02 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_03 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_04 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_05 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_07 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_12 */ CH_LIST_ENT(16, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* RTW_CHD_5G_17 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_18 */ CH_LIST_ENT(17, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_19 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_20 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_21 */ CH_LIST_ENT(11, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_22 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_23 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_24 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_25 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_26 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_27 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_28 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_29 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_30 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_31 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_33 */ CH_LIST_ENT(22, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_34 */ CH_LIST_ENT(13, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B3_DFS), + /* RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* RTW_CHD_5G_36 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_38 */ CH_LIST_ENT(16, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_39 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_DFS), + /* RTW_CHD_5G_40 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_41 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_42 */ CH_LIST_ENT(24, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_43 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_44 */ CH_LIST_ENT(21, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_45 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* RTW_CHD_5G_47 */ CH_LIST_ENT(19, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE), + /* RTW_CHD_5G_48 */ CH_LIST_ENT(20, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_49 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_50 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_51 */ CH_LIST_ENT(13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_52 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_53 */ CH_LIST_ENT(17, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 149, 153, 157, 161, 165, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_54 */ CH_LIST_ENT(8, 36, 40, 44, 48, 149, 153, 157, 161, 0), + /* RTW_CHD_5G_55 */ CH_LIST_ENT(28, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B2_DFS | CLA_5G_B3_PASSIVE | CLA_5G_B3_DFS | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_56 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 144, 149, 153, 157, 161, 165, 169, 173, 177, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_57 */ CH_LIST_ENT(25, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_58 */ CH_LIST_ENT(16, 36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE | CLA_5G_B3_PASSIVE | CLA_5G_B4_PASSIVE), + /* RTW_CHD_5G_59 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* RTW_CHD_5G_60 */ CH_LIST_ENT(26, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), + /* RTW_CHD_5G_61 */ CH_LIST_ENT(23, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 149, 153, 157, 161, 165, 169, 173, CLA_5G_B2_DFS | CLA_5G_B3_DFS), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of enum rtw_regd */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of enum rtw_regd */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g, .regd_5g = RTW_REGD_##_regd_5g, .chd_5g = RTW_CHD_5G_##_chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = RTW_REGD_##_regd_2g, .chd_2g = RTW_CHD_2G_##_chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(NA, INVALID, NA, INVALID) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + [0x00] = CHPLAN_ENT(ETSI , 02, ETSI , 49), + [0x01] = CHPLAN_ENT(ETSI , 02, ETSI , 50), + [0x02] = CHPLAN_ENT(ETSI , 03, ETSI , 07), + [0x03] = CHPLAN_ENT(ACMA , 02, ACMA , 33), + [0x04] = CHPLAN_ENT(ETSI , 02, ETSI , 51), + [0x05] = CHPLAN_ENT(ETSI , 02, ETSI , 06), + [0x06] = CHPLAN_ENT(ETSI , 02, ETSI , 07), + [0x07] = CHPLAN_ENT(ETSI , 02, ETSI , 23), + [0x08] = CHPLAN_ENT(ETSI , 02, ETSI , 21), + [0x09] = CHPLAN_ENT(ETSI , 02, ETSI , 17), + [0x0A] = CHPLAN_ENT(NA , 00, NA , 00), + [0x0B] = CHPLAN_ENT(ETSI , 02, ETSI , 22), + [0x0C] = CHPLAN_ENT(FCC , 03, FCC , 54), + [0x0D] = CHPLAN_ENT(MKK , 04, MKK , 14), + [0x0E] = CHPLAN_ENT(ETSI , 01, ETSI , 57), + [0x0F] = CHPLAN_ENT(ETSI , 01, ETSI , 58), + [0x10] = CHPLAN_ENT(IC , 02, IC , 56), + [0x11] = CHPLAN_ENT(FCC , 02, FCC , 59), + [0x12] = CHPLAN_ENT(ETSI , 02, ETSI , 60), + [0x13] = CHPLAN_ENT(ETSI , 02, ETSI , 61), + [0x1B] = CHPLAN_ENT(FCC , 02, FCC , 52), + [0x1C] = CHPLAN_ENT(KCC , 02, KCC , 53), + [0x20] = CHPLAN_ENT(WW , 01, NA , 00), + [0x21] = CHPLAN_ENT(ETSI , 02, NA , 00), + [0x22] = CHPLAN_ENT(FCC , 03, NA , 00), + [0x23] = CHPLAN_ENT(MKK , 04, NA , 00), + [0x24] = CHPLAN_ENT(ETSI , 05, NA , 00), + [0x25] = CHPLAN_ENT(FCC , 03, FCC , 03), + [0x26] = CHPLAN_ENT(ETSI , 01, ETSI , 02), + [0x27] = CHPLAN_ENT(MKK , 04, MKK , 02), + [0x28] = CHPLAN_ENT(KCC , 01, KCC , 05), + [0x29] = CHPLAN_ENT(FCC , 01, FCC , 06), + [0x2A] = CHPLAN_ENT(FCC , 02, NA , 00), + [0x2B] = CHPLAN_ENT(IC , 02, IC , 33), + [0x2C] = CHPLAN_ENT(MKK , 02, NA , 00), + [0x2D] = CHPLAN_ENT(CHILE, 01, CHILE, 22), + [0x2E] = CHPLAN_ENT(WW , 03, WW , 37), + [0x2F] = CHPLAN_ENT(CHILE, 01, CHILE, 38), + [0x30] = CHPLAN_ENT(FCC , 01, FCC , 07), + [0x31] = CHPLAN_ENT(FCC , 01, FCC , 08), + [0x32] = CHPLAN_ENT(FCC , 01, FCC , 09), + [0x33] = CHPLAN_ENT(FCC , 01, FCC , 10), + [0x34] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x35] = CHPLAN_ENT(ETSI , 01, ETSI , 03), + [0x36] = CHPLAN_ENT(ETSI , 01, ETSI , 04), + [0x37] = CHPLAN_ENT(MKK , 04, MKK , 10), + [0x38] = CHPLAN_ENT(MKK , 04, MKK , 11), + [0x39] = CHPLAN_ENT(NCC , 03, NCC , 12), + [0x3A] = CHPLAN_ENT(ETSI , 02, ETSI , 02), + [0x3B] = CHPLAN_ENT(ACMA , 02, ACMA , 01), + [0x3C] = CHPLAN_ENT(ETSI , 02, ETSI , 10), + [0x3D] = CHPLAN_ENT(ETSI , 02, ETSI , 15), + [0x3E] = CHPLAN_ENT(KCC , 02, KCC , 03), + [0x3F] = CHPLAN_ENT(FCC , 03, FCC , 22), + [0x40] = CHPLAN_ENT(NCC , 03, NCC , 13), + [0x41] = CHPLAN_ENT(WW , 06, NA , 00), + [0x42] = CHPLAN_ENT(ETSI , 02, ETSI , 14), + [0x43] = CHPLAN_ENT(FCC , 03, FCC , 06), + [0x44] = CHPLAN_ENT(NCC , 03, NCC , 09), + [0x45] = CHPLAN_ENT(ACMA , 01, ACMA , 01), + [0x46] = CHPLAN_ENT(FCC , 03, FCC , 15), + [0x47] = CHPLAN_ENT(ETSI , 01, ETSI , 10), + [0x48] = CHPLAN_ENT(ETSI , 01, ETSI , 07), + [0x49] = CHPLAN_ENT(ETSI , 01, ETSI , 06), + [0x4A] = CHPLAN_ENT(IC , 03, IC , 33), + [0x4B] = CHPLAN_ENT(KCC , 02, KCC , 22), + [0x4C] = CHPLAN_ENT(FCC , 03, FCC , 28), + [0x4D] = CHPLAN_ENT(MEX , 02, MEX , 01), + [0x4E] = CHPLAN_ENT(ETSI , 02, ETSI , 42), + [0x4F] = CHPLAN_ENT(NA , 00, MKK , 43), + [0x50] = CHPLAN_ENT(ETSI , 01, ETSI , 16), + [0x51] = CHPLAN_ENT(ETSI , 01, ETSI , 09), + [0x52] = CHPLAN_ENT(ETSI , 01, ETSI , 17), + [0x53] = CHPLAN_ENT(NCC , 03, NCC , 18), + [0x54] = CHPLAN_ENT(ETSI , 01, ETSI , 15), + [0x55] = CHPLAN_ENT(FCC , 03, FCC , 01), + [0x56] = CHPLAN_ENT(ETSI , 01, ETSI , 19), + [0x57] = CHPLAN_ENT(FCC , 03, FCC , 20), + [0x58] = CHPLAN_ENT(MKK , 02, MKK , 14), + [0x59] = CHPLAN_ENT(ETSI , 01, ETSI , 21), + [0x5A] = CHPLAN_ENT(NA , 00, FCC , 44), + [0x5B] = CHPLAN_ENT(NA , 00, FCC , 45), + [0x5C] = CHPLAN_ENT(NA , 00, FCC , 43), + [0x5D] = CHPLAN_ENT(ETSI , 02, ETSI , 08), + [0x5E] = CHPLAN_ENT(ETSI , 02, ETSI , 03), + [0x5F] = CHPLAN_ENT(MKK , 02, MKK , 47), + [0x60] = CHPLAN_ENT(FCC , 03, FCC , 09), + [0x61] = CHPLAN_ENT(FCC , 02, FCC , 01), + [0x62] = CHPLAN_ENT(FCC , 02, FCC , 03), + [0x63] = CHPLAN_ENT(ETSI , 01, ETSI , 23), + [0x64] = CHPLAN_ENT(MKK , 02, MKK , 24), + [0x65] = CHPLAN_ENT(ETSI , 02, ETSI , 24), + [0x66] = CHPLAN_ENT(FCC , 03, FCC , 27), + [0x67] = CHPLAN_ENT(FCC , 03, FCC , 25), + [0x68] = CHPLAN_ENT(FCC , 02, FCC , 27), + [0x69] = CHPLAN_ENT(FCC , 02, FCC , 25), + [0x6A] = CHPLAN_ENT(ETSI , 02, ETSI , 25), + [0x6B] = CHPLAN_ENT(FCC , 01, FCC , 29), + [0x6C] = CHPLAN_ENT(FCC , 01, FCC , 26), + [0x6D] = CHPLAN_ENT(FCC , 02, FCC , 28), + [0x6E] = CHPLAN_ENT(FCC , 01, FCC , 25), + [0x6F] = CHPLAN_ENT(NA , 00, ETSI , 06), + [0x70] = CHPLAN_ENT(NA , 00, ETSI , 30), + [0x71] = CHPLAN_ENT(NA , 00, ETSI , 25), + [0x72] = CHPLAN_ENT(NA , 00, ETSI , 31), + [0x73] = CHPLAN_ENT(FCC , 01, FCC , 01), + [0x74] = CHPLAN_ENT(FCC , 02, FCC , 19), + [0x75] = CHPLAN_ENT(ETSI , 01, ETSI , 32), + [0x76] = CHPLAN_ENT(FCC , 02, FCC , 22), + [0x77] = CHPLAN_ENT(ETSI , 01, ETSI , 34), + [0x78] = CHPLAN_ENT(FCC , 03, FCC , 35), + [0x79] = CHPLAN_ENT(MKK , 02, MKK , 02), + [0x7A] = CHPLAN_ENT(ETSI , 02, ETSI , 28), + [0x7B] = CHPLAN_ENT(ETSI , 02, ETSI , 46), + [0x7C] = CHPLAN_ENT(ETSI , 02, ETSI , 47), + [0x7D] = CHPLAN_ENT(MKK , 04, MKK , 48), + [0x7E] = CHPLAN_ENT(MKK , 02, MKK , 48), + [0x7F] = CHPLAN_ENT(WW , 01, WW , 55), +}; + +static const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +static u8 rtk_regdb_get_default_regd_2g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_2g; + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +static u8 rtk_regdb_get_default_regd_5g(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) + return RTW_ChannelPlanMap[id].regd_5g; + return RTW_REGD_NA; +} +#endif + +static bool rtk_regdb_is_domain_code_valid(u8 id) +{ + if (id < RTW_ChannelPlanMap_size) { + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g != RTW_CHD_2G_INVALID + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g != RTW_CHD_5G_INVALID + #endif + ) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + + if (flags) + *flags = 0; + +#if CONFIG_IEEE80211_BAND_5GHZ + if (ch > 14) { + u8 chd_5g = RTW_ChannelPlanMap[id].chd_5g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_5g[chd_5g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_5g[chd_5g]); index++) { + if (CH_LIST_CH(rtw_channel_def_5g[chd_5g], index) == ch) { + if (flags) { + if ((rtw_is_5g_band1(ch) && (attrib & CLA_5G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + + if ((rtw_is_5g_band2(ch) && (attrib & CLA_5G_B2_DFS)) + || (rtw_is_5g_band3(ch) && (attrib & CLA_5G_B3_DFS)) + || (rtw_is_5g_band4(ch) && (attrib & CLA_5G_B4_DFS))) + *flags |= RTW_CHF_DFS; + } + return true; + } + } + } else +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + { + u8 chd_2g = RTW_ChannelPlanMap[id].chd_2g; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_2g[chd_2g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_2g[chd_2g]); index++) { + if (CH_LIST_CH(rtw_channel_def_2g[chd_2g], index) == ch) { + if (flags) { + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + } + + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +enum rtw_chd_6g { + RTW_CHD_6G_INVALID = 0, + + RTW_CHD_6G_00, + RTW_CHD_6G_01, + RTW_CHD_6G_02, + RTW_CHD_6G_03, + RTW_CHD_6G_04, + RTW_CHD_6G_05, /* 6G Worldwide */ + RTW_CHD_6G_06, + + RTW_CHD_6G_MAX, + RTW_CHD_6G_NULL = RTW_CHD_6G_00, +}; + +static const struct ch_list_t rtw_channel_def_6g[] = { + /* RTW_CHD_6G_INVALID */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_00 */ CH_LIST_ENT(0, 0), + /* RTW_CHD_6G_01 */ CH_LIST_ENT(24, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 0), + /* RTW_CHD_6G_02 */ CH_LIST_ENT(6, 97, 101, 105, 109, 113, 117, 0), + /* RTW_CHD_6G_03 */ CH_LIST_ENT(18, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 0), + /* RTW_CHD_6G_04 */ CH_LIST_ENT(11, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), + /* RTW_CHD_6G_05 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, CLA_6G_B1_PASSIVE | CLA_6G_B2_PASSIVE | CLA_6G_B3_PASSIVE | CLA_6G_B4_PASSIVE), + /* RTW_CHD_6G_06 */ CH_LIST_ENT(59, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 0), +}; + +struct chplan_6g_ent_t { + u8 regd; /* value of enum rtw_regd */ + u8 chd; +}; + +#define CHPLAN_6G_ENT(_regd, _chd) {.regd = RTW_REGD_##_regd, .chd = RTW_CHD_6G_##_chd} + +#define CHPLAN_6G_ENT_NOT_DEFINED CHPLAN_6G_ENT(NA, INVALID) + +static const struct chplan_6g_ent_t rtw_chplan_6g_map[] = { + [0x00] = CHPLAN_6G_ENT(NA , 00), + [0x01] = CHPLAN_6G_ENT(FCC , 01), + [0x02] = CHPLAN_6G_ENT(FCC , 02), + [0x03] = CHPLAN_6G_ENT(FCC , 03), + [0x04] = CHPLAN_6G_ENT(FCC , 04), + [0x05] = CHPLAN_6G_ENT(FCC , 06), + [0x06] = CHPLAN_6G_ENT(ETSI , 01), + [0x07] = CHPLAN_6G_ENT(IC , 06), + [0x08] = CHPLAN_6G_ENT(KCC , 06), + [0x09] = CHPLAN_6G_ENT(KCC , 01), + [0x1B] = CHPLAN_6G_ENT(ACMA , 01), + [0x1C] = CHPLAN_6G_ENT(MKK , 01), + [0x7F] = CHPLAN_6G_ENT(WW , 05), +}; + +static const int rtw_chplan_6g_map_size = sizeof(rtw_chplan_6g_map) / sizeof(rtw_chplan_6g_map[0]); + +static u8 rtk_regdb_get_default_regd_6g(u8 id) +{ + if (id < rtw_chplan_6g_map_size) + return rtw_chplan_6g_map[id].regd; + return RTW_REGD_NA; +} + +static bool rtk_regdb_is_domain_code_6g_valid(u8 id) +{ + if (id < rtw_chplan_6g_map_size) { + const struct chplan_6g_ent_t *chplan_map = &rtw_chplan_6g_map[id]; + + if (chplan_map->chd != RTW_CHD_6G_INVALID) + return true; + } + + return false; +} + +static bool rtk_regdb_domain_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + u8 index, attrib; + u8 chd_6g; + + if (flags) + *flags = 0; + + chd_6g = rtw_chplan_6g_map[id].chd; + + attrib = CH_LIST_ATTRIB(rtw_channel_def_6g[chd_6g]); + + for (index = 0; index < CH_LIST_LEN(rtw_channel_def_6g[chd_6g]); index++) { + if (CH_LIST_CH(rtw_channel_def_6g[chd_6g], index) == ch) { + if (flags) { + if ((rtw_is_6g_band1(ch) && (attrib & CLA_6G_B1_PASSIVE)) /* band1 passive */ + || (rtw_is_6g_band2(ch) && (attrib & CLA_6G_B2_PASSIVE)) /* band2 passive */ + || (rtw_is_6g_band3(ch) && (attrib & CLA_6G_B3_PASSIVE)) /* band3 passive */ + || (rtw_is_6g_band4(ch) && (attrib & CLA_6G_B4_PASSIVE)) /* band4 passive */ + ) + *flags |= RTW_CHF_NO_IR; + } + return true; + } + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x4D, 0x05, DEF , 0, 1, 1, 1, _I_), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x5E, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x06, 0x06, DEF , 1, 1, 1, 1, _I_), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x11, 0x00, DEF , 0, 1, 1, 1, _I_), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 0x05, DEF , 1, 1, 1, 1, _I_), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x0A, 0x00, DEF , 0, 0, 1, 1, ___), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x10, 0x07, DEF , 1, 1, 1, 1, SI_), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x5E, 0x00, DEF , 1, 1, 1, 1, ___), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 0x00, DEF , 0, 1, 1, 1, ___), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x76, 0x01, CHILE , 1, 1, 1, 1, _I_), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x06, 0x00, CN , 1, 1, 1, 1, ___), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 0x00, DEF , 0, 1, 1, 1, ___), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x0B, 0x06, UK , 1, 1, 1, 1, _IV), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 0x01, DEF , 1, 0, 1, 1, _I_), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 0x00, DEF , 0, 1, 1, 1, ___), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x0A, 0x00, DEF , 0, 0, 0, 0, ___), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x7D, 0x1C, DEF , 1, 1, 1, 1, _IV), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 0x08, DEF , 0, 1, 1, 1, _IV), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x3C, 0x06, DEF , 1, 1, 1, 1, _IV), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x3C, 0x00, DEF , 0, 1, 1, 1, ___), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 0x01, DEF , 1, 1, 1, 1, _I_), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x07, 0x06, DEF , 1, 1, 1, 1, _I_), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 0x00, DEF , 0, 1, 1, 1, ___), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x06, 0x00, DEF , 0, 1, 1, 1, ___), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x03, 0x1B, DEF , 1, 1, 1, 1, _IV), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PS", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Palestine */ + COUNTRY_CHPLAN_ENT("PT", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x5E, 0x06, QATAR , 1, 1, 1, 1, _IV), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Serbia */ + COUNTRY_CHPLAN_ENT("RU", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _IV), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x5E, 0x06, DEF , 0, 1, 1, 1, _I_), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 0x05, DEF , 1, 1, 1, 1, _I_), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x5E, 0x06, THAILAND, 1, 1, 1, 1, _IV), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x03, 0x00, DEF , 0, 1, 1, 1, ___), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x04, 0x00, DEF , 0, 1, 1, 1, ___), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 0x00, DEF , 0, 1, 1, 1, ___), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0x00, DEF , 0, 0, 0, 0, ___), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 0x06, DEF , 1, 1, 1, 1, _IV), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x5E, 0x00, UKRAINE , 0, 1, 1, 1, ___), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x1B, 0x05, DEF , 1, 1, 1, 1, SI_), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x3A, 0x06, DEF , 1, 1, 1, 1, _I_), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 0x00, DEF , 0, 1, 1, 1, ___), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 0x05, DEF , 1, 1, 1, 1, _I_), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 0x00, DEF , 0, 1, 1, 1, ___), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x3A, 0x00, DEF , 0, 1, 1, 1, ___), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Samoa */ + COUNTRY_CHPLAN_ENT("XK", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* Kosovo */ + COUNTRY_CHPLAN_ENT("YE", 0x0A, 0x00, DEF , 0, 1, 1, 1, ___), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x5E, 0x06, DEF , 1, 1, 1, 1, _I_), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x5E, 0x00, DEF , 0, 1, 1, 1, ___), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x5E, 0x00, DEF , 1, 1, 1, 1, ___), /* Zimbabwe */ +}; + +static bool rtk_regdb_get_chplan_from_alpha2(const char *alpha2, struct country_chplan *ent) +{ + const struct country_chplan *map = country_chplan_map; + u16 map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); + int i; + + for (i = 0; i < map_sz; i++) { + if (strncmp(alpha2, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + return false; +} + +#ifdef CONFIG_RTW_DEBUG +static void rtk_regdb_dump_chplan_test(void *sel) +{ + int i, j; + + /* check 2G CHD redundent */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = RTW_CHD_2G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_2g[i]) == CH_LIST_LEN(rtw_channel_def_2g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_2g[i], 0), &CH_LIST_CH(rtw_channel_def_2g[j], 0), CH_LIST_LEN(rtw_channel_def_2g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "2G chd:%u and %u is the same\n", i, j); + } + } + + /* check 2G CHD invalid channel */ + for (i = RTW_CHD_2G_00; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_bch2freq(BAND_ON_24G, CH_LIST_CH(rtw_channel_def_2g[i], j)) == 0) + RTW_PRINT_SEL(sel, "2G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_2g[i], j), i, j); + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + /* check 5G CHD redundent */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = RTW_CHD_5G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_5g[i]) == CH_LIST_LEN(rtw_channel_def_5g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_5g[i], 0), &CH_LIST_CH(rtw_channel_def_5g[j], 0), CH_LIST_LEN(rtw_channel_def_5g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "5G chd:%u and %u is the same\n", i, j); + } + } + + /* check 5G CHD invalid channel */ + for (i = RTW_CHD_5G_00; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_bch2freq(BAND_ON_5G, CH_LIST_CH(rtw_channel_def_5g[i], j)) == 0) + RTW_PRINT_SEL(sel, "5G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_5g[i], j), i, j); + } + } +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check 6G CHD redundent */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = RTW_CHD_6G_00; j < i; j++) { + if (CH_LIST_LEN(rtw_channel_def_6g[i]) == CH_LIST_LEN(rtw_channel_def_6g[j]) + && _rtw_memcmp(&CH_LIST_CH(rtw_channel_def_6g[i], 0), &CH_LIST_CH(rtw_channel_def_6g[j], 0), CH_LIST_LEN(rtw_channel_def_6g[i]) + 1) == _TRUE) + RTW_PRINT_SEL(sel, "6G chd:%u and %u is the same\n", i, j); + } + } + + /* check 6G CHD invalid channel */ + for (i = RTW_CHD_6G_00; i < RTW_CHD_6G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_6g[i]); j++) { + if (rtw_bch2freq(BAND_ON_6G, CH_LIST_CH(rtw_channel_def_6g[i], j)) == 0) + RTW_PRINT_SEL(sel, "6G invalid ch:%u at (%d,%d)\n", CH_LIST_CH(rtw_channel_def_6g[i], j), i, j); + } + } +#endif + + /* check chplan 2G_5G redundent */ + for (i = 0; i < RTW_ChannelPlanMap_size; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_valid(j)) + continue; + if (_rtw_memcmp(&RTW_ChannelPlanMap[i], &RTW_ChannelPlanMap[j], sizeof(RTW_ChannelPlanMap[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 0x%02x and 0x%02x is the same\n", i, j); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + /* check chplan 6G redundent */ + for (i = 0; i < rtw_chplan_6g_map_size; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + for (j = 0; j < i; j++) { + if (!rtw_is_channel_plan_6g_valid(j)) + continue; + if (_rtw_memcmp(&rtw_chplan_6g_map[i], &rtw_chplan_6g_map[j], sizeof(rtw_chplan_6g_map[i])) == _TRUE) + RTW_PRINT_SEL(sel, "channel plan 6g 0x%02x and 0x%02x is the same\n", i, j); + } + } +#endif + + + /* check country invalid chplan/chplan_6g */ +{ + struct country_chplan ent; + u8 code[2]; + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + if (!rtw_is_channel_plan_valid(ent.domain_code)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code:0x%02X\n", code[0], code[1], ent.domain_code); + #if CONFIG_IEEE80211_BAND_6GHZ + if (!rtw_is_channel_plan_6g_valid(ent.domain_code_6g)) + RTW_PRINT_SEL(sel, "country \"%c%c\" has invalid domain_code_6g:0x%02X\n", code[0], code[1], ent.domain_code_6g); + #endif + } + } +} +} +#endif /* CONFIG_RTW_DEBUG */ + +static void rtk_regdb_get_ver_str(char *buf, size_t buf_len) +{ + snprintf(buf, buf_len, "%s%s" + "%s%s-%s%s" + , RTW_MODULE_NAME, strlen(RTW_MODULE_NAME) ? "-" : "" + , RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER, RTW_COUNTRY_MAP_M_VER); +} + +struct rtw_regdb_ops regdb_ops = { + .get_default_regd_2g = rtk_regdb_get_default_regd_2g, +#if CONFIG_IEEE80211_BAND_5GHZ + .get_default_regd_5g = rtk_regdb_get_default_regd_5g, +#endif + .is_domain_code_valid = rtk_regdb_is_domain_code_valid, + .domain_get_ch = rtk_regdb_domain_get_ch, + +#if CONFIG_IEEE80211_BAND_6GHZ + .get_default_regd_6g = rtk_regdb_get_default_regd_6g, + .is_domain_code_6g_valid = rtk_regdb_is_domain_code_6g_valid, + .domain_6g_get_ch = rtk_regdb_domain_6g_get_ch, +#endif + + .get_chplan_from_alpha2 = rtk_regdb_get_chplan_from_alpha2, + +#ifdef CONFIG_RTW_DEBUG + .dump_chplan_test = rtk_regdb_dump_chplan_test, +#endif + .get_ver_str = rtk_regdb_get_ver_str, +}; + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_ap.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_ap.c new file mode 100755 index 00000000..51993c15 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_ap.c @@ -0,0 +1,7902 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_AP_C_ + +#include + +#ifdef CONFIG_AP_MODE + +extern unsigned char RTW_WPA_OUI[]; +extern unsigned char WMM_OUI[]; +extern unsigned char WPS_OUI[]; +extern unsigned char P2P_OUI[]; +extern unsigned char WFD_OUI[]; + +void init_mlme_ap_info(_adapter *padapter) +{ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + + _rtw_spinlock_init(&pmlmepriv->bcn_update_lock); + /* pmlmeext->bstart_bss = _FALSE; */ +} + +void free_mlme_ap_info(_adapter *padapter) +{ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + + stop_ap_mode(padapter); + _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); + +} + +/* +* Set TIM IE +* return length of total TIM IE +*/ +u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period + , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie) +{ + u8 *p = tim_ie; + u8 i, n1, n2; + u8 bmp_len; + + if (rtw_bmp_not_empty(tim_bmp, tim_bmp_len)) { + /* find the first nonzero octet in tim_bitmap */ + for (i = 0; i < tim_bmp_len; i++) + if (tim_bmp[i]) + break; + n1 = i & 0xFE; + + /* find the last nonzero octet in tim_bitmap, except octet 0 */ + for (i = tim_bmp_len - 1; i > 0; i--) + if (tim_bmp[i]) + break; + n2 = i; + bmp_len = n2 - n1 + 1; + } else { + n1 = n2 = 0; + bmp_len = 1; + } + + *p++ = WLAN_EID_TIM; + *p++ = 2 + 1 + bmp_len; + *p++ = dtim_cnt; + *p++ = dtim_period; + *p++ = (rtw_bmp_is_set(tim_bmp, tim_bmp_len, 0) ? BIT0 : 0) | n1; + _rtw_memcpy(p, tim_bmp + n1, bmp_len); + +#if 0 + RTW_INFO("n1:%u, n2:%u, bmp_offset:%u, bmp_len:%u\n", n1, n2, n1 / 2, bmp_len); + RTW_INFO_DUMP("tim_ie: ", tim_ie + 2, 2 + 1 + bmp_len); +#endif + return 2 + 2 + 1 + bmp_len; +} + +static void update_BCNTIM(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network); + unsigned char *pie = pnetwork_mlmeext->IEs; + +#if 0 + + + /* update TIM IE */ + /* if(rtw_tim_map_anyone_be_set(padapter, pstapriv->tim_bitmap)) */ +#endif + if (_TRUE) { + u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; + + p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); + if (p != NULL && tim_ielen > 0) { + tim_ielen += 2; + + premainder_ie = p + tim_ielen; + + tim_ie_offset = (sint)(p - pie); + + remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; + + /*append TIM IE from dst_ie offset*/ + dst_ie = p; + } else { + tim_ielen = 0; + + /*calculate head_len*/ + offset = _FIXED_IE_LENGTH_; + + /* get ssid_ie len */ + p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); + if (p != NULL) + offset += tmp_len + 2; + + /*get supported rates len*/ + p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); + if (p != NULL) + offset += tmp_len + 2; + + /* DS Parameter Set IE */ + p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _DSSET_IE_, &tmp_len, + pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_); + if (p) + offset += tmp_len + 2; + + premainder_ie = pie + offset; + + remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; + + /*append TIM IE from offset*/ + dst_ie = pie + offset; + + } + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + /* append TIM IE */ + dst_ie += rtw_set_tim_ie(0, 1, pstapriv->tim_bitmap, pstapriv->aid_bmp_len, dst_ie); + + /*copy remainder IE*/ + if (pbackup_remainder_ie) { + _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + } + + offset = (uint)(dst_ie - pie); + pnetwork_mlmeext->IELength = offset + remainder_ielen; + + } +} + +void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len) +{ + PNDIS_802_11_VARIABLE_IEs pIE; + u8 bmatch = _FALSE; + u8 *pie = pnetwork->IEs; + u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0; + + if (pnetwork->IELength + len > MAX_IE_SZ) { + RTW_ERR("Can't add IE to beacon, because size is more than MAX_IE_SZ\n"); + return; + } + + /* Search element id (index) exits or not */ + for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { + pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i); + + if (pIE->ElementID > index) + break; + else if (pIE->ElementID == index) { /* already exist the same IE */ + p = (u8 *)pIE; + ielen = pIE->Length; + bmatch = _TRUE; + break; + } + + p = (u8 *)pIE; + ielen = pIE->Length; + i += (pIE->Length + 2); + } + + /* Backup remainder IE */ + if (p != NULL && ielen > 0) { + ielen += 2; + + premainder_ie = p + ielen; + + ie_offset = (sint)(p - pie); + + remainder_ielen = pnetwork->IELength - ie_offset - ielen; + + if (bmatch) + dst_ie = p; + else + dst_ie = (p + ielen); + } + + if (dst_ie == NULL) + return; + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + *dst_ie++ = index; + *dst_ie++ = len; + + _rtw_memcpy(dst_ie, data, len); + dst_ie += len; + + /* Append remainder IE */ + if (pbackup_remainder_ie) { + _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + } + + offset = (uint)(dst_ie - pie); + pnetwork->IELength = offset + remainder_ielen; +} + +void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index) +{ + u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + uint offset, ielen, ie_offset, remainder_ielen = 0; + u8 *pie = pnetwork->IEs; + + p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_); + if (p != NULL && ielen > 0) { + ielen += 2; + + premainder_ie = p + ielen; + + ie_offset = (sint)(p - pie); + + remainder_ielen = pnetwork->IELength - ie_offset - ielen; + + dst_ie = p; + } else + return; + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + /* copy remainder IE */ + if (pbackup_remainder_ie) { + _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + } + + offset = (uint)(dst_ie - pie); + pnetwork->IELength = offset + remainder_ielen; +} + +/** + * rtw_add_bcn_ie_ex - Add Element ID Extension into Element ID (0xff) + * Frame format: | element id (0xff) | length | element id extension | content | + * + * @eid_ex: element id extension + * @data: eid_ex + content + * @len: length +*/ +void rtw_add_bcn_ie_ex(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 eid_ex, u8 *data, u8 len) +{ + struct ieee80211_info_element *pie; + bool find_ex_ie = _FALSE; + bool bmatch = _FALSE; + u8 *ies = pnetwork->IEs; + u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0; + + if (pnetwork->IELength + len > MAX_IE_SZ) { + RTW_ERR("Can't add IE to beacon, because size is more than MAX_IE_SZ\n"); + return; + } + + /* Search element id extension exits or not */ + for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { + pie = (struct ieee80211_info_element *)(ies + i); + + if (pie->id == WLAN_EID_EXTENSION) { + find_ex_ie = _TRUE; + if (pie->data[0] > eid_ex) { /* first byte of data is element id extension */ + break; + } else if (pie->data[0] == eid_ex) { /* already exist the same Element ID Extension */ + p = (u8 *)pie; + ielen = pie->len; + bmatch = _TRUE; + break; + } + } else if (find_ex_ie) { /* append to last element id (0xff) */ + break; + } + + p = (u8 *)pie; + ielen = pie->len; + i += (pie->len + 2); + } + + /* Backup remainder IE */ + if (p != NULL && ielen > 0) { + ielen += 2; + premainder_ie = p + ielen; + ie_offset = (sint)(p - ies); + remainder_ielen = pnetwork->IELength - ie_offset - ielen; + + if (bmatch) + dst_ie = p; + else + dst_ie = (p + ielen); + } + + if (dst_ie == NULL) + return; + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + *dst_ie++ = WLAN_EID_EXTENSION; + *dst_ie++ = len; + + _rtw_memcpy(dst_ie, data, len); + dst_ie += len; + + /* Append remainder IE */ + if (pbackup_remainder_ie) { + _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + } + + offset = (uint)(dst_ie - ies); + pnetwork->IELength = offset + remainder_ielen; +} + +void rtw_remove_bcn_ie_ex(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8* pindex_ex, u8 index_ex_len) +{ + u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; + uint offset, ielen, ie_offset, remainder_ielen = 0; + u8 *pie = pnetwork->IEs; + + p = rtw_get_ie_ex(pie + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, index, pindex_ex, index_ex_len, NULL, &ielen); + if (p != NULL && ielen > 0) { + premainder_ie = p + ielen; + + ie_offset = (sint)(p - pie); + + remainder_ielen = pnetwork->IELength - ie_offset - ielen; + + dst_ie = p; + } else + return; + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie && premainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + /* copy remainder IE */ + if (pbackup_remainder_ie) { + _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); + + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + } + + offset = (uint)(dst_ie - pie); + pnetwork->IELength = offset + remainder_ielen; +} + +u8 chk_sta_is_alive(struct sta_info *psta); +u8 chk_sta_is_alive(struct sta_info *psta) +{ + u8 ret = _FALSE; +#ifdef DBG_EXPIRATION_CHK + RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n" + , MAC_ARG(psta->phl_sta->mac_addr) + , 0 /* TODO: psta->phl_sta->hal_sta->rssi_stat.rssi */ + /* , STA_RX_PKTS_ARG(psta) */ + , STA_RX_PKTS_DIFF_ARG(psta) + , psta->expire_to + , psta->state & WIFI_SLEEP_STATE ? "PS, " : "" + , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : "" + , psta->sleepq_len + ); +#endif + + /* if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta)) */ + if ((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) { +#if 0 + if (psta->state & WIFI_SLEEP_STATE) + ret = _TRUE; +#endif + } else + ret = _TRUE; + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(psta->padapter)) { + u8 bcn_alive, hwmp_alive; + + hwmp_alive = (psta->sta_stats.rx_hwmp_pkts != + psta->sta_stats.last_rx_hwmp_pkts); + bcn_alive = (psta->sta_stats.rx_beacon_pkts != + psta->sta_stats.last_rx_beacon_pkts); + /* The reference for nexthop_lookup */ + psta->alive = ret || hwmp_alive || bcn_alive; + /* The reference for expire_timeout_chk */ + /* Exclude bcn_alive to avoid a misjudge condition + that a peer unexpectedly leave and restart quickly*/ + ret = ret || hwmp_alive; + } +#endif + + sta_update_last_rx_pkts(psta); + + return ret; +} + +/** + * issue_aka_chk_frame - issue active keep alive check frame + * aka = active keep alive + */ +#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK +static int issue_aka_chk_frame(_adapter *adapter, struct sta_info *psta) +{ + int ret = _FAIL; + u8 *target_addr = psta->phl_sta->mac_addr; + + if (MLME_IS_AP(adapter)) { + /* issue null data to check sta alive */ + if (psta->state & WIFI_SLEEP_STATE) + ret = issue_nulldata(adapter, + psta->padapter_link, + target_addr, 0, 1, 50); + else + ret = issue_nulldata(adapter, + psta->padapter_link, + target_addr, 0, 3, 50); + } + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(adapter)) { + struct rtw_mesh_path *mpath; + + rtw_rcu_read_lock(); + mpath = rtw_mesh_path_lookup(adapter, target_addr); + if (!mpath) { + mpath = rtw_mesh_path_add(adapter, target_addr); + if (IS_ERR(mpath)) { + rtw_rcu_read_unlock(); + RTW_ERR(FUNC_ADPT_FMT" rtw_mesh_path_add for "MAC_FMT" fail.\n", + FUNC_ADPT_ARG(adapter), MAC_ARG(target_addr)); + return _FAIL; + } + } + if (mpath->flags & RTW_MESH_PATH_ACTIVE) + ret = _SUCCESS; + else { + u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_PEER_AKA; + /* issue PREQ to check peer alive */ + rtw_mesh_queue_preq(mpath, flags); + ret = _FALSE; + } + rtw_rcu_read_unlock(); + } +#endif + return ret; +} +#endif + +void expire_timeout_post_chk(_adapter *padapter, u32 ap_chk_sta_bmp) +{ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta; + u8 updated = _FALSE; +#if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) + u8 switch_channel_by_drv = _TRUE; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct rtw_chan_def hw_chdef = {0}; + struct rtw_chan_def union_chdef = {0}; + struct rtw_chan_def bk_chdef = {0}; +#endif + char del_asoc_list[NUM_STA]; + u8 del_num = 0; + u8 i; + + _rtw_memset(del_asoc_list, NUM_STA, NUM_STA); + + #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK + if (padapter->mlmeextpriv.active_keep_alive_check) { + if (rtw_phl_mr_get_chandef(dvobj->phl, padapter->phl_role, + padapter_link->wrlink, + &union_chdef) + != RTW_PHL_STATUS_SUCCESS) { + RTW_ERR("fun:%s line:%d get chandef failed\n", __FUNCTION__, __LINE__); + rtw_warn_on(1); + } + + if (pmlmeext->chandef.chan != union_chdef.chan) + switch_channel_by_drv = _FALSE; + + /* switch to correct channel of current network before issue keep-alive frames */ + rtw_get_oper_chdef(padapter, padapter_link, &hw_chdef); + if (switch_channel_by_drv == _TRUE && hw_chdef.chan != pmlmeext->chandef.chan) { + _rtw_memcpy(&bk_chdef, &hw_chdef, sizeof(struct rtw_chan_def)); + set_bch_bwmode(padapter, padapter_link, union_chdef.band, + union_chdef.chan, union_chdef.offset, + union_chdef.bw, RFK_TYPE_FORCE_NOT_DO); + } + } + #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ + + /* check loop */ + for (i = 0; i < NUM_STA; i++) { + #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK + int ret = _FAIL; + #endif + + if (!(BIT(i) & ap_chk_sta_bmp)) + continue; + + psta = rtw_get_stainfo_by_offset(pstapriv, i); + + if (psta == NULL) + continue; + + #ifdef CONFIG_ATMEL_RC_PATCH + if (_rtw_memcmp(pstapriv->atmel_rc_pattern, psta->phl_sta->mac_addr, ETH_ALEN) == _TRUE) + continue; + if (psta->flag_atmel_rc) + continue; + #endif + + if (!(psta->state & WIFI_ASOC_STATE)) + continue; + + #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK + if (padapter->mlmeextpriv.active_keep_alive_check) { + /* issue active keep alive frame to check */ + ret = issue_aka_chk_frame(padapter, psta); + + psta->keep_alive_trycnt++; + if (ret == _SUCCESS) { + RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" is alive\n" + , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr)); + psta->expire_to = pstapriv->expire_to; + psta->keep_alive_trycnt = 0; + continue; + } else if (psta->keep_alive_trycnt <= 3) { + RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" keep_alive_trycnt=%d\n" + , FUNC_ADPT_ARG(padapter) , MAC_ARG(psta->phl_sta->mac_addr), psta->keep_alive_trycnt); + psta->expire_to = 1; + continue; + } + } + #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ + + psta->keep_alive_trycnt = 0; + del_asoc_list[del_num++] = i; + rtw_stapriv_asoc_list_lock(pstapriv); + if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) + rtw_stapriv_asoc_list_del(pstapriv, psta); + rtw_stapriv_asoc_list_unlock(pstapriv); + } + + /* delete loop */ + for (i = 0; i < del_num; i++) { + u8 sta_addr[ETH_ALEN]; + + psta = rtw_get_stainfo_by_offset(pstapriv, del_asoc_list[i]); + _rtw_memcpy(sta_addr, psta->phl_sta->mac_addr, ETH_ALEN); + + RTW_INFO(FUNC_ADPT_FMT" asoc expire "MAC_FMT", state=0x%x\n" + , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr), psta->state); + /* ToDo CONFIG_RTW_MLD: call only once for each MLD */ + updated |= ap_free_sta(padapter, psta, _FALSE, 0, WLAN_REASON_DEAUTH_LEAVING, _FALSE); + #ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) + rtw_mesh_expire_peer(padapter, sta_addr); + #endif + } + + #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK + if (padapter->mlmeextpriv.active_keep_alive_check) { + /* back to the original operation channel */ + if (switch_channel_by_drv == _TRUE && bk_chdef.chan > 0) + set_bch_bwmode(padapter, padapter_link, bk_chdef.band, + bk_chdef.chan, bk_chdef.offset, bk_chdef.bw, + RFK_TYPE_FORCE_NOT_DO); + } + #endif + + associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL); +} + +void expire_timeout_chk(_adapter *padapter, u32 *ap_chk_sta_bmp) +{ + _list *phead, *plist; + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + u8 chk_alive_num = 0; + int i; + int stainfo_offset; + u8 flush_num = 0; + char flush_list[NUM_STA]={0}; + #ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + #endif + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter) + && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) + ) { + struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg; + + rtw_mesh_path_expire(padapter); + + /* TBD: up layer timeout mechanism */ + /* if (!mcfg->plink_timeout) + return; */ + } +#endif + +#ifdef CONFIG_RTW_WDS + rtw_wds_path_expire(padapter); +#endif + + _rtw_spinlock_bh(&pstapriv->auth_list_lock); + + phead = &pstapriv->auth_list; + plist = get_next(phead); + + /* check auth_queue */ +#ifdef DBG_EXPIRATION_CHK + if (rtw_end_of_queue_search(phead, plist) == _FALSE) { + RTW_INFO(FUNC_ADPT_FMT" auth_list, cnt:%u\n" + , FUNC_ADPT_ARG(padapter), pstapriv->auth_list_cnt); + } +#endif + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, auth_list); + + plist = get_next(plist); + + +#ifdef CONFIG_ATMEL_RC_PATCH + if (_rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->phl_sta->mac_addr), ETH_ALEN) == _TRUE) + continue; + if (psta->flag_atmel_rc) + continue; +#endif + if (psta->expire_to > 0) { + psta->expire_to--; + if (psta->expire_to == 0) { + stainfo_offset = rtw_stainfo_offset(pstapriv, psta); + if (stainfo_offset_valid(stainfo_offset)) + flush_list[flush_num++] = stainfo_offset; + else + rtw_warn_on(1); + } + } + + } + + _rtw_spinunlock_bh(&pstapriv->auth_list_lock); + for (i = 0; i < flush_num; i++) { + psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]); + RTW_INFO(FUNC_ADPT_FMT" auth expire "MAC_FMT"\n" + , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr)); + rtw_free_mld_stainfo(padapter, psta->phl_sta->mld); + psta = NULL; + } + + #ifdef CONFIG_P2P + if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && padapter->registrypriv.p2p_go_skip_keep_alive == _TRUE) + return; + #endif + + rtw_stapriv_asoc_list_lock(pstapriv); + + phead = &pstapriv->asoc_list; + plist = get_next(phead); + + /* check asoc_queue */ +#ifdef DBG_EXPIRATION_CHK + if (rtw_end_of_queue_search(phead, plist) == _FALSE) { + RTW_INFO(FUNC_ADPT_FMT" asoc_list, cnt:%u\n" + , FUNC_ADPT_ARG(padapter), pstapriv->asoc_list_cnt); + } +#endif + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); +#ifdef CONFIG_ATMEL_RC_PATCH + RTW_INFO("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__, + psta, pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->phl_sta->mac_addr[0], psta->phl_sta->mac_addr[5]); + if (_rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->phl_sta->mac_addr), ETH_ALEN) == _TRUE) + continue; + if (psta->flag_atmel_rc) + continue; + RTW_INFO("%s: debug line:%d\n", __func__, __LINE__); +#endif +#ifdef CONFIG_AUTO_AP_MODE + if (psta->isrc) + continue; +#endif + if (chk_sta_is_alive(psta) || !psta->expire_to) { + psta->expire_to = pstapriv->expire_to; + psta->keep_alive_trycnt = 0; + #if !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT) + psta->under_exist_checking = 0; + #endif + } else + psta->expire_to--; + +#if !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT) + if ((psta->flags & WLAN_STA_HT +#if CONFIG_IEEE80211_BAND_6GHZ + || psta->phl_sta->chandef.band == BAND_ON_6G +#endif + ) && (psta->ampdu_priv.agg_enable_bitmap || psta->under_exist_checking)) { + /* check sta by delba(addba) for 11n STA */ + /* ToDo: use CCX report to check for all STAs */ + /* RTW_INFO("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->ampdu_priv.agg_enable_bitmap, psta->under_exist_checking); */ + + if (psta->expire_to <= (pstapriv->expire_to - 50)) { + RTW_INFO("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2); + psta->under_exist_checking = 0; + psta->expire_to = 0; + } else if (psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking == 0)) { + RTW_INFO("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2); + psta->under_exist_checking = 1; + /* tear down TX AMPDU */ + send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */ + psta->ampdu_priv.agg_enable_bitmap = 0x0;/* reset */ + psta->ampdu_priv.candidate_tid_bitmap = 0x0;/* reset */ + } + } +#endif /* !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT) */ + + if (psta->expire_to <= 0) { + if (padapter->registrypriv.wifi_spec == 1) { + psta->expire_to = pstapriv->expire_to; + continue; + } + +#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK +#ifdef CONFIG_80211N_HT + +#define KEEP_ALIVE_TRYCNT (3) + + if (psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT) { + if (psta->state & WIFI_STA_ALIVE_CHK_STATE) + psta->state ^= WIFI_STA_ALIVE_CHK_STATE; + else + psta->keep_alive_trycnt = 0; + + } else if ((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE)) + psta->keep_alive_trycnt = 0; + if ((psta->htpriv.ht_option == _TRUE +#if CONFIG_IEEE80211_BAND_6GHZ + || psta->phl_sta->chandef.band == BAND_ON_6G +#endif + ) && (psta->ampdu_priv.ampdu_enable == _TRUE)) { + uint priority = 1; /* test using BK */ + u8 issued = 0; + + /* issued = (psta->ampdu_priv.agg_enable_bitmap>>priority)&0x1; */ + issued |= (psta->ampdu_priv.candidate_tid_bitmap >> priority) & 0x1; + + if (0 == issued) { + if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { + psta->ampdu_priv.candidate_tid_bitmap |= BIT((u8)priority); + + if (psta->state & WIFI_SLEEP_STATE) + psta->expire_to = 2; /* 2x2=4 sec */ + else + psta->expire_to = 1; /* 2 sec */ + + psta->state |= WIFI_STA_ALIVE_CHK_STATE; + + /* add_ba_hdl(padapter, (u8*)paddbareq_parm); */ + + RTW_INFO("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt); + + issue_addba_req(padapter, psta->phl_sta->mac_addr, (u8)priority); + + _set_timer(&psta->addba_retry_timer, ADDBA_TO); + + psta->keep_alive_trycnt++; + + continue; + } + } + } + if (psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE) { + psta->keep_alive_trycnt = 0; + psta->state ^= WIFI_STA_ALIVE_CHK_STATE; + RTW_INFO("change to another methods to check alive if staion is at ps mode\n"); + } + +#endif /* CONFIG_80211N_HT */ +#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ + if (psta->state & WIFI_SLEEP_STATE) { + if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { + /* to check if alive by another methods if staion is at ps mode. */ + psta->expire_to = pstapriv->expire_to; + psta->state |= WIFI_STA_ALIVE_CHK_STATE; + + /* RTW_INFO("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->phl_sta->mac_addr)); */ + + /* to update bcn with tim_bitmap for this station */ + rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid); + rtw_update_beacon(padapter, + padapter_link, + _TIM_IE_, NULL, _TRUE, 0); + + if (!padapter->mlmeextpriv.active_keep_alive_check) + continue; + } + } + + { + int stainfo_offset; + + stainfo_offset = rtw_stainfo_offset(pstapriv, psta); + if (stainfo_offset_valid(stainfo_offset)) + *ap_chk_sta_bmp |= BIT(stainfo_offset); + continue; + } + } else { + /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ + if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) + && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME / pstapriv->asoc_list_cnt) / 2) + ) { + RTW_INFO(FUNC_ADPT_FMT" sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n" + , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr) + , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt); + wakeup_sta_to_xmit(padapter, psta); + } + } + } + + rtw_stapriv_asoc_list_unlock(pstapriv); + +#ifndef CONFIG_POST_CORE_KEEP_ALIVE + expire_timeout_post_chk(padapter, *ap_chk_sta_bmp); +#endif +} + +#ifdef CONFIG_BMC_TX_RATE_SELECT +u8 rtw_ap_find_mini_tx_rate(_adapter *adapter) +{ + _list *phead, *plist; + u8 mini_tx_rate = DESC_RATEVHTSS4MCS9, sta_tx_rate; + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &adapter->stapriv; + + rtw_stapriv_asoc_list_lock(pstapriv); + phead = &pstapriv->asoc_list; + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + + sta_tx_rate = psta->phl_sta->ra_info.curr_tx_rate & 0x7F; + if (sta_tx_rate < mini_tx_rate) + mini_tx_rate = sta_tx_rate; + } + rtw_stapriv_asoc_list_unlock(pstapriv); + + return mini_tx_rate; +} + +u8 rtw_ap_find_bmc_rate(_adapter *adapter, struct _ADAPTER_LINK *adapter_link, u8 tx_rate) +{ + u8 tx_ini_rate = DESC_RATE6M; + + switch (tx_rate) { + case DESC_RATEVHTSS3MCS9: + case DESC_RATEVHTSS3MCS8: + case DESC_RATEVHTSS3MCS7: + case DESC_RATEVHTSS3MCS6: + case DESC_RATEVHTSS3MCS5: + case DESC_RATEVHTSS3MCS4: + case DESC_RATEVHTSS3MCS3: + case DESC_RATEVHTSS2MCS9: + case DESC_RATEVHTSS2MCS8: + case DESC_RATEVHTSS2MCS7: + case DESC_RATEVHTSS2MCS6: + case DESC_RATEVHTSS2MCS5: + case DESC_RATEVHTSS2MCS4: + case DESC_RATEVHTSS2MCS3: + case DESC_RATEVHTSS1MCS9: + case DESC_RATEVHTSS1MCS8: + case DESC_RATEVHTSS1MCS7: + case DESC_RATEVHTSS1MCS6: + case DESC_RATEVHTSS1MCS5: + case DESC_RATEVHTSS1MCS4: + case DESC_RATEVHTSS1MCS3: + case DESC_RATEMCS15: + case DESC_RATEMCS14: + case DESC_RATEMCS13: + case DESC_RATEMCS12: + case DESC_RATEMCS11: + case DESC_RATEMCS7: + case DESC_RATEMCS6: + case DESC_RATEMCS5: + case DESC_RATEMCS4: + case DESC_RATEMCS3: + case DESC_RATE54M: + case DESC_RATE48M: + case DESC_RATE36M: + case DESC_RATE24M: + tx_ini_rate = DESC_RATE24M; + break; + case DESC_RATEVHTSS3MCS2: + case DESC_RATEVHTSS3MCS1: + case DESC_RATEVHTSS2MCS2: + case DESC_RATEVHTSS2MCS1: + case DESC_RATEVHTSS1MCS2: + case DESC_RATEVHTSS1MCS1: + case DESC_RATEMCS10: + case DESC_RATEMCS9: + case DESC_RATEMCS2: + case DESC_RATEMCS1: + case DESC_RATE18M: + case DESC_RATE12M: + tx_ini_rate = DESC_RATE12M; + break; + case DESC_RATEVHTSS3MCS0: + case DESC_RATEVHTSS2MCS0: + case DESC_RATEVHTSS1MCS0: + case DESC_RATEMCS8: + case DESC_RATEMCS0: + case DESC_RATE9M: + case DESC_RATE6M: + tx_ini_rate = DESC_RATE6M; + break; + case DESC_RATE11M: + case DESC_RATE5_5M: + case DESC_RATE2M: + case DESC_RATE1M: + tx_ini_rate = DESC_RATE1M; + break; + default: + tx_ini_rate = DESC_RATE6M; + break; + } + + if (WIFI_ROLE_LINK_IS_ON_5G(adapter_link)) + if (tx_ini_rate < DESC_RATE6M) + tx_ini_rate = DESC_RATE6M; + + return tx_ini_rate; +} + +void rtw_update_bmc_sta_tx_rate(_adapter *adapter) +{ + struct sta_info *psta = NULL; + u8 tx_rate; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *adapter_link = GET_PRIMARY_LINK(adapter); + + psta = rtw_get_bcmc_stainfo(adapter, adapter_link); + if (psta == NULL) { + RTW_ERR(ADPT_FMT "could not get bmc_sta !!\n", ADPT_ARG(adapter)); + return; + } + + if (adapter->bmc_tx_rate != MGN_UNKNOWN) { + psta->init_rate = adapter->bmc_tx_rate; + goto _exit; + } + + if (adapter->stapriv.asoc_sta_count <= 2) + goto _exit; + + tx_rate = rtw_ap_find_mini_tx_rate(adapter); + #ifdef CONFIG_BMC_TX_LOW_RATE + tx_rate = rtw_ap_find_bmc_rate(adapter, adapter_link, tx_rate); + #endif + + psta->init_rate = hwrate_to_mrate(tx_rate); + +_exit: + RTW_INFO(ADPT_FMT" BMC Tx rate - %s\n", ADPT_ARG(adapter), MGN_RATE_STR(psta->init_rate)); +} +#endif + +void rtw_init_bmc_sta_tx_rate(_adapter *padapter, struct sta_info *psta) +{ +/* ToDo: need API to query hal_sta->ra_info.ramask */ +#if 0 +#ifdef CONFIG_BMC_TX_LOW_RATE + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); +#endif + u8 rate_idx = 0; + u8 brate_table[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M, + MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}; + + if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) + return; + + if (padapter->bmc_tx_rate != MGN_UNKNOWN) + psta->init_rate = padapter->bmc_tx_rate; + else { + #ifdef CONFIG_BMC_TX_LOW_RATE + if (IsEnableHWOFDM(pmlmeext->cur_wireless_mode) && (psta->phl_sta->ra_info.ramask && 0xFF0)) + rate_idx = get_lowest_rate_idx_ex(psta->phl_sta->ra_info.ramask, 4); /*from basic rate*/ + else + rate_idx = get_lowest_rate_idx(psta->phl_sta->ra_info.ramask); /*from basic rate*/ + #else + rate_idx = get_highest_rate_idx(psta->phl_sta->ra_info.ramask); /*from basic rate*/ + #endif + if (rate_idx < 12) + psta->init_rate = brate_table[rate_idx]; + else + psta->init_rate = MGN_1M; + } +#endif + RTW_INFO(ADPT_FMT" BMC Init Tx rate - %s\n", ADPT_ARG(padapter), MGN_RATE_STR(psta->init_rate)); +} + +#if defined(CONFIG_80211N_HT) && defined(CONFIG_BEAMFORMING) +void update_sta_info_apmode_ht_bf_cap(_adapter *padapter, struct sta_info *psta) +{ + struct _ADAPTER_LINK *padapter_link = psta->padapter_link; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; + struct ht_priv *phtpriv_sta = &psta->htpriv; + + u8 cur_beamform_cap = 0; + + /*Config Tx beamforming setting*/ + if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && + GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap))) { + SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE); + /*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/ + SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6); + } + + if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) && + GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap))) { + SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE); + /*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/ + SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4); + } + if (cur_beamform_cap) + RTW_INFO("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->phl_sta->aid, cur_beamform_cap); + + phtpriv_sta->beamform_cap = cur_beamform_cap; +} +#endif /*CONFIG_80211N_HT && CONFIG_BEAMFORMING*/ + +#ifdef CONFIG_80211N_HT +void update_sta_bw_apmode(_adapter *padapter, struct sta_info *psta) +{ + struct _ADAPTER_LINK *padapter_link = psta->padapter_link; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; + struct ht_priv *phtpriv_sta = &psta->htpriv; + + if (phtpriv_sta->ht_option) { + if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) + psta->phl_sta->chandef.bw = CHANNEL_WIDTH_40; + else + psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20; + + if (phtpriv_sta->op_present + && !GET_HT_OP_ELE_STA_CHL_WIDTH(phtpriv_sta->ht_op)) + psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20; + + if ((psta->ht_40mhz_intolerant) || (pmlmepriv->sw_to_20mhz)) + psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20; + + if (pmlmeext->chandef.bw < psta->phl_sta->chandef.bw) + psta->phl_sta->chandef.bw = pmlmeext->chandef.bw; + + phtpriv_sta->ch_offset = pmlmepriv->sw_to_20mhz ? CHAN_OFFSET_NO_EXT : pmlmeext->chandef.offset; + } +} +#endif /* CONFIG_80211N_HT */ + +/* notes: + * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */ +void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta) +{ + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct _ADAPTER_LINK *padapter_link = psta->padapter_link; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct protocol_cap_t *protocol_cap = &(padapter_link->wrlink->protocol_cap); +#ifdef CONFIG_80211N_HT + struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; + struct ht_priv *phtpriv_sta = &psta->htpriv; + struct ampdu_priv *ampdu_priv_ap = &pmlmepriv->ampdu_priv; + struct ampdu_priv *ampdu_priv_sta = &psta->ampdu_priv; +#endif /* CONFIG_80211N_HT */ + u8 cur_ldpc_cap = 0, cur_stbc_cap = 0; + /* set intf_tag to if1 */ + /* psta->intf_tag = 0; */ + + RTW_INFO("%s\n", __FUNCTION__); + + /*alloc macid when call rtw_alloc_stainfo(),release macid when call rtw_free_stainfo()*/ + + if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) + psta->ieee8021x_blocked = _TRUE; + else + psta->ieee8021x_blocked = _FALSE; + + + /* update sta's cap */ + + psta->phl_sta->chandef.chan = pmlmeext->chandef.chan; + psta->phl_sta->chandef.band = pmlmeext->chandef.band; + + /* ERP */ + VCS_update(padapter, psta); +#ifdef CONFIG_80211N_HT + /* HT related cap */ + if (phtpriv_sta->ht_option) { + /* check if sta supports rx ampdu */ + ampdu_priv_sta->ampdu_enable = ampdu_priv_ap->ampdu_enable; + + ampdu_priv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; + + update_sta_bw_apmode(padapter, psta); + + /* check if sta support s Short GI 20M */ + if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) + phtpriv_sta->sgi_20m = _TRUE; + + /* check if sta support s Short GI 40M */ + if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) { + if (psta->phl_sta->chandef.bw == CHANNEL_WIDTH_40) /* according to psta->bw_mode */ + phtpriv_sta->sgi_40m = _TRUE; + else + phtpriv_sta->sgi_40m = _FALSE; + } + + psta->qos_option = _TRUE; + + /* B0 Config LDPC Coding Capability */ + if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && + GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) { + SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX)); + RTW_INFO("Enable HT Tx LDPC for STA(%d)\n", psta->phl_sta->aid); + } + + /* B7 B8 B9 Config STBC setting */ + if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) && + GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) { + SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX)); + RTW_INFO("Enable HT Tx STBC for STA(%d)\n", psta->phl_sta->aid); + } + + psta->phl_sta->asoc_cap.stbc_ht_tx = + GET_HT_CAP_ELE_TX_STBC((u8 *)(&phtpriv_sta->ht_cap)); + psta->phl_sta->asoc_cap.stbc_ht_rx = + protocol_cap->stbc_ht_tx ? + GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)) : 0; + + #ifdef CONFIG_BEAMFORMING + update_sta_info_apmode_ht_bf_cap(padapter, psta); + #endif + } else { + ampdu_priv_sta->ampdu_enable = _FALSE; + + phtpriv_sta->sgi_20m = _FALSE; + phtpriv_sta->sgi_40m = _FALSE; + psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20; + phtpriv_sta->ch_offset = CHAN_OFFSET_NO_EXT; + } + + phtpriv_sta->ldpc_cap = cur_ldpc_cap; + phtpriv_sta->stbc_cap = cur_stbc_cap; + + /* Rx AMPDU */ + send_delba(padapter, 0, psta->phl_sta->mac_addr);/* recipient */ + + /* TX AMPDU */ + send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */ + ampdu_priv_sta->agg_enable_bitmap = 0x0;/* reset */ + ampdu_priv_sta->candidate_tid_bitmap = 0x0;/* reset */ +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_80211AC_VHT + update_sta_vht_info_apmode(padapter, psta); +#endif + +#ifdef CONFIG_80211AX_HE + update_sta_he_info_apmode(padapter, psta); +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + update_sta_6ghz_info_apmode(padapter, psta); +#endif + + psta->phl_sta->chandef.offset = (psta->phl_sta->chandef.bw > CHANNEL_WIDTH_20) ? + pmlmeext->chandef.offset : CHAN_OFFSET_NO_EXT; + + /* ToDo: need API to inform hal_sta->ra_info.is_support_sgi */ + /* psta->phl_sta->ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta)); */ + update_ldpc_stbc_cap(psta); + + /* todo: init other variables */ + + _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); + + _rtw_spinlock_bh(&psta->lock); + + /* Check encryption */ + if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) + psta->state |= WIFI_UNDER_KEY_HANDSHAKE; + + psta->state |= WIFI_ASOC_STATE; + + _rtw_spinunlock_bh(&psta->lock); +} + +static void update_ap_info(_adapter *padapter, struct sta_info *psta) +{ + struct _ADAPTER_LINK *padapter_link = psta->padapter_link; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; +#ifdef CONFIG_80211N_HT + struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; + struct ampdu_priv *ampdu_priv_ap = &pmlmepriv->ampdu_priv; +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) + psta->qos_option = 1; +#endif + + psta->phl_sta->wmode = pmlmeext->cur_wireless_mode; + + psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates); + _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen); + +#ifdef CONFIG_80211N_HT + /* HT related cap */ + if (phtpriv_ap->ht_option) { + /* check if sta supports rx ampdu */ + /* ampdu_priv_ap->ampdu_enable = ampdu_priv_ap->ampdu_enable; */ + + /* check if sta support s Short GI 20M */ + if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) + phtpriv_ap->sgi_20m = _TRUE; + /* check if sta support s Short GI 40M */ + if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) + phtpriv_ap->sgi_40m = _TRUE; + + psta->qos_option = _TRUE; + } else { + ampdu_priv_ap->ampdu_enable = _FALSE; + + phtpriv_ap->sgi_20m = _FALSE; + phtpriv_ap->sgi_40m = _FALSE; + } + + _rtw_memcpy(&psta->phl_sta->chandef, &pmlmeext->chandef, sizeof(struct rtw_chan_def)); + phtpriv_ap->ch_offset = pmlmeext->chandef.offset; + + ampdu_priv_ap->agg_enable_bitmap = 0x0;/* reset */ + ampdu_priv_ap->candidate_tid_bitmap = 0x0;/* reset */ + + _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv)); + +#ifdef CONFIG_80211AC_VHT + _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv)); + +#ifdef CONFIG_80211AX_HE + _rtw_memcpy(&psta->hepriv, &pmlmepriv->hepriv, sizeof(struct he_priv)); +#endif /* CONFIG_80211AX_HE */ + +#endif /* CONFIG_80211AC_VHT */ + +#endif /* CONFIG_80211N_HT */ + + _rtw_spinlock_bh(&psta->lock); + psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */ + psta->state |= WIFI_ASOC_STATE; + _rtw_spinunlock_bh(&psta->lock); + + rtw_init_bmc_sta_tx_rate(padapter, psta); +} + +void rtw_ap_set_edca(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, enum rtw_ac ac, u32 parm) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta = rtw_get_stainfo(pstapriv, padapter_link->mac_addr); + + if (psta && psta->phl_sta) { + psta->phl_sta->asoc_cap.edca[ac].ac = ac; + psta->phl_sta->asoc_cap.edca[ac].param = parm; + } + rtw_hw_set_edca(padapter, padapter_link, ac, parm); +} + +static void rtw_set_hw_wmm_param(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + u8 AIFS, ECWMin, ECWMax, aSifsTime; + u8 acm_mask; + u16 TXOP; + u32 acParm, i; + u32 edca[4], inx[4]; + struct registry_priv *pregpriv = &padapter->registrypriv; + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + + acm_mask = 0; +#ifdef CONFIG_80211N_HT + if (pregpriv->ht_enable && + (WIFI_ROLE_LINK_IS_ON_5G(padapter_link) || (pmlmeext->cur_wireless_mode & WLAN_MD_11N))) + aSifsTime = 16; + else +#endif /* CONFIG_80211N_HT */ + aSifsTime = 10; + + if (pmlmeinfo->WMM_enable == 0) { + padapter->mlmepriv.acm_mask = 0; + + AIFS = aSifsTime + (2 * pmlmeinfo->slotTime); + + if (pmlmeext->cur_wireless_mode & (WLAN_MD_11G | WLAN_MD_11A)) { + ECWMin = 4; + ECWMax = 10; + } else if (pmlmeext->cur_wireless_mode & WLAN_MD_11B) { + ECWMin = 5; + ECWMax = 10; + } else { + ECWMin = 4; + ECWMax = 10; + } + + TXOP = 0; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 0, acParm); + rtw_ap_set_edca(padapter, padapter_link, 1, acParm); + rtw_ap_set_edca(padapter, padapter_link, 2, acParm); + + ECWMin = 2; + ECWMax = 3; + TXOP = 0x2f; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 3, acParm); + + } else { + edca[0] = edca[1] = edca[2] = edca[3] = 0; + + /*TODO:*/ + acm_mask = 0; + padapter->mlmepriv.acm_mask = acm_mask; + +#if 0 + /* BK */ + /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ +#endif + AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime; + ECWMin = 4; + ECWMax = 10; + TXOP = 0; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 1, acParm); + edca[XMIT_BK_QUEUE] = acParm; + RTW_INFO("WMM(BK): %x\n", acParm); + + /* BE */ + AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime; + ECWMin = 4; + ECWMax = 6; + TXOP = 0; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 0, acParm); + edca[XMIT_BE_QUEUE] = acParm; + RTW_INFO("WMM(BE): %x\n", acParm); + + /* VI */ + AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime; + ECWMin = 3; + ECWMax = 4; + TXOP = 94; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 2, acParm); + edca[XMIT_VI_QUEUE] = acParm; + RTW_INFO("WMM(VI): %x\n", acParm); + + /* VO */ + AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime; + ECWMin = 2; + ECWMax = 3; + TXOP = 47; + acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); + rtw_ap_set_edca(padapter, padapter_link, 3, acParm); + edca[XMIT_VO_QUEUE] = acParm; + RTW_INFO("WMM(VO): %x\n", acParm); + + + if (padapter->registrypriv.acm_method == 1) + rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask)); + else + padapter->mlmepriv.acm_mask = acm_mask; + + inx[0] = 0; + inx[1] = 1; + inx[2] = 2; + inx[3] = 3; + + if (padapter->registrypriv.wifi_spec == 1) { + u32 j, tmp, change_inx = _FALSE; + + /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ + for (i = 0 ; i < 4 ; i++) { + for (j = i + 1 ; j < 4 ; j++) { + /* compare CW and AIFS */ + if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) + change_inx = _TRUE; + else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) { + /* compare TXOP */ + if ((edca[j] >> 16) > (edca[i] >> 16)) + change_inx = _TRUE; + } + + if (change_inx) { + tmp = edca[i]; + edca[i] = edca[j]; + edca[j] = tmp; + + tmp = inx[i]; + inx[i] = inx[j]; + inx[j] = tmp; + + change_inx = _FALSE; + } + } + } + } + + for (i = 0 ; i < 4 ; i++) { + pxmitpriv->wmm_para_seq[i] = inx[i]; + RTW_INFO("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]); + } + + } + +} +static void rtw_ap_check_scan(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + _list *plist, *phead; + u32 delta_time, lifetime; + struct wlan_network *pnetwork = NULL; + WLAN_BSSID_EX *pbss = NULL; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + _queue *queue = &(pmlmepriv->scanned_queue); + u8 do_scan = _FALSE; + u8 reason = RTW_AUTO_SCAN_REASON_UNSPECIFIED; + struct link_mlme_priv *lmlmepriv = &padapter_link->mlmepriv; + + lifetime = SCANQUEUE_LIFETIME; /* 20 sec */ + + _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock)); + phead = get_list_head(queue); + if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE) + if (padapter->registrypriv.wifi_spec) { + do_scan = _TRUE; + reason |= RTW_AUTO_SCAN_REASON_2040_BSS; + } + _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock)); + +#if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS) + if (padapter->registrypriv.acs_auto_scan) { + do_scan = _TRUE; + reason |= RTW_AUTO_SCAN_REASON_ACS; + rtw_acs_start(padapter); + } +#endif/*CONFIG_RTW_ACS*/ + + if (_TRUE == do_scan) { + RTW_INFO("%s : drv scans by itself and wait_completed\n", __func__); + rtw_drv_scan_by_self(padapter, reason); + rtw_scan_abort(padapter, 0); + } + +#if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS) + if (padapter->registrypriv.acs_auto_scan) + rtw_acs_stop(padapter); +#endif + + _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock)); + + phead = get_list_head(queue); + plist = get_next(phead); + + while (1) { + + if (rtw_end_of_queue_search(phead, plist) == _TRUE) + break; + + pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); + + if (rtw_chset_search_bch(adapter_to_chset(padapter) + , pnetwork->network.Configuration.Band + , pnetwork->network.Configuration.DSConfig) >= 0 + && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE + && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) { + delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned); + + if (delta_time < lifetime) { + + uint ie_len = 0; + u8 *pbuf = NULL; + u8 *ie = NULL; + + pbss = &pnetwork->network; + ie = pbss->IEs; + + /*check if HT CAP INFO IE exists or not*/ + pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_)); + if (pbuf == NULL) { + /* HT CAP INFO IE don't exist, it is b/g mode bss.*/ + + if (_FALSE == ATOMIC_READ(&lmlmepriv->olbc)) + ATOMIC_SET(&lmlmepriv->olbc, _TRUE); + + if (_FALSE == ATOMIC_READ(&lmlmepriv->olbc_ht)) + ATOMIC_SET(&lmlmepriv->olbc_ht, _TRUE); + if (padapter->registrypriv.wifi_spec) + RTW_INFO("%s: %s is a/b/g ap\n", __func__, pnetwork->network.Ssid.Ssid); + } + } + } + + plist = get_next(plist); + + } + + _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock)); +#ifdef CONFIG_80211N_HT + lmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/ +#endif +} + +void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter, struct _ADAPTER_LINK *adapter_link) +{ + WLAN_BSSID_EX *pnetwork = &(adapter_link->mlmepriv.cur_network.network); + struct sta_info *sta = NULL; + + /* update cur_wireless_mode */ + update_wireless_mode(adapter, adapter_link); + + /* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */ + UpdateBrateTbl(adapter, pnetwork->SupportedRates); + rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); + + /* update capability after cur_wireless_mode updated */ + update_capinfo(adapter, adapter_link, rtw_get_capability(pnetwork)); + + /* update AP's sta info */ + sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress); + if (!sta) { + RTW_INFO(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress)); + rtw_warn_on(1); + return; + } + + update_ap_info(adapter, sta); +} + +static void _rtw_iface_undersurvey_chk(const char *func, _adapter *adapter) +{ + int i; + _adapter *iface; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct mlme_priv *pmlmepriv; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if ((iface) && rtw_is_adapter_up(iface)) { + pmlmepriv = &iface->mlmepriv; + if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)) + RTW_ERR("%s ("ADPT_FMT") under survey\n", func, ADPT_ARG(iface)); + } + } +} + +void rtw_core_ap_swch_start(_adapter *padapter, struct createbss_parm *parm) +{ + struct dvobj_priv *pdvobj = padapter->dvobj; + int i; + u8 ht_option = 0; + _adapter *iface; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct _ADAPTER_LINK *iface_link; + + RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + + if (parm->ch_to_set != 0) { + set_bch_bwmode(padapter, padapter_link, parm->req_band, + parm->ch_to_set, parm->offset_to_set, parm->bw_to_set, RFK_TYPE_FORCE_DO); + rtw_phl_mr_dump_cur_chandef(adapter_to_dvobj(padapter)->phl, padapter->phl_role); + } + +#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + for (i = 0; i < pdvobj->iface_nums; i++) { + iface = pdvobj->padapters[i]; + + if (!(parm->ifbmp_ch_changed & BIT(i)) || !iface) + continue; + + iface_link = GET_PRIMARY_LINK(iface); + + #ifdef CONFIG_80211N_HT + ht_option = iface_link->mlmepriv.htpriv.ht_option; + #endif + + rtw_cfg80211_ch_switch_notify(iface, + iface_link, + &iface_link->mlmeextpriv.chandef, + ht_option, 0); + } +#endif /* defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */ + + rtw_rfctl_update_op_mode(adapter_to_rfctl(padapter), parm->ifbmp, 1, parm->excl_ifbmp); +} + +#ifdef CONFIG_DBCC_SUPPORT +static void _go_dbcc_update_ie(_adapter *a) +{ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + struct link_mlme_ext_priv *mlmeext = &(alink->mlmeextpriv); + struct link_mlme_priv *mlmepriv = &(alink->mlmepriv); + struct link_mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info); + WLAN_BSSID_EX *network = &(mlmeinfo->network); + struct HT_caps_element *ht_caps; + u32 ht_cap_ie_len = 0; + u8 *ht_cap_ie = NULL, *ie = network->IEs; + + if (!rtw_phl_mr_is_db(adapter_to_dvobj(a)->phl)) + return; +#ifdef CONFIG_P2P + if (!MLME_IS_GO(a)) + return; +#ifdef CONFIG_80211N_HT + if (!mlmepriv->htpriv.ht_option) + return; + + if (!mlmeinfo->HT_caps_enable) + return; + + ht_cap_ie = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ht_cap_ie_len, (network->IELength - _BEACON_IE_OFFSET_)); + if (ht_cap_ie && ht_cap_ie_len > 0) { + ht_caps = (struct HT_caps_element *)(ht_cap_ie + 2); + RTW_INFO(FUNC_ADPT_FMT": orig ht caps info = 0x%02x\n", FUNC_ADPT_ARG(a), ht_caps->u.HT_cap_element.HT_caps_info); + SET_HT_CAP_ELE_SM_PS(&(ht_caps->u.HT_cap_element.HT_caps_info), SM_PS_STATIC); + RTW_INFO(FUNC_ADPT_FMT": update ht caps info = 0x%02x\n", FUNC_ADPT_ARG(a), ht_caps->u.HT_cap_element.HT_caps_info); + } +#endif +#endif +} +#endif + +void rtw_core_ap_start(_adapter *padapter, struct createbss_parm *parm) +{ + struct dvobj_priv *pdvobj = padapter->dvobj; + int i; + _adapter *iface; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct _ADAPTER_LINK *iface_link; + struct link_mlme_priv *mlme; + + RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + if (0) { + RTW_INFO(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter)); + dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter)); + } + + for (i = 0; i < pdvobj->iface_nums; i++) { + iface = pdvobj->padapters[i]; + + if (!(parm->ifbmp & BIT(i)) || !iface) + continue; + + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + /* update beacon content only if bstart_bss is _TRUE */ + if (iface_link->mlmeextpriv.bstart_bss != _TRUE) + continue; + + mlme = &(iface_link->mlmepriv); + + #ifdef CONFIG_80211N_HT + if ((ATOMIC_READ(&mlme->olbc) == _TRUE) || (ATOMIC_READ(&mlme->olbc_ht) == _TRUE)) { + /* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */ + mlme->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK); + mlme->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS; + rtw_update_beacon(iface, iface_link, _HT_ADD_INFO_IE_, NULL, _FALSE, 0); + } + #endif + + rtw_update_beacon(iface, iface_link, _TIM_IE_, NULL, _FALSE, 0); + } + +#ifdef CONFIG_DBCC_SUPPORT + _go_dbcc_update_ie(padapter); +#endif + + /* after chanctx_add & before send bcn */ +#ifndef CONFIG_AP_CMD_DISPR + rtw_hw_start_bss_network(padapter); +#endif + + rtw_scan_abort(padapter, 0); + _rtw_iface_undersurvey_chk(__func__, padapter); + + /* send beacon */ +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING) || defined(CONFIG_HWSIM) + for (i = 0; i < pdvobj->iface_nums; i++) { + iface = pdvobj->padapters[i]; + if (!(parm->ifbmp & BIT(i)) || !iface) + continue; + + if (send_beacon(iface) == _FAIL) + RTW_INFO(ADPT_FMT" issue_beacon, fail!\n", ADPT_ARG(pdvobj->padapters[i])); + } +#endif + + if (parm->is_change_chbw) + rtw_phl_cmd_stop_beacon(adapter_to_dvobj(padapter)->phl, padapter_link->wrlink, + _FALSE, PHL_CMD_DIRECTLY, 0); + + +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT + if (MLME_IS_AP(padapter) && padapter->tbtx_capability == _TRUE) { + _set_timer(&pmlmeext->tbtx_token_dispatch_timer, 1); + RTW_INFO("Start token dispatch\n"); + } +#endif +} +void rtw_core_ap_chan_decision(_adapter *padapter, struct createbss_parm *parm) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + bool is_chctx_add = false; + struct rtw_chan_def new_chdef = {0}; + struct rtw_mr_chctx_info mr_cc_info = {0}; + + if (!(parm->req_ch == 0 && padapter->mlmeextpriv.mlmext_info.state == WIFI_FW_AP_STATE)) + return; + +#ifdef CONFIG_DBCC_SUPPORT + _rtw_memcpy(&new_chdef, &pmlmepriv->ori_chandef, sizeof(struct rtw_chan_def)); + +#ifdef CONFIG_DBCC_P2P_BG_LISTEN + /*B0,B1 GO start*/ + rtw_dbcc_chk_disable_hdl(padapter, &new_chdef, PHL_CMD_DIRECTLY, DBCC_CHK_AP_START); +#endif + + is_chctx_add = rtw_phl_chanctx_chk(dvobj->phl, padapter->phl_role, + padapter_link->wrlink, + &new_chdef, &mr_cc_info); + + RTW_INFO("%s => chctx_chk:%s\n", __func__, (is_chctx_add) ? "Y" : "N"); + RTW_INFO("PHL- CH:%d, BW:%d OFF:%d\n", new_chdef.chan, new_chdef.bw, new_chdef.offset); + if (is_chctx_add == false && mr_cc_info.sugg_opmode == MR_OP_DBCC) { + _rtw_memcpy(&pmlmeext->chandef, &pmlmepriv->ori_chandef, sizeof(struct rtw_chan_def)); + rtw_phl_mr_trig_dbcc_enable(dvobj->phl); + parm->is_trigger_dbcc = _TRUE; + } +#endif +} + +void rtw_core_ap_prepare(_adapter *padapter, struct createbss_parm *parm) +{ + u8 mlme_act = MLME_ACTION_UNKNOWN; + u16 bcn_interval; + struct registry_priv *pregpriv = &padapter->registrypriv; + struct security_priv *psecuritypriv = &(padapter->securitypriv); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + s8 req_band = REQ_BAND_NONE; + s16 req_ch = REQ_CH_NONE, req_bw = REQ_BW_NONE, req_offset = REQ_OFFSET_NONE; + struct rtw_chan_def chdef_to_set = {0}; + int i; + u8 ifbmp_ch_changed = 0; +#ifdef CONFIG_MCC_MODE + struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj); + u8 mcc_sup = phl_com->dev_cap.mcc_sup; +#endif + struct rtw_chan_def new_chdef = {0}; + struct rtw_mr_chctx_info mr_cc_info = {0}; + _adapter *iface = NULL; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct _ADAPTER_LINK *iface_link = NULL; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */ + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network); + + RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + + if (parm->req_ch != 0) { + /* bypass other setting, go checking ch, bw, offset */ + mlme_act = MLME_OPCH_SWITCH; + req_band = parm->req_band; + req_ch = parm->req_ch; + req_bw = parm->req_bw; + req_offset = parm->req_offset; + goto chbw_decision; + } else { + /* request comes from upper layer */ + if (MLME_IS_AP(padapter)) + mlme_act = MLME_AP_STARTED; + else if (MLME_IS_MESH(padapter)) + mlme_act = MLME_MESH_STARTED; + else + rtw_warn_on(1); + req_ch = 0; + /* MLD network info copied from adapter->mlmepriv.cur_network */ + _rtw_memcpy(&padapter->mlmeextpriv.mlmext_info.dev_network, + &padapter->mlmepriv.dev_cur_network.network, + padapter->mlmepriv.dev_cur_network.network.Length); + /* Link network info copied from adapter_link->mlmepriv.cur_network */ + _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); + } + + bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod; + pmlmeinfo->bcn_interval = bcn_interval; + + /* check if there is wps ie, */ + /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ + /* and at first time the security ie ( RSN/WPA IE) will not include in beacon. */ + if (NULL == rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL)) + pmlmeext->bstart_bss = _TRUE; + + /* todo: update wmm, ht cap */ + /* pmlmeinfo->WMM_enable; */ + /* pmlmeinfo->HT_enable; */ + if (pmlmepriv->qospriv.qos_option) + pmlmeinfo->WMM_enable = _TRUE; + +#ifdef CONFIG_80211N_HT + if (pmlmepriv->htpriv.ht_option) { + pmlmeinfo->WMM_enable = _TRUE; + pmlmeinfo->HT_enable = _TRUE; + } else + pmlmeinfo->HT_enable = _FALSE; +#endif + +#ifdef CONFIG_80211AC_VHT + if (pmlmepriv->vhtpriv.vht_option) + pmlmeinfo->VHT_enable = _TRUE; + else + pmlmeinfo->VHT_enable = _FALSE; +#endif + +#ifdef CONFIG_80211AX_HE + if (pmlmepriv->hepriv.he_option) + pmlmeinfo->HE_enable = _TRUE; + else + pmlmeinfo->HE_enable = _FALSE; +#endif + + if (pmlmepriv->cur_network.join_res != _TRUE) { /* setting only at first time */ + /* WEP Key will be set before this function, do not clear CAM. */ + if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) + && !MLME_IS_MESH(padapter) /* mesh group key is set before this function */ + ) + flush_all_cam_entry(padapter, PHL_CMD_DIRECTLY, 0); /* clear CAM */ + } + +#ifdef CONFIG_RTW_MULTI_AP + rtw_map_config_monitor(padapter, mlme_act); +#endif + +chbw_decision: + /*SCC && MCC at the same hw band*/ + ifbmp_ch_changed = rtw_ap_bchbw_decision(padapter, parm->ifbmp, parm->excl_ifbmp, req_band + , req_ch, req_bw, req_offset, &chdef_to_set); + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(parm->ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + iface = dvobj->padapters[i]; + + if (!rtw_iface_at_same_hwband(padapter, iface)) + continue; + + /* let pnetwork_mlme == pnetwork_mlmeext */ + /* MLD network info copied from adapter */ + _rtw_memcpy(&(iface->mlmepriv.dev_cur_network.network) + , &(iface->mlmeextpriv.mlmext_info.dev_network) + , iface->mlmeextpriv.mlmext_info.dev_network.Length); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + /* Link network info copied from adapter_link */ + iface_link = GET_PRIMARY_LINK(dvobj->padapters[i]); + _rtw_memcpy(&(iface_link->mlmepriv.cur_network.network) + , &(iface_link->mlmeextpriv.mlmext_info.network) + , iface_link->mlmeextpriv.mlmext_info.network.Length); + + rtw_start_bss_hdl_after_chbw_decided(iface, iface_link); + + /* Set EDCA param reg after update cur_wireless_mode & update_capinfo */ + if (pregpriv->wifi_spec == 1) + rtw_set_hw_wmm_param(iface, iface_link); + + rtw_ap_link_regu_forbid_update(iface_link, false); + } + + new_chdef.band = pmlmeext->chandef.band; + new_chdef.chan = pmlmeext->chandef.chan; + new_chdef.bw = pmlmeext->chandef.bw; + new_chdef.offset = pmlmeext->chandef.offset; + + if (!padapter_link->is_ap_chan_ctx_added) { + /* add chandef first time */ + padapter_link->is_ap_chan_ctx_added = rtw_phl_chanctx_add(dvobj->phl, padapter->phl_role, + padapter_link->wrlink, &new_chdef, &mr_cc_info); + + } else if (parm->is_change_chbw || + padapter_link->wrlink->chandef.band != new_chdef.band || + padapter_link->wrlink->chandef.chan != new_chdef.chan || + padapter_link->wrlink->chandef.bw != new_chdef.bw || + padapter_link->wrlink->chandef.offset != new_chdef.offset) { + /* change chandef */ + rtw_phl_cmd_stop_beacon(dvobj->phl, padapter_link->wrlink, + _TRUE, PHL_CMD_DIRECTLY, 0); + rtw_phl_chanctx_del(dvobj->phl, padapter->phl_role, padapter_link->wrlink, NULL); + padapter_link->is_ap_chan_ctx_added = rtw_phl_chanctx_add(dvobj->phl, padapter->phl_role, + padapter_link->wrlink, &new_chdef, &mr_cc_info); + } else { + /* chandef doesn't change, just get the union chandef */ + rtw_phl_mr_get_chandef(dvobj->phl, padapter->phl_role, padapter_link->wrlink, &new_chdef); + } + + rtw_hw_update_chan_def(padapter, padapter_link); + +#if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ + rtw_dfs_rd_en_dec_on_mlme_act(padapter, padapter_link, mlme_act, parm->excl_ifbmp); +#endif + RTW_INFO("%s: is_ap_chan_ctx_added:%s\n", __func__, (padapter_link->is_ap_chan_ctx_added) ? "Y" : "N"); + RTW_INFO("PHL union_chdef - BAND: %d, CH:%d, BW:%d OFF:%d\n", new_chdef.band, new_chdef.chan, new_chdef.bw, new_chdef.offset); + if (chdef_to_set.chan != new_chdef.chan || chdef_to_set.band != new_chdef.band) { + RTW_INFO("Core - BAND:%d, CH:%d, BW:%d OFF:%d\n", chdef_to_set.band, chdef_to_set.chan, chdef_to_set.bw, chdef_to_set.offset); + RTW_ERR("chan set mismatch!!!\n"); + } + + if (padapter_link->is_ap_chan_ctx_added == false) { + RTW_ERR("%s : rtw_phl_chanctx_add fail\n", __func__); + if (0) + rtw_warn_on(1); + } + +_exit: + parm->ifbmp_ch_changed = ifbmp_ch_changed; + parm->req_band = new_chdef.band; + parm->ch_to_set = new_chdef.chan; + parm->offset_to_set = new_chdef.offset; + parm->bw_to_set = new_chdef.bw; +} + +int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len) +{ + int ret = _SUCCESS; + u8 *p; + u8 *pHT_caps_ie = NULL; + u8 *pHT_info_ie = NULL; + u16 cap, ht_cap = _FALSE; + uint ie_len = 0; + int group_cipher, pairwise_cipher, gmcs; + u32 akm; + u8 mfp_opt = MFP_NO; + u8 channel = 0, network_type; + u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01}; + u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; + u8 WIFI_ALLIANCE_OUI[] = {0x50, 0x6f, 0x9a}; + HT_CAP_AMPDU_DENSITY best_ampdu_density = 0; + struct registry_priv *pregistrypriv = &padapter->registrypriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_security_priv *lsecuritypriv = &padapter_link->securitypriv; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; + u8 *ie = pbss_network->IEs; + u8 vht_cap = _FALSE; + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); + struct rtw_chan_def chandef = {0}; + enum band_type band = BAND_ON_24G; + u8 rf_num = 0; + int ret_rm; + /* SSID */ + /* Supported rates */ + /* DS Params */ + /* WLAN_EID_COUNTRY */ + /* ERP Information element */ + /* Extended supported rates */ + /* WPA/WPA2 */ + /* Radio Resource Management */ + /* Wi-Fi Wireless Multimedia Extensions */ + /* ht_capab, ht_oper */ + /* WPS IE */ + + RTW_INFO("%s, len=%d\n", __FUNCTION__, len); + + if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) + return _FAIL; + + + if (len > MAX_IE_SZ) + return _FAIL; + + pbss_network->IELength = len; + + _rtw_memset(ie, 0, MAX_IE_SZ); + + _rtw_memcpy(ie, pbuf, pbss_network->IELength); + + + if (padapter->mlmepriv.dev_cur_network.network.InfrastructureMode != Ndis802_11APMode + && padapter->mlmepriv.dev_cur_network.network.InfrastructureMode != Ndis802_11_mesh + ) { + rtw_warn_on(1); + return _FAIL; + } + + + rtw_ap_check_scan(padapter, padapter_link); + + + pbss_network->PhyInfo.rssi= 0; + + /* MLD mac address */ + _rtw_memcpy(padapter->mlmepriv.dev_cur_network.network.MacAddress, adapter_mac_addr(padapter), ETH_ALEN); + /* Link mac address */ + _rtw_memcpy(pbss_network->MacAddress, padapter_link->mac_addr, ETH_ALEN); + + /* beacon interval */ + p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; */ /* 8: TimeStamp, 2: Beacon Interval 2:Capability */ + /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */ + pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p); + + /* capability */ + p = rtw_get_capability_from_ie(ie); + cap = RTW_GET_LE16(p); + + /* SSID */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID)); + _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len); + pbss_network->Ssid.SsidLength = ie_len; + } + +#ifdef CONFIG_RTW_MESH + /* Mesh ID */ + if (MLME_IS_MESH(padapter)) { + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_MESH_ID, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + _rtw_memset(&pbss_network->mesh_id, 0, sizeof(NDIS_802_11_SSID)); + _rtw_memcpy(pbss_network->mesh_id.Ssid, (p + 2), ie_len); + pbss_network->mesh_id.SsidLength = ie_len; + } + } +#endif + + /* Parsing extended capabilities IE */ + rtw_parse_ext_cap_ie(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), ie \ + , pbss_network->IELength, _BEACON_IE_OFFSET_); + + /* channel and band */ + rtw_ies_get_bchbw(ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_, + &chandef.band, &chandef.chan, (u8 *)&chandef.bw, (u8 *)&chandef.offset, + (u8 *)&chandef.center_freq1, (u8 *)&chandef.center_freq2, 1, 1, 1); + + if (chandef.chan != 0) { + pbss_network->Configuration.Band = band = chandef.band; + pbss_network->Configuration.DSConfig = channel = chandef.chan; + } + + if (pbss_network->Configuration.Band == BAND_ON_6G) + /* DSSET uses in 2.4G and 5G band; Remove DSSET when using 6G band */ + rtw_remove_bcn_ie(padapter, pbss_network, _DSSET_IE_); + + /* support rate ie & ext support ie & IElen & SupportedRates */ + network_type = rtw_update_rate_bymode(pbss_network, pregistrypriv->wireless_mode); + + /* parsing ERP_IE */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + if(pregistrypriv->wireless_mode == WLAN_MD_11B) + { + pbss_network->IELength = pbss_network->IELength - *(p+1) - 2; + ret_rm = rtw_ies_remove_ie(ie , &len, _BEACON_IE_OFFSET_, _ERPINFO_IE_,NULL,0); + RTW_DBG("%s, remove_ie of ERP_IE=%d\n", __FUNCTION__, ret_rm); + } else + ERP_IE_handler(padapter, padapter_link, (PNDIS_802_11_VARIABLE_IEs)p); + + } + + /* update privacy/security */ + if (cap & BIT(4)) + pbss_network->Privacy = 1; + else + pbss_network->Privacy = 0; + + psecuritypriv->wpa_psk = 0; + + /* wpa2 */ + akm = 0; + gmcs = 0; + group_cipher = 0; + pairwise_cipher = 0; + psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; + psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; + psecuritypriv->akmp = 0; + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, &akm, &mfp_opt, NULL) == _SUCCESS) { + psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; + psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ + psecuritypriv->wpa_psk |= BIT(1); + + psecuritypriv->wpa2_group_cipher = group_cipher; + psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; + psecuritypriv->akmp = akm; + +#ifdef CONFIG_IOCTL_CFG80211 + /** + * Kernel < v5.x, the auth_type set as + * NL80211_AUTHTYPE_AUTOMATIC in + * cfg80211_rtw_start_ap(). if the AKM SAE in the RSN + * IE, we have to update the auth_type for SAE in + * rtw_check_beacon_data() + */ + if (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) { + RTW_INFO("%s: Auth type as SAE\n", __func__); + psecuritypriv->auth_type = MLME_AUTHTYPE_SAE; + psecuritypriv->auth_alg = WLAN_AUTH_SAE; + } +#endif /* CONFIG_IOCTL_CFG80211 */ +#if 0 + switch (group_cipher) { + case WPA_CIPHER_NONE: + psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; + break; + case WPA_CIPHER_WEP40: + psecuritypriv->wpa2_group_cipher = _WEP40_; + break; + case WPA_CIPHER_TKIP: + psecuritypriv->wpa2_group_cipher = _TKIP_; + break; + case WPA_CIPHER_CCMP: + psecuritypriv->wpa2_group_cipher = _AES_; + break; + case WPA_CIPHER_WEP104: + psecuritypriv->wpa2_group_cipher = _WEP104_; + break; + } + + switch (pairwise_cipher) { + case WPA_CIPHER_NONE: + psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; + break; + case WPA_CIPHER_WEP40: + psecuritypriv->wpa2_pairwise_cipher = _WEP40_; + break; + case WPA_CIPHER_TKIP: + psecuritypriv->wpa2_pairwise_cipher = _TKIP_; + break; + case WPA_CIPHER_CCMP: + psecuritypriv->wpa2_pairwise_cipher = _AES_; + break; + case WPA_CIPHER_WEP104: + psecuritypriv->wpa2_pairwise_cipher = _WEP104_; + break; + } +#endif + } + + } + + /* wpa */ + ie_len = 0; + group_cipher = 0; + pairwise_cipher = 0; + psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; + psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; + for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { + p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); + if ((p) && (_rtw_memcmp(p + 2, OUI1, 4))) { + if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; + psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ + + psecuritypriv->wpa_psk |= BIT(0); + + psecuritypriv->wpa_group_cipher = group_cipher; + psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; + +#if 0 + switch (group_cipher) { + case WPA_CIPHER_NONE: + psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; + break; + case WPA_CIPHER_WEP40: + psecuritypriv->wpa_group_cipher = _WEP40_; + break; + case WPA_CIPHER_TKIP: + psecuritypriv->wpa_group_cipher = _TKIP_; + break; + case WPA_CIPHER_CCMP: + psecuritypriv->wpa_group_cipher = _AES_; + break; + case WPA_CIPHER_WEP104: + psecuritypriv->wpa_group_cipher = _WEP104_; + break; + } + + switch (pairwise_cipher) { + case WPA_CIPHER_NONE: + psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; + break; + case WPA_CIPHER_WEP40: + psecuritypriv->wpa_pairwise_cipher = _WEP40_; + break; + case WPA_CIPHER_TKIP: + psecuritypriv->wpa_pairwise_cipher = _TKIP_; + break; + case WPA_CIPHER_CCMP: + psecuritypriv->wpa_pairwise_cipher = _AES_; + break; + case WPA_CIPHER_WEP104: + psecuritypriv->wpa_pairwise_cipher = _WEP104_; + break; + } +#endif + } + + break; + + } + + if ((p == NULL) || (ie_len == 0)) + break; + + } + + if (mfp_opt == MFP_INVALID) { + RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter)); + return _FAIL; + } + psecuritypriv->mfp_opt = mfp_opt; + +#ifdef CONFIG_RTW_80211K + rm_update_cap(pbuf, padapter, len, _BEACON_IE_OFFSET_); +#endif +#ifdef CONFIG_RTW_FSM_RRM + rrm_update_cap(pbuf, padapter, len, _BEACON_IE_OFFSET_); +#endif + /* wmm */ + ie_len = 0; + pmlmepriv->qospriv.qos_option = 0; +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) + pmlmepriv->qospriv.qos_option = 1; +#endif + if (pregistrypriv->wmm_enable) { + for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { + p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); + if ((p) && _rtw_memcmp(p + 2, WMM_PARA_IE, 6)) { + pmlmepriv->qospriv.qos_option = 1; + + *(p + 8) |= BIT(7); /* QoS Info, support U-APSD */ + + /* disable all ACM bits since the WMM admission control is not supported */ + *(p + 10) &= ~BIT(4); /* BE */ + *(p + 14) &= ~BIT(4); /* BK */ + *(p + 18) &= ~BIT(4); /* VI */ + *(p + 22) &= ~BIT(4); /* VO */ + + WMM_param_handler(padapter, padapter_link, + (PNDIS_802_11_VARIABLE_IEs)p); + + break; + } + + if ((p == NULL) || (ie_len == 0)) + break; + } + } +#ifdef CONFIG_80211N_HT + if(pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode)) + { + /* parsing HT_CAP_IE */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor = MAX_AMPDU_FACTOR_64K; + struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); + + if (0) { + RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter)); + dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len); + } + + pHT_caps_ie = p; + + ht_cap = _TRUE; + network_type |= WLAN_MD_11N; + + rtw_ht_use_default_setting(padapter, padapter_link); + + /* Update HT Capabilities Info field */ + if (pmlmepriv->htpriv.sgi_20m == _FALSE) + pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20); + + if (pmlmepriv->htpriv.sgi_40m == _FALSE) + pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40); + + if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX)) + pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING); + + if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX)) + pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC); + + if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX)) + pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R); + + /* Update A-MPDU Parameters field */ + pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY); + + if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || + (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { + rtw_hal_get_def_var(padapter, padapter_link, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2)); + } else + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); + + rtw_hal_get_def_var(padapter, padapter_link, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); /* set Max Rx AMPDU size to 64K */ + + _rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element)); + + /* Update Supported MCS Set field */ + { + u8 rx_nss = 0; + int i; + + rx_nss = get_phy_rx_nss(padapter, padapter_link); + + /* RX MCS Bitmask */ + switch (rx_nss) { + case 1: + set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R); + break; + case 2: + set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R); + break; + case 3: + set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R); + break; + case 4: + set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_4R); + break; + default: + RTW_WARN("rf_type:%d or rx_nss:%u is not expected\n", + GET_HAL_RFPATH(adapter_to_dvobj(padapter)), rx_nss); + } + for (i = 0; i < 10; i++) + *(HT_CAP_ELE_RX_MCS_MAP(pht_cap) + i) &= pmlmeext->default_supported_mcs_set[i]; + } + +#ifdef CONFIG_BEAMFORMING + /* Use registry value to enable HT Beamforming. */ + /* ToDo: use configure file to set these capability. */ + pht_cap->tx_BF_cap_info = 0; + + /* HT Beamformer */ + if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) { + /* Transmit NDP Capable */ + SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1); + /* Explicit Compressed Steering Capable */ + SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1); + /* Compressed Steering Number Antennas */ + SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1); + rtw_hal_get_def_var(padapter, padapter_link, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num); + if (rf_num > 3) + rf_num = 3; + SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num); + } + + /* HT Beamformee */ + if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) { + /* Receive NDP Capable */ + SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1); + /* Explicit Compressed Beamforming Feedback Capable */ + SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2); + rtw_hal_get_def_var(padapter, padapter_link, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num); + if (rf_num > 3) + rf_num = 3; + SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num); + } +#endif /* CONFIG_BEAMFORMING */ + + _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); + + if (0) { + RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter)); + dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len); + } + } + + /* parsing HT_INFO_IE */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) { + pHT_info_ie = p; + if (channel == 0) + pbss_network->Configuration.DSConfig = GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2); + else if (channel != GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)) { + RTW_INFO(FUNC_ADPT_FMT" ch inconsistent, DSSS:%u, HT primary:%u\n" + , FUNC_ADPT_ARG(padapter), channel, GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)); + } + } + } +#endif /* CONFIG_80211N_HT */ + pmlmepriv->cur_network.network_type = network_type; + +#ifdef CONFIG_80211N_HT + pmlmepriv->htpriv.ht_option = _FALSE; + + if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || + (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { + /* todo: */ + /* ht_cap = _FALSE; */ + } + + /* ht_cap */ + if (pregistrypriv->ht_enable && + is_supported_ht(pregistrypriv->wireless_mode) && ht_cap == _TRUE && + (pbss_network->Configuration.Band == BAND_ON_24G || + pbss_network->Configuration.Band == BAND_ON_5G)) { + + pmlmepriv->htpriv.ht_option = _TRUE; + pmlmepriv->qospriv.qos_option = 1; + + pmlmepriv->ampdu_priv.ampdu_enable = pregistrypriv->ampdu_enable ? _TRUE : _FALSE; + + HT_caps_handler(padapter, padapter_link, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie); + + HT_info_handler(padapter, padapter_link, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie); + } +#endif + + pmlmepriv->upper_layer_setting = _FALSE; + +#ifdef CONFIG_80211AC_VHT + pmlmepriv->vhtpriv.vht_option = _FALSE; + + if (pmlmepriv->htpriv.ht_option == _TRUE + && pbss_network->Configuration.Band == BAND_ON_5G + && REGSTY_IS_11AC_ENABLE(pregistrypriv) + && is_supported_vht(pregistrypriv->wireless_mode) + && RFCTL_REG_EN_11AC(rfctl)) { + /* Parsing VHT_CAP_IE */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_VHT_CAPABILITY, + &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len > 0) + vht_cap = _TRUE; + else + RTW_INFO(FUNC_ADPT_FMT" No vht_capability_ie from hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter)); + + /* Update VHT related IEs */ + if (vht_cap == _TRUE) { + RTW_INFO(FUNC_ADPT_FMT" VHT IEs is configured by hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter)); + pmlmepriv->upper_layer_setting = _TRUE; + pmlmepriv->vhtpriv.vht_option = _TRUE; + + rtw_check_for_vht20(padapter, ie + _BEACON_IE_OFFSET_, + pbss_network->IELength - _BEACON_IE_OFFSET_); + rtw_check_vht_ies(padapter, padapter_link, pbss_network); + } + else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) { + rtw_vht_ies_detach(padapter, padapter_link, pbss_network); + rtw_vht_ies_attach(padapter, padapter_link, pbss_network); + } + } + + if (pmlmepriv->vhtpriv.vht_option == _FALSE) + rtw_vht_ies_detach(padapter, padapter_link, pbss_network); +#endif /* CONFIG_80211AC_VHT */ + +#ifdef CONFIG_80211AX_HE + pmlmepriv->hepriv.he_option = _FALSE; + + /* An HE STA is also a VHT STA if operating in the 5 GHz band */ + /* An HE STA is also a HT STA in the 2GHz band */ + + if (REGSTY_IS_11AX_ENABLE(pregistrypriv) + && is_supported_he(pregistrypriv->wireless_mode) + && RFCTL_REG_EN_11AX(rfctl) + && ((band == BAND_ON_5G && pmlmepriv->vhtpriv.vht_option == _TRUE) + || (band == BAND_ON_24G && pmlmepriv->htpriv.ht_option == _TRUE) + || (band == BAND_ON_6G))) { + u8 he_cap = _FALSE; + u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY; + + p = rtw_get_ie_ex(ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_, + WLAN_EID_EXTENSION, &he_cap_eid_ext, 1, NULL, &ie_len); + if (p && ie_len > 0) + he_cap = _TRUE; + + /* If He capability is in beacon IE, enable he_option */ + pmlmepriv->hepriv.he_option = he_cap; + + /* Update HE related IEs */ + if (he_cap == _TRUE) { + RTW_INFO(FUNC_ADPT_FMT" HE IEs is configured by hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter)); + pmlmepriv->upper_layer_setting = _TRUE; + + rtw_update_he_ies(padapter, padapter_link, pbss_network, &chandef); + } else if (REGSTY_IS_11AX_AUTO(pregistrypriv)) { + rtw_he_ies_detach(padapter, padapter_link, pbss_network); + rtw_he_ies_attach(padapter, padapter_link, pbss_network, band); + } + } + if (pmlmepriv->hepriv.he_option == _FALSE) + rtw_he_ies_detach(padapter, padapter_link, pbss_network); +#endif + +#ifdef CONFIG_80211BE_EHT + padapter->mlmepriv.mlopriv.mlo_option = _FALSE; + /* ToDo CONFIG_RTW_MLD: check if hostapd will provide hints to enable mlo */ +#ifdef CONFIG_MLD_TEST + padapter->mlmepriv.mlopriv.mlo_option = _TRUE; +#endif +#endif + +#ifdef CONFIG_80211N_HT + if(pregistrypriv->ht_enable && is_supported_ht(pregistrypriv->wireless_mode) + && pbss_network->Configuration.DSConfig <= 14 /*&& padapter->registrypriv.wifi_spec == 1*/) + { + #ifdef CONFIG_RTW_WNM + rtw_wnm_add_btm_ext_cap(pmlmepriv->ext_capab_ie_data, + &(pmlmepriv->ext_capab_ie_len)); + #endif + #ifdef CONFIG_RTW_MBO + rtw_mbo_add_internw_ext_cap(pmlmepriv->ext_capab_ie_data, + &(pmlmepriv->ext_capab_ie_len)); + #endif + rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), BSS_COEXT); + rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pbss_network->IEs, \ + &(pbss_network->IELength), _BEACON_IE_OFFSET_); + } +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_RTW_80211K + padapter->rmpriv.enable = _FALSE; + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_RMEnabledCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len) { + RTW_INFO("[%s]Get EID_RMEnabledCapability, len = %d\n", __func__, ie_len); + padapter->rmpriv.enable = _TRUE; + _rtw_memcpy(padapter->rmpriv.rm_en_cap_def, p + 2, ie_len); + } +#endif /* CONFIG_RTW_80211K */ + +#ifdef CONFIG_RTW_FSM_RRM + padapter->fsmpriv.rmpriv.enable = _FALSE; + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_RMEnabledCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len) { + RTW_INFO("[%s]Get EID_RMEnabledCapability, len = %d\n", __func__, ie_len); + padapter->fsmpriv.rmpriv.enable = _TRUE; + _rtw_memcpy(padapter->fsmpriv.rmpriv.rm_en_cap_def, p + 2, ie_len); + } +#endif /* CONFIG_RTW_FSM_RRM */ + +#ifdef CONFIG_RTW_MBO + ie_len = 0; + padapter->mlmepriv.mbopriv.enable = _FALSE; + for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { + p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); + if ((p) && (_rtw_memcmp(p + 2, WIFI_ALLIANCE_OUI, 3)) && (*(p+5) == MBO_OUI_TYPE)) { + /* find MBO-OCE information element */ + padapter->mlmepriv.mbopriv.enable = _TRUE; + rtw_mbo_ie_handler(padapter, &padapter->mlmepriv.mbopriv, p + 6, ie_len - 4); + break; + } + if ((p == NULL) || (ie_len == 0)) + break; + } +#endif /* CONFIG_RTW_MBO */ + + /* Build supported operating class element if ECSA enabled*/ +#ifdef CONFIG_ECSA_PHL + if (rtw_is_ecsa_enabled(padapter)) { + u8 buf[32]; + ie_len = get_supported_op_class(padapter, buf, sizeof(buf)); + rtw_add_bcn_ie(padapter, pbss_network, WLAN_EID_SUPPORT_OP_CLASS, + buf, ie_len); + + rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, + &(pmlmepriv->ext_capab_ie_len), EXT_CH_SWITCH); + rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, + pmlmepriv->ext_capab_ie_len, pbss_network->IEs, + &(pbss_network->IELength), _BEACON_IE_OFFSET_); + } +#endif + + pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network); + + rtw_ies_get_bchbw(pbss_network->IEs + _BEACON_IE_OFFSET_, + pbss_network->IELength - _BEACON_IE_OFFSET_, + &pmlmepriv->ori_chandef.band, + &pmlmepriv->ori_chandef.chan, + (u8 *)&pmlmepriv->ori_chandef.bw, + (u8 *)&pmlmepriv->ori_chandef.offset, + (u8 *)&pmlmepriv->ori_chandef.center_freq1, + (u8 *)&pmlmepriv->ori_chandef.center_freq2, + 1, 1, 1); + + rtw_warn_on(pmlmepriv->ori_chandef.chan == 0); + + ret = rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK); + if (ret == _FAIL) + RTW_ERR("%s: start bss cm fail\n", __func__); + + { + int sk_band = RTW_GET_SCAN_BAND_SKIP(padapter); + + if (sk_band) + RTW_CLR_SCAN_BAND_SKIP(padapter, sk_band); + } + + return ret; + +} + +#if CONFIG_RTW_MACADDR_ACL +void rtw_macaddr_acl_init(_adapter *adapter, u8 period) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct wlan_acl_pool *acl; + _queue *acl_node_q; + int i; + + if (period >= RTW_ACL_PERIOD_NUM) { + rtw_warn_on(1); + return; + } + + acl = &stapriv->acl_list[period]; + acl_node_q = &acl->acl_node_q; + + _rtw_spinlock_init(&(acl_node_q->lock)); + + _rtw_spinlock_bh(&(acl_node_q->lock)); + _rtw_init_listhead(&(acl_node_q->queue)); + acl->num = 0; + acl->mode = RTW_ACL_MODE_DISABLED; + for (i = 0; i < NUM_ACL; i++) { + _rtw_init_listhead(&acl->aclnode[i].list); + acl->aclnode[i].valid = _FALSE; + } + _rtw_spinunlock_bh(&(acl_node_q->lock)); +} + +static void _rtw_macaddr_acl_deinit(_adapter *adapter, u8 period, bool clear_only) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct wlan_acl_pool *acl; + _queue *acl_node_q; + _list *head, *list; + struct rtw_wlan_acl_node *acl_node; + + if (period >= RTW_ACL_PERIOD_NUM) { + rtw_warn_on(1); + return; + } + + acl = &stapriv->acl_list[period]; + acl_node_q = &acl->acl_node_q; + + _rtw_spinlock_bh(&(acl_node_q->lock)); + head = get_list_head(acl_node_q); + list = get_next(head); + while (rtw_end_of_queue_search(head, list) == _FALSE) { + acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); + list = get_next(list); + + if (acl_node->valid == _TRUE) { + acl_node->valid = _FALSE; + rtw_list_delete(&acl_node->list); + acl->num--; + } + } + _rtw_spinunlock_bh(&(acl_node_q->lock)); + + if (!clear_only) + _rtw_spinlock_free(&(acl_node_q->lock)); + + rtw_warn_on(acl->num); + acl->mode = RTW_ACL_MODE_DISABLED; +} + +void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period) +{ + _rtw_macaddr_acl_deinit(adapter, period, 0); +} + +void rtw_macaddr_acl_clear(_adapter *adapter, u8 period) +{ + _rtw_macaddr_acl_deinit(adapter, period, 1); +} + +void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct wlan_acl_pool *acl; + + if (period >= RTW_ACL_PERIOD_NUM) { + rtw_warn_on(1); + return; + } + + acl = &stapriv->acl_list[period]; + + RTW_INFO(FUNC_ADPT_FMT" p=%u, mode=%d\n" + , FUNC_ADPT_ARG(adapter), period, mode); + + acl->mode = mode; +} + +int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr) +{ + _list *list, *head; + u8 existed = 0; + int i = -1, ret = 0; + struct rtw_wlan_acl_node *acl_node; + struct sta_priv *stapriv = &adapter->stapriv; + struct wlan_acl_pool *acl; + _queue *acl_node_q; + + if (period >= RTW_ACL_PERIOD_NUM) { + rtw_warn_on(1); + ret = -1; + goto exit; + } + + acl = &stapriv->acl_list[period]; + acl_node_q = &acl->acl_node_q; + + _rtw_spinlock_bh(&(acl_node_q->lock)); + + head = get_list_head(acl_node_q); + list = get_next(head); + + /* search for existed entry */ + while (rtw_end_of_queue_search(head, list) == _FALSE) { + acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); + list = get_next(list); + + if (_rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) { + if (acl_node->valid == _TRUE) { + existed = 1; + break; + } + } + } + if (existed) + goto release_lock; + + if (acl->num >= NUM_ACL) + goto release_lock; + + /* find empty one and use */ + for (i = 0; i < NUM_ACL; i++) { + + acl_node = &acl->aclnode[i]; + if (acl_node->valid == _FALSE) { + + _rtw_init_listhead(&acl_node->list); + _rtw_memcpy(acl_node->addr, addr, ETH_ALEN); + acl_node->valid = _TRUE; + + rtw_list_insert_tail(&acl_node->list, get_list_head(acl_node_q)); + acl->num++; + break; + } + } + +release_lock: + _rtw_spinunlock_bh(&(acl_node_q->lock)); + + if (!existed && (i < 0 || i >= NUM_ACL)) + ret = -1; + + RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n" + , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr) + , (existed ? "existed" : ((i < 0 || i >= NUM_ACL) ? "no room" : "added")) + , acl->num); +exit: + return ret; +} + +int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr) +{ + _list *list, *head; + int ret = 0; + struct rtw_wlan_acl_node *acl_node; + struct sta_priv *stapriv = &adapter->stapriv; + struct wlan_acl_pool *acl; + _queue *acl_node_q; + u8 is_baddr = is_broadcast_mac_addr(addr); + u8 match = 0; + + if (period >= RTW_ACL_PERIOD_NUM) { + rtw_warn_on(1); + goto exit; + } + + acl = &stapriv->acl_list[period]; + acl_node_q = &acl->acl_node_q; + + _rtw_spinlock_bh(&(acl_node_q->lock)); + + head = get_list_head(acl_node_q); + list = get_next(head); + + while (rtw_end_of_queue_search(head, list) == _FALSE) { + acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); + list = get_next(list); + + if (is_baddr || _rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) { + if (acl_node->valid == _TRUE) { + acl_node->valid = _FALSE; + rtw_list_delete(&acl_node->list); + acl->num--; + match = 1; + } + } + } + + _rtw_spinunlock_bh(&(acl_node_q->lock)); + + RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n" + , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr) + , is_baddr ? "clear all" : (match ? "match" : "no found") + , acl->num); + +exit: + return ret; +} +#endif /* CONFIG_RTW_MACADDR_ACL */ +#ifdef CONFIG_CMD_DISP +u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk) +{ + struct set_stakey_parm param; + u8 res = _SUCCESS; + + _rtw_memcpy(param.addr, addr, ETH_ALEN); + param.algorithm = alg; + param.keyid = keyid; + if (!!(alg & _SEC_TYPE_256_)) + _rtw_memcpy(param.key, key, 32); + else + _rtw_memcpy(param.key, key, 16); + param.gk = gk; + + set_stakey_hdl(adapter, ¶m, PHL_CMD_NO_WAIT, 0); +exit: + return res; +} + +u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta) +{ + return rtw_ap_set_sta_key(padapter + , psta->phl_sta->mac_addr + , psta->dot118021XPrivacy + , psta->dot118021x_UncstKey.skey + , 0 + , 0 + ); +} + +static int rtw_ap_set_key(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *key, u8 alg, int keyid, u8 set_tx) +{ + u8 keylen; + struct setkey_parm setkeyparm; + int res = _SUCCESS; + + /* RTW_INFO("%s\n", __FUNCTION__); */ + + _rtw_memset(&setkeyparm, 0, sizeof(struct setkey_parm)); + + setkeyparm.keyid = (u8)keyid; + if (is_wep_enc(alg)) + padapter->securitypriv.key_mask |= BIT(setkeyparm.keyid); + + setkeyparm.algorithm = alg; + + setkeyparm.set_tx = set_tx; + + switch (alg) { + case _WEP40_: + keylen = 5; + break; + case _WEP104_: + keylen = 13; + break; + case _GCMP_256_: + case _CCMP_256_: + keylen = 32; + break; + case _TKIP_: + case _TKIP_WTMIC_: + case _AES_: + case _GCMP_: + #ifdef CONFIG_IEEE80211W + case _BIP_CMAC_128_: + #endif + default: + keylen = 16; + } + + _rtw_memcpy(&(setkeyparm.key[0]), key, keylen); + setkey_hdl(padapter, padapter_link, &setkeyparm, PHL_CMD_NO_WAIT, 0); + +exit: + return res; +} +#else /* CONFIG_FSM */ +u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk) +{ + struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct cmd_obj *cmd; + struct set_stakey_parm *param; + u8 res = _SUCCESS; + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = adapter; + + param = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); + if (param == NULL) { + rtw_mfree((u8 *) cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + init_h2fwcmd_w_parm_no_rsp(cmd, param, CMD_SET_STAKEY); + + _rtw_memcpy(param->addr, addr, ETH_ALEN); + param->algorithm = alg; + param->keyid = keyid; + if (!!(alg & _SEC_TYPE_256_)) + _rtw_memcpy(param->key, key, 32); + else + _rtw_memcpy(param->key, key, 16); + param->gk = gk; + + res = rtw_enqueue_cmd(cmdpriv, cmd); + +exit: + return res; +} + +u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta) +{ + return rtw_ap_set_sta_key(padapter + , psta->phl_sta->mac_addr + , psta->dot118021XPrivacy + , psta->dot118021x_UncstKey.skey + , 0 + , 0 + ); +} + +static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx) +{ + u8 keylen; + struct cmd_obj *pcmd; + struct setkey_parm *psetkeyparm; + struct cmd_priv *pcmdpriv = &(adapter_to_dvobj(padapter)->cmdpriv); + int res = _SUCCESS; + + /* RTW_INFO("%s\n", __FUNCTION__); */ + + pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmd == NULL) { + res = _FAIL; + goto exit; + } + pcmd->padapter = padapter; + + psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm)); + if (psetkeyparm == NULL) { + rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + + psetkeyparm->keyid = (u8)keyid; + if (is_wep_enc(alg)) + padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid); + + psetkeyparm->algorithm = alg; + + psetkeyparm->set_tx = set_tx; + + switch (alg) { + case _WEP40_: + keylen = 5; + break; + case _WEP104_: + keylen = 13; + break; + case _GCMP_256_: + case _CCMP_256_: + keylen = 32; + break; + case _TKIP_: + case _TKIP_WTMIC_: + case _AES_: + case _GCMP_: + #ifdef CONFIG_IEEE80211W + case _BIP_CMAC_128_: + #endif + default: + keylen = 16; + } + + _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen); + + init_h2fwcmd_w_parm_no_rsp(pcmd, psetkeyparm, CMD_SET_KEY); + + res = rtw_enqueue_cmd(pcmdpriv, pcmd); + +exit: + + return res; +} +#endif +int rtw_ap_set_group_key(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *key, u8 alg, int keyid) +{ + RTW_INFO("%s\n", __FUNCTION__); + + return rtw_ap_set_key(padapter, padapter_link, key, alg, keyid, 1); +} + +int rtw_ap_set_wep_key(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *key, u8 keylen, int keyid, u8 set_tx) +{ + u8 alg; + + switch (keylen) { + case 5: + alg = _WEP40_; + break; + case 13: + alg = _WEP104_; + break; + default: + alg = _NO_PRIVACY_; + } + + RTW_INFO("%s\n", __FUNCTION__); + + return rtw_ap_set_key(padapter, padapter_link, key, alg, keyid, set_tx); +} + +#if 0 +u8 rtw_ap_bmc_frames_hdl(_adapter *padapter) +{ +#define HIQ_XMIT_COUNTS (6) + struct sta_info *psta_bmc; + _list *xmitframe_plist, *xmitframe_phead; + struct xmit_frame *pxmitframe = NULL; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct sta_priv *pstapriv = &padapter->stapriv; + bool update_tim = _FALSE; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + + if (padapter->registrypriv.wifi_spec != 1) + return H2C_SUCCESS; + + + psta_bmc = rtw_get_bcmc_stainfo(padapter, padapter_link); + if (!psta_bmc) + return H2C_SUCCESS; + + + _rtw_spinlock_bh(&pxmitpriv->lock); + + if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) { + int tx_counts = 0; + + _update_beacon(padapter, padapter_link, _TIM_IE_, NULL, _FALSE, 0, "update TIM with TIB=1"); + + RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len); + + xmitframe_phead = get_list_head(&psta_bmc->sleep_q); + xmitframe_plist = get_next(xmitframe_phead); + + while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) { + pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); + + xmitframe_plist = get_next(xmitframe_plist); + + rtw_list_delete(&pxmitframe->list); + + psta_bmc->sleepq_len--; + tx_counts++; + + if (psta_bmc->sleepq_len > 0) + pxmitframe->attrib.mdata = 1; + else + pxmitframe->attrib.mdata = 0; + + if (tx_counts == HIQ_XMIT_COUNTS) + pxmitframe->attrib.mdata = 0; + + pxmitframe->attrib.triggered = 1; + #if 0 + if (xmitframe_hiq_filter(pxmitframe) == _TRUE) + pxmitframe->attrib.qsel = rtw_hal_get_qsel(padapter,QSLT_HIGH_ID);/*HIQ*/ + #endif + + rtw_intf_xmitframe_enqueue(padapter, pxmitframe); + + if (tx_counts == HIQ_XMIT_COUNTS) + break; + + } + + } else { + if (psta_bmc->sleepq_len == 0) { + + /*RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/ + + if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) + update_tim = _TRUE; + + rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0); + rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0); + + if (update_tim == _TRUE) { + RTW_INFO("clear TIB\n"); + _update_beacon(padapter, padapter_link, _TIM_IE_, NULL, _TRUE, 0, "bmc sleepq and HIQ empty"); + } + } + } + + _rtw_spinunlock_bh(&pxmitpriv->lock); + +#if 0 + /* HIQ Check */ + rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); + + while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000) { + rtw_msleep_os(100); + rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); + } + + + printk("check if hiq empty=%d\n", empty); +#endif + + return H2C_SUCCESS; +} +#endif + +#ifdef CONFIG_NATIVEAP_MLME + +static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type) +{ + struct link_mlme_priv *pmlmepriv = &(psta->padapter_link->mlmepriv); + + RTW_INFO("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->phl_sta->mac_addr), sta_info_type); +#ifdef CONFIG_80211N_HT + if (sta_info_type & STA_INFO_UPDATE_BW) { + + if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) { + if ((pmlmepriv->sw_to_20mhz && psta->phl_sta->chandef.bw != CHANNEL_WIDTH_20) + || (!pmlmepriv->sw_to_20mhz && psta->phl_sta->chandef.bw == CHANNEL_WIDTH_20) + ) { + update_sta_bw_apmode(padapter, psta); + rtw_sta_hal_ra_mask_update_cmd(padapter, psta, 0); + } + } + } +#endif /* CONFIG_80211N_HT */ + /* + if (sta_info_type & STA_INFO_UPDATE_RATE) { + + } + */ + + if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE) + VCS_update(padapter, psta); + + /* + if (sta_info_type & STA_INFO_UPDATE_CAP) { + + } + + if (sta_info_type & STA_INFO_UPDATE_HT_CAP) { + + } + + if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) { + + } + */ + +} + +static void update_bcn_erpinfo_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network); + unsigned char *p, *ie = pnetwork->IEs; + u32 len = 0; + + RTW_INFO("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable); + + if (!pmlmeinfo->ERP_enable) + return; + + /* parsing ERP_IE */ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); + if (p && len > 0) { + PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p; + + if (pmlmepriv->num_sta_non_erp == 1) + pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; + else + pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION); + + if (pmlmepriv->num_sta_no_short_preamble > 0) + pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE; + else + pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE); + + ERP_IE_handler(padapter, padapter_link, pIE); + } + +} + +static void update_bcn_htcap_ie(_adapter *padapter) +{ + RTW_INFO("%s\n", __FUNCTION__); + +} + +static void update_bcn_htinfo_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ +#ifdef CONFIG_80211N_HT + /* + u8 beacon_updated = _FALSE; + u32 sta_info_update_type = STA_INFO_UPDATE_NONE; + */ + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network); + unsigned char *p, *ie = pnetwork->IEs; + u32 len = 0; + + if (pmlmepriv->htpriv.ht_option == _FALSE) + return; + + if (pmlmeinfo->HT_info_enable != 1) + return; + + + RTW_INFO("%s current operation mode=0x%X\n", + __FUNCTION__, pmlmepriv->ht_op_mode); + + RTW_INFO("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n", + pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, ATOMIC_READ(&pmlmepriv->olbc)); + + /*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/ + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); + if (p && len > 0) { + struct HT_info_element *pht_info = NULL; + + pht_info = (struct HT_info_element *)(p + 2); + + /* for STA Channel Width/Secondary Channel Offset*/ + if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->chandef.chan <= 14)) { + if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE) + || (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (ATOMIC_READ(&pmlmepriv->olbc) == _TRUE)) { + SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0); + SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0); + + pmlmepriv->sw_to_20mhz = 1; + /* + sta_info_update_type |= STA_INFO_UPDATE_BW; + beacon_updated = _TRUE; + */ + + RTW_INFO("%s:switching to 20Mhz\n", __FUNCTION__); + + /*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/ + } + } else { + + if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE) + && (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (ATOMIC_READ(&pmlmepriv->olbc) == _FALSE)) { + + if (pmlmeext->chandef.bw >= CHANNEL_WIDTH_40) { + + SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1); + + SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, + (pmlmeext->chandef.offset == CHAN_OFFSET_UPPER) ? + HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW); + + pmlmepriv->sw_to_20mhz = 0; + /* + sta_info_update_type |= STA_INFO_UPDATE_BW; + beacon_updated = _TRUE; + */ + + RTW_INFO("%s:switching back to 40Mhz\n", __FUNCTION__); + } + } + } + + /* to update ht_op_mode*/ + *(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode); + + } + + /*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/ +#endif /* CONFIG_80211N_HT */ +} + +static void update_bcn_rsn_ie(_adapter *padapter) +{ + RTW_INFO("%s\n", __FUNCTION__); + +} + +static void update_bcn_wpa_ie(_adapter *padapter) +{ + RTW_INFO("%s\n", __FUNCTION__); + +} + +static void update_bcn_wmm_ie(_adapter *padapter) +{ + RTW_INFO("%s\n", __FUNCTION__); + +} + +static void update_bcn_wps_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL; + uint wps_ielen = 0, wps_offset, remainder_ielen; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network); + unsigned char *ie = pnetwork->IEs; + u32 ielen = pnetwork->IELength; + + + RTW_INFO("%s\n", __FUNCTION__); + + pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen); + + if (pwps_ie == NULL || wps_ielen == 0) + return; + + pwps_ie_src = pmlmepriv->wps_beacon_ie; + if (pwps_ie_src == NULL) + return; + + wps_offset = (uint)(pwps_ie - ie); + + premainder_ie = pwps_ie + wps_ielen; + + remainder_ielen = ielen - wps_offset - wps_ielen; + + if (remainder_ielen > 0) { + pbackup_remainder_ie = rtw_malloc(remainder_ielen); + if (pbackup_remainder_ie) + _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); + } + + wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ + if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { + _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); + pwps_ie += (wps_ielen + 2); + + if (pbackup_remainder_ie) + _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); + + /* update IELength */ + pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen; + } + + if (pbackup_remainder_ie) + rtw_mfree(pbackup_remainder_ie, remainder_ielen); + + /* deal with the case without set_tx_beacon_cmd() in rtw_update_beacon() */ +#if defined(CONFIG_INTERRUPT_BASED_TXBCN) || defined(CONFIG_PCI_HCI) + if ((padapter->mlmeextpriv.mlmext_info.state & 0x03) == WIFI_FW_AP_STATE) { + u8 sr = 0; + rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); + + if (sr) { + set_fwstate(pmlmepriv, WIFI_UNDER_WPS); + RTW_INFO("%s, set WIFI_UNDER_WPS\n", __func__); + } else { + clr_fwstate(pmlmepriv, WIFI_UNDER_WPS); + RTW_INFO("%s, clr WIFI_UNDER_WPS\n", __func__); + } + } +#endif +} + +static void update_bcn_p2p_ie(_adapter *padapter) +{ + +} + +#ifdef CONFIG_ECSA_PHL +static bool _update_csa_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + struct core_ecsa_info *ecsa_info = &(padapter->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + WLAN_BSSID_EX *pnetwork = &(padapter_link->mlmeextpriv.mlmext_info.network); + u8 chan = ecsa_param->new_chan_def.chan; + u8 count = ecsa_param->count; + u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_; + sint ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_; + u8 *csa_ie; + sint csa_ie_len; + + csa_ie = rtw_get_ie(ies, WLAN_EID_CHANNEL_SWITCH, &csa_ie_len, ies_len); + + if (csa_ie && csa_ie_len == CSA_IE_LEN) { + if (count > 0) { + /* update CSA IE */ + #ifdef DBG_CSA + RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, update CSA IE\n", + FUNC_ADPT_ARG(padapter), chan, count); + #endif + + csa_ie = csa_ie + 2; + csa_ie[2] = count; + } else { + /* remove CSA IE */ + RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, remove CSA IE\n", + FUNC_ADPT_ARG(padapter), chan, count); + + rtw_remove_bcn_ie(padapter, pnetwork, WLAN_EID_CHANNEL_SWITCH); + SET_ECSA_STATE(padapter, ECSA_ST_SW_DONE); + } + return _TRUE; + } else { + RTW_ERR("CSA : "FUNC_ADPT_FMT" unexpected case\n", + FUNC_ADPT_ARG(padapter)); + return _FALSE; + } +} + +static bool _update_ecsa_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + struct core_ecsa_info *ecsa_info = &(padapter->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + WLAN_BSSID_EX *pnetwork = &(padapter_link->mlmeextpriv.mlmext_info.network); + u8 chan = ecsa_param->new_chan_def.chan; + u8 count = ecsa_param->count; + u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_; + sint ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_; + u8 *ecsa_ie; + sint ecsa_ie_len; + + ecsa_ie = rtw_get_ie(ies, WLAN_EID_ECSA, &ecsa_ie_len, ies_len); + + if (ecsa_ie && ecsa_ie_len == ECSA_IE_LEN) { + if (count > 0) { + /* update CSA IE */ + #ifdef DBG_CSA + RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, update ECSA IE\n", + FUNC_ADPT_ARG(padapter), chan, count); + #endif + ecsa_ie = ecsa_ie + 2; + ecsa_ie[3] = count; + } else { + /* remove ECSA IE */ + RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, remove ECSA IE\n", + FUNC_ADPT_ARG(padapter), chan, count); + + rtw_remove_bcn_ie(padapter, pnetwork, WLAN_EID_ECSA); + SET_ECSA_STATE(padapter, ECSA_ST_SW_DONE); + } + return _TRUE; + } else { + RTW_ERR("CSA : "FUNC_ADPT_FMT" unexpected case\n", + FUNC_ADPT_ARG(padapter)); + return _FALSE; + } +} +#endif + +static u8 update_csa_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + u8 update = _FALSE; +#ifdef CONFIG_ECSA_PHL + struct core_ecsa_info *ecsa_info = &(padapter->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + + if (!CHK_ECSA_STATE(padapter, ECSA_ST_SW_START)) + return _FALSE; + + update = _update_csa_ie(padapter, padapter_link); + + if (rtw_is_ecsa_enabled(padapter)) + update |= _update_ecsa_ie(padapter, padapter_link); + + if (ecsa_param->count > 0) + ecsa_param->count--; + +#endif /* CONFIG_ECSA_PHL */ + return update; +} + +static void update_bcn_vendor_spec_ie(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, u8 *oui) +{ + RTW_INFO("%s\n", __FUNCTION__); + + if (_rtw_memcmp(RTW_WPA_OUI, oui, 4)) + update_bcn_wpa_ie(padapter); + else if (_rtw_memcmp(WMM_OUI, oui, 4)) + update_bcn_wmm_ie(padapter); + else if (_rtw_memcmp(WPS_OUI, oui, 4)) + update_bcn_wps_ie(padapter, padapter_link); + else if (_rtw_memcmp(P2P_OUI, oui, 4)) + update_bcn_p2p_ie(padapter); + else + RTW_INFO("unknown OUI type!\n"); + + +} + +void _update_beacon(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 ie_id, u8 *oui, u8 tx, u8 flags, const char *tag) +{ + struct link_mlme_priv *pmlmepriv; + struct link_mlme_ext_priv *pmlmeext; + bool updated = 1; /* treat as upadated by default */ + + if (!padapter) + return; + + pmlmepriv = &(padapter_link->mlmepriv); + pmlmeext = &(padapter_link->mlmeextpriv); + + if (pmlmeext->bstart_bss == _FALSE) + return; + + _rtw_spinlock_bh(&pmlmepriv->bcn_update_lock); + + switch (ie_id) { + case _TIM_IE_: + update_BCNTIM(padapter, padapter_link); + break; + + case _ERPINFO_IE_: + update_bcn_erpinfo_ie(padapter, padapter_link); + break; + + case _HT_CAPABILITY_IE_: + update_bcn_htcap_ie(padapter); + break; + + case _RSN_IE_2_: + update_bcn_rsn_ie(padapter); + break; + + case _HT_ADD_INFO_IE_: + update_bcn_htinfo_ie(padapter, padapter_link); + break; + +#ifdef CONFIG_RTW_MESH + case WLAN_EID_MESH_CONFIG: + updated = rtw_mesh_update_bss_peering_status(padapter, &(pmlmeext->mlmext_info.network)); + updated |= rtw_mesh_update_bss_formation_info(padapter, &(pmlmeext->mlmext_info.network)); + updated |= rtw_mesh_update_bss_forwarding_state(padapter, &(pmlmeext->mlmext_info.network)); + break; +#endif + case WLAN_EID_CHANNEL_SWITCH: + updated = update_csa_ie(padapter, padapter_link); + break; + + case _VENDOR_SPECIFIC_IE_: + update_bcn_vendor_spec_ie(padapter, padapter_link, oui); + break; + + case 0xFF: + default: + break; + } + + if (updated) + pmlmepriv->update_bcn = _TRUE; + + _rtw_spinunlock_bh(&pmlmepriv->bcn_update_lock); + +#ifndef CONFIG_INTERRUPT_BASED_TXBCN +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING) + if (tx && updated) { + /* send_beacon(padapter); */ /* send_beacon must execute on TSR level */ + if (0) + RTW_INFO(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag); + if(flags == RTW_CMDF_WAIT_ACK) + set_tx_beacon_cmd(padapter, padapter_link, RTW_CMDF_WAIT_ACK); + else + set_tx_beacon_cmd(padapter, padapter_link, 0); + } +#else + { + /* PCI will issue beacon when BCN interrupt occurs. */ + } +#endif +#endif /* !CONFIG_INTERRUPT_BASED_TXBCN */ +} + +#ifdef CONFIG_80211N_HT + +void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len) +{ + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + u8 beacon_updated = _FALSE; + struct link_mlme_priv *pmlmepriv; + u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr); + u8 category, action; + + psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); + if (psta == NULL) + return; + pmlmepriv = &(psta->padapter_link->mlmepriv); + + + category = frame_body[0]; + action = frame_body[1]; + + if (frame_body_len > 0) { + if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) { + u8 ie_data = frame_body[4]; + + if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) { + if (psta->ht_40mhz_intolerant == 0) { + psta->ht_40mhz_intolerant = 1; + pmlmepriv->num_sta_40mhz_intolerant++; + beacon_updated = _TRUE; + } + } else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { + if (pmlmepriv->ht_20mhz_width_req == _FALSE) { + pmlmepriv->ht_20mhz_width_req = _TRUE; + beacon_updated = _TRUE; + } + } else + beacon_updated = _FALSE; + } + } + + if (frame_body_len > 8) { + /* if EID_BSSIntolerantChlReport ie exists */ + if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) { + /*todo:*/ + if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) { + pmlmepriv->ht_intolerant_ch_reported = _TRUE; + beacon_updated = _TRUE; + } + } + } + + if (beacon_updated) { + + rtw_update_beacon(padapter, psta->padapter_link, _HT_ADD_INFO_IE_, NULL, _TRUE, 0); + associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_BW); + } + + + +} + +void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field) +{ + u8 e_field, m_field; + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + + psta = rtw_get_stainfo(pstapriv, ta); + if (psta == NULL) + return; + + e_field = (ctrl_field & BIT(0)) ? 1 : 0; /*SM Power Save Enabled*/ + m_field = (ctrl_field & BIT(1)) ? 1 : 0; /*SM Mode, 0:static SMPS, 1:dynamic SMPS*/ + + if (e_field) { + if (m_field) { /*mode*/ + psta->smps_mode = SM_PS_DYNAMIC; + RTW_ERR("Don't support dynamic SMPS\n"); + } + else + psta->smps_mode = SM_PS_STATIC; + } else { + /*disable*/ + psta->smps_mode = SM_PS_DISABLE; + } + + if (psta->smps_mode != SM_PS_DYNAMIC) + rtw_ssmps_wk_cmd(padapter, psta, e_field, 1); +} + +/* +op_mode +Set to 0 (HT pure) under the followign conditions + - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or + - all STAs in the BSS are 20 MHz HT in 20 MHz BSS +Set to 1 (HT non-member protection) if there may be non-HT STAs + in both the primary and the secondary channel +Set to 2 if only HT STAs are associated in BSS, + however and at least one 20 MHz HT STA is associated +Set to 3 (HT mixed mode) when one or more non-HT STAs are associated + (currently non-GF HT station is considered as non-HT STA also) +*/ +int rtw_ht_operation_update(_adapter *padapter, struct _ADAPTER_LINK *padapter_link) +{ + u16 cur_op_mode, new_op_mode; + int op_mode_changes = 0; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; + + if (pmlmepriv->htpriv.ht_option == _FALSE) + return 0; + + /*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) + return 0;*/ + + RTW_INFO("%s current operation mode=0x%X\n", + __FUNCTION__, pmlmepriv->ht_op_mode); + + if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) + && pmlmepriv->num_sta_ht_no_gf) { + pmlmepriv->ht_op_mode |= + HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; + op_mode_changes++; + } else if ((pmlmepriv->ht_op_mode & + HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && + pmlmepriv->num_sta_ht_no_gf == 0) { + pmlmepriv->ht_op_mode &= + ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; + op_mode_changes++; + } + + if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && + (pmlmepriv->num_sta_no_ht || ATOMIC_READ(&pmlmepriv->olbc_ht))) { + pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; + op_mode_changes++; + } else if ((pmlmepriv->ht_op_mode & + HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && + (pmlmepriv->num_sta_no_ht == 0 && !ATOMIC_READ(&pmlmepriv->olbc_ht))) { + pmlmepriv->ht_op_mode &= + ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; + op_mode_changes++; + } + + /* Note: currently we switch to the MIXED op mode if HT non-greenfield + * station is associated. Probably it's a theoretical case, since + * it looks like all known HT STAs support greenfield. + */ + new_op_mode = 0; + if (pmlmepriv->num_sta_no_ht /*|| + (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/) + new_op_mode = OP_MODE_MIXED; + else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH) + && pmlmepriv->num_sta_ht_20mhz) + new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; + else if (ATOMIC_READ(&pmlmepriv->olbc_ht)) + new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; + else + new_op_mode = OP_MODE_PURE; + + cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; + if (cur_op_mode != new_op_mode) { + pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; + pmlmepriv->ht_op_mode |= new_op_mode; + op_mode_changes++; + } + + RTW_INFO("%s new operation mode=0x%X changes=%d\n", + __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes); + + return op_mode_changes; + +} + +#endif /* CONFIG_80211N_HT */ + +void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type) +{ + /* update associcated stations cap. */ + if (updated == _TRUE) { + _list *phead, *plist; + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + + rtw_stapriv_asoc_list_lock(pstapriv); + + phead = &pstapriv->asoc_list; + plist = get_next(phead); + + /* check asoc_queue */ + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + + plist = get_next(plist); + + associated_stainfo_update(padapter, psta, sta_info_type); + } + + rtw_stapriv_asoc_list_unlock(pstapriv); + + } + +} + +/* called > TSR LEVEL for USB or SDIO Interface*/ +void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta) +{ + u8 beacon_updated = _FALSE; + struct registry_priv *pregistrypriv = &(padapter->registrypriv); + struct _ADAPTER_LINK *padapter_link = psta->padapter_link; + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &(padapter_link->mlmeextpriv); + + +#if 0 + if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && + !psta->no_short_preamble_set) { + psta->no_short_preamble_set = 1; + pmlmepriv->num_sta_no_short_preamble++; + if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && + (pmlmepriv->num_sta_no_short_preamble == 1)) + ieee802_11_set_beacons(hapd->iface); + } +#endif + + + if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { + if (!psta->no_short_preamble_set) { + psta->no_short_preamble_set = 1; + + pmlmepriv->num_sta_no_short_preamble++; + + if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) && + (pmlmepriv->num_sta_no_short_preamble == 1)) + beacon_updated = _TRUE; + } + } else { + if (psta->no_short_preamble_set) { + psta->no_short_preamble_set = 0; + + pmlmepriv->num_sta_no_short_preamble--; + + if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) && + (pmlmepriv->num_sta_no_short_preamble == 0)) + beacon_updated = _TRUE; + } + } + +#if 0 + if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) { + psta->nonerp_set = 1; + pmlmepriv->num_sta_non_erp++; + if (pmlmepriv->num_sta_non_erp == 1) + ieee802_11_set_beacons(hapd->iface); + } +#endif + + if (psta->flags & WLAN_STA_NONERP) { + if (!psta->nonerp_set) { + psta->nonerp_set = 1; + + pmlmepriv->num_sta_non_erp++; + + if (pmlmepriv->num_sta_non_erp == 1) { + beacon_updated = _TRUE; + rtw_update_beacon(padapter, padapter_link, _ERPINFO_IE_, NULL, _FALSE, 0); + } + } + + } else { + if (psta->nonerp_set) { + psta->nonerp_set = 0; + + pmlmepriv->num_sta_non_erp--; + + if (pmlmepriv->num_sta_non_erp == 0) { + beacon_updated = _TRUE; + rtw_update_beacon(padapter, padapter_link, _ERPINFO_IE_, NULL, _FALSE, 0); + } + } + + } + + +#if 0 + if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) && + !psta->no_short_slot_time_set) { + psta->no_short_slot_time_set = 1; + pmlmepriv->num_sta_no_short_slot_time++; + if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && + (pmlmepriv->num_sta_no_short_slot_time == 1)) + ieee802_11_set_beacons(hapd->iface); + } +#endif + + if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) { + if (!psta->no_short_slot_time_set) { + psta->no_short_slot_time_set = 1; + + pmlmepriv->num_sta_no_short_slot_time++; + + if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) && + (pmlmepriv->num_sta_no_short_slot_time == 1)) + beacon_updated = _TRUE; + } + } else { + if (psta->no_short_slot_time_set) { + psta->no_short_slot_time_set = 0; + + pmlmepriv->num_sta_no_short_slot_time--; + + if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) && + (pmlmepriv->num_sta_no_short_slot_time == 0)) + beacon_updated = _TRUE; + } + } + +#ifdef CONFIG_80211N_HT + if(pregistrypriv->ht_enable && + is_supported_ht(pregistrypriv->wireless_mode)) { + if (psta->flags & WLAN_STA_HT) { + u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); + + RTW_INFO("HT: STA " MAC_FMT " HT Capabilities Info: 0x%04x\n", + MAC_ARG(psta->phl_sta->mac_addr), ht_capab); + + if (psta->no_ht_set) { + psta->no_ht_set = 0; + pmlmepriv->num_sta_no_ht--; + } + + if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { + if (!psta->no_ht_gf_set) { + psta->no_ht_gf_set = 1; + pmlmepriv->num_sta_ht_no_gf++; + } + RTW_INFO("%s STA " MAC_FMT " - no " + "greenfield, num of non-gf stations %d\n", + __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr), + pmlmepriv->num_sta_ht_no_gf); + } + + if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) { + if (!psta->ht_20mhz_set) { + psta->ht_20mhz_set = 1; + pmlmepriv->num_sta_ht_20mhz++; + } + RTW_INFO("%s STA " MAC_FMT " - 20 MHz HT, " + "num of 20MHz HT STAs %d\n", + __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr), + pmlmepriv->num_sta_ht_20mhz); + } + + if (((ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) != 0) && + (psta->ht_40mhz_intolerant == 0)) { + psta->ht_40mhz_intolerant = 1; + pmlmepriv->num_sta_40mhz_intolerant++; + RTW_INFO("%s STA " MAC_FMT " - 40MHZ_INTOLERANT, ", + __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr)); + } + + } else { + if (!psta->no_ht_set) { + psta->no_ht_set = 1; + pmlmepriv->num_sta_no_ht++; + } + if (pmlmepriv->htpriv.ht_option == _TRUE) { + RTW_INFO("%s STA " MAC_FMT + " - no HT, num of non-HT stations %d\n", + __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr), + pmlmepriv->num_sta_no_ht); + } + } + + if (rtw_ht_operation_update(padapter, padapter_link) > 0) { + rtw_update_beacon(padapter, padapter_link, _HT_CAPABILITY_IE_, NULL, _FALSE, 0); + rtw_update_beacon(padapter, padapter_link, _HT_ADD_INFO_IE_, NULL, _FALSE, 0); + beacon_updated = _TRUE; + } + } +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) { + struct sta_priv *pstapriv = &padapter->stapriv; + + rtw_update_beacon(padapter, padapter_link, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0); + if (pstapriv->asoc_list_cnt == 1) + _set_timer(&padapter->mesh_atlm_param_req_timer, 0); + beacon_updated = _TRUE; + } +#endif + + if (beacon_updated) + rtw_update_beacon(padapter, padapter_link, 0xFF, NULL, _TRUE, 0); + + /* update associcated stations cap. */ + associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); + + RTW_INFO("%s, updated=%d\n", __func__, beacon_updated); + +} + +u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta) +{ + u8 beacon_updated = _FALSE; + struct sta_priv *pstapriv = &padapter->stapriv; + struct link_mlme_priv *pmlmepriv = NULL; + struct link_mlme_ext_priv *pmlmeext = NULL; + + if (!psta) + return beacon_updated; + + pmlmepriv = &(psta->padapter_link->mlmepriv); + pmlmeext = &(psta->padapter_link->mlmeextpriv); + if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid)) { + rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid); + beacon_updated = _TRUE; + rtw_update_beacon(padapter, psta->padapter_link, _TIM_IE_, NULL, _FALSE, 0); + } + + if (psta->no_short_preamble_set) { + psta->no_short_preamble_set = 0; + pmlmepriv->num_sta_no_short_preamble--; + if (pmlmeext->cur_wireless_mode > WLAN_MD_11B + && pmlmepriv->num_sta_no_short_preamble == 0) + beacon_updated = _TRUE; + } + + if (psta->nonerp_set) { + psta->nonerp_set = 0; + pmlmepriv->num_sta_non_erp--; + if (pmlmepriv->num_sta_non_erp == 0) { + beacon_updated = _TRUE; + rtw_update_beacon(padapter, psta->padapter_link, _ERPINFO_IE_, NULL, _FALSE, 0); + } + } + + if (psta->no_short_slot_time_set) { + psta->no_short_slot_time_set = 0; + pmlmepriv->num_sta_no_short_slot_time--; + if (pmlmeext->cur_wireless_mode > WLAN_MD_11B + && pmlmepriv->num_sta_no_short_slot_time == 0) + beacon_updated = _TRUE; + } + +#ifdef CONFIG_80211N_HT + if (psta->no_ht_gf_set) { + psta->no_ht_gf_set = 0; + pmlmepriv->num_sta_ht_no_gf--; + } + + if (psta->no_ht_set) { + psta->no_ht_set = 0; + pmlmepriv->num_sta_no_ht--; + } + + if (psta->ht_20mhz_set) { + psta->ht_20mhz_set = 0; + pmlmepriv->num_sta_ht_20mhz--; + } + + if (psta->ht_40mhz_intolerant) { + psta->ht_40mhz_intolerant = 0; + if (pmlmepriv->num_sta_40mhz_intolerant > 0) + pmlmepriv->num_sta_40mhz_intolerant--; + else + rtw_warn_on(1); + } + + if (rtw_ht_operation_update(padapter, psta->padapter_link) > 0) { + rtw_update_beacon(padapter, psta->padapter_link, _HT_CAPABILITY_IE_, NULL, _FALSE, 0); + rtw_update_beacon(padapter, psta->padapter_link, _HT_ADD_INFO_IE_, NULL, _FALSE, 0); + beacon_updated = _TRUE; + } +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) { + rtw_update_beacon(padapter, psta->padapter_link, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0); + if (pstapriv->asoc_list_cnt == 0) + _cancel_timer_ex(&padapter->mesh_atlm_param_req_timer); + beacon_updated = _TRUE; + } +#endif + + if (beacon_updated == _TRUE) + rtw_update_beacon(padapter, psta->padapter_link, 0xFF, NULL, _TRUE, 0); + +#if 0 + /* update associated stations cap. */ + associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); /* move it to avoid deadlock */ +#endif + + RTW_INFO("%s, updated=%d\n", __func__, beacon_updated); + + return beacon_updated; + +} + +u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u8 subtype, u16 reason, bool enqueue) +{ + u8 beacon_updated = _FALSE; + + if (!psta) + return beacon_updated; + + RTW_INFO("%s sta "MAC_FMT"\n", __func__, MAC_ARG(psta->phl_sta->mac_addr)); + + if (active == _TRUE) { +#ifdef CONFIG_80211N_HT + /* tear down Rx AMPDU */ + send_delba(padapter, 0, psta->phl_sta->mac_addr);/* recipient */ + + /* tear down TX AMPDU */ + send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */ + +#endif /* CONFIG_80211N_HT */ + + if (!MLME_IS_MESH(padapter)) { + if (subtype == RTW_IEEE80211_STYPE_DISASSOC >> 4) + issue_disasoc(padapter, psta->phl_sta->mac_addr, reason); + else /* if not specified or not valid, use deauth by default */ + issue_deauth(padapter, psta->phl_sta->mac_addr, reason); + } + } + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) + rtw_mesh_path_flush_by_nexthop(psta); +#endif + +#ifdef CONFIG_80211N_HT + psta->ampdu_priv.agg_enable_bitmap = 0x0;/* reset */ + psta->ampdu_priv.candidate_tid_bitmap = 0x0;/* reset */ +#endif + + _rtw_spinlock_bh(&psta->lock); + psta->state &= ~(WIFI_ASOC_STATE | WIFI_UNDER_KEY_HANDSHAKE); + +#ifdef CONFIG_IOCTL_CFG80211 + if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) { + rtw_mfree(psta->pauth_frame, psta->auth_len); + psta->pauth_frame = NULL; + psta->auth_len = 0; + } + + if (psta->passoc_req && psta->assoc_req_len > 0) { + rtw_mfree(psta->passoc_req, psta->assoc_req_len); + psta->passoc_req = NULL; + psta->assoc_req_len = 0; + } +#endif /* CONFIG_IOCTL_CFG80211 */ + _rtw_spinunlock_bh(&psta->lock); + + if (!MLME_IS_MESH(padapter)) { + #ifdef CONFIG_RTW_WDS + rtw_wds_path_flush_by_nexthop(psta); + #endif + +#ifdef CONFIG_IOCTL_CFG80211 + #ifdef COMPAT_KERNEL_RELEASE + rtw_cfg80211_indicate_sta_disassoc(padapter, psta->phl_sta->mac_addr, reason); + #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) + rtw_cfg80211_indicate_sta_disassoc(padapter, psta->phl_sta->mac_addr, reason); + #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */ + /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */ + #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */ +#else + rtw_indicate_sta_disassoc_event(padapter, psta); +#endif + } + + beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); + + report_del_sta_event(padapter, psta->phl_sta->mac_addr, reason, enqueue, _FALSE); + + return beacon_updated; + +} + +int rtw_sta_flush(_adapter *padapter, bool enqueue) +{ + _list *phead, *plist; + int ret = 0; + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 flush_num = 0; + char flush_list[NUM_STA]; + int i; + + if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) + return ret; + + /* pick sta from sta asoc_queue */ + rtw_stapriv_asoc_list_lock(pstapriv); + phead = &pstapriv->asoc_list; + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + int stainfo_offset; + + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + + rtw_stapriv_asoc_list_del(pstapriv, psta); + + stainfo_offset = rtw_stainfo_offset(pstapriv, psta); + if (stainfo_offset_valid(stainfo_offset)) + flush_list[flush_num++] = stainfo_offset; + else + rtw_warn_on(1); + } + rtw_stapriv_asoc_list_unlock(pstapriv); + + RTW_INFO(FUNC_NDEV_FMT" flush_num:%d\n", FUNC_NDEV_ARG(padapter->pnetdev), flush_num); + + /* call ap_free_sta() for each sta picked */ + for (i = 0; i < flush_num; i++) { + u8 sta_addr[ETH_ALEN]; + + psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]); + if (psta != NULL) { + _rtw_memcpy(sta_addr, psta->phl_sta->mac_addr, ETH_ALEN); + ap_free_sta(padapter, psta, _TRUE, 0, WLAN_REASON_DEAUTH_LEAVING, enqueue); + } + #ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(padapter)) + rtw_mesh_expire_peer(padapter, sta_addr); + #endif + } + + if (MLME_IS_ASOC(padapter) && !MLME_IS_MESH(padapter)) + issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); + + associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL); + + return ret; +} + +/* called > TSR LEVEL for USB or SDIO Interface*/ +void sta_info_update(_adapter *padapter, struct sta_info *psta) +{ + int flags = psta->flags; + struct link_mlme_priv *pmlmepriv = &(psta->padapter_link->mlmepriv); + + + /* update wmm cap. */ + if (WLAN_STA_WME & flags) + psta->qos_option = 1; + else + psta->qos_option = 0; + + if (pmlmepriv->qospriv.qos_option == 0) + psta->qos_option = 0; + + +#ifdef CONFIG_80211N_HT + /* update 802.11n ht cap. */ + if (WLAN_STA_HT & flags) { + psta->htpriv.ht_option = _TRUE; + psta->qos_option = 1; + + psta->smps_mode = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS) >> 2; + } else + psta->htpriv.ht_option = _FALSE; + + if (pmlmepriv->htpriv.ht_option == _FALSE) + psta->htpriv.ht_option = _FALSE; +#endif + +#ifdef CONFIG_80211AC_VHT + /* update 802.11AC vht cap. */ + if (WLAN_STA_VHT & flags) + psta->vhtpriv.vht_option = _TRUE; + else + psta->vhtpriv.vht_option = _FALSE; + + if (pmlmepriv->vhtpriv.vht_option == _FALSE) + psta->vhtpriv.vht_option = _FALSE; +#endif + +#ifdef CONFIG_80211AX_HE + /* update 802.11AX he cap. */ + if (WLAN_STA_HE & flags) { + psta->hepriv.he_option = _TRUE; +#if CONFIG_IEEE80211_BAND_6GHZ + if (flags & WLAN_STA_6G_BAND_CAP) + psta->smps_mode = GET_HE_6G_BAND_CAP_SM_PS(psta->hepriv.he_6g_band_cap + 1); +#endif + } else { + psta->hepriv.he_option = _FALSE; + } + + if (pmlmepriv->hepriv.he_option == _FALSE) + psta->hepriv.he_option = _FALSE; + +#endif + + update_sta_info_apmode(padapter, psta); +} + +/* restore hw setting from sw data structures */ +void rtw_ap_restore_network(_adapter *padapter) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta; + _list *phead, *plist; + u8 chk_alive_num = 0; + char chk_alive_list[NUM_STA]; + int i; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_security_priv *psecuritypriv = &(padapter_link->securitypriv); + + rtw_setopmode_cmd(padapter + , MLME_IS_AP(padapter) ? Ndis802_11APMode : Ndis802_11_mesh + , RTW_CMDF_DIRECTLY + ); + + set_bch_bwmode(padapter, padapter_link, pmlmeext->chandef.band, pmlmeext->chandef.chan, + pmlmeext->chandef.offset, pmlmeext->chandef.bw, RFK_TYPE_FORCE_NOT_DO); + + rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY); + + if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || + (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) { + /* restore group key, WEP keys is restored in ips_leave() */ + rtw_set_key(padapter, padapter_link, psecuritypriv->dot118021XGrpKeyid, 0, _FALSE); + } + + rtw_stapriv_asoc_list_lock(pstapriv); + + phead = &pstapriv->asoc_list; + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + int stainfo_offset; + + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + + stainfo_offset = rtw_stainfo_offset(pstapriv, psta); + if (stainfo_offset_valid(stainfo_offset)) + chk_alive_list[chk_alive_num++] = stainfo_offset; + } + + rtw_stapriv_asoc_list_unlock(pstapriv); + + for (i = 0; i < chk_alive_num; i++) { + psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); + + if (psta == NULL){ + RTW_INFO(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter)); + } else if (psta->state & WIFI_ASOC_STATE) { + rtw_sta_hal_media_status_rpt_cmd(padapter, psta, true, RTW_CMDF_DIRECTLY); + /* pairwise key */ + /* per sta pairwise key and settings */ + if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || + (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) + rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _FALSE); + } + } + +} + +void start_ap_mode(_adapter *padapter) +{ + int i; + struct sta_priv *pstapriv = &padapter->stapriv; +#ifdef CONFIG_CONCURRENT_MODE + struct security_priv *psecuritypriv = &padapter->securitypriv; +#endif + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + pmlmepriv->update_bcn = _FALSE; + + /*init_mlme_ap_info(padapter);*/ + + pmlmeext->bstart_bss = _FALSE; + + pmlmepriv->num_sta_non_erp = 0; + + pmlmepriv->num_sta_no_short_slot_time = 0; + + pmlmepriv->num_sta_no_short_preamble = 0; + + pmlmepriv->num_sta_ht_no_gf = 0; +#ifdef CONFIG_80211N_HT + pmlmepriv->num_sta_no_ht = 0; +#endif /* CONFIG_80211N_HT */ + pmlmeinfo->HT_info_enable = 0; + pmlmeinfo->HT_caps_enable = 0; + pmlmeinfo->HT_enable = 0; + + pmlmepriv->num_sta_ht_20mhz = 0; + pmlmepriv->num_sta_40mhz_intolerant = 0; + ATOMIC_SET(&pmlmepriv->olbc, _FALSE); + ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE); + +#ifdef CONFIG_80211N_HT + pmlmepriv->ht_20mhz_width_req = _FALSE; + pmlmepriv->ht_intolerant_ch_reported = _FALSE; + pmlmepriv->ht_op_mode = 0; + pmlmepriv->sw_to_20mhz = 0; +#endif + + _rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data)); + pmlmepriv->ext_capab_ie_len = 0; + +#ifdef CONFIG_CONCURRENT_MODE + psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID; +#endif + + for (i = 0 ; i < pstapriv->max_aid; i++) + pstapriv->sta_aid[i] = NULL; + +#ifdef CONFIG_RTW_WDS + if (MLME_IS_AP(padapter)) + rtw_wds_pathtbl_init(padapter); +#endif + rtw_ap_stop_set_state(padapter, AP_STOP_ST_IDLE); + + if (rtw_mi_check_status(padapter, MI_AP_MODE)) + RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G); +} + +void stop_ap_mode(_adapter *padapter) +{ + u8 self_action = MLME_ACTION_UNKNOWN; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; +#if 0 + int chanctx_num = 0; +#endif + struct rtw_chan_def chan_def = {0}; + + RTW_INFO("%s -"ADPT_FMT"\n", __func__, ADPT_ARG(padapter)); + + if (MLME_IS_AP(padapter)) + self_action = MLME_AP_STOPPED; + else if (MLME_IS_MESH(padapter)) + self_action = MLME_MESH_STOPPED; + else + rtw_warn_on(1); + + pmlmepriv->update_bcn = _FALSE; + /*pmlmeext->bstart_bss = _FALSE;*/ + padapter->netif_up = _FALSE; + /* _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); */ + + /* reset and init security priv , this can refine with rtw_reset_securitypriv */ + _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; + padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; + _rtw_memset((unsigned char *)&padapter_link->securitypriv, 0, sizeof(struct link_security_priv)); + + rtw_rfctl_update_op_mode(adapter_to_rfctl(padapter), BIT(padapter->iface_id), 0, 0); + + /* free scan queue */ + rtw_free_network_queue(padapter, _TRUE); + rtw_free_mld_network_queue(padapter, _TRUE); + +#if CONFIG_RTW_MACADDR_ACL + rtw_macaddr_acl_clear(padapter, RTW_ACL_PERIOD_BSS); +#endif + + rtw_sta_flush(padapter, _FALSE); + + padapter->mlmepriv.ap_isolate = 0; +#ifdef CONFIG_RTW_WDS + adapter_set_use_wds(padapter, 0); +#endif +#ifdef CONFIG_RTW_MULTI_AP + padapter->multi_ap = 0; +#endif + rtw_free_mlme_priv_ie_data(&padapter->mlmepriv); + + pmlmeext->bstart_bss = _FALSE; + +#ifdef CONFIG_RTW_MULTI_AP + rtw_map_config_monitor(padapter, self_action); +#endif +#if 0 + chanctx_num = rtw_phl_chanctx_del(adapter_to_dvobj(padapter)->phl, + padapter->phl_role, &chan_def); + + if (chanctx_num && chan_def.chan != 0) + set_bch_bwmode(padapter, chan_def.band, chan_def.chan, chan_def.offset, chan_def.bw, RFK_TYPE_FORCE_NOT_DO); +#endif + +#ifdef CONFIG_DFS_MASTER + rtw_indicate_cac_state_on_bss_stop(padapter); +#endif + +#ifdef CONFIG_RTW_WDS + if (MLME_IS_AP(padapter)) + rtw_wds_pathtbl_unregister(padapter); +#endif + _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); +} + +#endif /* CONFIG_NATIVEAP_MLME */ + +void rtw_ap_update_clients_rainfo(struct _ADAPTER *a, u8 flag) +{ + struct link_mlme_ext_priv *pmlmeext; + struct sta_priv *pstapriv = &a->stapriv; + struct sta_info *psta; + const struct sta_info *ap_self_psta = rtw_get_stainfo(pstapriv, a->phl_role->mac_addr); + _list *plist, *phead; + u8 i; + + /* update RA mask of all clients */ + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + + /* no need to update RA info of ap self */ + if (psta && psta != ap_self_psta) { + pmlmeext = &psta->padapter_link->mlmeextpriv; + psta->phl_sta->chandef.bw = pmlmeext->chandef.bw; + rtw_sta_hal_ra_mask_update_cmd(a, psta, flag); + } + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); +} + +void rtw_ap_update_bss_bchbw(_adapter *adapter, struct _ADAPTER_LINK *adapter_link, + WLAN_BSSID_EX *bss, struct rtw_chan_def *chandef) +{ +#define UPDATE_VHT_CAP 1 +#define UPDATE_HT_CAP 1 + struct link_mlme_priv *mlmepriv = &adapter_link->mlmepriv; +#ifdef CONFIG_80211N_HT + struct ht_priv *htpriv = &mlmepriv->htpriv; +#endif +#ifdef CONFIG_80211AC_VHT + struct vht_priv *vhtpriv = &mlmepriv->vhtpriv; +#endif + u8 *p; + uint ie_len = 0; + +#ifdef CONFIG_80211AX_HE + struct he_priv *hepriv = &mlmepriv->hepriv; + u8 *he_op_info = NULL; + + if ((hepriv->he_option == _TRUE) && (chandef->band == BAND_ON_6G)) { + he_op_info = rtw_ies_get_he_6g_op_info_ie( + bss->IEs + _FIXED_IE_LENGTH_, + bss->IELength - _FIXED_IE_LENGTH_); + + /* update channel in IE */ + if (he_op_info && + (bss->Configuration.DSConfig != chandef->chan || + bss->Configuration.Band != chandef->band)) { + SET_HE_OP_INFO_PRIMARY_CHAN(he_op_info, chandef->chan); + SET_HE_OP_INFO_CHAN_WIDTH(he_op_info, chandef->bw); + SET_HE_OP_INFO_CENTER_FREQ_0(he_op_info, (u8)chandef->center_freq1); + SET_HE_OP_INFO_CENTER_FREQ_1(he_op_info, (u8)chandef->center_freq2); + } + + bss->Configuration.DSConfig = chandef->chan; + + if (bss->Configuration.Band != chandef->band) { + bss->Configuration.Band = chandef->band; + change_band_update_ie(adapter, adapter_link, bss, chandef); + } + + /* TODO remove unnecessary IE ie., HT VHT IE */ + return; + } +#endif + /* update channel in IE */ + if (bss->Configuration.DSConfig != chandef->chan) { + p = rtw_get_ie((bss->IEs + _FIXED_IE_LENGTH_), _DSSET_IE_, + &ie_len, (bss->IELength - _FIXED_IE_LENGTH_)); + + if (p && ie_len > 0) + *(p + 2) = chandef->chan; + + bss->Configuration.DSConfig = chandef->chan; + } + + /* band is changed, update ERP, support rate, ext support rate IE */ + if (bss->Configuration.Band != chandef->band) { + bss->Configuration.Band = chandef->band; + change_band_update_ie(adapter, adapter_link, bss, chandef); + } + +#ifdef CONFIG_80211AC_VHT + if (vhtpriv->vht_option == _TRUE) { + u8 *vht_cap_ie, *vht_op_ie; + int vht_cap_ielen, vht_op_ielen; + u8 center_freq; + struct rtw_chan_def chdef = {0}; + + vht_cap_ie = rtw_get_ie((bss->IEs + _FIXED_IE_LENGTH_), WLAN_EID_VHT_CAPABILITY, &vht_cap_ielen, (bss->IELength - _FIXED_IE_LENGTH_)); + vht_op_ie = rtw_get_ie((bss->IEs + _FIXED_IE_LENGTH_), WLAN_EID_VHT_OPERATION, &vht_op_ielen, (bss->IELength - _FIXED_IE_LENGTH_)); + chdef.chan = chandef->chan; + chdef.bw = chandef->bw; + chdef.offset = chandef->offset; + chdef.band = chandef->band; + center_freq = rtw_phl_get_center_ch(&chdef); + + /* update vht cap ie */ + if (vht_cap_ie && vht_cap_ielen) { + #if UPDATE_VHT_CAP + if ((chandef->bw == CHANNEL_WIDTH_160 || chandef->bw == CHANNEL_WIDTH_80_80) && vhtpriv->sgi_160m) + SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 1); + else + SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0); + + if (chandef->bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m) + SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1); + else + SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0); + #endif + } + + /* update vht op ie */ + if (vht_op_ie && vht_op_ielen) { + if (chandef->bw < CHANNEL_WIDTH_80) { + RTW_INFO(FUNC_ADPT_FMT" update VHT 20/40M\n", FUNC_ADPT_ARG(adapter)); + SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, CH_WIDTH_20_40M); + SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0); + SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0); + } else if (chandef->bw == CHANNEL_WIDTH_80) { + RTW_INFO(FUNC_ADPT_FMT" update VHT 80M, center_freq = %u\n", FUNC_ADPT_ARG(adapter), center_freq); + SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, CH_WIDTH_80_160M); + SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq); + SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0); + } else { + RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), chandef->bw); + rtw_warn_on(1); + } + } + } +#endif /* CONFIG_80211AC_VHT */ +#ifdef CONFIG_80211N_HT + { + u8 *ht_cap_ie, *ht_op_ie; + int ht_cap_ielen, ht_op_ielen; + + ht_cap_ie = rtw_get_ie((bss->IEs + _FIXED_IE_LENGTH_), EID_HTCapability, &ht_cap_ielen, (bss->IELength - _FIXED_IE_LENGTH_)); + ht_op_ie = rtw_get_ie((bss->IEs + _FIXED_IE_LENGTH_), EID_HTInfo, &ht_op_ielen, (bss->IELength - _FIXED_IE_LENGTH_)); + + /* update ht cap ie */ + if (ht_cap_ie && ht_cap_ielen) { + #if UPDATE_HT_CAP + if (chandef->bw >= CHANNEL_WIDTH_40) + SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1); + else + SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0); + + if (chandef->bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m) + SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1); + else + SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0); + + if (htpriv->sgi_20m) + SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1); + else + SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0); + #endif + } + + /* update ht op ie */ + if (ht_op_ie && ht_op_ielen) { + SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, chandef->chan); + switch (chandef->offset) { + case CHAN_OFFSET_UPPER: + SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCA); + break; + case CHAN_OFFSET_LOWER: + SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCB); + break; + case CHAN_OFFSET_NO_EXT: + default: + break; + SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCN); + } + + if (chandef->bw >= CHANNEL_WIDTH_40) + SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1); + else + SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0); + } + } +#endif /* CONFIG_80211N_HT */ +} + +static int rtw_ap_gen_HE_freq(enum band_type band, u8 ch, u8 bw, u8 offset, u8 *freq0, u8 *freq1) +{ + + *freq0 = 0; + *freq1 = 0; + + if (band != BAND_ON_6G) + return -1; + + if (bw == CHANNEL_WIDTH_160) { + *freq1 = rtw_get_center_ch_by_band(band, ch, bw, offset); + *freq0 = rtw_get_center_ch_by_band(band, ch, CHANNEL_WIDTH_80, offset); + } else { + *freq0 = rtw_get_center_ch_by_band(band, ch, bw, offset); + *freq1 = 0; + } + return 0; +} + +static u8 rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp + , enum band_type cur_ie_band[], u8 cur_ie_ch[], u8 cur_ie_bw[], u8 cur_ie_offset[] + , enum band_type dec_band[], u8 dec_ch[], u8 dec_bw[], u8 dec_offset[] + , const char *caller) +{ + _adapter *iface; + WLAN_BSSID_EX *network; + u8 ifbmp_ch_changed = 0, freq0 = 0, freq1 = 0; + int i; + struct _ADAPTER_LINK *iface_link = NULL; + struct link_mlme_ext_priv *mlmeext; + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + + iface = dvobj->padapters[i]; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + mlmeext = &(iface_link->mlmeextpriv); + + if (MLME_IS_ASOC(iface)) { + RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u,%u => %u,%u,%u,%u%s\n", caller, ADPT_ARG(iface) + , mlmeext->chandef.band, mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset + , dec_band[i], dec_ch[i], dec_bw[i], dec_offset[i] + , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : ""); + } else { + RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u,%u => %u,%u,%u,%u%s\n", caller, ADPT_ARG(iface) + , cur_ie_band[i], cur_ie_ch[i], cur_ie_bw[i], cur_ie_offset[i] + , dec_band[i], dec_ch[i], dec_bw[i], dec_offset[i] + , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : ""); + } + } + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + + iface = dvobj->padapters[i]; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + mlmeext = &(iface_link->mlmeextpriv); + network = &(mlmeext->mlmext_info.network); + + /* ch setting differs from mlmeext.network IE */ + if (cur_ie_ch[i] != dec_ch[i] + || cur_ie_bw[i] != dec_bw[i] + || cur_ie_offset[i] != dec_offset[i]) + ifbmp_ch_changed |= BIT(i); + + /* ch setting differs from existing one */ + if (MLME_IS_ASOC(iface) + && (mlmeext->chandef.chan != dec_ch[i] + || mlmeext->chandef.band != dec_band[i] + || mlmeext->chandef.bw != dec_bw[i] + || mlmeext->chandef.offset != dec_offset[i]) + ) { + if (rtw_linked_check(iface) == _TRUE) { + #ifdef CONFIG_ECSA_PHL + if (CHK_ECSA_STATE(iface, ECSA_ST_NONE)) + #endif + rtw_sta_flush(iface, _FALSE); + } + } + + rtw_ap_gen_HE_freq(dec_band[i], dec_ch[i], dec_bw[i], dec_offset[i], &freq0, &freq1); + mlmeext->chandef.center_freq1 = (u32)freq0; + mlmeext->chandef.center_freq2 = (u32)freq1; + mlmeext->chandef.band = dec_band[i]; + mlmeext->chandef.chan = dec_ch[i]; + mlmeext->chandef.bw = dec_bw[i]; + mlmeext->chandef.offset = dec_offset[i]; + + rtw_ap_update_bss_bchbw(iface, iface_link, network, &mlmeext->chandef); + } + + return ifbmp_ch_changed; +} + +static u8 rtw_ap_ch_specific_chk(_adapter *adapter, enum band_type band, u8 ch, u8 *bw, u8 *offset, const char *caller) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + struct rtw_chset *chset = adapter_to_chset(adapter); + int ch_idx; + u8 ret = _SUCCESS; + + if (rtw_rfctl_is_regu_forbid_bss(rfctl, band)) { + RTW_WARN("%s %s AP not allowed by regulatory\n", __func__, band_str(band)); + ret = _FAIL; + goto exit; + } + + ch_idx = rtw_chset_search_bch(chset, band, ch); + if (ch_idx < 0) { + RTW_WARN("%s ch:%u doesn't fit in chplan\n", caller, ch); + ret = _FAIL; + goto exit; + } + if (chset->chs[ch_idx].flags & RTW_CHF_NO_IR) { + RTW_WARN("%s ch:%u is passive\n", caller, ch); + ret = _FAIL; + goto exit; + } + + rtw_adjust_bchbw(adapter, band, ch, bw, offset); + + if (!rtw_get_offset_by_bchbw(band, ch, *bw, offset)) { + RTW_WARN("%s %u, %u,%u has no valid offset\n", caller, band, ch, *bw); + ret = _FAIL; + goto exit; + } + + while (!rtw_chset_is_bchbw_valid(chset, band, ch, *bw, *offset, 0, 0) + || (!rtw_rfctl_radar_detect_supported(rfctl) && rtw_chset_is_dfs_bchbw(chset, band, ch, *bw, *offset)) + ) { + if (*bw > CHANNEL_WIDTH_20) + (*bw)--; + if (*bw == CHANNEL_WIDTH_20) { + *offset = CHAN_OFFSET_NO_EXT; + break; + } + } + + + if (!rtw_rfctl_radar_detect_supported(rfctl) && rtw_chset_is_dfs_bchbw(chset, band, ch, *bw, *offset)) { + RTW_WARN("%s DFS channel %u can't be used\n", caller, ch); + ret = _FAIL; + goto exit; + } + +exit: + return ret; +} + +u8 rtw_ap_bchbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp, s8 req_band + , s16 req_ch, s8 req_bw, s8 req_offset, struct rtw_chan_def *chdef) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct rtw_chset *chset = adapter_to_chset(adapter); + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + bool ch_avail = _FALSE; + enum band_type cur_ie_band[CONFIG_IFACE_NUMBER] = {BAND_ON_24G}; + u8 cur_ie_freq0[CONFIG_IFACE_NUMBER] = {0}; + u8 cur_ie_freq1[CONFIG_IFACE_NUMBER] = {0}; + u8 cur_ie_ch[CONFIG_IFACE_NUMBER] = {0}; + u8 cur_ie_bw[CONFIG_IFACE_NUMBER] = {0}; + u8 cur_ie_offset[CONFIG_IFACE_NUMBER] = {0}; + enum band_type dec_band[CONFIG_IFACE_NUMBER] = {BAND_ON_24G}; + u8 dec_hwband[CONFIG_IFACE_NUMBER] = {0}; + u8 dec_ch[CONFIG_IFACE_NUMBER] = {0}; + u8 dec_bw[CONFIG_IFACE_NUMBER] = {0}; + u8 dec_offset[CONFIG_IFACE_NUMBER] = {0}; + u8 u_ch = 0, u_bw = 0, u_offset = 0; + enum band_type u_band = BAND_ON_24G; + WLAN_BSSID_EX *network; + struct mi_state mstate; + struct mi_state mstate_others; + bool set_u_ch = _FALSE; + u8 ifbmp_others = 0xFF & ~ifbmp & ~excl_ifbmp; + u8 ifbmp_ch_changed = 0; + bool ifbmp_all_mesh = 0; + _adapter *iface; + int i; +#ifdef CONFIG_MCC_MODE + struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj); + u8 mcc_sup = phl_com->dev_cap.mcc_sup; +#endif + struct _ADAPTER_LINK *adapter_link = GET_PRIMARY_LINK(adapter); + struct _ADAPTER_LINK *iface_link; + struct link_mlme_ext_priv *mlmeext; +#ifdef CONFIG_DBCC_SUPPORT + enum phl_band_idx hw_band = adapter_link->wrlink->hw_band; + + dec_hwband[adapter->iface_id] = hw_band; +#endif + +#ifdef CONFIG_RTW_MESH + for (i = 0; i < dvobj->iface_nums; i++) + if ((ifbmp & BIT(i)) && dvobj->padapters[i]) + if (!MLME_IS_MESH(dvobj->padapters[i])) + break; + ifbmp_all_mesh = i >= dvobj->iface_nums ? 1 : 0; +#endif + + RTW_INFO("%s ifbmp:0x%02x excl_ifbmp:0x%02x req:%d,%d,%d\n", __func__ + , ifbmp, excl_ifbmp, req_ch, req_bw, req_offset); + rtw_mi_status_by_ifbmp(adapter, ifbmp, &mstate); + rtw_mi_status_by_ifbmp(adapter, ifbmp_others, &mstate_others); + RTW_INFO("%s others ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u\n" + , __func__, MSTATE_STA_LD_NUM(&mstate_others), MSTATE_STA_LG_NUM(&mstate_others) + , MSTATE_AP_NUM(&mstate_others), MSTATE_MESH_NUM(&mstate_others)); + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + iface = dvobj->padapters[i]; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + mlmeext = &(iface_link->mlmeextpriv); + network = &(mlmeext->mlmext_info.network); + + /* get current IE channel settings */ + rtw_ies_get_bchbw(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network) + , &cur_ie_band[i] , &cur_ie_ch[i] , &cur_ie_bw[i] + , &cur_ie_offset[i], &cur_ie_freq0[i], &cur_ie_freq1[i], 1, 1, 1); + + /* prepare temporary channel setting decision */ + if (req_ch == 0) { + /* request comes from upper layer, use cur_ie values */ + dec_band[i] = cur_ie_band[i]; + dec_ch[i] = cur_ie_ch[i]; + dec_bw[i] = cur_ie_bw[i]; + dec_offset[i] = cur_ie_offset[i]; + } else { + /* use chbw of cur_ie updated with specifying req as temporary decision */ + + if (req_ch <= REQ_CH_NONE) { + dec_ch[i] = cur_ie_ch[i]; + dec_band[i] = cur_ie_band[i]; + } else { + dec_ch[i] = req_ch; + dec_band[i] = req_band; + } + + if (req_bw <= REQ_BW_NONE) { + if (req_bw == REQ_BW_ORI) + dec_bw[i] = iface_link->mlmepriv.ori_chandef.bw; + else + dec_bw[i] = cur_ie_bw[i]; + } else { + dec_bw[i] = req_bw; + } + + dec_offset[i] = (req_offset <= REQ_OFFSET_NONE) ? cur_ie_offset[i] : req_offset; + #ifdef CONFIG_DBCC_SUPPORT + dec_hwband[i] = iface_link->wrlink->hw_band; + #endif + } + } + + if (MSTATE_STA_LD_NUM(&mstate_others) || MSTATE_STA_LG_NUM(&mstate_others) + || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others) + ) { + /* has linked/linking STA or has AP/Mesh mode */ + rtw_warn_on(!rtw_mi_get_ch_setting_union_by_ifbmp(adapter, ifbmp_others, &u_band, &u_ch, &u_bw, &u_offset)); + RTW_INFO("%s others union:%u,%u,%u,%u\n", __func__, u_band, u_ch, u_bw, u_offset); + } + +#ifdef CONFIG_MCC_MODE + if (mcc_sup && req_ch == 0) { + /* will disable MCC in ap starter prepare after v10 merge */ + if (rtw_hw_mcc_chk_inprogress(adapter, adapter_link)) { + u8 if_id = adapter->iface_id; + + mlmeext = &(adapter_link->mlmeextpriv); + /* check channel settings are the same */ + if (cur_ie_ch[if_id] == mlmeext->chandef.chan + && cur_ie_band[if_id] == mlmeext->chandef.band + && cur_ie_bw[if_id] == mlmeext->chandef.bw + && cur_ie_offset[if_id] == mlmeext->chandef.offset) { + + RTW_INFO(FUNC_ADPT_FMT"req ch settings are the same as current ch setting, go to exit\n" + , FUNC_ADPT_ARG(adapter)); + goto exit; + } else { + RTW_WARN(FUNC_ADPT_FMT"request channel settings are different from current channel setting(%d,%d,%d,%d,%d,%d), restart MCC\n" + , FUNC_ADPT_ARG(adapter) + , cur_ie_ch[if_id], cur_ie_bw[if_id], cur_ie_offset[if_id] + , mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset); + #if 0 + rtw_hal_set_mcc_setting_disconnect(adapter); + #endif + } + } + } +#endif /* CONFIG_MCC_MODE */ + + if (MSTATE_STA_LG_NUM(&mstate_others) || MSTATE_STA_LD_NUM(&mstate_others) + || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others) + ) { + /* has linked or linking STA mode or AP/Mesh mode */ + + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + iface = dvobj->padapters[i]; + + if (!rtw_iface_at_same_hwband(adapter, iface)) + continue; + + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + #ifdef CONFIG_MCC_MODE + if (mcc_sup) { + if (!rtw_is_bchbw_grouped(u_band, u_ch, u_bw, u_offset, + dec_band[i], dec_ch[i], dec_bw[i], dec_offset[i])) { + mlmeext = &(iface_link->mlmeextpriv); + mlmeext->chandef.chan = chdef->chan = dec_ch[i]; + mlmeext->chandef.bw = chdef->bw = dec_bw[i]; + mlmeext->chandef.offset = chdef->offset = dec_offset[i]; + mlmeext->chandef.band = chdef->band = dec_band[i]; + + /* Trigger CSA should update ifbmp_ch_changed */ + #ifdef CONFIG_ECSA_PHL + if (CHK_ECSA_STATE(iface, ECSA_ST_SW_START) && + (cur_ie_ch[i] != dec_ch[i] + || cur_ie_band[i] != dec_band[i] + || cur_ie_bw[i] != dec_bw[i] + || cur_ie_offset[i] != dec_offset[i])) { + ifbmp_ch_changed |= BIT(i); + RTW_INFO("CSA : "FUNC_ADPT_FMT" : Trigger CSA in mcc mode\n", + FUNC_ADPT_ARG(iface)); + } + + RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u,%u\n", FUNC_ADPT_ARG(iface) + , chdef->band, chdef->chan, chdef->bw, chdef->offset); + #endif + goto exit; + } + } + #endif /* CONFIG_MCC_MODE */ + + rtw_adjust_bchbw(iface, u_band, u_ch, &dec_bw[i], &dec_offset[i]); + #ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(iface)) + rtw_mesh_adjust_bchbw(u_band, u_ch, &dec_bw[i], &dec_offset[i]); + #endif + + if (req_ch == 0 && dec_bw[i] > u_bw + && rtw_chset_is_dfs_bchbw(chset, u_band, u_ch, u_bw, u_offset) + ) { + /* request comes from upper layer, prevent from additional channel waiting */ + dec_bw[i] = u_bw; + if (dec_bw[i] == CHANNEL_WIDTH_20) + dec_offset[i] = CHAN_OFFSET_NO_EXT; + } + + /* follow */ + rtw_chset_sync_bchbw(chset + , &dec_band[i], &dec_ch[i], &dec_bw[i], &dec_offset[i] + , &u_band, &u_ch, &u_bw, &u_offset, 1, 0); + } + + set_u_ch = _TRUE; + + } else { + /* autonomous decision */ + u8 ori_ch = 0, ori_offset = CHAN_OFFSET_NO_EXT; + u8 ori_band = 0; + u8 max_bw; + bool by_int_info; + + if (req_ch <= REQ_CH_NONE) /* channel is not specified */ + goto choose_chbw; + + /* get tmp dec union of ifbmp */ + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + #ifdef CONFIG_DBCC_SUPPORT + if (dec_hwband[i] != hw_band) + continue; + #endif + + if (u_ch == 0) { + u_band = dec_band[i]; + u_ch = dec_ch[i]; + u_bw = dec_bw[i]; + u_offset = dec_offset[i]; + rtw_adjust_bchbw(adapter, u_band, u_ch, &u_bw, &u_offset); + rtw_get_offset_by_bchbw(u_band, u_ch, u_bw, &u_offset); + } else { + enum band_type tmp_band = dec_band[i]; + u8 tmp_ch = dec_ch[i]; + u8 tmp_bw = dec_bw[i]; + u8 tmp_offset = dec_offset[i]; + + rtw_adjust_bchbw(adapter, tmp_band, tmp_ch, &tmp_bw, &tmp_offset); + rtw_get_offset_by_bchbw(tmp_band, tmp_ch, tmp_bw, &u_offset); + rtw_warn_on(!rtw_is_bchbw_grouped(u_band, u_ch, u_bw, u_offset, tmp_band, tmp_ch, tmp_bw, tmp_offset)); + rtw_sync_bchbw(&tmp_band, &tmp_ch, &tmp_bw, &tmp_offset, &u_band, &u_ch, &u_bw, &u_offset); + } + } + + #ifdef CONFIG_RTW_MESH + /* if ifbmp are all mesh, apply bw restriction */ + if (ifbmp_all_mesh) + rtw_mesh_adjust_bchbw(u_band, u_ch, &u_bw, &u_offset); + #endif + + RTW_INFO("%s ifbmp:0x%02x tmp union:%u,%u,%u,%u\n", __func__, ifbmp, u_band, u_ch, u_bw, u_offset); + + /* check if tmp dec union is usable */ + if (rtw_ap_ch_specific_chk(adapter, u_band, u_ch, &u_bw, &u_offset, __func__) == _FAIL) { + /* channel can't be used */ + if (req_ch > 0) { + /* specific channel and not from IE => don't change channel setting */ + goto exit; + } + goto choose_chbw; + } else if (rtw_chset_is_bchbw_non_ocp(chset, u_band, u_ch, u_bw, u_offset)) { + RTW_WARN("%s DFS channel %u,%u under non ocp\n", __func__, u_ch, u_bw); + if (req_ch > 0 && req_bw > REQ_BW_NONE) { + /* change_chbw with specific channel and specific bw, goto update_bss_chbw directly */ + goto update_bss_chbw; + } + } else + goto update_bss_chbw; + +choose_chbw: + by_int_info = req_ch == REQ_CH_INT_INFO ? 1 : 0; + if (req_band <= REQ_BAND_NONE || req_band >= BAND_MAX) { + /* band is unspecified/invalid means channel is also unspecified */ + req_ch = 0; + req_band = BAND_MAX; + } else if (req_ch <= REQ_CH_NONE) + req_ch = 0; + max_bw = req_bw > REQ_BW_NONE ? req_bw : CHANNEL_WIDTH_20; + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + iface = dvobj->padapters[i]; + + if (!rtw_iface_at_same_hwband(adapter, iface)) + continue; + + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + iface_link = GET_PRIMARY_LINK(iface); + mlmeext = &(iface_link->mlmeextpriv); + + if (req_bw <= REQ_BW_NONE) { + if (req_bw == REQ_BW_ORI) { + if (max_bw < iface_link->mlmepriv.ori_chandef.bw) + max_bw = iface_link->mlmepriv.ori_chandef.bw; + } else { + if (max_bw < cur_ie_bw[i]) + max_bw = cur_ie_bw[i]; + } + } + + if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate)) { + if (ori_ch == 0) { + ori_band = mlmeext->chandef.band; + ori_ch = mlmeext->chandef.chan; + ori_offset = mlmeext->chandef.offset; + } else if (ori_ch != mlmeext->chandef.chan) { + rtw_warn_on(1); + } else if (mlmeext->chandef.offset != CHAN_OFFSET_NO_EXT) { + if (ori_offset == CHAN_OFFSET_NO_EXT) + ori_offset = mlmeext->chandef.offset; + else if (ori_offset != mlmeext->chandef.offset) + rtw_warn_on(1); + } + } else { + if (ori_ch == 0) { + ori_band = cur_ie_band[i]; + ori_ch = cur_ie_ch[i]; + ori_offset = cur_ie_offset[i]; + } else if (ori_ch != cur_ie_ch[i]) { + rtw_warn_on(1); + } else if (cur_ie_offset[i] != CHAN_OFFSET_NO_EXT) { + if (ori_offset == CHAN_OFFSET_NO_EXT) + ori_offset = cur_ie_offset[i]; + else if (ori_offset != cur_ie_offset[i]) + rtw_warn_on(1); + } + } + } + req_offset = req_offset > REQ_OFFSET_NONE ? req_offset : CHAN_OFFSET_NO_EXT; + + ch_avail = rtw_rfctl_choose_bchbw(rfctl + , req_band, req_ch, max_bw, req_offset + , ori_band, ori_ch, ori_offset + , &u_band, &u_ch, &u_bw + , &u_offset, by_int_info, ifbmp_all_mesh, __func__); + if (ch_avail == _FALSE) + goto exit; + +update_bss_chbw: + for (i = 0; i < dvobj->iface_nums; i++) { + if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) + continue; + iface = dvobj->padapters[i]; + + if (!rtw_iface_at_same_hwband(adapter, iface)) + continue; + + dec_ch[i] = u_ch; + dec_band[i] = u_band; + if (dec_bw[i] > u_bw) + dec_bw[i] = u_bw; + if (dec_bw[i] == CHANNEL_WIDTH_20) + dec_offset[i] = CHAN_OFFSET_NO_EXT; + else + dec_offset[i] = u_offset; + + #ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(iface)) + rtw_mesh_adjust_bchbw(dec_band[i], dec_ch[i], &dec_bw[i], &dec_offset[i]); + #endif + } + + set_u_ch = _TRUE; + } + + ifbmp_ch_changed = rtw_ap_update_chbw_by_ifbmp(dvobj, ifbmp + , cur_ie_band, cur_ie_ch, cur_ie_bw, cur_ie_offset + , dec_band, dec_ch, dec_bw, dec_offset + , __func__); + + if (u_ch != 0) + RTW_INFO("%s union:%u,%u,%u,%u\n", __func__, u_band, u_ch, u_bw, u_offset); + + if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_SURVEY)) { + /* scanning, leave ch setting to scan state machine */ + set_u_ch = _FALSE; + RTW_INFO("%s, %d NG union:%u,%u,%u,%u\n" + , __FUNCTION__, __LINE__, u_band, u_ch, u_bw, u_offset); + } + + if (set_u_ch == _TRUE) { + chdef->band = u_band; + chdef->chan = u_ch; + chdef->bw = u_bw; + chdef->offset= u_offset; + } +exit: + return ifbmp_ch_changed; +} + +u8 rtw_ap_sta_states_check(_adapter *adapter) +{ + struct sta_info *psta; + struct sta_priv *pstapriv = &adapter->stapriv; + _list *plist, *phead; + u8 rst = _FALSE; + + if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter)) + return _FALSE; + + if (pstapriv->auth_list_cnt !=0) + return _TRUE; + + rtw_stapriv_asoc_list_lock(pstapriv); + phead = &pstapriv->asoc_list; + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + + if (!(psta->state & WIFI_ASOC_STATE)) { + RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under linking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state); + rst = _TRUE; + break; + } else if (psta->state & WIFI_UNDER_KEY_HANDSHAKE) { + RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under key handshaking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state); + rst = _TRUE; + break; + } + } + rtw_stapriv_asoc_list_unlock(pstapriv); + return rst; +} + +void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap) +{ + sta->capability = RTW_GET_LE16(cap); + if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + sta->flags |= WLAN_STA_SHORT_PREAMBLE; + else + sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; +} + +u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len) +{ + u8 rate_set[12]; + u8 rate_num; + int i; + u16 status = _STATS_SUCCESSFUL_; + + rtw_ies_get_supported_rate(tlv_ies, tlv_ies_len, rate_set, &rate_num); + if (rate_num == 0) { + RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" with no supported rate\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr)); + status = _STATS_FAILURE_; + goto exit; + } + + _rtw_memcpy(sta->bssrateset, rate_set, rate_num); + sta->bssratelen = rate_num; + + if (MLME_IS_AP(adapter)) { + /* this function force only CCK rates to be bassic rate... */ + UpdateBrateTblForSoftAP(sta->bssrateset, sta->bssratelen); + } + + /* if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) */ /* ? */ + sta->flags |= WLAN_STA_NONERP; + for (i = 0; i < sta->bssratelen; i++) { + if ((sta->bssrateset[i] & 0x7f) > 22) { + sta->flags &= ~WLAN_STA_NONERP; + break; + } + } + +exit: + return status; +} + +u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) +{ + struct security_priv *sec = &adapter->securitypriv; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + u8 *wpa_ie; + int wpa_ie_len; + int group_cipher = 0, pairwise_cipher = 0, gmcs = 0; + u32 akm = 0; + u8 mfp_opt = MFP_NO; + u8 spp_opt = 0; + u16 status = _STATS_SUCCESSFUL_; + + sta->dot8021xalg = 0; + sta->wpa_psk = 0; + sta->wpa_group_cipher = 0; + sta->wpa2_group_cipher = 0; + sta->wpa_pairwise_cipher = 0; + sta->wpa2_pairwise_cipher = 0; + sta->akm_suite_type = 0; + _rtw_memset(sta->wpa_ie, 0, sizeof(sta->wpa_ie)); + + if ((sec->wpa_psk & BIT(1)) && elems->rsn_ie) { + wpa_ie = elems->rsn_ie; + wpa_ie_len = elems->rsn_ie_len; + + if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, &akm, &mfp_opt, &spp_opt) == _SUCCESS) { + sta->dot8021xalg = 1;/* psk, todo:802.1x */ + sta->wpa_psk |= BIT(1); + + /* RSN optional field absent; the validation is already checked in rtw_rsne_info_parse() */ + if (!group_cipher) { + RTW_INFO("STA lacks WPA2 Group Suite Cipher --> Default\n"); + group_cipher = sec->wpa2_group_cipher; + } + if (!pairwise_cipher) { + RTW_INFO("STA lacks WPA2 Pairwise Suite Cipher --> Default\n"); + pairwise_cipher = sec->wpa2_pairwise_cipher; + } + if (!akm) { + RTW_INFO("STA lacks WPA2 AKM Cipher --> Default\n"); + akm = sec->akmp; + } + + sta->wpa2_group_cipher = group_cipher & sec->wpa2_group_cipher; + sta->wpa2_pairwise_cipher = pairwise_cipher & sec->wpa2_pairwise_cipher; + sta->akm_suite_type = akm; + + if (MLME_IS_AP(adapter) && (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) && (MFP_NO == mfp_opt)) { + status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + goto exit; + } + + /* RSN optional field exists but no match */ + if (!sta->wpa2_group_cipher) { + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + goto exit; + } + if (!sta->wpa2_pairwise_cipher) { + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + goto exit; + } + if (MLME_IS_AP(adapter) && (!CHECK_BIT(sec->akmp, akm))) { + status = WLAN_STATUS_AKMP_NOT_VALID; + goto exit; + } + } + else { + status = WLAN_STATUS_INVALID_IE; + goto exit; + } + } + else if ((sec->wpa_psk & BIT(0)) && elems->wpa_ie) { + wpa_ie = elems->wpa_ie; + wpa_ie_len = elems->wpa_ie_len; + + if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + sta->dot8021xalg = 1;/* psk, todo:802.1x */ + sta->wpa_psk |= BIT(0); + + sta->wpa_group_cipher = group_cipher & sec->wpa_group_cipher; + sta->wpa_pairwise_cipher = pairwise_cipher & sec->wpa_pairwise_cipher; + + if (!sta->wpa_group_cipher) { + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + goto exit; + } + + if (!sta->wpa_pairwise_cipher) { + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + goto exit; + } + } else { + status = WLAN_STATUS_INVALID_IE; + goto exit; + } + + } else { + wpa_ie = NULL; + wpa_ie_len = 0; + } + + if (sec->dot11PrivacyAlgrthm != _NO_PRIVACY_) { + /*check if amsdu is allowed */ + if (rtw_check_amsdu_disable(adapter->registrypriv.amsdu_mode, spp_opt) == _TRUE) + sta->flags |= WLAN_STA_AMSDU_DISABLE; + } + + /* mfp_opt=0 for WPS connection */ + if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS) && elems->wps_ie) + goto ignore_mfp_opt; + + if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt < MFP_OPTIONAL) + || (mfp_opt == MFP_REQUIRED && sec->mfp_opt < MFP_OPTIONAL) + ) { + status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + goto exit; + } +ignore_mfp_opt: + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(adapter)) { + /* MFP is mandatory for secure mesh */ + if (adapter->mesh_info.mesh_auth_id) + sta->flags |= WLAN_STA_MFP; + } else +#endif + if (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL) + sta->flags |= WLAN_STA_MFP; + +#ifdef CONFIG_IEEE80211W + if ((sta->flags & WLAN_STA_MFP) + && (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL) + && security_type_bip_to_gmcs(sec->dot11wCipher) != gmcs + ) { + status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + goto exit; + } +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + if (MLME_IS_AP(adapter) && + (sec->auth_type == MLME_AUTHTYPE_SAE) && + (CHECK_BIT(WLAN_AKM_TYPE_SAE, sta->akm_suite_type)) && + (WLAN_AUTH_OPEN == sta->authalg)) { + /* WPA3-SAE, PMK caching */ + if (rtw_cached_pmkid(adapter, sta->phl_sta->mac_addr) == -1) { + RTW_INFO("SAE: No PMKSA cache entry found\n"); + status = WLAN_STATUS_INVALID_PMKID; + goto exit; + } else { + RTW_INFO("SAE: PMKSA cache entry found\n"); + } + } +#endif /* CONFIG_IOCTL_CFG80211 */ + + if (!MLME_IS_AP(adapter)) + goto exit; + + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); + /* if (hapd->conf->wps_state && wpa_ie == NULL) { */ /* todo: to check ap if supporting WPS */ + if (wpa_ie == NULL) { + if (elems->wps_ie) { + RTW_INFO("STA included WPS IE in " + "(Re)Association Request - assume WPS is " + "used\n"); + sta->flags |= WLAN_STA_WPS; + /* wpabuf_free(sta->wps_ie); */ + /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ + /* elems.wps_ie_len - 4); */ + } else { + RTW_INFO("STA did not include WPA/RSN IE " + "in (Re)Association Request - possible WPS " + "use\n"); + sta->flags |= WLAN_STA_MAYBE_WPS; + } + + /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ + /* that the selected registrar of AP is _FLASE */ + if ((sec->wpa_psk > 0) + && (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) + ) { + struct mlme_priv *mlme = &adapter->mlmepriv; + + if (mlme->wps_beacon_ie) { + u8 selected_registrar = 0; + + rtw_get_wps_attr_content(mlme->wps_beacon_ie, mlme->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); + + if (!selected_registrar) { + RTW_INFO("selected_registrar is _FALSE , or AP is not ready to do WPS\n"); + status = _STATS_UNABLE_HANDLE_STA_; + goto exit; + } + } + } + + } else { + int copy_len; + + if (sec->wpa_psk == 0) { + RTW_INFO("STA " MAC_FMT + ": WPA/RSN IE in association request, but AP don't support WPA/RSN\n", + MAC_ARG(sta->phl_sta->mac_addr)); + status = WLAN_STATUS_INVALID_IE; + goto exit; + } + + if (elems->wps_ie) { + RTW_INFO("STA included WPS IE in " + "(Re)Association Request - WPS is " + "used\n"); + sta->flags |= WLAN_STA_WPS; + copy_len = 0; + } else + copy_len = ((wpa_ie_len + 2) > sizeof(sta->wpa_ie)) ? (sizeof(sta->wpa_ie)) : (wpa_ie_len + 2); + + if (copy_len > 0) + _rtw_memcpy(sta->wpa_ie, wpa_ie - 2, copy_len); + } + +exit: + return status; +} + +void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len) +{ + struct link_mlme_priv *mlme = &sta->padapter_link->mlmepriv; + unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; + u8 *p; + + sta->flags &= ~WLAN_STA_WME; + sta->qos_option = 0; + sta->qos_info = 0; + sta->has_legacy_ac = _TRUE; + sta->uapsd_vo = 0; + sta->uapsd_vi = 0; + sta->uapsd_be = 0; + sta->uapsd_bk = 0; + + if (!mlme->qospriv.qos_option) + goto exit; + +#ifdef CONFIG_RTW_MESH + if (MLME_IS_MESH(adapter)) { + /* QoS is mandatory in mesh */ + sta->flags |= WLAN_STA_WME; + } +#endif + + p = rtw_get_ie_ex(tlv_ies, tlv_ies_len, WLAN_EID_VENDOR_SPECIFIC, WMM_IE, 6, NULL, NULL); + if (!p) + goto exit; + + sta->flags |= WLAN_STA_WME; + sta->qos_option = 1; + sta->qos_info = *(p + 8); + sta->max_sp_len = (sta->qos_info >> 5) & 0x3; + + if ((sta->qos_info & 0xf) != 0xf) + sta->has_legacy_ac = _TRUE; + else + sta->has_legacy_ac = _FALSE; + + if (sta->qos_info & 0xf) { + if (sta->qos_info & BIT(0)) + sta->uapsd_vo = BIT(0) | BIT(1); + else + sta->uapsd_vo = 0; + + if (sta->qos_info & BIT(1)) + sta->uapsd_vi = BIT(0) | BIT(1); + else + sta->uapsd_vi = 0; + + if (sta->qos_info & BIT(2)) + sta->uapsd_bk = BIT(0) | BIT(1); + else + sta->uapsd_bk = 0; + + if (sta->qos_info & BIT(3)) + sta->uapsd_be = BIT(0) | BIT(1); + else + sta->uapsd_be = 0; + } + +exit: + return; +} + +void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) +{ + struct link_mlme_priv *mlme = &sta->padapter_link->mlmepriv; + + sta->flags &= ~WLAN_STA_HT; + +#ifdef CONFIG_80211N_HT + if (mlme->htpriv.ht_option == _FALSE) + goto exit; + + /* save HT capabilities in the sta object */ + _rtw_memset(&sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); + if (elems->ht_capabilities && elems->ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { + sta->flags |= WLAN_STA_HT; + sta->flags |= WLAN_STA_WME; + _rtw_memcpy(&sta->htpriv.ht_cap, elems->ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); + + if (elems->ht_operation && elems->ht_operation_len == HT_OP_IE_LEN) { + _rtw_memcpy(sta->htpriv.ht_op, elems->ht_operation, HT_OP_IE_LEN); + sta->htpriv.op_present = 1; + } + } +exit: +#endif + + return; +} + +void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) +{ + struct link_mlme_priv *mlme = &sta->padapter_link->mlmepriv; + + sta->flags &= ~WLAN_STA_VHT; + +#ifdef CONFIG_80211AC_VHT + if (mlme->vhtpriv.vht_option == _FALSE) + goto exit; + + _rtw_memset(&sta->vhtpriv, 0, sizeof(struct vht_priv)); + if (elems->vht_capabilities && elems->vht_capabilities_len == VHT_CAP_IE_LEN) { + sta->flags |= WLAN_STA_VHT; + _rtw_memcpy(sta->vhtpriv.vht_cap, elems->vht_capabilities, VHT_CAP_IE_LEN); + + if (elems->vht_operation && elems->vht_operation_len== VHT_OP_IE_LEN) { + _rtw_memcpy(sta->vhtpriv.vht_op, elems->vht_operation, VHT_OP_IE_LEN); + sta->vhtpriv.op_present = 1; + } + + if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) { + _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1); + sta->vhtpriv.notify_present = 1; + } + } +exit: +#endif + + return; +} + +void rtw_ap_parse_sta_he_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) +{ + struct link_mlme_priv *mlme = &sta->padapter_link->mlmepriv; + + sta->flags &= ~WLAN_STA_HE; + +#ifdef CONFIG_80211AX_HE + if (mlme->hepriv.he_option == _FALSE) + goto exit; + + _rtw_memset(&sta->hepriv, 0, sizeof(struct he_priv)); + if (elems->he_capabilities && (elems->he_capabilities_len <= HE_CAP_ELE_MAX_LEN)) { + sta->flags |= WLAN_STA_HE; + _rtw_memcpy(sta->hepriv.he_cap, elems->he_capabilities, elems->he_capabilities_len); + + if (elems->he_operation && (elems->he_operation_len <= HE_OPER_ELE_MAX_LEN)) { + _rtw_memcpy(sta->hepriv.he_op, elems->he_operation, elems->he_operation_len); + sta->hepriv.op_present = 1; + } + +#if 0 + if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) { + _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1); + sta->vhtpriv.notify_present = 1; + } +#endif + } +#if CONFIG_IEEE80211_BAND_6GHZ + if (elems->he_6g_band_cap && (elems->he_6g_band_cap_len == HE_6G_BAND_CAP_MAX_LEN)) { + sta->flags |= WLAN_STA_6G_BAND_CAP; + _rtw_memcpy(sta->hepriv.he_6g_band_cap, elems->he_6g_band_cap, elems->he_6g_band_cap_len); + } else { + sta->flags &= ~WLAN_STA_6G_BAND_CAP; + } +#endif +exit: +#endif + + return; +} + +void rtw_ap_parse_sta_multi_ap_ie(_adapter *adapter, struct sta_info *sta, u8 *ies, int ies_len) +{ + sta->flags &= ~WLAN_STA_MULTI_AP; + +#ifdef CONFIG_RTW_MULTI_AP + if (adapter->multi_ap + && (rtw_get_multi_ap_ie_ext(ies, ies_len) & MULTI_AP_BACKHAUL_STA) + ) { + if (adapter->multi_ap & MULTI_AP_BACKHAUL_BSS) /* with backhaul bss, enable WDS */ + sta->flags |= WLAN_STA_MULTI_AP | WLAN_STA_WDS; + else if (adapter->multi_ap & MULTI_AP_FRONTHAUL_BSS) /* fronthaul bss only */ + sta->flags |= WLAN_STA_MULTI_AP; + } +#endif +} + +#if CONFIG_RTW_AP_DATA_BMC_TO_UC +static bool rtw_ap_data_bmc_to_uc(_adapter *adapter + , const u8 *da, const u8 *sa, const u8 *ori_ta + , u16 os_qid, _list *b2u_list) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct xmit_priv *xmitpriv = &adapter->xmitpriv; + _list *head, *list; + struct sta_info *sta; + char b2u_sta_id[NUM_STA]; + u8 b2u_sta_num = 0; + bool bmc_need = _FALSE; + int i; + + rtw_stapriv_asoc_list_lock(stapriv); + head = &stapriv->asoc_list; + list = get_next(head); + + while ((rtw_end_of_queue_search(head, list)) == _FALSE) { + int stainfo_offset; + + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + stainfo_offset = rtw_stainfo_offset(stapriv, sta); + if (stainfo_offset_valid(stainfo_offset)) + b2u_sta_id[b2u_sta_num++] = stainfo_offset; + } + rtw_stapriv_asoc_list_unlock(stapriv); + + if (!b2u_sta_num) + goto exit; + + for (i = 0; i < b2u_sta_num; i++) { + struct xmit_frame *b2uframe = NULL; + struct pkt_attrib *attrib; + + sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]); + if (!(sta->state & WIFI_ASOC_STATE) + || _rtw_memcmp(sta->phl_sta->mac_addr, sa, ETH_ALEN) == _TRUE + || (ori_ta && _rtw_memcmp(sta->phl_sta->mac_addr, ori_ta, ETH_ALEN) == _TRUE) + || is_broadcast_mac_addr(sta->phl_sta->mac_addr) + || is_zero_mac_addr(sta->phl_sta->mac_addr)) + continue; + + if (core_tx_alloc_xmitframe(adapter, &b2uframe, os_qid) == FAIL) { + bmc_need = _TRUE; + break; + } + + attrib = &b2uframe->attrib; + + _rtw_memcpy(attrib->ra, sta->phl_sta->mac_addr, ETH_ALEN); + _rtw_memcpy(attrib->ta, sta->padapter_link->mac_addr, ETH_ALEN); + #ifdef CONFIG_RTW_WDS + if (adapter_use_wds(adapter) && (sta->flags & WLAN_STA_WDS)) { + _rtw_memcpy(attrib->dst, da, ETH_ALEN); + attrib->wds = 1; + } else + #endif + _rtw_memcpy(attrib->dst, attrib->ra, ETH_ALEN); + _rtw_memcpy(attrib->src, sa, ETH_ALEN); + + rtw_list_insert_tail(&b2uframe->list, b2u_list); + } + +exit: + return bmc_need; +} + +void dump_ap_b2u_flags(void *sel, _adapter *adapter) +{ + RTW_PRINT_SEL(sel, "%4s %4s\n", "src", "fwd"); + RTW_PRINT_SEL(sel, "0x%02x 0x%02x\n", adapter->b2u_flags_ap_src, adapter->b2u_flags_ap_fwd); +} +#endif /* CONFIG_RTW_AP_DATA_BMC_TO_UC */ + +static int rtw_ap_nexthop_resolve(_adapter *adapter, struct xmit_frame *xframe) +{ + struct pkt_attrib *attrib = &xframe->attrib; + int ret = _SUCCESS; + +#ifdef CONFIG_RTW_WDS + if (adapter_use_wds(adapter)) { + if (rtw_wds_nexthop_lookup(adapter, attrib->dst, attrib->ra) == 0) { + if (_rtw_memcmp(attrib->dst, attrib->ra, ETH_ALEN) == _FALSE) + attrib->wds = 1; + } else { + ret = _FAIL; + } + } else +#endif + _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN); + + return ret; +} + +#ifdef CONFIG_RTW_WDS +static void rtw_ap_data_flood_for_unknown_da(_adapter *adapter, const u8 *da, + const u8 *sa, const u8 *ori_ta, + u16 os_qid, _list *f_list) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct xmit_priv *xmitpriv = &adapter->xmitpriv; + _list *head, *list; + struct sta_info *sta; + char sta_id[NUM_STA]; + u8 sta_num = 0; + int i; + + rtw_stapriv_asoc_list_lock(stapriv); + head = &stapriv->asoc_list; + list = get_next(head); + + while ((rtw_end_of_queue_search(head, list)) == _FALSE) { + int stainfo_offset; + + sta = LIST_CONTAINOR(list, struct sta_info, asoc_list); + list = get_next(list); + + stainfo_offset = rtw_stainfo_offset(stapriv, sta); + if (stainfo_offset_valid(stainfo_offset)) + sta_id[sta_num++] = stainfo_offset; + } + + rtw_stapriv_asoc_list_unlock(stapriv); + + if (!sta_num) + goto exit; + + for (i = 0; i < sta_num; i++) { + struct xmit_frame *frame; + struct pkt_attrib *attrib; + + sta = rtw_get_stainfo_by_offset(stapriv, sta_id[i]); + if (!(sta->state & WIFI_ASOC_STATE) + || !(sta->flags & WLAN_STA_WDS) + || _rtw_memcmp(sta->phl_sta->mac_addr, sa, ETH_ALEN) == _TRUE + || (ori_ta && _rtw_memcmp(sta->phl_sta->mac_addr, ori_ta, ETH_ALEN) == _TRUE) + || is_broadcast_mac_addr(sta->phl_sta->mac_addr) + || is_zero_mac_addr(sta->phl_sta->mac_addr)) + continue; + + if (core_tx_alloc_xmitframe(adapter, &frame, os_qid) == FAIL) + break; + + attrib = &frame->attrib; + + _rtw_memcpy(attrib->ra, sta->phl_sta->mac_addr, ETH_ALEN); + _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(attrib->dst, da, ETH_ALEN); + _rtw_memcpy(attrib->src, sa, ETH_ALEN); + attrib->wds = 1; + + rtw_list_insert_tail(&frame->list, f_list); + } + +exit: + return; +} +#endif /* CONFIG_RTW_WDS */ + +int rtw_ap_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, + struct sk_buff *pkt, _list *f_list) +{ + struct pkt_file pktfile; + struct ethhdr etherhdr; + struct pkt_attrib *attrib; + u8 is_da_mcast; + + int res = _SUCCESS; + + _rtw_open_pktfile(pkt, &pktfile); + if (_rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN) != ETH_HLEN) { + res = _FAIL; + goto exit; + } + + xframe->pkt = pkt; +#if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC + _rtw_init_listhead(f_list); +#endif + + is_da_mcast = IS_MCAST(etherhdr.h_dest); + if (is_da_mcast) { + #if CONFIG_RTW_AP_DATA_BMC_TO_UC + if (rtw_ap_src_b2u_policy_chk(adapter->b2u_flags_ap_src, etherhdr.h_dest) + && adapter->registrypriv.wifi_spec == 0 + && adapter->xmitpriv.free_xmitframe_cnt > (NR_XMITFRAME / 4)) { + if (rtw_ap_data_bmc_to_uc(adapter, etherhdr.h_dest, + etherhdr.h_source, NULL, + os_qid, f_list) == 0) { + res = RTW_ORI_NO_NEED; + goto exit; + } + } + #endif + } + + attrib = &xframe->attrib; + + _rtw_memcpy(attrib->dst, etherhdr.h_dest, ETH_ALEN); + _rtw_memcpy(attrib->src, etherhdr.h_source, ETH_ALEN); + _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + + if (is_da_mcast) { + _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN); + } else { + res = rtw_ap_nexthop_resolve(adapter, xframe); + #ifdef CONFIG_RTW_WDS + if (res != _SUCCESS) { + /* unknown DA, flood frame to every WDS STA */ + rtw_ap_data_flood_for_unknown_da(adapter, etherhdr.h_dest, + etherhdr.h_source, NULL, + os_qid, f_list); + res = RTW_ORI_NO_NEED; + } + #endif + } + +exit: + return res; +} + +int rtw_ap_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + u8 *whdr = get_recvframe_data(rframe); + u8 is_ra_bmc = 0; + sint ret = _FAIL; + + if (!(MLME_STATE(adapter) & WIFI_ASOC_STATE)) + goto exit; + + switch (rattrib->to_fr_ds) { + case 2: + if (IS_MCAST(GetAddr1Ptr(whdr))) + goto exit; + _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + _rtw_memcpy(rattrib->src, get_addr2_ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->bssid, GetAddr1Ptr(whdr), ETH_ALEN); + break; + case 3: + is_ra_bmc = IS_MCAST(GetAddr1Ptr(whdr)) ? 1 : 0; + _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN); + _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + _rtw_memcpy(rattrib->src, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */ + if (!is_ra_bmc) + _rtw_memcpy(rattrib->bssid, GetAddr1Ptr(whdr), ETH_ALEN); + break; + default: + ret = RTW_RX_HANDLED; /* don't count for drop */ + goto exit; + } + + if (rattrib->addr_cam_vld) + *sta = rtw_get_stainfo_by_macid(stapriv, rattrib->macid); + else + *sta = rtw_get_stainfo(stapriv, rattrib->ta); + + if (*sta == NULL) { + if (!is_ra_bmc && !IS_RADAR_DETECTED(adapter_to_rfctl(adapter))) { + #ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL + RTW_INFO(FUNC_ADPT_FMT" issue_deauth to "MAC_FMT" with reason(7), unknown TA\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(rattrib->ta)); + issue_deauth(adapter, rattrib->ta, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); + #endif + } + ret = RTW_RX_HANDLED; + goto exit; + } + +#ifdef CONFIG_RTW_WDS_AUTO_EN + if (rattrib->to_fr_ds == 3 && !(sta->flags & WLAN_STA_WDS)) + sta->flags |= WLAN_STA_WDS; +#endif + + _rtw_spinlock_bh(&stapriv->active_time_lock); + if ((*sta)->start_active == _FALSE) { + (*sta)->start_active = _TRUE; + (*sta)->start_active_time = rtw_get_current_time(); + (*sta)->latest_active_time = (*sta)->start_active_time; + } else { + (*sta)->latest_active_time = rtw_get_current_time(); + } + _rtw_spinunlock_bh(&stapriv->active_time_lock); + + process_pwrbit_data(adapter, rframe, *sta); + + if ((get_frame_sub_type(whdr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) + process_wmmps_data(adapter, rframe, *sta); + + if (get_frame_sub_type(whdr) & BIT(6)) { + /* No data, will not indicate to upper layer, temporily count it here */ + count_rx_stats(adapter, rframe, *sta); + ret = RTW_RX_HANDLED; + goto exit; + } + + ret = _SUCCESS; + +exit: + return ret; +} + +int rtw_ap_rx_msdu_act_check(union recv_frame *rframe + , const u8 *da, const u8 *sa + , u8 *msdu, enum rtw_rx_llc_hdl llc_hdl + , struct xmit_frame **fwd_frame, _list *f_list) +{ + _adapter *adapter = rframe->u.hdr.adapter; + struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib; + struct rtw_wds_path *wpath; + u8 is_da_bmc = IS_MCAST(da); + u8 is_da_self = !is_da_bmc && _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN); + u8 is_da_peer = 0; + int in_wds_tbl = 0; + u16 os_qid; + struct xmit_frame *xframe; + struct pkt_attrib *xattrib; + u8 fwd_ra[ETH_ALEN] = {0}; + int act = 0; + +#ifdef CONFIG_RTW_WDS + /* update/create wds info for SA, RA */ + if (adapter_use_wds(adapter) + && (rframe->u.hdr.psta->state & WIFI_ASOC_STATE) + && _rtw_memcmp(sa, rframe->u.hdr.psta->phl_sta->mac_addr, ETH_ALEN) == _FALSE + ) { + rtw_rcu_read_lock(); + wpath = rtw_wds_path_lookup(adapter, sa); + if (!wpath) + rtw_wds_path_add(adapter, sa, rframe->u.hdr.psta); + else { + rtw_wds_path_assign_nexthop(wpath, rframe->u.hdr.psta); + wpath->last_update = rtw_get_current_time(); + } + rtw_rcu_read_unlock(); + } +#endif + + /* SA is self, need no further process */ + if (_rtw_memcmp(sa, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE) + goto exit; + + if (is_da_bmc) { + /* DA is bmc addr */ + act |= RTW_RX_MSDU_ACT_INDICATE; + if (adapter->mlmepriv.ap_isolate) + goto exit; + goto fwd_chk; + + } + + if (is_da_self) { + /* DA is self, indicate */ + act |= RTW_RX_MSDU_ACT_INDICATE; + goto exit; + } + + /* DA is not self */ +#ifdef CONFIG_RTW_WDS + if (adapter_use_wds(adapter)) + in_wds_tbl = rtw_wds_nexthop_lookup(adapter, da, fwd_ra) == 0; +#endif + if (!in_wds_tbl) + is_da_peer = rtw_get_stainfo(&adapter->stapriv, da) ? 1 : 0; + + if (in_wds_tbl || is_da_peer) { + /* DA is known (peer or can be forwarded by peer) */ + if (adapter->mlmepriv.ap_isolate) { + #if defined(DBG_RX_DROP_FRAME) + RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") through peer, ap_isolate\n" + , FUNC_ADPT_ARG(adapter), MAC_ARG(da)); + #endif + goto exit; + } + goto fwd_chk; + } + + /* DA is unknown*/ + act |= RTW_RX_MSDU_ACT_INDICATE; + if (adapter->mlmepriv.ap_isolate) { + /* + * unknown DA and ap_isolate, indicate only + * (bridge will not forward packets to originating port) + */ + goto exit; + } + +fwd_chk: + + if (adapter->stapriv.asoc_list_cnt <= 1) + goto exit; + + os_qid = rtw_os_recv_select_queue(msdu, llc_hdl); + +#if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC + _rtw_init_listhead(f_list); +#endif + +#if CONFIG_RTW_AP_DATA_BMC_TO_UC + if (is_da_bmc) { + if (rtw_ap_fwd_b2u_policy_chk(adapter->b2u_flags_ap_fwd, da, rattrib->to_fr_ds == 3 && !IS_MCAST(rattrib->ra)) + && adapter->registrypriv.wifi_spec == 0 + && adapter->xmitpriv.free_xmitframe_cnt > (NR_XMITFRAME / 4) + ) { + if (rtw_ap_data_bmc_to_uc(adapter + , da, sa, rframe->u.hdr.psta->phl_sta->mac_addr + , os_qid, f_list) == 0 + ) { + if (!rtw_is_list_empty(f_list)) + goto set_act_fwd; + else + goto exit; + } + } + } else +#endif +#ifdef CONFIG_RTW_WDS + if (adapter_use_wds(adapter) && !in_wds_tbl && !is_da_peer) { + /* unknown DA, flood frame to every WDS STA except receiving one */ + rtw_ap_data_flood_for_unknown_da(adapter + , da, sa, rframe->u.hdr.psta->phl_sta->mac_addr + , os_qid, f_list); + if (!rtw_is_list_empty(f_list)) + goto set_act_fwd; + else + goto exit; + } else +#endif + ; + + if (core_tx_alloc_xmitframe(adapter, &xframe, os_qid) == FAIL) { + #ifdef DBG_TX_DROP_FRAME + RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" core_tx_alloc_xmitframe fail\n" + , FUNC_ADPT_ARG(adapter)); + #endif + goto exit; + } + + xattrib = &xframe->attrib; + + _rtw_memcpy(xattrib->dst, da, ETH_ALEN); + _rtw_memcpy(xattrib->src, sa, ETH_ALEN); + _rtw_memcpy(xattrib->ta, adapter_mac_addr(adapter), ETH_ALEN); + + #ifdef CONFIG_RTW_WDS + if (in_wds_tbl && _rtw_memcmp(da, fwd_ra, ETH_ALEN) == _FALSE) { + _rtw_memcpy(xattrib->ra, fwd_ra, ETH_ALEN); + xattrib->wds = 1; + } else + #endif + _rtw_memcpy(xattrib->ra, da, ETH_ALEN); + + *fwd_frame = xframe; + +#if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC +set_act_fwd: +#endif + act |= RTW_RX_MSDU_ACT_FORWARD; + +exit: + return act; +} + +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT +void rtw_issue_action_token_req(_adapter *padapter, struct sta_info *pstat) +{ + /* Token Request Format + Category code : 1 Byte + Action code : 1 Byte + Element field: 4 Bytes, the duration of data transmission requested for the station. + */ + + u8 val = 0x0; + u8 category = RTW_WLAN_CATEGORY_TBTX; + u32 tbtx_duration = TBTX_TX_DURATION*1000; + u8 *pframe; + unsigned short *fctrl; + struct xmit_frame *pmgntframe; + struct pkt_attrib *pattrib; + struct rtw_ieee80211_hdr *pwlanhdr; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct _ADAPTER_LINK *padapter_link = pstat->padapter_link; + struct link_mlme_ext_info *lmlmeinfo = &(padapter_link->mlmeextpriv,mlmext_info); + WLAN_BSSID_EX *pnetwork = &(lmlmeinfo->network); + + + if (alink_regu_block_tx(padapter_link)) + return; + + RTW_DBG("%s: %6ph\n", __FUNCTION__, pstat->phl_sta->mac_addr); + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (pmgntframe == NULL) + return; + + /* update attribute */ + pattrib = &pmgntframe->attrib; + update_mgnt_tx_rate(padapter, padapter_link, IEEE80211_OFDM_RATE_24MB); // issue action request using OFDM rate? 20190320 Bruce add + update_mgntframe_attrib(padapter, padapter_link, pattrib); + + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + + pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->phl_sta->mac_addr, ETH_ALEN); + _rtw_memcpy((void *)get_addr2_ptr(pwlanhdr), padapter_link->mac_addr, ETH_ALEN); + _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pnetwork->network)), ETH_ALEN); + + SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); + pmlmeext->mgnt_seq++; + set_frame_sub_type(pframe, WIFI_ACTION); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); + pframe = rtw_set_fixed_ie(pframe, 1, &(val), &(pattrib->pktlen)); + pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(tbtx_duration), &(pattrib->pktlen)); + + pattrib->last_txcmdsz = pattrib->pktlen; + padapter->stapriv.last_token_holder = pstat; + dump_mgntframe(padapter, pmgntframe); + +} +#endif /* CONFIG_RTW_TOKEN_BASED_XMIT */ + +void rtw_ap_set_sta_wmode(_adapter *padapter, struct sta_info *sta) +{ + struct link_mlme_priv *pmlmepriv = &(sta->padapter_link->mlmepriv); + WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; + enum wlan_mode network_type = WLAN_MD_INVALID; + +#ifdef CONFIG_80211AX_HE + if (sta->hepriv.he_option == _TRUE) + network_type = WLAN_MD_11AX; +#endif +#ifdef CONFIG_80211AC_VHT + if (network_type == WLAN_MD_INVALID) { + if (sta->vhtpriv.vht_option == _TRUE) + network_type = WLAN_MD_11AC; + } +#endif +#ifdef CONFIG_80211N_HT + if (network_type == WLAN_MD_INVALID) { + if (sta->htpriv.ht_option == _TRUE) + network_type = WLAN_MD_11N; + } +#endif + + if (pcur_network->Configuration.DSConfig > 14) + network_type |= WLAN_MD_11A; + else { + if ((cckratesonly_included(sta->bssrateset, sta->bssratelen)) == _TRUE) + network_type |= WLAN_MD_11B; + else if ((cckrates_included(sta->bssrateset, sta->bssratelen)) == _TRUE) + network_type |= WLAN_MD_11BG; + else + network_type |= WLAN_MD_11G; + } + + sta->phl_sta->wmode = network_type; +} + +#if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS) +void rtw_acs_start(_adapter *padapter) +{ + RTW_INFO(FUNC_ADPT_FMT" not support\n", FUNC_ADPT_ARG(padapter)); +} + +void rtw_acs_stop(_adapter *padapter) +{ + RTW_INFO(FUNC_ADPT_FMT" not support\n", FUNC_ADPT_ARG(padapter)); +} +#endif /* defined(CONFIG_RTW_ACS) && defined(WKARD_ACS) */ + +#ifdef CONFIG_AP_CMD_DISPR + +static enum rtw_phl_status _ap_start_swch_start_notify(struct _ADAPTER *padapter) +{ + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct rtw_wifi_role_t *role = padapter->phl_role; + enum rtw_phl_status status; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SWCH_START); + + msg.band_idx = padapter->ap_start_cmd_bidx; + msg.rsvd[0].ptr = (u8*)role; + + status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d), + &msg, &attr, NULL); + + return status; +} + +static void _ap_start_swch_done_notify_cb(void *priv, struct phl_msg *msg) +{ + struct _ADAPTER *a = (struct _ADAPTER *)priv; + + + RTW_DBG(FUNC_ADPT_FMT ": ap_start_cmd_state=%u\n", + FUNC_ADPT_ARG(a), a->ap_start_cmd_state); + + if (msg->inbuf) { + rtw_vmfree(msg->inbuf, msg->inlen); + msg->inbuf = NULL; + } +} + +static enum rtw_phl_status +_ap_start_swch_done_notify(struct _ADAPTER *a, struct rtw_chan_def *chandef) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + u8 *info = NULL; + enum rtw_phl_status status; + + + info = rtw_vmalloc(sizeof(struct rtw_chan_def)); + if (!info) { + RTW_ERR(FUNC_ADPT_FMT ": Allocate msg hub buffer fail!\n", + FUNC_ADPT_ARG(a)); + return RTW_PHL_STATUS_RESOURCE; + } + _rtw_memcpy(info, chandef, sizeof(struct rtw_chan_def)); + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SWCH_DONE); + + msg.band_idx = a->ap_start_cmd_bidx; + msg.inbuf = info; + msg.inlen = sizeof(struct rtw_chan_def); + + attr.completion.completion = _ap_start_swch_done_notify_cb; + attr.completion.priv = a; + + status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d), + &msg, &attr, NULL); + if (status != RTW_PHL_STATUS_SUCCESS) { + rtw_vmfree(info, sizeof(struct rtw_chan_def)); + RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n", + FUNC_ADPT_ARG(a), status); + } + + return status; +} + +static void _ap_start_end_notify_cb(void *priv, struct phl_msg *msg) +{ + + if (msg->inbuf) { + rtw_vmfree(msg->inbuf, msg->inlen); + msg->inbuf = NULL; + } +} + +static enum rtw_phl_status +_ap_start_end_notify(struct _ADAPTER *padapter, bool success, bool abort) +{ + struct rtw_wifi_role_t *role = padapter->phl_role; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + u8 *info = NULL; + + RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_START\n", FUNC_ADPT_ARG(padapter)); + + info = rtw_vmalloc(sizeof(u8)); + if (info == NULL) { + RTW_ERR("%s: alloc buffer failed!\n", __func__); + return RTW_PHL_STATUS_RESOURCE; + } + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_START_END); + if (success) { + *info = RTW_PHL_STATUS_SUCCESS; + } else { + *info = RTW_PHL_STATUS_FAILURE; + } + + msg.inbuf = info; + msg.inlen = 1; + msg.band_idx = padapter->ap_start_cmd_bidx; + msg.rsvd[0].ptr = (u8*)role; + + if(abort) + attr.opt = MSG_OPT_SEND_IN_ABORT; + attr.completion.completion = _ap_start_end_notify_cb; + attr.completion.priv = padapter; + + + status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d), + &msg, &attr, NULL); + if (status != RTW_PHL_STATUS_SUCCESS) { + rtw_vmfree(info, sizeof(u8)); + RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n", + FUNC_ADPT_ARG(padapter), status); + } + + return status; +} + +static void ap_free_cmdobj(struct cmd_obj *pcmd) +{ + struct _ADAPTER *padapter = NULL; + + if (!pcmd) + return; + + padapter = pcmd->padapter; + if (!padapter) + return; + + if (pcmd->sctx) { + if (pcmd->res == H2C_SUCCESS) + rtw_sctx_done(&pcmd->sctx); + else + rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); + } + + rtw_free_cmd_obj(pcmd); + + return; +} + +static void _ap_start_cmd_done(struct cmd_obj *pcmd) +{ + struct _ADAPTER *padapter = pcmd->padapter; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct rtw_wifi_role_t *role = padapter->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *mlme = &(alink->mlmepriv); + enum rtw_phl_status status; + + if (pcmd->cmd_token == 0){ + RTW_ERR("%s : token is NULL!\n", __func__); + return; + } + + status = rtw_phl_free_cmd_token(GET_PHL_INFO(d), + padapter->ap_start_cmd_bidx, + &(pcmd->cmd_token)); + + padapter->ap_start_cmd_state = 0; + + if (status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR(FUNC_ADPT_FMT ": free_cmd_token fail(0x%x)!\n", + FUNC_ADPT_ARG(padapter), status); + + ap_free_cmdobj(pcmd); + + rtw_indicate_connect(padapter); + mlme->cur_network.join_res = _TRUE; /* for check if already set beacon */ + + RTW_INFO("%s\n", __func__); +} + +enum rtw_phl_status rtw_free_bcn_entry(struct _ADAPTER *padapter){ + + struct dvobj_priv *d = adapter_to_dvobj(padapter); + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + +#ifdef RTW_PHL_BCN + status = rtw_phl_free_bcn_entry(d->phl, padapter_link->wrlink); + if (status != RTW_PHL_STATUS_SUCCESS) { + RTW_INFO("%s - phl_free_bcn_entry failed\n", __func__); + } +#endif + + return status; +} + +static enum phl_mdl_ret_code _ap_start_req_acquired(void *dispr, void *priv) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct createbss_parm *parm = (struct createbss_parm *)pcmd->parmbuf; + struct rtw_wifi_role_t *role = padapter->phl_role; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + padapter->ap_start_cmd_bidx = pcmd->band_idx; + + rtw_core_ap_chan_decision(padapter, parm); + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_START_PREPARE); + msg.band_idx = padapter->ap_start_cmd_bidx; + + status = rtw_phl_send_msg_to_dispr(dvobj->phl, + &msg, + &attr, + NULL); + if (status != RTW_PHL_STATUS_SUCCESS) { + #ifdef CONFIG_DBCC_SUPPORT + if (parm->is_trigger_dbcc == _TRUE) + rtw_phl_mr_cancel_dbcc_action(dvobj->phl); + #endif + return MDL_RET_FAIL; + } else { + SET_STATUS_FLAG(padapter->ap_start_cmd_state, CMD_APSTART_ACQUIRE); + return MDL_RET_SUCCESS; + } +} + +static enum phl_mdl_ret_code _ap_start_req_abort(void *dispr, void *priv) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + + if (TEST_STATUS_FLAG(padapter->ap_start_cmd_state, CMD_APSTART_ACQUIRE)) { + status = _ap_start_end_notify(padapter, false, true); + } + + padapter->ap_start_cmd_state = 0; + RTW_INFO("%s\n", __func__); + return MDL_RET_SUCCESS; +} + +const char *ap_get_evt_str(u32 evt) +{ + switch (evt) { + /* AP */ + case MSG_EVT_AP_START_PREPARE: + return "MSG_EVT_AP_START_PREPARE"; + case MSG_EVT_AP_START: + return "MSG_EVT_AP_START"; + case MSG_EVT_AP_START_END: + return "MSG_EVT_AP_START_END"; + case MSG_EVT_AP_STOP_PREPARE: + return "MSG_EVT_AP_STOP_PREPARE"; + case MSG_EVT_AP_STOP: + return "MSG_EVT_AP_STOP"; + case MSG_EVT_AP_STOP_END: + return "MSG_EVT_AP_STOP_END"; + + case MSG_EVT_SWCH_START: + return "MSG_EVT_SWCH_START"; + case MSG_EVT_SWCH_DONE: + return "MSG_EVT_SWCH_DONE"; + case MSG_EVT_ROLE_NTFY: + return "MSG_EVT_ROLE_NTFY"; + + /* STA */ + case MSG_EVT_CONNECT_START: + return "MSG_EVT_CONNECT_START"; + case MSG_EVT_CONNECT_LINKED: + return "MSG_EVT_CONNECT_LINKED"; + case MSG_EVT_CONNECT_END: + return "MSG_EVT_CONNECT_END"; + case MSG_EVT_DISCONNECT_PREPARE: + return "MSG_EVT_DISCONNECT_PREPARE"; + case MSG_EVT_DISCONNECT: + return "MSG_EVT_DISCONNECT"; + + case MSG_EVT_DBCC_DISABLE: + return "MSG_EVT_DBCC_DISABLE"; + default: + printk("%s evt=0x%08x\n",__func__, evt); + return "unknown EVT"; + } +} + +static enum phl_mdl_ret_code _ap_start_req_ev_hdlr(void *dispr, void *priv, struct phl_msg *msg) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct createbss_parm *parm = (struct createbss_parm *)pcmd->parmbuf; + struct rtw_wifi_role_t *wifi_role = padapter->phl_role; + struct rtw_phl_com_t *phl_com = wifi_role->phl_com; + void *d = phlcom_to_drvpriv(phl_com); + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": + msg_id=0x%08x\n", + FUNC_ADPT_ARG(padapter), msg->msg_id); + + if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_START) { + /*RTW_INFO(FUNC_ADPT_FMT ": Message is not from ap start module, " + "skip msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));*/ + return MDL_RET_IGNORE; + } + + RTW_INFO("[AP_START] %s("ADPT_FMT")\n", + ap_get_evt_str(MSG_EVT_ID_FIELD(msg->msg_id)), ADPT_ARG(padapter)); + + if (IS_MSG_FAIL(msg->msg_id)) { + RTW_WARN(FUNC_ADPT_FMT ": cmd dispatcher notify cmd failure on " + "msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + } + + switch (MSG_EVT_ID_FIELD(msg->msg_id)) { + case MSG_EVT_AP_START_PREPARE: + + if ((parm->req_ch == 0 && + pmlmeinfo->state == WIFI_FW_AP_STATE) || + parm->req_ch != 0 + ) + rtw_core_ap_prepare(padapter, parm); + + status = _ap_start_swch_start_notify(padapter); + if(status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR("%s :: [MSG_EVT_AP_START_PREPARE] rtw_phl_send_msg_to_dispr failed\n", __func__); + break; + + case MSG_EVT_SWCH_START: + rtw_core_ap_swch_start(padapter, parm); + status = _ap_start_swch_done_notify(padapter, &padapter_link->wrlink->chandef); + if(status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR("%s :: [SWCH_START] rtw_phl_send_msg_to_dispr failed\n", __func__); + break; + + case MSG_EVT_SWCH_DONE: + status = rtw_phl_ap_started(adapter_to_dvobj(padapter)->phl, + padapter->ap_start_cmd_bidx, padapter->phl_role); + if(status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR("%s :: [MSG_EVT_SWCH_DONE] rtw_phl_send_msg_to_dispr failed\n", __func__); + break; + + case MSG_EVT_AP_START: + rtw_core_ap_start(padapter, parm); /* send beacon */ + status = _ap_start_end_notify(padapter, true, false); + break; + + case MSG_EVT_AP_START_END: + + if (msg->inbuf == NULL) { + RTW_WARN("[MSG_EVT_AP_START_END] Msg info buffer NULL!\n"); + break; + } + + if (*(msg->inbuf) == RTW_PHL_STATUS_FAILURE){ + RTW_WARN("[MSG_EVT_AP_START_END] Msg_inbuf is FAIL!\n"); + stop_ap_hdl(padapter); + } + + _ap_start_cmd_done(pcmd); + break; + + default: + /* unknown state */ + break; + } + + + if (status != RTW_PHL_STATUS_SUCCESS) { + /* Trigger stop AP flow when start AP failure */ + stop_ap_hdl(padapter); + _ap_start_cmd_done(pcmd); + } + + return MDL_RET_SUCCESS; +} + +static enum phl_mdl_ret_code _ap_start_req_set_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + + return MDL_RET_IGNORE; +} + +static enum phl_mdl_ret_code _ap_start_req_query_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + enum phl_mdl_ret_code ret = MDL_RET_IGNORE; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + + switch (info->op_code) { + case FG_REQ_OP_GET_ROLE: + info->outbuf = (u8*)padapter->phl_role; + ret = MDL_RET_SUCCESS; + break; + + case FG_REQ_OP_GET_ROLE_LINK: + info->outbuf = (u8*)padapter_link->wrlink; + ret = MDL_RET_SUCCESS; + break; + + default: + break; + } + + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + return ret; +} + +static void rtw_cmd_ap_start_req_init(struct cmd_obj *pcmd, struct phl_cmd_token_req *fgreq) +{ + struct _ADAPTER *padapter = pcmd->padapter; + u8 res = _SUCCESS; + + /* Fill foreground command request */ + fgreq->module_id= PHL_FG_MDL_AP_START; + fgreq->opt = FG_CMD_OPT_EXCLUSIVE; + fgreq->priv = pcmd; + fgreq->role = padapter->phl_role; + + fgreq->acquired = _ap_start_req_acquired; + fgreq->abort = _ap_start_req_abort; + fgreq->msg_hdlr = _ap_start_req_ev_hdlr; + fgreq->set_info = _ap_start_req_set_info; + fgreq->query_info = _ap_start_req_query_info; + + padapter->ap_start_cmd_state = 0; + pcmd->cmd_token = 0; + + RTW_INFO("%s\n", __func__); +} + +enum rtw_phl_status rtw_ap_start_cmd(struct cmd_obj *pcmd) +{ + struct _ADAPTER *padapter = pcmd->padapter; + struct phl_cmd_token_req fgreq={0}; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + enum rtw_phl_status status; + struct rtw_wifi_role_t *role = padapter->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + rtw_mi_set_scan_deny(padapter, 2000); + rtw_cmd_ap_start_req_init(pcmd, &fgreq); + + RTW_DBG(FUNC_ADPT_FMT ": \n", FUNC_ADPT_ARG(padapter)); + + /* cmd_dispatcher would copy whole phl_cmd_token_req */ + status = rtw_phl_add_cmd_token_req(d->phl, padapter_link->wrlink->hw_band, &fgreq, &(pcmd->cmd_token)); + if ((status != RTW_PHL_STATUS_SUCCESS) && + (status != RTW_PHL_STATUS_PENDING)) + goto error; + + status = RTW_PHL_STATUS_SUCCESS; + +error: + return status; + +} + +static void _ap_stop_cmd_done(struct cmd_obj *pcmd) +{ + struct _ADAPTER *padapter = pcmd->padapter; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct rtw_wifi_role_t *role = padapter->phl_role; + enum rtw_phl_status status; + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + + if (!padapter->ap_stop_cmd_token){ + RTW_ERR("%s : token is NULL!\n", __func__); + return; + } + + status = rtw_phl_free_cmd_token(GET_PHL_INFO(d), + padapter->ap_stop_cmd_bidx, + &padapter->ap_stop_cmd_token); + + padapter->ap_stop_cmd_token = 0; + padapter->ap_stop_cmd_state = 0; + if (status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR(FUNC_ADPT_FMT ": free_cmd_token fail(0x%x)!\n", + FUNC_ADPT_ARG(padapter), status); + + ap_free_cmdobj(pcmd); + rtw_ap_stop_set_state(padapter, AP_STOP_ST_DONE); + + RTW_INFO(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); +} + +static enum rtw_phl_status _ap_stop_ap_stop_notify(struct _ADAPTER *adapter) +{ + struct dvobj_priv *d = adapter_to_dvobj(adapter); + struct rtw_wifi_role_t *role = adapter->phl_role; + enum rtw_phl_status status; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_STOP); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_STOP); + + msg.band_idx = adapter->ap_stop_cmd_bidx; + msg.rsvd[0].ptr = (u8*)role; + + status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d), + &msg, &attr, NULL); + + if (status != RTW_PHL_STATUS_SUCCESS) { + RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n", FUNC_ADPT_ARG(adapter), status); + } + return status; +} + +static enum rtw_phl_status _ap_stop_ap_end_notify(struct _ADAPTER *adapter) +{ + struct dvobj_priv *d = adapter_to_dvobj(adapter); + struct rtw_wifi_role_t *role = adapter->phl_role; + enum rtw_phl_status status; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_STOP); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_STOP_END); + + msg.band_idx = adapter->ap_stop_cmd_bidx; + msg.inbuf = (u8 *)role; + + status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d), + &msg, &attr, NULL); + + if (status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n", FUNC_ADPT_ARG(adapter), status); + + return status; +} + +static void _ap_stop_abort_notify_cb(void *priv, struct phl_msg *msg) +{ + _adapter *padapter = (_adapter *)priv; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct _ADAPTER *adapter = (struct _ADAPTER *)priv; + enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS; + struct rtw_chan_def chan_def = {0}; + u8 chctx_num = 0; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *adapter_link = GET_PRIMARY_LINK(adapter); + +#ifdef RTW_PHL_BCN + phl_status = rtw_phl_free_bcn_entry(d->phl, adapter_link->wrlink); + if (phl_status != RTW_PHL_STATUS_SUCCESS) { + RTW_INFO("%s - phl_free_bcn_entry failed\n", __func__); + } +#endif +} + +static enum rtw_phl_status _ap_stop_abort_notify(struct _ADAPTER *adapter, bool abort) +{ + struct dvobj_priv *d = adapter_to_dvobj(adapter); + struct rtw_wifi_role_t *role = adapter->phl_role; + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + struct phl_msg msg = {0}; + struct phl_msg_attribute attr = {0}; + + SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_STOP); + SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_STOP); + msg.band_idx = adapter->ap_stop_cmd_bidx; + msg.rsvd[0].ptr = (u8*)role; + + if(abort) + attr.opt = MSG_OPT_SEND_IN_ABORT; + attr.completion.completion = _ap_stop_abort_notify_cb; + attr.completion.priv = adapter; + + status = rtw_phl_send_msg_to_dispr(d->phl, + &msg, + &attr, + NULL); + if (status != RTW_PHL_STATUS_SUCCESS) { + RTW_INFO("[%s] Abort send msg fail!\n", __func__); + } + + return status; +} + +static enum phl_mdl_ret_code _ap_stop_req_acquired(void *dispr, void *priv) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + struct rtw_wifi_role_t *role = padapter->phl_role; + struct phl_msg msg = {0}; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + + rtw_ap_stop_set_state(padapter, AP_STOP_ST_ACQUIRED); + + SET_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_ACQUIRE); + padapter->ap_stop_cmd_bidx = padapter_link->wrlink->hw_band; + + rtw_phl_ap_stop(adapter_to_dvobj(padapter)->phl, + padapter->ap_stop_cmd_bidx,role); + + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + + return MDL_RET_SUCCESS; + +} + +static enum phl_mdl_ret_code _ap_stop_req_abort(void *dispr, void *priv) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + + if(TEST_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_STARTED)){ + /* case1: MSG_EVT_AP_STOP has been processed*/ + } + else if(TEST_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_ACQUIRE)){ + /* case2: MSG_EVT_AP_STOP in msgQ + case3: MSG_EVT_AP_STOP doesn't back to msg_hdlr yet */ + if (RTW_PHL_STATUS_SUCCESS != _ap_stop_abort_notify(padapter, true)) { + /* do not execute core_mr_handle because do not know if the I/O operation is acceptable */ + //core_mr_delete_chctx(adapter, &chctx_num, &chan_def); + } + } + else{ + /* apstop token stay in tokenOpQ */ + } + + padapter->ap_stop_cmd_state = 0; + RTW_INFO("%s\n", __func__); + return MDL_RET_SUCCESS; +} + +static enum phl_mdl_ret_code _ap_stop_req_ev_hdlr(void *dispr, void *priv, struct phl_msg* msg) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct rtw_wifi_role_t *wifi_role = padapter->phl_role; + enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": + msg_id=0x%08x\n", + FUNC_ADPT_ARG(padapter), msg->msg_id); + + if ((MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_STOP) && + (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_MRC)) { + RTW_DBG(FUNC_ADPT_FMT ": Message is not from ap stop/mrc module, " + "skip msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + return MDL_RET_IGNORE; + } + + RTW_INFO("[AP_STOP] %s("ADPT_FMT")\n", + ap_get_evt_str(MSG_EVT_ID_FIELD(msg->msg_id)), ADPT_ARG(padapter)); + + if (IS_MSG_FAIL(msg->msg_id)) { + RTW_WARN(FUNC_ADPT_FMT ": cmd dispatcher notify cmd failure on " + "msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + } + + switch(MSG_EVT_ID_FIELD(msg->msg_id)) { + case MSG_EVT_AP_STOP_PREPARE: + { + SET_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_STARTED); + status = _ap_stop_ap_stop_notify(padapter); + if (status != RTW_PHL_STATUS_SUCCESS) { + RTW_ERR("%s :: [MSG_EVT_AP_STOP_PREPARE] ap_stop_notify fail\n", __func__); + _ap_stop_cmd_done(pcmd); + } + break; + } + case MSG_EVT_AP_STOP: + { + #ifdef CONFIG_DBCC_SUPPORT + struct rtw_mr_chctx_info mr_cc_info = {0}; + #ifdef CONFIG_DBCC_P2P_BG_LISTEN + bool is_dis_dbcc = false; + + /*B1 GO stop*/ + is_dis_dbcc = rtw_dbcc_chk_disable_hdl(padapter, NULL, PHL_CMD_DIRECTLY, DBCC_CHK_AP_STOP); + #endif + #endif + + stop_ap_hdl(padapter); + + #ifdef CONFIG_DBCC_SUPPORT + #ifdef CONFIG_DBCC_P2P_BG_LISTEN + if (is_dis_dbcc) + #endif + { + rtw_phl_chanctx_chk(GET_PHL_INFO(dvobj), + padapter->phl_role, + padapter_link->wrlink, + NULL, + &mr_cc_info); + if (mr_cc_info.sugg_opmode == MR_OP_DBCC) /*current stay in DBCC*/ + rtw_phl_mr_trig_dbcc_disable(GET_PHL_INFO(dvobj)); + } + #endif + + status = _ap_stop_ap_end_notify(padapter); + if (status != RTW_PHL_STATUS_SUCCESS) { + _ap_stop_cmd_done(pcmd); + #ifdef CONFIG_DBCC_SUPPORT + if (mr_cc_info.sugg_opmode == MR_OP_DBCC) + rtw_phl_mr_cancel_dbcc_action(GET_PHL_INFO(dvobj)); + #endif + } + break; + } + case MSG_EVT_AP_STOP_END: + if (padapter->ap_add_del_sta_cmd_token != 0) { + status = rtw_phl_cancel_cmd_token(GET_PHL_INFO(dvobj), + padapter_link->wrlink->hw_band, + &padapter->ap_add_del_sta_cmd_token); + if (status != RTW_PHL_STATUS_SUCCESS) + RTW_ERR(FUNC_ADPT_FMT ": cancel_cmd_token fail(0x%x)!\n", + FUNC_ADPT_ARG(padapter), status); + } + RTW_INFO(FUNC_ADPT_FMT ": MSG_EVT_AP_STOP_END\n", FUNC_ADPT_ARG(padapter)); + #ifdef CONFIG_DBCC_P2P_BG_LISTEN + /*B0,GO stop*/ + if (rtw_dbcc_chk_enable_hdl(padapter, PHL_CMD_DIRECTLY, DBCC_CHK_AP_STOP)) + rtw_phl_mr_trig_dbcc_enable(GET_PHL_INFO(dvobj)); + + rtw_discon_end_dbcc_en_notify(padapter, PHL_FG_MDL_AP_STOP); + break; + case MSG_EVT_DISCONNECT_END_DBCC_EN: + RTW_INFO(FUNC_ADPT_FMT ": MSG_EVT_DISCONNECT_END_DBCC_EN\n", + FUNC_ADPT_ARG(padapter)); + #endif + _ap_stop_cmd_done(pcmd); + break; + +#ifdef CONFIG_DBCC_SUPPORT + case MSG_EVT_DBCC_DISABLE: + if (MSG_MDL_ID_FIELD(msg->msg_id) == PHL_MDL_MRC) { + struct rtw_wifi_role_t *role; + + role = (struct rtw_wifi_role_t *)msg->inbuf; + RTW_INFO("[STOP_AP-FG] WR(%d) RX MRC- DBCC DISABLE MSG\n", role->id); + } + break; +#endif + + default: + /* unknown state */ + break; + } + + return MDL_RET_SUCCESS; +} + +static enum phl_mdl_ret_code _ap_stop_req_set_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *padapter = pcmd->padapter; + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + + return MDL_RET_IGNORE; +} + +static enum phl_mdl_ret_code _ap_stop_req_query_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct cmd_obj *pcmd = (struct cmd_obj *)priv; + struct _ADAPTER *a = pcmd->padapter; + enum phl_mdl_ret_code ret = MDL_RET_IGNORE; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(a)); + + switch (info->op_code) { + case FG_REQ_OP_GET_ROLE: + info->outbuf = (u8*)a->phl_role; + ret = MDL_RET_SUCCESS; + break; + + case FG_REQ_OP_GET_ROLE_LINK: + info->outbuf = (u8*)alink->wrlink; + ret = MDL_RET_SUCCESS; + break; + + default: + break; + } + + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(a)); + return ret; +} + +void rtw_ap_stop_set_state(struct _ADAPTER *a, u8 st) +{ + _rtw_spinlock_bh(&a->ap_stop_st_lock); + a->ap_stop_state = st; + _rtw_spinunlock_bh(&a->ap_stop_st_lock); +} + +#define WATI_AP_STOP_TO 10000 /* unit: ms */ +int rtw_ap_stop_wait(struct _ADAPTER *a) +{ + u32 timeout = WATI_AP_STOP_TO; + systime start_t; + u32 pass_t = 0; + u32 msg_i; /* message interval */ + u32 msg_t = 0; /* next time point to print message */ + int err = 0; + + if (!rtw_is_adapter_up(a)) + return err; + + if (a->ap_stop_state == AP_STOP_ST_IDLE) + return err; + + msg_i = timeout / 10; /* at most print 10 msg in whole waiting time */ + + _rtw_spinlock_bh(&a->ap_stop_st_lock); + start_t = rtw_get_current_time(); + while (a->ap_stop_state != AP_STOP_ST_DONE) { + if (!rtw_is_adapter_up(a)) + break; + + if (pass_t >= msg_t) { + RTW_INFO(FUNC_ADPT_FMT ": ap stop st=%u, %u ms/%u pass...\n", + FUNC_ADPT_ARG(a), a->ap_stop_state, pass_t, timeout); + msg_t += msg_i; + } + _rtw_spinunlock_bh(&a->ap_stop_st_lock); + + pass_t = rtw_get_passing_time_ms(start_t); + if (pass_t > timeout) { + RTW_ERR(FUNC_ADPT_FMT ": Timeout, fail to ap stop!" + " used:%u > max:%u ms\n", + FUNC_ADPT_ARG(a), pass_t, timeout); + err = -2; /* Timeout */ + _rtw_spinlock_bh(&a->ap_stop_st_lock); + rtw_warn_on(1); + break; + } + rtw_msleep_os(50); + + _rtw_spinlock_bh(&a->ap_stop_st_lock); + } + _rtw_spinunlock_bh(&a->ap_stop_st_lock); + + return err; +} + +static void rtw_cmd_ap_stop_req_init(struct cmd_obj *pcmd, struct phl_cmd_token_req *fgreq) +{ + struct _ADAPTER *padapter = pcmd->padapter; + + RTW_DBG(FUNC_ADPT_FMT ": \n", FUNC_ADPT_ARG(padapter)); + + /* Fill foreground command request */ + fgreq->module_id= PHL_FG_MDL_AP_STOP; + fgreq->opt = FG_CMD_OPT_EXCLUSIVE; + fgreq->priv = pcmd; + fgreq->role = padapter->phl_role; + + fgreq->acquired = _ap_stop_req_acquired; + fgreq->abort = _ap_stop_req_abort; + fgreq->msg_hdlr = _ap_stop_req_ev_hdlr; + fgreq->set_info = _ap_stop_req_set_info; + fgreq->query_info = _ap_stop_req_query_info; + + rtw_ap_stop_set_state(padapter, AP_STOP_ST_REQUESTING); + padapter->ap_stop_cmd_state = 0; + padapter->ap_stop_cmd_token = 0; +} + +enum rtw_phl_status rtw_ap_stop_cmd(struct cmd_obj *pcmd) +{ + struct _ADAPTER *padapter = pcmd->padapter; + struct phl_cmd_token_req fgreq={0}; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + enum rtw_phl_status pstatus; + struct rtw_wifi_role_t *role = padapter->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + + rtw_cmd_ap_stop_req_init(pcmd, &fgreq); + + /* cmd_dispatcher would copy whole phl_cmd_token_req */ + pstatus = rtw_phl_add_cmd_token_req(d->phl, padapter_link->wrlink->hw_band, &fgreq, &padapter->ap_stop_cmd_token); + if((pstatus != RTW_PHL_STATUS_SUCCESS) && + (pstatus != RTW_PHL_STATUS_PENDING)) + goto error; + + pstatus = RTW_PHL_STATUS_SUCCESS; + +error: + return pstatus; + +} + +static void _ap_add_del_sta_cmd_done(struct _ADAPTER *padapter) +{ + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct rtw_wifi_role_t *role = padapter->phl_role; + enum rtw_phl_status status; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + padapter->ap_add_del_sta_cmd_state = ADD_DEL_STA_ST_IDLE; + + if (!padapter->ap_add_del_sta_cmd_token){ + RTW_ERR("%s : token is NULL!\n", __func__); + return; + } + + status = rtw_phl_free_cmd_token(GET_PHL_INFO(d), + padapter_link->wrlink->hw_band, + &padapter->ap_add_del_sta_cmd_token); + padapter->ap_add_del_sta_cmd_token = 0; + + if (status != RTW_PHL_STATUS_SUCCESS) { + RTW_ERR(FUNC_ADPT_FMT ": free_cmd_token fail(0x%x)!\n", + FUNC_ADPT_ARG(padapter), status); + return; + } + + RTW_INFO(FUNC_ADPT_FMT": free token success\n", FUNC_ADPT_ARG(padapter)); +} + +/* use this function must add lock */ +static struct rtw_add_del_sta_obj *rtw_ap_get_stainfo_by_add_sta_list(struct _ADAPTER *padapter) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct rtw_add_del_sta_obj *add_del_sta_obj = NULL; + _list *phead, *plist; + + phead = &pstapriv->add_sta_list; + plist = get_next(phead); + if (rtw_end_of_queue_search(phead, plist) == _FALSE) { + add_del_sta_obj = LIST_CONTAINOR(plist, struct rtw_add_del_sta_obj, list); + plist = get_next(plist); + } + + return add_del_sta_obj; +} + +static enum phl_mdl_ret_code _ap_add_del_sta_req_acquired(void *dispr, void *priv) +{ + struct _ADAPTER *padapter = (struct _ADAPTER *)priv; + struct sta_priv *pstapriv = &padapter->stapriv; + struct rtw_wifi_role_t *role = padapter->phl_role; + struct rtw_add_del_sta_obj *add_del_sta_obj; + struct sta_info *psta = NULL; + struct phl_msg_attribute attr = {0}; + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + struct phl_msg msg = {0}; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + if (padapter->ap_add_del_sta_cmd_state != ADD_DEL_STA_ST_REQUESTING) + RTW_ERR(FUNC_ADPT_FMT ": add_del_sta_st=%u, not requesting?!\n", + FUNC_ADPT_ARG(padapter), padapter->ap_add_del_sta_cmd_state); + + padapter->ap_add_del_sta_cmd_state = ADD_DEL_STA_ST_ACQUIRED; + + add_del_sta_obj = rtw_ap_get_stainfo_by_add_sta_list(padapter); + + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + + if (!add_del_sta_obj) { + RTW_ERR(FUNC_ADPT_FMT": add_del_sta_obj is null\n", + FUNC_ADPT_ARG(padapter)); + return status; + } + + psta = add_del_sta_obj->sta; + if (!psta) { + RTW_ERR(FUNC_ADPT_FMT": psta is null\n", FUNC_ADPT_ARG(padapter)); + return status; + } + + RTW_INFO(FUNC_ADPT_FMT ": %s STA\n", + FUNC_ADPT_ARG(padapter), add_del_sta_obj->is_add_sta ? "ADD" : "DEL"); + + if (add_del_sta_obj->is_add_sta) + status = rtw_phl_connect_prepare(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, padapter->phl_role, + padapter_link->wrlink, psta->phl_sta->mac_addr); + else + status = rtw_phl_disconnect(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, + padapter->phl_role, _TRUE); + + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + + return (status == RTW_PHL_STATUS_SUCCESS ? MDL_RET_SUCCESS : MDL_RET_FAIL); + +} + +static enum phl_mdl_ret_code _ap_add_del_sta_req_abort(void *dispr, void *priv) +{ + struct _ADAPTER *padapter = (struct _ADAPTER *)priv; + struct sta_priv *pstapriv = &padapter->stapriv; + struct rtw_add_del_sta_obj *add_del_sta_obj = NULL; + _list *phead = NULL, *plist = NULL; + + RTW_INFO("%s\n", __func__); + + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + + phead = &pstapriv->add_sta_list; + plist = get_next(phead); + + while (rtw_end_of_queue_search(phead, plist) == _FALSE) { + add_del_sta_obj = LIST_CONTAINOR(plist, struct rtw_add_del_sta_obj, list); + plist = get_next(plist); + rtw_list_delete(&add_del_sta_obj->list); + rtw_mfree(add_del_sta_obj, sizeof(struct rtw_add_del_sta_obj)); + } + + pstapriv->add_sta_list_cnt = 0; + padapter->ap_add_del_sta_cmd_token = 0; + padapter->ap_add_del_sta_cmd_state = ADD_DEL_STA_ST_IDLE; + + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + + return MDL_RET_SUCCESS; +} + +static enum phl_mdl_ret_code _ap_add_del_sta_req_ev_hdlr(void *dispr, void *priv, struct phl_msg* msg) +{ + struct _ADAPTER *padapter = (struct _ADAPTER *)priv; + struct rtw_wifi_role_t *wifi_role = padapter->phl_role; + struct sta_priv *pstapriv = &padapter->stapriv; + struct rtw_add_del_sta_obj *add_del_sta_obj = NULL; + struct sta_info *psta = NULL; + struct phl_msg next_msg = {0}; + _list *phead, *plist; + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + struct rtw_phl_stainfo_t *phl_stainfo; +#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) + u8 *passoc_req = NULL; + u32 assoc_req_len = 0; +#endif + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (MLME_IS_AP(padapter) == _FALSE) + return MDL_RET_IGNORE; + + RTW_INFO(FUNC_ADPT_FMT ": + msg_id=0x%08x\n", + FUNC_ADPT_ARG(padapter), msg->msg_id); + + if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_ADD_DEL_STA) { + //RTW_INFO(FUNC_ADPT_FMT ": Message is not from ap add sta module, " + // "skip msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + return MDL_RET_IGNORE; + } + + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + + RTW_INFO("add_sta_list, cnt:%u\n", pstapriv->add_sta_list_cnt); + + add_del_sta_obj = rtw_ap_get_stainfo_by_add_sta_list(padapter); + if (!add_del_sta_obj || !add_del_sta_obj->sta) { + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + RTW_ERR(FUNC_ADPT_FMT": add_del_sta_obj or psta is null\n", + FUNC_ADPT_ARG(padapter)); + goto free_token; + } + psta = add_del_sta_obj->sta; + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + + RTW_INFO("[AP_STA] %s("ADPT_FMT") aid=%d\n", + ap_get_evt_str(MSG_EVT_ID_FIELD(msg->msg_id)), ADPT_ARG(padapter), add_del_sta_obj->aid); + + + if (IS_MSG_FAIL(msg->msg_id)) { + RTW_WARN(FUNC_ADPT_FMT ": cmd dispatcher notify cmd failure on " + "msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id); + } + + switch (MSG_EVT_ID_FIELD(msg->msg_id)) { + case MSG_EVT_CONNECT_START: +#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) + + rtw_alloc_stainfo_hw(&padapter->stapriv, psta); + rtw_hw_connected_apmode(padapter, psta); + + RTW_INFO("indicate_sta_assoc_event to upper layer - hostapd\n"); + + _rtw_spinlock_bh(&psta->lock); + if (psta->passoc_req && psta->assoc_req_len > 0) { + passoc_req = rtw_zmalloc(psta->assoc_req_len); + if (passoc_req) { + assoc_req_len = psta->assoc_req_len; + _rtw_memcpy(passoc_req, psta->passoc_req, assoc_req_len); + } + } + _rtw_spinunlock_bh(&psta->lock); + + if (passoc_req && assoc_req_len > 0) { + rtw_cfg80211_indicate_sta_assoc(padapter, passoc_req, assoc_req_len); + rtw_mfree(passoc_req, assoc_req_len); + } + + if (is_wep_enc(padapter->securitypriv.dot11PrivacyAlgrthm)) + rtw_ap_wep_pk_setting(padapter, psta); + #ifdef CONFIG_RTS_FULL_BW + rtw_set_rts_bw(adapter); + #endif/*CONFIG_RTS_FULL_BW*/ + + status = rtw_phl_connected(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, + padapter->phl_role, psta->phl_sta); + if (status == RTW_PHL_STATUS_FAILURE) { + RTW_ERR("%s :: [MSG_EVT_CONNECT_START] rtw_phl_send_msg_to_dispr failed\n", + __func__); + + goto free_token; + } + break; + + case MSG_EVT_DISCONNECT_PREPARE: + + rtw_wfd_st_switch(psta, 0); + psta->hw_decrypted = _FALSE; + #ifdef CONFIG_IOCTL_CFG80211 + #ifdef COMPAT_KERNEL_RELEASE + + #elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) + rtw_cfg80211_indicate_sta_disassoc(padapter, pstadel->macaddr, *(u16 *)pstadel->rsvd); + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */ + #endif /* CONFIG_IOCTL_CFG80211 */ + + rtw_hw_disconnect(padapter, psta); + + rtw_free_mld_stainfo(padapter, psta->phl_sta->mld); + + status = rtw_phl_disconnect(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, + padapter->phl_role, _FALSE); + if (status == RTW_PHL_STATUS_FAILURE) { + RTW_ERR("%s :: [MSG_EVT_DISCONNECT_PREPARE] rtw_phl_send_msg_to_dispr failed\n", __func__); + goto free_token; + } + break; +#endif + case MSG_EVT_CONNECT_END: + case MSG_EVT_DISCONNECT: + + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + + rtw_list_delete(&add_del_sta_obj->list); + pstapriv->add_sta_list_cnt--; + rtw_mfree(add_del_sta_obj, sizeof(struct rtw_add_del_sta_obj)); + add_del_sta_obj = NULL; + + if (pstapriv->add_sta_list_cnt > 0) { /* token extend */ + add_del_sta_obj = rtw_ap_get_stainfo_by_add_sta_list(padapter); + if (!add_del_sta_obj || !add_del_sta_obj->sta) { + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + RTW_ERR(FUNC_ADPT_FMT": add_del_sta_obj or psta is null\n", + FUNC_ADPT_ARG(padapter)); + goto free_token; + } + + psta = add_del_sta_obj->sta; + + if (add_del_sta_obj->is_add_sta) + status = rtw_phl_connect_prepare(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, + padapter->phl_role, + padapter_link->wrlink, + psta->phl_sta->mac_addr); + else + status = rtw_phl_disconnect(adapter_to_dvobj(padapter)->phl, + padapter_link->wrlink->hw_band, + padapter->phl_role, + _TRUE); + + if (status != RTW_PHL_STATUS_SUCCESS) { + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + RTW_ERR("%s :: [%s] rtw_phl_send_msg_to_dispr failed\n", + __func__, + (MSG_EVT_ID_FIELD(msg->msg_id) == MSG_EVT_CONNECT_END) ? + "MSG_EVT_CONNECT_END" : "MSG_EVT_DISCONNECT"); + goto free_token; + } + + } else { + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + /* no more STA */ + status = RTW_PHL_STATUS_SUCCESS; + goto free_token; + } + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + break; + + default: + /* unknown state */ + RTW_ERR("%s :: [0x%04x] unknown state\n", __func__, MSG_EVT_ID_FIELD(msg->msg_id)); + break; + } + + return MDL_RET_SUCCESS; + +free_token: + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + if (add_del_sta_obj) { + rtw_list_delete(&add_del_sta_obj->list); + pstapriv->add_sta_list_cnt--; + rtw_mfree(add_del_sta_obj, sizeof(struct rtw_add_del_sta_obj)); + add_del_sta_obj = NULL; + } + + _ap_add_del_sta_cmd_done(padapter); /* free token */ + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + return status; +} + +static enum phl_mdl_ret_code _ap_add_del_sta_req_set_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct _ADAPTER *padapter = (struct _ADAPTER *)priv; + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter)); + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter)); + + return MDL_RET_IGNORE; +} + +static enum phl_mdl_ret_code _ap_add_del_sta_req_query_info(void *dispr, void *priv, struct phl_module_op_info* info) +{ + struct _ADAPTER *a = (struct _ADAPTER *)priv; + enum phl_mdl_ret_code ret = MDL_RET_IGNORE; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + + + RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(a)); + + switch (info->op_code) { + case FG_REQ_OP_GET_ROLE: + info->outbuf = (u8*)a->phl_role; + ret = MDL_RET_SUCCESS; + break; + + case FG_REQ_OP_GET_ROLE_LINK: + info->outbuf = (u8*)alink->wrlink; + ret = MDL_RET_SUCCESS; + break; + + default: + break; + } + + RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(a)); + return ret; +} + +void rtw_cmd_ap_add_del_sta_req_free(struct _ADAPTER *padapter) +{ + _rtw_spinlock_free(&padapter->ap_add_del_sta_lock); +} + +void rtw_cmd_ap_add_del_sta_req_init(struct _ADAPTER *padapter) +{ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct phl_cmd_token_req *req; + + RTW_DBG(FUNC_ADPT_FMT ": \n", FUNC_ADPT_ARG(padapter)); + /* Fill foreground command request */ + + _rtw_spinlock_init(&padapter->ap_add_del_sta_lock); + + req = &padapter->add_del_sta_req; + req->module_id= PHL_FG_MDL_AP_ADD_DEL_STA; + req->priv = padapter; + req->role = padapter->phl_role; + + req->acquired = _ap_add_del_sta_req_acquired; + req->abort = _ap_add_del_sta_req_abort; + req->msg_hdlr = _ap_add_del_sta_req_ev_hdlr; + req->set_info = _ap_add_del_sta_req_set_info; + req->query_info = _ap_add_del_sta_req_query_info; + + padapter->ap_add_del_sta_cmd_token = 0; + padapter->ap_add_del_sta_cmd_state = ADD_DEL_STA_ST_IDLE; +} + +enum rtw_phl_status rtw_ap_add_del_sta_cmd(struct _ADAPTER *padapter) +{ + struct phl_cmd_token_req *fgreq; + struct dvobj_priv *d = adapter_to_dvobj(padapter); + enum rtw_phl_status status; + struct rtw_wifi_role_t *role = padapter->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + fgreq = &padapter->add_del_sta_req; + /* cmd_dispatcher would copy whole phl_cmd_token_req */ + status = rtw_phl_add_cmd_token_req(d->phl, + padapter_link->wrlink->hw_band, + fgreq, &padapter->ap_add_del_sta_cmd_token); + + if ((status != RTW_PHL_STATUS_SUCCESS) && + (status != RTW_PHL_STATUS_PENDING)) { + RTW_ERR(FUNC_ADPT_FMT": add token fail\n", FUNC_ADPT_ARG(padapter)); + goto exit; + } + + RTW_INFO(FUNC_ADPT_FMT ": add token success\n", FUNC_ADPT_ARG(padapter)); + status = RTW_PHL_STATUS_SUCCESS; +exit: + return status; +} + +bool rtw_add_del_sta_cmd_check(struct _ADAPTER *padapter, unsigned char *MacAddr, bool add_sta) +{ + enum rtw_phl_status status = _FAIL; + struct sta_priv *pstapriv = &padapter->stapriv; + struct rtw_add_del_sta_obj *add_del_sta_obj = NULL; + struct sta_info *psta; + + if (add_sta) + psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); + else + psta = rtw_get_stainfo_to_free(&padapter->stapriv, MacAddr); + if (!psta) { + RTW_ERR(FUNC_ADPT_FMT": psta is null\n", FUNC_ADPT_ARG(padapter)); + return _FAIL; + } + + add_del_sta_obj = (struct rtw_add_del_sta_obj *)rtw_zmalloc(sizeof(struct rtw_add_del_sta_obj)); + if (!add_del_sta_obj) { + RTW_ERR(FUNC_ADPT_FMT": add_del_sta_obj is null\n", FUNC_ADPT_ARG(padapter)); + return _FAIL; + } + + _rtw_init_listhead(&add_del_sta_obj->list); + add_del_sta_obj->sta = psta; + add_del_sta_obj->aid = psta->phl_sta->aid; + add_del_sta_obj->is_add_sta = add_sta; + + _rtw_spinlock_bh(&padapter->ap_add_del_sta_lock); + + rtw_list_insert_tail(&add_del_sta_obj->list, &pstapriv->add_sta_list); + pstapriv->add_sta_list_cnt++; + + if (padapter->ap_add_del_sta_cmd_state == ADD_DEL_STA_ST_IDLE) { + status = rtw_ap_add_del_sta_cmd(padapter); + if (status == RTW_PHL_STATUS_SUCCESS) + padapter->ap_add_del_sta_cmd_state = ADD_DEL_STA_ST_REQUESTING; + } else { + RTW_INFO(FUNC_ADPT_FMT": reuse token\n", FUNC_ADPT_ARG(padapter)); + } + + _rtw_spinunlock_bh(&padapter->ap_add_del_sta_lock); + return (status == RTW_PHL_STATUS_SUCCESS) ? _SUCCESS : _FAIL; +} + +void rtw_update_probe_rsp_basic_rate_and_ext(struct xmit_frame *xframe) { + struct pkt_attrib *pattrib = &xframe->attrib; + struct _ADAPTER *padapter = xframe->padapter; + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *lmlmeext = &(padapter_link->mlmeextpriv); + struct link_mlme_ext_info *lmlmeinfo = &(lmlmeext->mlmext_info); + WLAN_BSSID_EX *cur_network = &(lmlmeinfo->network); + u8 *basic_rate_ie = NULL, *ext_rate_ie = NULL; + u8 hdr_len = sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *ies = NULL; + sint ies_len = 0; + sint ie_len = 0; + unsigned int rate_len = 0; + + ies = xframe->buf_addr + TXDESC_OFFSET + hdr_len + _BEACON_IE_OFFSET_; + ies_len = pattrib->pktlen - hdr_len - _BEACON_IE_OFFSET_; + + basic_rate_ie = rtw_get_ie(ies, WLAN_EID_SUPP_RATES, &ie_len, ies_len); + if (basic_rate_ie != NULL) { + rate_len = rtw_get_rateset_len(cur_network->SupportedRates); + rtw_ies_update_ie(ies, &ies_len, 0, WLAN_EID_SUPP_RATES, + cur_network->SupportedRates, + (rate_len > NDIS_802_11_LENGTH_RATES ? + NDIS_802_11_LENGTH_RATES : rate_len)); + if (rate_len > NDIS_802_11_LENGTH_RATES) + pattrib->pktlen += (NDIS_802_11_LENGTH_RATES - ie_len); + else + pattrib->pktlen += (rate_len - ie_len); + } + + ext_rate_ie = rtw_get_ie(ies, WLAN_EID_EXT_SUPP_RATES, + &ie_len, ies_len); + if (ext_rate_ie != NULL) { + if (rate_len <= NDIS_802_11_LENGTH_RATES) { + rtw_ies_remove_ie(ies, &ies_len, 0, + WLAN_EID_EXT_SUPP_RATES, NULL, 0); + pattrib->pktlen -= (ie_len + 2); + } else { + rtw_ies_update_ie(ies, &ies_len, 0, + WLAN_EID_EXT_SUPP_RATES, + cur_network->SupportedRates + + NDIS_802_11_LENGTH_RATES, + rate_len - NDIS_802_11_LENGTH_RATES); + pattrib->pktlen += (rate_len - NDIS_802_11_LENGTH_RATES + - ie_len); + } + } else if (rate_len > NDIS_802_11_LENGTH_RATES) { + rtw_ies_add_ie(ies, &ies_len, 0, WLAN_EID_EXT_SUPP_RATES, + cur_network->SupportedRates + + NDIS_802_11_LENGTH_RATES, + rate_len - NDIS_802_11_LENGTH_RATES); + pattrib->pktlen += ((rate_len - NDIS_802_11_LENGTH_RATES) + 2); + } +} + +#endif + +#if CONFIG_AP_REGU_FORBID +bool rtw_ap_link_regu_forbid_apply(struct _ADAPTER_LINK *alink, bool forbid, bool enqueue) +{ + if (forbid) { + if (!LINK_MLME_IS_REGU_FORBID(alink)) { + SET_LINK_MLME_STATE(alink, WIFI_REGU_FORBID); + if (LINK_MLME_IS_ASOC(alink)) + rtw_sta_flush(alink->adapter, enqueue); + rtw_link_hal_core_stop_beacon(alink, forbid, enqueue ? 0 : RTW_CMDF_DIRECTLY); + return true; + } + } else { + if (LINK_MLME_IS_REGU_FORBID(alink)) { + _CLR_LINK_MLME_STATE_(alink, WIFI_REGU_FORBID); + rtw_link_hal_core_stop_beacon(alink, forbid, enqueue ? 0 : RTW_CMDF_DIRECTLY); + return true; + } + } + + return false; +} + +bool rtw_ap_link_regu_forbid_update(struct _ADAPTER_LINK *alink, bool enqueue) +{ + return rtw_ap_link_regu_forbid_apply(alink + , rtw_rfctl_is_regu_forbid_bss(adapter_to_rfctl(alink->adapter), ALINK_GET_BAND(alink)) + , enqueue); +} +#endif + +#endif /* CONFIG_AP_MODE */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_beamforming.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_beamforming.c new file mode 100755 index 00000000..7deb6f3f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_beamforming.c @@ -0,0 +1,2138 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2021 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_BEAMFORMING_C_ + +#include + +#ifdef CONFIG_BEAMFORMING + +#ifdef RTW_WKARD_TX_DISABLE_BFEE +void rtw_core_bf_watchdog(_adapter *padapter) +{ + struct registry_priv *pregpriv = &padapter->registrypriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj); + struct rtw_wifi_role_t *wrole = NULL; + struct rtw_phl_stainfo_t *psta = NULL; + struct rtw_stats *phl_stats = NULL; + bool enable_bfee = false; + struct protocol_cap_t *proto_cap; + struct _ADAPTER_LINK *padapter_link; + u8 lidx; + + do { + if (padapter == NULL) + break; + + if (1 != pregpriv->dyn_txbf) { + break; + } + + wrole = padapter->phl_role; + //psta = padapter->stainfo; + + if (wrole == NULL) + break; + + if (PHL_RTYPE_STATION != wrole->type || PHL_RTYPE_TDLS != wrole->type) + break; + + if (MLME_NO_LINK == wrole->mstate) + break; + + for (lidx = 0; lidx < padapter->adapter_link_num; lidx++) { + padapter_link = GET_LINK(padapter, lidx); + + if (MLME_NO_LINK == padapter_link->wrlink->mstate) + break; + + psta = rtw_phl_get_stainfo_self(adapter_to_dvobj(padapter)->phl, padapter_link->wrlink); + proto_cap = &(padapter_link->wrlink->protocol_cap); + + if (psta == NULL) + break; + + if ((proto_cap->he_su_bfme || + proto_cap->he_mu_bfme) && + (psta->asoc_cap.he_su_bfmr || psta->asoc_cap.he_mu_bfmr)) + enable_bfee = true; + + if ((proto_cap->vht_su_bfme || + proto_cap->vht_mu_bfme) && + (psta->asoc_cap.vht_su_bfmr || + psta->asoc_cap.vht_mu_bfmr)) + enable_bfee = true; + + if (proto_cap->ht_su_bfme && + psta->asoc_cap.ht_su_bfmr) + enable_bfee = true; + + if (enable_bfee == false) + break; + + phl_stats = &(phl_com->phl_stats); + if ((phl_stats->tx_traffic.lvl > phl_stats->rx_traffic.lvl) && + (phl_stats->tx_traffic.lvl >= RTW_TFC_HIGH)) + enable_bfee = false; + + /*Per wrole->hw_band to control bfee, not per hw_port*/ + rtw_phl_bfee_ctrl(GET_PHL_INFO(dvobj), wrole, enable_bfee); + /*RTW_INFO("[WKARD] Enable/Disable BFee function : BFee %d\n", enable_bfee);*/ + } + } while (0); +} +#endif /*RTW_WKARD_TX_DISABLE_BFEE*/ + +#if 0 +struct ndpa_sta_info { + u16 aid:12; + u16 feedback_type:1; + u16 nc_index:3; +}; + +static void _get_txvector_parameter(_adapter *adapter, struct sta_info *sta, u8 *g_id, u16 *p_aid) +{ + struct mlme_priv *mlme; + u16 aid; + u8 *bssid; + u16 val16; + u8 i; + + + mlme = &adapter->mlmepriv; + + if (check_fwstate(mlme, WIFI_AP_STATE)) { + /* + * Sent by an AP and addressed to a STA associated with that AP + * or sent by a DLS or TDLS STA in a direct path to + * a DLS or TDLS peer STA + */ + + aid = sta->phl_sta->aid; + bssid = adapter_mac_addr(adapter); + RTW_INFO("%s: AID=0x%x BSSID=" MAC_FMT "\n", + __FUNCTION__, sta->phl_sta->aid, MAC_ARG(bssid)); + + /* AID[0:8] */ + aid &= 0x1FF; + /* BSSID[44:47] xor BSSID[40:43] */ + val16 = ((bssid[5] & 0xF0) >> 4) ^ (bssid[5] & 0xF); + /* (dec(AID[0:8]) + dec(BSSID)*2^5) mod 2^9 */ + *p_aid = (aid + (val16 << 5)) & 0x1FF; + *g_id = 63; + } else if ((check_fwstate(mlme, WIFI_ADHOC_STATE) == _TRUE) + || (check_fwstate(mlme, WIFI_ADHOC_MASTER_STATE) == _TRUE)) { + /* + * Otherwise, includes + * 1. Sent to an IBSS STA + * 2. Sent by an AP to a non associated STA + * 3. Sent to a STA for which it is not known + * which condition is applicable + */ + *p_aid = 0; + *g_id = 63; + } else { + /* Addressed to AP */ + bssid = sta->phl_sta->mac_addr; + RTW_INFO("%s: BSSID=" MAC_FMT "\n", __FUNCTION__, MAC_ARG(bssid)); + + /* BSSID[39:47] */ + *p_aid = (bssid[5] << 1) | (bssid[4] >> 7); + *g_id = 0; + } + + RTW_INFO("%s: GROUP_ID=0x%02x PARTIAL_AID=0x%04x\n", + __FUNCTION__, *g_id, *p_aid); +} + +/* + * Parameters + * adapter _adapter* + * sta struct sta_info* + * sta_bf_cap beamforming capabe of sta + * sounding_dim Number of Sounding Dimensions + * comp_steering Compressed Steering Number of Beamformer Antennas Supported + */ +static void _get_sta_beamform_cap(_adapter *adapter, struct sta_info *sta, + u8 *sta_bf_cap, u8 *sounding_dim, u8 *comp_steering) +{ + struct beamforming_info *info; + struct ht_priv *ht; +#ifdef CONFIG_80211AC_VHT + struct vht_priv *vht; +#endif /* CONFIG_80211AC_VHT */ +#ifdef CONFIG_80211AX_HE + struct he_priv *he; +#endif /* CONFIG_80211AX_HE */ + u16 bf_cap; + + + *sta_bf_cap = 0; + *sounding_dim = 0; + *comp_steering = 0; + + info = GET_BEAMFORM_INFO(adapter); + ht = &adapter->mlmepriv.htpriv; +#ifdef CONFIG_80211AC_VHT + vht = &adapter->mlmepriv.vhtpriv; +#endif /* CONFIG_80211AC_VHT */ + +#ifdef CONFIG_80211AX_HE + he = &adapter->mlmepriv.hepriv; +#endif /* CONFIG_80211AX_HE */ + + if (is_supported_ht(sta->phl_sta->wmode) == _TRUE) { + /* HT */ + bf_cap = ht->beamform_cap; + + if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) { + info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT; + *sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT; + *sounding_dim = (bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6; + } + if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) { + info->beamforming_cap |= BEAMFORMER_CAP_HT_EXPLICIT; + *sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT; + *comp_steering = (bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4; + } + } + +#ifdef CONFIG_80211AC_VHT + if (is_supported_vht(sta->phl_sta->wmode) == _TRUE) { + /* VHT */ + bf_cap = vht->beamform_cap; + + /* We are SU Beamformee because the STA is SU Beamformer */ + if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) { + info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU; + *sta_bf_cap |= BEAMFORMER_CAP_VHT_SU; + + /* We are MU Beamformee because the STA is MU Beamformer */ + if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) { + info->beamforming_cap |= BEAMFORMEE_CAP_VHT_MU; + *sta_bf_cap |= BEAMFORMER_CAP_VHT_MU; + } + + *sounding_dim = (bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12; + } + /* We are SU Beamformer because the STA is SU Beamformee */ + if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) { + info->beamforming_cap |= BEAMFORMER_CAP_VHT_SU; + *sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU; + + /* We are MU Beamformer because the STA is MU Beamformee */ + if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) { + info->beamforming_cap |= BEAMFORMER_CAP_VHT_MU; + *sta_bf_cap |= BEAMFORMEE_CAP_VHT_MU; + } + + *comp_steering = (bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8; + } + } +#endif /* CONFIG_80211AC_VHT */ + +#ifdef CONFIG_80211AX_HE + /* CONFIG_80211AX_HE_TODO */ +#endif /* CONFIG_80211AX_HE */ +} + +static u8 _send_ht_ndpa_packet(_adapter *adapter, u8 *ra, enum channel_width bw) +{ + /* General */ + struct xmit_priv *pxmitpriv; + struct mlme_ext_priv *pmlmeext; + struct mlme_ext_info *pmlmeinfo; + struct xmit_frame *pmgntframe; + /* Beamforming */ + struct beamforming_info *info; + struct beamformee_entry *bfee; + struct ndpa_sta_info sta_info; + u8 ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xE0, 0x4C}; + /* MISC */ + struct pkt_attrib *attrib; + struct rtw_ieee80211_hdr *pwlanhdr; + enum MGN_RATE txrate; + u8 *pframe; + u16 duration = 0; + u8 aSifsTime = 0; + + + RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra)); + + pxmitpriv = &adapter->xmitpriv; + pmlmeext = &adapter->mlmeextpriv; + pmlmeinfo = &pmlmeext->mlmext_info; + bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra); + if (!bfee) { + RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__); + return _FALSE; + } + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (!pmgntframe) { + RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__); + return _FALSE; + } + + txrate = rtw_hal_get_htndp_tx_rate(adapter, bfee->comp_steering_num_of_bfer); + + /* update attribute */ + attrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, attrib); + /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */ + attrib->subtype = WIFI_ACTION_NOACK; + attrib->bwmode = bw; + /*attrib->qsel = rtw_hal_get_qsel(padapter, QSLT_MGNT_ID);*/ /* set in update_mgntframe_attrib() */ + attrib->order = 1; + attrib->rate = (u8)txrate; + attrib->bf_pkt_type = 0; + + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control */ + pwlanhdr->frame_ctl = 0; + set_frame_sub_type(pframe, attrib->subtype); + set_htc_order_bit(pframe); + + /* Duration */ + if (pmlmeext->cur_wireless_mode == WIRELESS_11B) + aSifsTime = 10; + else + aSifsTime = 16; + duration = 2 * aSifsTime + 40; + if (bw == CHANNEL_WIDTH_40) + duration += 87; + else + duration += 180; + set_duration(pframe, duration); + + /* DA */ + _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); + /* SA */ + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + /* BSSID */ + _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + + /* HT control field */ + SET_HT_CTRL_CSI_STEERING(pframe + 24, 3); + SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1); + + /* + * Frame Body + * Category field: vender-specific value, 0x7F + * OUI: 0x00E04C + */ + _rtw_memcpy(pframe + 28, ActionHdr, 4); + + attrib->pktlen = 32; + attrib->last_txcmdsz = attrib->pktlen; + + dump_mgntframe(adapter, pmgntframe); + + return _TRUE; +} + +static u8 _send_vht_ndpa_packet(_adapter *adapter, u8 *ra, u16 aid, enum channel_width bw) +{ + /* General */ + struct xmit_priv *pxmitpriv; + struct mlme_ext_priv *pmlmeext; + struct xmit_frame *pmgntframe; + /* Beamforming */ + struct beamforming_info *info; + struct beamformee_entry *bfee; + struct ndpa_sta_info sta_info; + /* MISC */ + struct pkt_attrib *attrib; + struct rtw_ieee80211_hdr *pwlanhdr; + u8 *pframe; + enum MGN_RATE txrate; + u16 duration = 0; + u8 sequence = 0, aSifsTime = 0; + + + RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra)); + + pxmitpriv = &adapter->xmitpriv; + pmlmeext = &adapter->mlmeextpriv; + info = GET_BEAMFORM_INFO(adapter); + bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra); + if (!bfee) { + RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__); + return _FALSE; + } + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (!pmgntframe) { + RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__); + return _FALSE; + } + + txrate = rtw_hal_get_vht_ndp_tx_rate(adapter, bfee->comp_steering_num_of_bfer); + + /* update attribute */ + attrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, attrib); + /*pattrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */ + attrib->subtype = WIFI_NDPA; + attrib->bwmode = bw; + /*attrib->qsel = rtw_hal_get_qsel(padapter, QSLT_MGNT_ID);*/ /* set in update_mgntframe_attrib() */ + attrib->rate = (u8)txrate; + attrib->bf_pkt_type = 0; + + _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET); + pframe = pmgntframe->buf_addr + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control */ + pwlanhdr->frame_ctl = 0; + set_frame_sub_type(pframe, attrib->subtype); + + /* Duration */ + if (WIFI_ROLE_IS_ON_5G(adapter) || is_supported_ht(pmlmeext->cur_wireless_mode)) + aSifsTime = 16; + else + aSifsTime = 10; + duration = 2 * aSifsTime + 44; + if (bw == CHANNEL_WIDTH_80) + duration += 40; + else if (bw == CHANNEL_WIDTH_40) + duration += 87; + else + duration += 180; + set_duration(pframe, duration); + + /* RA */ + _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); + + /* TA */ + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + + /* Sounding Sequence, bit0~1 is reserved */ + sequence = info->sounding_sequence << 2; + if (info->sounding_sequence >= 0x3f) + info->sounding_sequence = 0; + else + info->sounding_sequence++; + _rtw_memcpy(pframe + 16, &sequence, 1); + + /* STA Info */ + /* + * "AID12" Equal to 0 if the STA is an AP, mesh STA or + * STA that is a member of an IBSS + */ + if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _FALSE) + aid = 0; + sta_info.aid = aid; + /* "Feedback Type" set to 0 for SU */ + sta_info.feedback_type = 0; + /* "Nc Index" reserved if the Feedback Type field indicates SU */ + sta_info.nc_index = 0; + _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2); + + attrib->pktlen = 19; + attrib->last_txcmdsz = attrib->pktlen; + + dump_mgntframe(adapter, pmgntframe); + + return _TRUE; +} + +static u8 _send_vht_mu_ndpa_packet(_adapter *adapter, enum channel_width bw) +{ + /* General */ + struct xmit_priv *pxmitpriv; + struct mlme_ext_priv *pmlmeext; + struct xmit_frame *pmgntframe; + /* Beamforming */ + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + struct ndpa_sta_info sta_info; + /* MISC */ + struct pkt_attrib *attrib; + struct rtw_ieee80211_hdr *pwlanhdr; + enum MGN_RATE txrate; + u8 *pframe; + u8 *ra = NULL; + u16 duration = 0; + u8 sequence = 0, aSifsTime = 0; + u8 i; + + + RTW_INFO("+%s\n", __FUNCTION__); + + pxmitpriv = &adapter->xmitpriv; + pmlmeext = &adapter->mlmeextpriv; + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + txrate = MGN_VHT2SS_MCS0; + + /* + * Fill the first MU BFee entry (STA1) MAC addr to destination address then + * HW will change A1 to broadcast addr. + * 2015.05.28. Suggested by SD1 Chunchu. + */ + bfee = &info->bfee_entry[sounding->mu_sounding_list[0]]; + ra = bfee->mac_addr; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (!pmgntframe) { + RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__); + return _FALSE; + } + + /* update attribute */ + attrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, attrib); + /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */ + attrib->subtype = WIFI_NDPA; + attrib->bwmode = bw; + /*attrib->qsel = rtw_hal_get_qsel(padapter, QSLT_MGNT_ID);*/ /* set in update_mgntframe_attrib() */ + attrib->rate = (u8)txrate; + /* Set TxBFPktType of Tx desc to unicast type if there is only one MU STA for HW design */ + if (info->sounding_info.candidate_mu_bfee_cnt > 1) + attrib->bf_pkt_type = 1; + else + attrib->bf_pkt_type = 0; + + _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET); + pframe = pmgntframe->buf_addr + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control */ + pwlanhdr->frame_ctl = 0; + set_frame_sub_type(pframe, attrib->subtype); + + /* Duration */ + if (WIFI_ROLE_IS_ON_5G(adapter) || is_supported_ht(pmlmeext->cur_wireless_mode)) + aSifsTime = 16; + else + aSifsTime = 10; + duration = 2 * aSifsTime + 44; + if (bw == CHANNEL_WIDTH_80) + duration += 40; + else if (bw == CHANNEL_WIDTH_40) + duration += 87; + else + duration += 180; + set_duration(pframe, duration); + + /* RA */ + _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); + + /* TA */ + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + + /* Sounding Sequence, bit0~1 is reserved */ + sequence = info->sounding_sequence << 2; + if (info->sounding_sequence >= 0x3f) + info->sounding_sequence = 0; + else + info->sounding_sequence++; + _rtw_memcpy(pframe + 16, &sequence, 1); + + attrib->pktlen = 17; + + /* + * Construct STA info. for multiple STAs + * STA Info1, ..., STA Info n + */ + for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) { + bfee = &info->bfee_entry[sounding->mu_sounding_list[i]]; + sta_info.aid = bfee->aid; + sta_info.feedback_type = 1; /* 1'b1: MU */ + sta_info.nc_index = 0; + _rtw_memcpy(pframe + attrib->pktlen, (u8 *)&sta_info, 2); + attrib->pktlen += 2; + } + + attrib->last_txcmdsz = attrib->pktlen; + + dump_mgntframe(adapter, pmgntframe); + + return _TRUE; +} + +static u8 _send_bf_report_poll(_adapter *adapter, u8 *ra, u8 bFinalPoll) +{ + /* General */ + struct xmit_priv *pxmitpriv; + struct xmit_frame *pmgntframe; + /* MISC */ + struct pkt_attrib *attrib; + struct rtw_ieee80211_hdr *pwlanhdr; + u8 *pframe; + + + RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra)); + + pxmitpriv = &adapter->xmitpriv; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); + if (!pmgntframe) { + RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__); + return _FALSE; + } + + /* update attribute */ + attrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, attrib); + /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */ + attrib->subtype = WIFI_BF_REPORT_POLL; + attrib->bwmode = CHANNEL_WIDTH_20; + /*attrib->qsel = rtw_hal_get_qsel(padapter, QSLT_MGNT_ID);*/ /* set in update_mgntframe_attrib() */ + attrib->rate = MGN_6M; + if (bFinalPoll) + attrib->bf_pkt_type = 3; + else + attrib->bf_pkt_type = 2; + + _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET); + pframe = pmgntframe->buf_addr + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + /* Frame control */ + pwlanhdr->frame_ctl = 0; + set_frame_sub_type(pframe, attrib->subtype); + + /* Duration */ + set_duration(pframe, 100); + + /* RA */ + _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); + + /* TA */ + _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + + /* Feedback Segment Retransmission Bitmap */ + pframe[16] = 0xFF; + + attrib->pktlen = 17; + attrib->last_txcmdsz = attrib->pktlen; + + dump_mgntframe(adapter, pmgntframe); + + return _TRUE; +} + +static void _sounding_update_min_period(_adapter *adapter, u16 period, u8 leave) +{ + struct beamforming_info *info; + struct beamformee_entry *bfee; + u8 i = 0; + u16 min_val = 0xFFFF; + + + info = GET_BEAMFORM_INFO(adapter); + + if (_TRUE == leave) { + /* + * When a BFee left, + * we need to find the latest min sounding period + * from the remaining BFees + */ + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if ((bfee->used == _TRUE) + && (bfee->sound_period < min_val)) + min_val = bfee->sound_period; + } + + if (min_val == 0xFFFF) + info->sounding_info.min_sounding_period = 0; + else + info->sounding_info.min_sounding_period = min_val; + } else { + if ((info->sounding_info.min_sounding_period == 0) + || (period < info->sounding_info.min_sounding_period)) + info->sounding_info.min_sounding_period = period; + } +} + +static void _sounding_init(struct sounding_info *sounding) +{ + _rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU); + _rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU); + sounding->state = SOUNDING_STATE_NONE; + sounding->su_bfee_curidx = 0xFF; + sounding->candidate_mu_bfee_cnt = 0; + sounding->min_sounding_period = 0; + sounding->sound_remain_cnt_per_period = 0; +} + +static void _sounding_reset_vars(_adapter *adapter) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + u8 idx; + + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + _rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU); + _rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU); + sounding->su_bfee_curidx = 0xFF; + sounding->candidate_mu_bfee_cnt = 0; + + /* Clear bSound flag for the new period */ + for (idx = 0; idx < MAX_BEAMFORMEE_ENTRY_NUM; idx++) { + if ((info->bfee_entry[idx].used == _TRUE) + && (info->bfee_entry[idx].sounding == _TRUE)) { + info->bfee_entry[idx].sounding = _FALSE; + info->bfee_entry[idx].bCandidateSoundingPeer = _FALSE; + } + } +} + +/* + * Return + * 0 Prepare sounding list OK + * -1 Fail to prepare sounding list, because no beamformee need to souding + * -2 Fail to prepare sounding list, because beamformee state not ready + * + */ +static int _sounding_get_list(_adapter *adapter) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + u8 i, mu_idx = 0, su_idx = 0, not_ready = 0; + int ret = 0; + + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + /* Add MU BFee list first because MU priority is higher than SU */ + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (bfee->used == _FALSE) + continue; + + if (bfee->state != BEAMFORM_ENTRY_HW_STATE_ADDED) { + RTW_ERR("%s: Invalid BFee idx(%d) Hw state=%d\n", __FUNCTION__, i, bfee->state); + not_ready++; + continue; + } + + /* + * Decrease BFee's SoundCnt per period + * If the remain count is 0, + * then it can be sounded at this time + */ + if (bfee->SoundCnt) { + bfee->SoundCnt--; + if (bfee->SoundCnt) + continue; + } + + /* + * + * If the STA supports MU BFee capability then we add it to MUSoundingList directly + * because we can only sound one STA by unicast NDPA with MU cap enabled to get correct channel info. + * Suggested by BB team Luke Lee. 2015.11.25. + */ + if (bfee->cap & BEAMFORMEE_CAP_VHT_MU) { + /* MU BFee */ + if (mu_idx >= MAX_NUM_BEAMFORMEE_MU) { + RTW_ERR("%s: Too much MU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_MU); + continue; + } + + if (bfee->bApplySounding == _TRUE) { + bfee->bCandidateSoundingPeer = _TRUE; + bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period); + sounding->mu_sounding_list[mu_idx] = i; + mu_idx++; + } + } else if (bfee->cap & (BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) { + /* SU BFee (HT/VHT) */ + if (su_idx >= MAX_NUM_BEAMFORMEE_SU) { + RTW_ERR("%s: Too much SU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_SU); + continue; + } + + if (bfee->bDeleteSounding == _TRUE) { + sounding->su_sounding_list[su_idx] = i; + su_idx++; + } else if ((bfee->bApplySounding == _TRUE) + && (bfee->bSuspendSUCap == _FALSE)) { + bfee->bCandidateSoundingPeer = _TRUE; + bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period); + sounding->su_sounding_list[su_idx] = i; + su_idx++; + } + } + } + + sounding->candidate_mu_bfee_cnt = mu_idx; + + if (su_idx + mu_idx == 0) { + ret = -1; + if (not_ready) + ret = -2; + } + + RTW_INFO("-%s: There are %d SU and %d MU BFees in this sounding period\n", __FUNCTION__, su_idx, mu_idx); + + return ret; +} + +static void _sounding_handler(_adapter *adapter) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + u8 su_idx, i; + u32 timeout_period = 0; + u8 set_timer = _FALSE; + int ret = 0; + static u16 wait_cnt = 0; + + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + RTW_DBG("+%s: state=%d\n", __FUNCTION__, sounding->state); + if ((sounding->state != SOUNDING_STATE_INIT) + && (sounding->state != SOUNDING_STATE_SU_SOUNDDOWN) + && (sounding->state != SOUNDING_STATE_MU_SOUNDDOWN) + && (sounding->state != SOUNDING_STATE_SOUNDING_TIMEOUT)) { + RTW_WARN("%s: Invalid State(%d) and return!\n", __FUNCTION__, sounding->state); + return; + } + + if (sounding->state == SOUNDING_STATE_INIT) { + RTW_INFO("%s: Sounding start\n", __FUNCTION__); + + /* Init Var */ + _sounding_reset_vars(adapter); + + /* Get the sounding list of this sounding period */ + ret = _sounding_get_list(adapter); + if (ret == -1) { + wait_cnt = 0; + sounding->state = SOUNDING_STATE_NONE; + RTW_ERR("%s: No BFees found, set to SOUNDING_STATE_NONE\n", __FUNCTION__); + info->sounding_running--; + return; + } + if (ret == -2) { + RTW_WARN("%s: Temporarily cann't find BFee to sounding\n", __FUNCTION__); + if (wait_cnt < 5) { + wait_cnt++; + } else { + wait_cnt = 0; + sounding->state = SOUNDING_STATE_NONE; + RTW_ERR("%s: Wait changing state timeout!! Set to SOUNDING_STATE_NONE\n", __FUNCTION__); + } + info->sounding_running--; + return; + } + if (ret != 0) { + wait_cnt = 0; + RTW_ERR("%s: Unkown state(%d)!\n", __FUNCTION__, ret); + info->sounding_running--; + return; + + } + + wait_cnt = 0; + + if (check_fwstate(&adapter->mlmepriv, WIFI_UNDER_SURVEY) == _TRUE) { + RTW_INFO("%s: Sounding abort! scanning APs...\n", __FUNCTION__); + info->sounding_running--; + return; + } + } + + /* Get non-sound SU BFee index */ + for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) { + su_idx = sounding->su_sounding_list[i]; + if (su_idx >= MAX_BEAMFORMEE_ENTRY_NUM) + continue; + bfee = &info->bfee_entry[su_idx]; + if (_FALSE == bfee->sounding) + break; + } + if (i < MAX_NUM_BEAMFORMEE_SU) { + sounding->su_bfee_curidx = su_idx; + /* Set to sounding start state */ + sounding->state = SOUNDING_STATE_SU_START; + RTW_DBG("%s: Set to SOUNDING_STATE_SU_START\n", __FUNCTION__); + + bfee->sounding = _TRUE; + /* Reset sounding timeout flag for the new sounding */ + bfee->bSoundingTimeout = _FALSE; + + if (_TRUE == bfee->bDeleteSounding) { + u8 res = _FALSE; + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 0); + return; + } + + /* Start SU sounding */ + if (bfee->cap & BEAMFORMEE_CAP_VHT_SU) + _send_vht_ndpa_packet(adapter, bfee->mac_addr, bfee->aid, bfee->sound_bw); + else if (bfee->cap & BEAMFORMEE_CAP_HT_EXPLICIT) + _send_ht_ndpa_packet(adapter, bfee->mac_addr, bfee->sound_bw); + + /* Set sounding timeout timer */ + _set_timer(&info->sounding_timeout_timer, SU_SOUNDING_TIMEOUT); + return; + } + + if (sounding->candidate_mu_bfee_cnt > 0) { + /* + * If there is no SU BFee then find MU BFee and perform MU sounding + * + * Need to check the MU starting condition. 2015.12.15. + */ + sounding->state = SOUNDING_STATE_MU_START; + RTW_DBG("%s: Set to SOUNDING_STATE_MU_START\n", __FUNCTION__); + + /* Update MU BFee info */ + for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) { + bfee = &info->bfee_entry[sounding->mu_sounding_list[i]]; + bfee->sounding = _TRUE; + } + + /* Send MU NDPA */ + bfee = &info->bfee_entry[sounding->mu_sounding_list[0]]; + _send_vht_mu_ndpa_packet(adapter, bfee->sound_bw); + + /* Send BF report poll if more than 1 MU STA */ + for (i = 1; i < sounding->candidate_mu_bfee_cnt; i++) { + bfee = &info->bfee_entry[sounding->mu_sounding_list[i]]; + + if (i == (sounding->candidate_mu_bfee_cnt - 1))/* The last STA*/ + _send_bf_report_poll(adapter, bfee->mac_addr, _TRUE); + else + _send_bf_report_poll(adapter, bfee->mac_addr, _FALSE); + } + + sounding->candidate_mu_bfee_cnt = 0; + + /* Set sounding timeout timer */ + _set_timer(&info->sounding_timeout_timer, MU_SOUNDING_TIMEOUT); + return; + } + + info->sounding_running--; + sounding->state = SOUNDING_STATE_INIT; + RTW_INFO("%s: Sounding finished!\n", __FUNCTION__); +} + +static void _sounding_force_stop(_adapter *adapter) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + if ((sounding->state == SOUNDING_STATE_SU_START) + || (sounding->state == SOUNDING_STATE_MU_START)) { + u8 res = _FALSE; + _cancel_timer_ex(&info->sounding_timeout_timer); + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1); + return; + } + + info->sounding_running--; + sounding->state = SOUNDING_STATE_INIT; + RTW_INFO("%s: Sounding finished!\n", __FUNCTION__); +} + +static void _sounding_timer_handler(void *FunctionContext) +{ + _adapter *adapter; + struct beamforming_info *info; + struct sounding_info *sounding; + static u8 delay = 0; + + + RTW_DBG("+%s\n", __FUNCTION__); + + adapter = (_adapter *)FunctionContext; + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + if (SOUNDING_STATE_NONE == sounding->state) { + RTW_INFO("%s: Stop!\n", __FUNCTION__); + if (info->sounding_running) + RTW_WARN("%s: souding_running=%d when thread stop!\n", + __FUNCTION__, info->sounding_running); + return; + } + + _set_timer(&info->sounding_timer, sounding->min_sounding_period); + + if (!info->sounding_running) { + if (SOUNDING_STATE_INIT != sounding->state) { + RTW_WARN("%s: state(%d) != SOUNDING_STATE_INIT!!\n", __FUNCTION__, sounding->state); + sounding->state = SOUNDING_STATE_INIT; + } + delay = 0; + info->sounding_running++; + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1); + } else { + if (delay != 0xFF) + delay++; + RTW_WARN("%s: souding is still processing...(state:%d, running:%d, delay:%d)\n", + __FUNCTION__, sounding->state, info->sounding_running, delay); + if (delay > 3) { + RTW_WARN("%s: Stop sounding!!\n", __FUNCTION__); + _sounding_force_stop(adapter); + } + } +} + +static void _sounding_timeout_timer_handler(void *FunctionContext) +{ + _adapter *adapter; + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + + + RTW_WARN("+%s\n", __FUNCTION__); + + adapter = (_adapter *)FunctionContext; + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + if (SOUNDING_STATE_SU_START == sounding->state) { + sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT; + RTW_ERR("%s: Set to SU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__); + /* SU BFee */ + bfee = &info->bfee_entry[sounding->su_bfee_curidx]; + bfee->bSoundingTimeout = _TRUE; + RTW_WARN("%s: The BFee entry[%d] is Sounding Timeout!\n", __FUNCTION__, sounding->su_bfee_curidx); + } else if (SOUNDING_STATE_MU_START == sounding->state) { + sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT; + RTW_ERR("%s: Set to MU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__); + } else { + RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state); + return; + } + + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1); +} + +static struct beamformer_entry *_bfer_get_free_entry(_adapter *adapter) +{ + u8 i = 0; + struct beamforming_info *info; + struct beamformer_entry *bfer; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) { + bfer = &info->bfer_entry[i]; + if (bfer->used == _FALSE) + return bfer; + } + + return NULL; +} + +static struct beamformer_entry *_bfer_get_entry_by_addr(_adapter *adapter, u8 *ra) +{ + u8 i = 0; + struct beamforming_info *info; + struct beamformer_entry *bfer; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) { + bfer = &info->bfer_entry[i]; + if (bfer->used == _FALSE) + continue; + if (_rtw_memcmp(ra, bfer->mac_addr, ETH_ALEN) == _TRUE) + return bfer; + } + + return NULL; +} + +static struct beamformer_entry *_bfer_add_entry(_adapter *adapter, + struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering) +{ + struct mlme_priv *mlme; + struct beamforming_info *info; + struct beamformer_entry *bfer; + u8 *bssid; + u16 val16; + u8 i; + + + mlme = &adapter->mlmepriv; + info = GET_BEAMFORM_INFO(adapter); + + bfer = _bfer_get_entry_by_addr(adapter, sta->phl_sta->mac_addr); + if (!bfer) { + bfer = _bfer_get_free_entry(adapter); + if (!bfer) + return NULL; + } + + bfer->used = _TRUE; + _get_txvector_parameter(adapter, sta, &bfer->g_id, &bfer->p_aid); + _rtw_memcpy(bfer->mac_addr, sta->phl_sta->mac_addr, ETH_ALEN); + bfer->cap = bf_cap; + bfer->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT; + bfer->NumofSoundingDim = sounding_dim; + + if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_MU)) { + info->beamformer_mu_cnt += 1; + bfer->aid = sta->phl_sta->aid; + } else if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) { + info->beamformer_su_cnt += 1; + + /* Record HW idx info */ + for (i = 0; i < MAX_NUM_BEAMFORMER_SU; i++) { + if ((info->beamformer_su_reg_maping & BIT(i)) == 0) { + info->beamformer_su_reg_maping |= BIT(i); + bfer->su_reg_index = i; + break; + } + } + RTW_INFO("%s: Add BFer entry beamformer_su_reg_maping=%#x, su_reg_index=%d\n", + __FUNCTION__, info->beamformer_su_reg_maping, bfer->su_reg_index); + } + + return bfer; +} + +static void _bfer_remove_entry(_adapter *adapter, struct beamformer_entry *entry) +{ + struct beamforming_info *info; + + + info = GET_BEAMFORM_INFO(adapter); + + entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT; + + if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_MU)) { + info->beamformer_mu_cnt -= 1; + _rtw_memset(entry->gid_valid, 0, 8); + _rtw_memset(entry->user_position, 0, 16); + } else if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) { + info->beamformer_su_cnt -= 1; + } + + if (info->beamformer_mu_cnt == 0) + info->beamforming_cap &= ~BEAMFORMEE_CAP_VHT_MU; + if (info->beamformer_su_cnt == 0) + info->beamforming_cap &= ~(BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT); +} + +static u8 _bfer_set_entry_gid(_adapter *adapter, u8 *addr, u8 *gid, u8 *position) +{ + struct beamformer_entry bfer; + + _rtw_memset(&bfer, 0, sizeof(bfer)); + _rtw_memcpy(bfer.mac_addr, addr, ETH_ALEN); + + /* Parsing Membership Status Array */ + _rtw_memcpy(bfer.gid_valid, gid, 8); + + /* Parsing User Position Array */ + _rtw_memcpy(bfer.user_position, position, 16); + + /* Config HW GID table */ + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_GID_TABLE, (u8 *) &bfer, + sizeof(bfer), 1); + + return _SUCCESS; +} + +static struct beamformee_entry *_bfee_get_free_entry(_adapter *adapter) +{ + u8 i = 0; + struct beamforming_info *info; + struct beamformee_entry *bfee; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (bfee->used == _FALSE) + return bfee; + } + + return NULL; +} + +static struct beamformee_entry *_bfee_get_entry_by_addr(_adapter *adapter, u8 *ra) +{ + u8 i = 0; + struct beamforming_info *info; + struct beamformee_entry *bfee; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (bfee->used == _FALSE) + continue; + if (_rtw_memcmp(ra, bfee->mac_addr, ETH_ALEN) == _TRUE) + return bfee; + } + + return NULL; +} + +static u8 _bfee_get_first_su_entry_idx(_adapter *adapter, struct beamformee_entry *ignore) +{ + struct beamforming_info *info; + struct beamformee_entry *bfee; + u8 i; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (ignore && (bfee == ignore)) + continue; + if (bfee->used == _FALSE) + continue; + if ((!TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU)) + && TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) + return i; + } + + return 0xFF; +} + +/* + * Description: + * Get the first entry index of MU Beamformee. + * + * Return Value: + * Index of the first MU sta, or 0xFF for invalid index. + * + * 2015.05.25. Created by tynli. + * + */ +static u8 _bfee_get_first_mu_entry_idx(_adapter *adapter, struct beamformee_entry *ignore) +{ + struct beamforming_info *info; + struct beamformee_entry *bfee; + u8 i; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (ignore && (bfee == ignore)) + continue; + if (bfee->used == _FALSE) + continue; + if (TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU)) + return i; + } + + return 0xFF; +} + +static struct beamformee_entry *_bfee_add_entry(_adapter *adapter, + struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering) +{ + struct mlme_priv *mlme; + struct beamforming_info *info; + struct beamformee_entry *bfee; + u8 *bssid; + u16 val16; + u8 i; + + + mlme = &adapter->mlmepriv; + info = GET_BEAMFORM_INFO(adapter); + + bfee = _bfee_get_entry_by_addr(adapter, sta->phl_sta->mac_addr); + if (!bfee) { + bfee = _bfee_get_free_entry(adapter); + if (!bfee) + return NULL; + } + + bfee->used = _TRUE; + bfee->aid = sta->phl_sta->aid; + bfee->mac_id = sta->phl_sta->macid; + bfee->sound_bw = sta->phl_sta->chandef.bw; + + _get_txvector_parameter(adapter, sta, &bfee->g_id, &bfee->p_aid); + sta->phl_sta->bf_info.g_id = bfee->g_id; + sta->phl_sta->bf_info.p_aid = bfee->p_aid; + + _rtw_memcpy(bfee->mac_addr, sta->phl_sta->mac_addr, ETH_ALEN); + bfee->txbf = _FALSE; + bfee->sounding = _FALSE; + bfee->sound_period = 40; + _sounding_update_min_period(adapter, bfee->sound_period, _FALSE); + bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, info->sounding_info.min_sounding_period); + bfee->cap = bf_cap; + bfee->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT; + + bfee->bCandidateSoundingPeer = _FALSE; + bfee->bSoundingTimeout = _FALSE; + bfee->bDeleteSounding = _FALSE; + bfee->bApplySounding = _TRUE; + + bfee->tx_timestamp = 0; + bfee->tx_bytes = 0; + + bfee->LogStatusFailCnt = 0; + bfee->NumofSoundingDim = sounding_dim; + bfee->comp_steering_num_of_bfer = comp_steering; + bfee->bSuspendSUCap = _FALSE; + + if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_MU)) { + info->beamformee_mu_cnt += 1; + info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, NULL); + + if (_TRUE == info->bEnableSUTxBFWorkAround) { + /* When the first MU BFee added, discard SU BFee bfee's capability */ + if ((info->beamformee_mu_cnt == 1) && (info->beamformee_su_cnt > 0)) { + if (info->TargetSUBFee) { + info->TargetSUBFee->bSuspendSUCap = _TRUE; + info->TargetSUBFee->bDeleteSounding = _TRUE; + } else { + RTW_ERR("%s: UNEXPECTED!! info->TargetSUBFee is NULL!", __FUNCTION__); + } + info->TargetSUBFee = NULL; + _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO)); + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0); + } + } + + /* Record HW idx info */ + for (i = 0; i < MAX_NUM_BEAMFORMEE_MU; i++) { + if ((info->beamformee_mu_reg_maping & BIT(i)) == 0) { + info->beamformee_mu_reg_maping |= BIT(i); + bfee->mu_reg_index = i; + break; + } + } + RTW_INFO("%s: Add BFee entry beamformee_mu_reg_maping=%#x, mu_reg_index=%d\n", + __FUNCTION__, info->beamformee_mu_reg_maping, bfee->mu_reg_index); + + } else if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) { + info->beamformee_su_cnt += 1; + + if (_TRUE == info->bEnableSUTxBFWorkAround) { + /* Record the first SU BFee index. We only allow the first SU BFee to be sound */ + if ((info->beamformee_su_cnt == 1) && (info->beamformee_mu_cnt == 0)) { + info->TargetSUBFee = bfee; + _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO)); + bfee->bSuspendSUCap = _FALSE; + } else { + bfee->bSuspendSUCap = _TRUE; + } + } + + /* Record HW idx info */ + for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) { + if ((info->beamformee_su_reg_maping & BIT(i)) == 0) { + info->beamformee_su_reg_maping |= BIT(i); + bfee->su_reg_index = i; + break; + } + } + RTW_INFO("%s: Add BFee entry beamformee_su_reg_maping=%#x, su_reg_index=%d\n", + __FUNCTION__, info->beamformee_su_reg_maping, bfee->su_reg_index); + } + + return bfee; +} + +static void _bfee_remove_entry(_adapter *adapter, struct beamformee_entry *entry) +{ + struct beamforming_info *info; + u8 idx; + + + info = GET_BEAMFORM_INFO(adapter); + + entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT; + + if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_MU)) { + info->beamformee_mu_cnt -= 1; + info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, entry); + + if (_TRUE == info->bEnableSUTxBFWorkAround) { + if ((info->beamformee_mu_cnt == 0) && (info->beamformee_su_cnt > 0)) { + idx = _bfee_get_first_su_entry_idx(adapter, NULL); + info->TargetSUBFee = &info->bfee_entry[idx]; + _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO)); + info->TargetSUBFee->bSuspendSUCap = _FALSE; + } + } + } else if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) { + info->beamformee_su_cnt -= 1; + + /* When the target SU BFee leaves, disable workaround */ + if ((_TRUE == info->bEnableSUTxBFWorkAround) + && (entry == info->TargetSUBFee)) { + entry->bSuspendSUCap = _TRUE; + info->TargetSUBFee = NULL; + _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO)); + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0); + } + } + + if (info->beamformee_mu_cnt == 0) + info->beamforming_cap &= ~BEAMFORMER_CAP_VHT_MU; + if (info->beamformee_su_cnt == 0) + info->beamforming_cap &= ~(BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT); + + _sounding_update_min_period(adapter, 0, _TRUE); +} + +static enum beamforming_cap _bfee_get_entry_cap_by_macid(_adapter *adapter, u8 macid) +{ + struct beamforming_info *info; + struct beamformee_entry *bfee; + u8 i; + + + info = GET_BEAMFORM_INFO(adapter); + + for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (bfee->used == _FALSE) + continue; + if (bfee->mac_id == macid) + return bfee->cap; + } + + return BEAMFORMING_CAP_NONE; +} + +static void _beamforming_enter(_adapter *adapter, void *p) +{ + struct mlme_priv *mlme; + struct ht_priv *htpriv; +#ifdef CONFIG_80211AC_VHT + struct vht_priv *vhtpriv; +#endif + struct mlme_ext_priv *mlme_ext; + struct sta_info *sta, *sta_copy; + struct beamforming_info *info; + struct beamformer_entry *bfer = NULL; + struct beamformee_entry *bfee = NULL; + u8 wireless_mode; + u8 sta_bf_cap; + u8 sounding_dim = 0; /* number of sounding dimensions */ + u8 comp_steering_num = 0; /* compressed steering number */ + + + mlme = &adapter->mlmepriv; + htpriv = &mlme->htpriv; +#ifdef CONFIG_80211AC_VHT + vhtpriv = &mlme->vhtpriv; +#endif + mlme_ext = &adapter->mlmeextpriv; + info = GET_BEAMFORM_INFO(adapter); + + sta_copy = (struct sta_info *)p; + sta = rtw_get_stainfo(&adapter->stapriv, sta_copy->phl_sta->mac_addr); + if (!sta) { + RTW_ERR("%s: Cann't find STA info for " MAC_FMT "\n", + __FUNCTION__, MAC_ARG(sta_copy->phl_sta->mac_addr)); + return; + } + if (sta != sta_copy) { + RTW_WARN("%s: Origin sta(fake)=%p realsta=%p for " MAC_FMT "\n", + __FUNCTION__, sta_copy, sta, MAC_ARG(sta_copy->phl_sta->mac_addr)); + } + + /* The current setting does not support Beaforming */ + wireless_mode = sta->phl_sta->wmode; + if ((is_supported_ht(wireless_mode) == _FALSE) + && (is_supported_vht(wireless_mode) == _FALSE)) { + RTW_WARN("%s: Not support HT or VHT mode\n", __FUNCTION__); + return; + } + + if ((0 == htpriv->beamform_cap) +#ifdef CONFIG_80211AC_VHT + && (0 == vhtpriv->beamform_cap) +#endif +#ifdef CONFIG_80211AX_HE + /* CONFIG_80211AX_HE_TODO */ +#endif + ) { + RTW_INFO("The configuration disabled Beamforming! Skip...\n"); + return; + } + + _get_sta_beamform_cap(adapter, sta, + &sta_bf_cap, &sounding_dim, &comp_steering_num); + RTW_INFO("STA Beamforming Capability=0x%02X\n", sta_bf_cap); + if (sta_bf_cap == BEAMFORMING_CAP_NONE) + return; + if ((sta_bf_cap & BEAMFORMEE_CAP_HT_EXPLICIT) + || (sta_bf_cap & BEAMFORMEE_CAP_VHT_SU) + || (sta_bf_cap & BEAMFORMEE_CAP_VHT_MU)) + sta_bf_cap |= BEAMFORMEE_CAP; + if ((sta_bf_cap & BEAMFORMER_CAP_HT_EXPLICIT) + || (sta_bf_cap & BEAMFORMER_CAP_VHT_SU) + || (sta_bf_cap & BEAMFORMER_CAP_VHT_MU)) + sta_bf_cap |= BEAMFORMER_CAP; + + if (sta_bf_cap & BEAMFORMER_CAP) { + /* The other side is beamformer */ + bfer = _bfer_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num); + if (!bfer) + RTW_ERR("%s: Fail to allocate bfer entry!\n", __FUNCTION__); + } + if (sta_bf_cap & BEAMFORMEE_CAP) { + /* The other side is beamformee */ + bfee = _bfee_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num); + if (!bfee) + RTW_ERR("%s: Fail to allocate bfee entry!\n", __FUNCTION__); + } + if (!bfer && !bfee) + return; + + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8*)sta); + + /* Perform sounding if there is BFee */ + if ((info->beamformee_su_cnt != 0) + || (info->beamformee_mu_cnt != 0)) { + if (SOUNDING_STATE_NONE == info->sounding_info.state) { + info->sounding_info.state = SOUNDING_STATE_INIT; + /* Start sounding after 2 sec */ + _set_timer(&info->sounding_timer, 2000); + } + } +} + +static void _beamforming_reset(_adapter *adapter) +{ + RTW_ERR("%s: Not ready!!\n", __FUNCTION__); +} + +static void _beamforming_leave(_adapter *adapter, u8 *ra) +{ + struct beamforming_info *info; + struct beamformer_entry *bfer = NULL; + struct beamformee_entry *bfee = NULL; + u8 bHwStateAddInit = _FALSE; + + + RTW_INFO("+%s\n", __FUNCTION__); + + info = GET_BEAMFORM_INFO(adapter); + bfer = _bfer_get_entry_by_addr(adapter, ra); + bfee = _bfee_get_entry_by_addr(adapter, ra); + + if (!bfer && !bfee) { + RTW_WARN("%s: " MAC_FMT " is neither beamforming ee or er!!\n", + __FUNCTION__, MAC_ARG(ra)); + return; + } + + if (bfer) + _bfer_remove_entry(adapter, bfer); + + if (bfee) + _bfee_remove_entry(adapter, bfee); + + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, ra); + + /* Stop sounding if there is no any BFee */ + if ((info->beamformee_su_cnt == 0) + && (info->beamformee_mu_cnt == 0)) { + _cancel_timer_ex(&info->sounding_timer); + _sounding_init(&info->sounding_info); + } + + RTW_INFO("-%s\n", __FUNCTION__); +} + +static void _beamforming_sounding_down(_adapter *adapter, u8 status) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + RTW_INFO("+%s: sounding=%d, status=0x%02x\n", __FUNCTION__, sounding->state, status); + + if (sounding->state == SOUNDING_STATE_MU_START) { + RTW_INFO("%s: MU sounding done\n", __FUNCTION__); + sounding->state = SOUNDING_STATE_MU_SOUNDDOWN; + RTW_INFO("%s: Set to SOUNDING_STATE_MU_SOUNDDOWN\n", __FUNCTION__); + info->SetHalSoundownOnDemandCnt++; + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status); + } else if (sounding->state == SOUNDING_STATE_SU_START) { + RTW_INFO("%s: SU entry[%d] sounding down\n", __FUNCTION__, sounding->su_bfee_curidx); + bfee = &info->bfee_entry[sounding->su_bfee_curidx]; + sounding->state = SOUNDING_STATE_SU_SOUNDDOWN; + RTW_INFO("%s: Set to SOUNDING_STATE_SU_SOUNDDOWN\n", __FUNCTION__); + + /* + * + * bfee->bSoundingTimeout this flag still cannot avoid + * old sound down event happens in the new sounding period. + * 2015.12.10 + */ + if (_TRUE == bfee->bSoundingTimeout) { + RTW_WARN("%s: The entry[%d] is bSoundingTimeout!\n", __FUNCTION__, sounding->su_bfee_curidx); + bfee->bSoundingTimeout = _FALSE; + return; + } + + if (_TRUE == status) { + /* success */ + bfee->LogStatusFailCnt = 0; + info->SetHalSoundownOnDemandCnt++; + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status); + } else if (_TRUE == bfee->bDeleteSounding) { + RTW_WARN("%s: Delete entry[%d] sounding info!\n", __FUNCTION__, sounding->su_bfee_curidx); + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status); + bfee->bDeleteSounding = _FALSE; + } else { + bfee->LogStatusFailCnt++; + RTW_WARN("%s: LogStatusFailCnt=%d\n", __FUNCTION__, bfee->LogStatusFailCnt); + if (bfee->LogStatusFailCnt > 30) { + RTW_ERR("%s: LogStatusFailCnt > 30, Stop SOUNDING!!\n", __FUNCTION__); + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_LEAVE, bfee->mac_addr, ETH_ALEN, 1); + } + } + } else { + RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state); + return; + } + + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 0); +} + +static void _c2h_snd_txbf(_adapter *adapter, u8 *buf, u8 buf_len) +{ + struct beamforming_info *info; + u8 res; + + info = GET_BEAMFORM_INFO(adapter); + + _cancel_timer_ex(&info->sounding_timeout_timer); + + res = C2H_SND_TXBF_GET_SND_RESULT(buf) ? _TRUE : _FALSE; + RTW_INFO("+%s: %s\n", __FUNCTION__, res==_TRUE?"Success":"Fail!"); + + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1); +} + +/* + * Description: + * This function is for phydm only + */ +enum beamforming_cap rtw_bf_bfee_get_entry_cap_by_macid(void *mlme, u8 macid) +{ + _adapter *adapter; + enum beamforming_cap cap = BEAMFORMING_CAP_NONE; + + + adapter = mlme_to_adapter((struct mlme_priv *)mlme); + cap = _bfee_get_entry_cap_by_macid(adapter, macid); + + return cap; +} + +struct beamformer_entry *rtw_bf_bfer_get_entry_by_addr(_adapter *adapter, u8 *ra) +{ + return _bfer_get_entry_by_addr(adapter, ra); +} + +struct beamformee_entry *rtw_bf_bfee_get_entry_by_addr(_adapter *adapter, u8 *ra) +{ + return _bfee_get_entry_by_addr(adapter, ra); +} + +void rtw_bf_get_ndpa_packet(_adapter *adapter, union recv_frame *precv_frame) +{ + RTW_DBG("+%s\n", __FUNCTION__); +} + +u32 rtw_bf_get_report_packet(_adapter *adapter, union recv_frame *precv_frame) +{ + u32 ret = _SUCCESS; + struct beamforming_info *info; + struct beamformee_entry *bfee = NULL; + u8 *pframe; + u32 frame_len; + u8 *ta; + u8 *frame_body; + u8 category, action; + u8 *pMIMOCtrlField, *pCSIMatrix; + u8 Nc = 0, Nr = 0, CH_W = 0, Ng = 0, CodeBook = 0; + u16 CSIMatrixLen = 0; + + + RTW_INFO("+%s\n", __FUNCTION__); + + info = GET_BEAMFORM_INFO(adapter); + pframe = precv_frame->u.hdr.rx_data; + frame_len = precv_frame->u.hdr.len; + + /* Memory comparison to see if CSI report is the same with previous one */ + ta = get_addr2_ptr(pframe); + bfee = _bfee_get_entry_by_addr(adapter, ta); + if (!bfee) + return _FAIL; + + frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + category = frame_body[0]; + action = frame_body[1]; + + if ((category == RTW_WLAN_CATEGORY_VHT) + && (action == RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING)) { + pMIMOCtrlField = pframe + 26; + Nc = (*pMIMOCtrlField) & 0x7; + Nr = ((*pMIMOCtrlField) & 0x38) >> 3; + CH_W = (((*pMIMOCtrlField) & 0xC0) >> 6); + Ng = (*(pMIMOCtrlField+1)) & 0x3; + CodeBook = ((*(pMIMOCtrlField+1)) & 0x4) >> 2; + /* + * 24+(1+1+3)+2 + * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2) + */ + pCSIMatrix = pMIMOCtrlField + 3 + Nc; + CSIMatrixLen = frame_len - 26 - 3 - Nc; + info->TargetCSIInfo.bVHT = _TRUE; + } else if ((category == RTW_WLAN_CATEGORY_HT) + && (action == RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING)) { + pMIMOCtrlField = pframe + 26; + Nc = (*pMIMOCtrlField) & 0x3; + Nr = ((*pMIMOCtrlField) & 0xC) >> 2; + CH_W = ((*pMIMOCtrlField) & 0x10) >> 4; + Ng = ((*pMIMOCtrlField) & 0x60) >> 5; + CodeBook = ((*(pMIMOCtrlField+1)) & 0x6) >> 1; + /* + * 24+(1+1+6)+2 + * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2) + */ + pCSIMatrix = pMIMOCtrlField + 6 + Nr; + CSIMatrixLen = frame_len - 26 - 6 - Nr; + info->TargetCSIInfo.bVHT = _FALSE; + } + + /* Update current CSI report info */ + if ((_TRUE == info->bEnableSUTxBFWorkAround) + && (info->TargetSUBFee == bfee)) { + if ((info->TargetCSIInfo.Nc != Nc) || (info->TargetCSIInfo.Nr != Nr) || + (info->TargetCSIInfo.ChnlWidth != CH_W) || (info->TargetCSIInfo.Ng != Ng) || + (info->TargetCSIInfo.CodeBook != CodeBook)) { + info->TargetCSIInfo.Nc = Nc; + info->TargetCSIInfo.Nr = Nr; + info->TargetCSIInfo.ChnlWidth = CH_W; + info->TargetCSIInfo.Ng = Ng; + info->TargetCSIInfo.CodeBook = CodeBook; + + rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 1); + } + } + + RTW_INFO("%s: pkt type=%d-%d, Nc=%d, Nr=%d, CH_W=%d, Ng=%d, CodeBook=%d\n", + __FUNCTION__, category, action, Nc, Nr, CH_W, Ng, CodeBook); + + return ret; +} + +u8 rtw_bf_send_vht_gid_mgnt_packet(_adapter *adapter, u8 *ra, u8 *gid, u8 *position) +{ + /* General */ + struct xmit_priv *xmitpriv; + struct mlme_priv *mlmepriv; + struct xmit_frame *pmgntframe; + /* MISC */ + struct pkt_attrib *attrib; + struct rtw_ieee80211_hdr *wlanhdr; + u8 *pframe, *ptr; + + + xmitpriv = &adapter->xmitpriv; + mlmepriv = &adapter->mlmepriv; + + pmgntframe = alloc_mgtxmitframe(xmitpriv); + if (!pmgntframe) + return _FALSE; + + /* update attribute */ + attrib = &pmgntframe->attrib; + update_mgntframe_attrib(adapter, attrib); + attrib->rate = MGN_6M; + attrib->bwmode = CHANNEL_WIDTH_20; + attrib->subtype = WIFI_ACTION; + + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + + pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; + wlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + wlanhdr->frame_ctl = 0; + set_frame_sub_type(pframe, attrib->subtype); + set_duration(pframe, 0); + SetFragNum(pframe, 0); + SetSeqNum(pframe, 0); + + _rtw_memcpy(wlanhdr->addr1, ra, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN); + _rtw_memcpy(wlanhdr->addr3, get_bssid(mlmepriv), ETH_ALEN); + + pframe[24] = RTW_WLAN_CATEGORY_VHT; + pframe[25] = RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT; + /* Set Membership Status Array */ + ptr = pframe + 26; + _rtw_memcpy(ptr, gid, 8); + /* Set User Position Array */ + ptr = pframe + 34; + _rtw_memcpy(ptr, position, 16); + + attrib->pktlen = 54; + attrib->last_txcmdsz = attrib->pktlen; + + dump_mgntframe(adapter, pmgntframe); + + return _TRUE; +} + +/* + * Description: + * On VHT GID management frame by an MU beamformee. + */ +void rtw_bf_get_vht_gid_mgnt_packet(_adapter *adapter, union recv_frame *precv_frame) +{ + u8 *pframe; + u8 *ta, *gid, *position; + + + RTW_DBG("+%s\n", __FUNCTION__); + + pframe = precv_frame->u.hdr.rx_data; + + /* Get address by Addr2 */ + ta = get_addr2_ptr(pframe); + /* Remove signaling TA */ + ta[0] &= 0xFE; + + /* Membership Status Array */ + gid = pframe + 26; + /* User Position Array */ + position= pframe + 34; + + _bfer_set_entry_gid(adapter, ta, gid, position); +} + +void rtw_bf_init(_adapter *adapter) +{ + struct beamforming_info *info; + + + info = GET_BEAMFORM_INFO(adapter); + info->beamforming_cap = BEAMFORMING_CAP_NONE; + info->beamforming_state = BEAMFORMING_STATE_IDLE; +/* + info->bfee_entry[MAX_BEAMFORMEE_ENTRY_NUM]; + info->bfer_entry[MAX_BEAMFORMER_ENTRY_NUM]; +*/ + info->sounding_sequence = 0; + info->beamformee_su_cnt = 0; + info->beamformer_su_cnt = 0; + info->beamformee_su_reg_maping = 0; + info->beamformer_su_reg_maping = 0; + info->beamformee_mu_cnt = 0; + info->beamformer_mu_cnt = 0; + info->beamformee_mu_reg_maping = 0; + info->first_mu_bfee_index = 0xFF; + info->mu_bfer_curidx = 0xFF; + info->cur_csi_rpt_rate = HALMAC_OFDM24; + + _sounding_init(&info->sounding_info); + rtw_init_timer(&info->sounding_timer, _sounding_timer_handler, adapter); + rtw_init_timer(&info->sounding_timeout_timer, _sounding_timeout_timer_handler, adapter); + + info->SetHalBFEnterOnDemandCnt = 0; + info->SetHalBFLeaveOnDemandCnt = 0; + info->SetHalSoundownOnDemandCnt = 0; + + info->bEnableSUTxBFWorkAround = _TRUE; + info->TargetSUBFee = NULL; + + info->sounding_running = 0; +} + +void rtw_bf_cmd_hdl(_adapter *adapter, u8 type, u8 *pbuf) +{ + switch (type) { + case BEAMFORMING_CTRL_ENTER: + _beamforming_enter(adapter, pbuf); + break; + + case BEAMFORMING_CTRL_LEAVE: + if (pbuf == NULL) + _beamforming_reset(adapter); + else + _beamforming_leave(adapter, pbuf); + break; + + case BEAMFORMING_CTRL_START_PERIOD: + _sounding_handler(adapter); + break; + + case BEAMFORMING_CTRL_END_PERIOD: + _beamforming_sounding_down(adapter, *pbuf); + break; + + case BEAMFORMING_CTRL_SET_GID_TABLE: + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_SET_GID_TABLE, pbuf); + break; + + case BEAMFORMING_CTRL_SET_CSI_REPORT: + rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_CSI_REPORT, pbuf); + break; + + default: + break; + } +} + +u8 rtw_bf_cmd(_adapter *adapter, s32 type, u8 *pbuf, s32 size, u8 enqueue) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 *wk_buf; + u8 res = _SUCCESS; + + if (!enqueue) { + rtw_bf_cmd_hdl(adapter, type, pbuf); + goto exit; + } + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + if (pbuf != NULL) { + wk_buf = rtw_zmalloc(size); + if (wk_buf == NULL) { + rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + _rtw_memcpy(wk_buf, pbuf, size); + } else { + wk_buf = NULL; + size = 0; + } + + pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID; + pdrvextra_cmd_parm->type = type; + pdrvextra_cmd_parm->size = size; + pdrvextra_cmd_parm->pbuf = wk_buf; + + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; +} + +void rtw_bf_update_attrib(_adapter *adapter, struct pkt_attrib *attrib, struct sta_info *sta) +{ +/* bf_cmn_info move to hal_sta */ +#if 0 + if (sta) { + attrib->txbf_g_id = sta->phl_sta->bf_info.g_id; + attrib->txbf_p_aid = sta->phl_sta->bf_info.p_aid; + } +#endif +} + +void rtw_bf_c2h_handler(_adapter *adapter, u8 id, u8 *buf, u8 buf_len) +{ + switch (id) { + case CMD_ID_C2H_SND_TXBF: + _c2h_snd_txbf(adapter, buf, buf_len); + break; + } +} + +#define toMbps(bytes, secs) (rtw_division64(bytes >> 17, secs)) +void rtw_bf_update_traffic(_adapter *adapter) +{ + struct beamforming_info *info; + struct sounding_info *sounding; + struct beamformee_entry *bfee; + struct sta_info *sta; + u8 bfee_cnt, sounding_idx, i; + u16 tp[MAX_BEAMFORMEE_ENTRY_NUM] = {0}; + u16 tx_rate[MAX_BEAMFORMEE_ENTRY_NUM] = {0}; + u64 tx_bytes, last_bytes; + u32 time; + systime last_timestamp; + u8 set_timer = _FALSE; + + + info = GET_BEAMFORM_INFO(adapter); + sounding = &info->sounding_info; + + /* Check any bfee exist? */ + bfee_cnt = info->beamformee_su_cnt + info->beamformee_mu_cnt; + if (bfee_cnt == 0) + return; + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (_FALSE == bfee->used) + continue; + + sta = rtw_get_stainfo(&adapter->stapriv, bfee->mac_addr); + if (!sta) { + RTW_ERR("%s: Cann't find sta_info for " MAC_FMT "!\n", __FUNCTION__, MAC_ARG(bfee->mac_addr)); + continue; + } + + last_timestamp = bfee->tx_timestamp; + last_bytes = bfee->tx_bytes; + bfee->tx_timestamp = rtw_get_current_time(); + bfee->tx_bytes = sta->sta_stats.tx_bytes; + if (last_timestamp) { + if (bfee->tx_bytes >= last_bytes) + tx_bytes = bfee->tx_bytes - last_bytes; + else + tx_bytes = bfee->tx_bytes + (~last_bytes); + time = rtw_get_time_interval_ms(last_timestamp, bfee->tx_timestamp); + time = (time > 1000) ? time/1000 : 1; + tp[i] = toMbps(tx_bytes, time); + tx_rate[i] = rtw_get_current_tx_rate(adapter, sta); + RTW_INFO("%s: BFee idx(%d), MadId(%d), TxTP=%lld bytes (%d Mbps), txrate=%d\n", + __FUNCTION__, i, bfee->mac_id, tx_bytes, tp[i], tx_rate[i]); + } + } + + sounding_idx = rtw_hal_get_sounding_info(adapter, tp, MAX_BEAMFORMEE_ENTRY_NUM, tx_rate); + + for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) { + bfee = &info->bfee_entry[i]; + if (_FALSE == bfee->used) { + if (sounding_idx & BIT(i)) + RTW_WARN("%s: bfee(%d) not in used but need sounding?!\n", __FUNCTION__, i); + continue; + } + + if (sounding_idx & BIT(i)) { + if (_FALSE == bfee->bApplySounding) { + bfee->bApplySounding = _TRUE; + bfee->SoundCnt = 0; + set_timer = _TRUE; + } + } else { + if (_TRUE == bfee->bApplySounding) { + bfee->bApplySounding = _FALSE; + bfee->bDeleteSounding = _TRUE; + bfee->SoundCnt = 0; + set_timer = _TRUE; + } + } + } + + if (_TRUE == set_timer) { + if (SOUNDING_STATE_NONE == info->sounding_info.state) { + info->sounding_info.state = SOUNDING_STATE_INIT; + _set_timer(&info->sounding_timer, 0); + } + } +} +#else +/* + * rtw_bf_get_vht_gid_mgnt_packet() - Set VHT GID for MU beamformee + * @a: struct _ADAPTER* + * @rframe: union recv_frame* + * + * Return 0 for success, otherwise fail. + * + */ +int rtw_bf_get_vht_gid_mgnt_packet(struct _ADAPTER *a, union recv_frame *rframe) +{ + struct rtw_phl_gid_pos_tbl tbl = {0}; + u8 *data, *gid, *pos; + enum rtw_phl_status status; + int err = 0; + + + data = rframe->u.hdr.rx_data; + RTW_DBG(FUNC_ADPT_FMT ": GID setting for " MAC_FMT "\n", + FUNC_ADPT_ARG(a), MAC_ARG(get_addr2_ptr(data))); + /* Move to data start */ + data += 26; + + /* Membership Status Array */ + gid = data; + _rtw_memcpy(tbl.gid_vld, gid, RTW_VHT_GID_MGNT_FRAME_GID_SZ); + RTW_DBG_DUMP("Membership Status Array: ", tbl.gid_vld, RTW_VHT_GID_MGNT_FRAME_GID_SZ); + /* User Position Array */ + pos= data + RTW_VHT_GID_MGNT_FRAME_GID_SZ; + _rtw_memcpy(tbl.pos, pos, RTW_VHT_GID_MGNT_FRAME_POS_SZ); + RTW_DBG_DUMP("User Position Array: ", tbl.pos, RTW_VHT_GID_MGNT_FRAME_POS_SZ); + + /* Config HW GID table */ + status = rtw_phl_snd_cmd_set_vht_gid(GET_PHL_INFO(adapter_to_dvobj(a)), + a->phl_role, &tbl); + if (status == RTW_PHL_STATUS_SUCCESS) { + RTW_DBG(FUNC_ADPT_FMT ": Add VHT GID Success\n", + FUNC_ADPT_ARG(a)); + } else { + RTW_ERR(FUNC_ADPT_FMT ": Add VHT GID FAIL!(0x%x)\n", + FUNC_ADPT_ARG(a), status); + err = -1; + } + + return err; +} +#endif +#endif /* CONFIG_BEAMFORMING */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_br_ext.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_br_ext.c new file mode 100644 index 00000000..31c10c1f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_br_ext.c @@ -0,0 +1,1582 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_BR_EXT_C_ + +#ifdef __KERNEL__ + #include + #include + #include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + #include +#endif + #include + #include + #include +#endif + +#if 1 /* rtw_wifi_driver */ + #include +#else /* rtw_wifi_driver */ + #include "./8192cd_cfg.h" + + #ifndef __KERNEL__ + #include "./sys-support.h" + #endif + + #include "./8192cd.h" + #include "./8192cd_headers.h" + #include "./8192cd_br_ext.h" + #include "./8192cd_debug.h" +#endif /* rtw_wifi_driver */ + +#ifdef CL_IPV6_PASS + #ifdef __KERNEL__ + #include + #include + #include + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) + #include + #else + #include + #endif + #endif +#endif + +#ifdef CONFIG_BR_EXT + +/* #define BR_EXT_DEBUG */ + +#define NAT25_IPV4 01 +#define NAT25_IPV6 02 +#define NAT25_IPX 03 +#define NAT25_APPLE 04 +#define NAT25_PPPOE 05 + +#define RTL_RELAY_TAG_LEN (ETH_ALEN) +#define TAG_HDR_LEN 4 + +#define MAGIC_CODE 0x8186 +#define MAGIC_CODE_LEN 2 +#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ + +/*----------------------------------------------------------------- + How database records network address: + 0 1 2 3 4 5 6 7 8 9 10 + |----|----|----|----|----|----|----|----|----|----|----| + IPv4 |type| | IP addr | + IPX |type| Net addr | Node addr | + IPX |type| Net addr |Sckt addr| + Apple |type| Network |node| + PPPoE |type| SID | AC MAC | +-----------------------------------------------------------------*/ + + +/* Find a tag in pppoe frame and return the pointer */ +static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) +{ + unsigned char *cur_ptr, *start_ptr; + unsigned short tagLen, tagType; + + start_ptr = cur_ptr = (unsigned char *)ph->tag; + while ((cur_ptr - start_ptr) < ntohs(ph->length)) { + /* prevent un-alignment access */ + tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); + tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); + if (tagType == type) + return cur_ptr; + cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; + } + return 0; +} + + +static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) +{ + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + int data_len; + + data_len = tag->tag_len + TAG_HDR_LEN; + if (skb_tailroom(skb) < data_len) { + _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n"); + return -1; + } + + skb_put(skb, data_len); + /* have a room for new tag */ + _rtw_memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); + ph->length = htons(ntohs(ph->length) + data_len); + _rtw_memcpy((unsigned char *)ph->tag, tag, data_len); + return data_len; +} + +static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) +{ + int tail_len; + unsigned long end, tail; + + if ((src + len) > skb_tail_pointer(skb) || skb->len < len) + return -1; + + tail = (unsigned long)skb_tail_pointer(skb); + end = (unsigned long)src + len; + if (tail < end) + return -1; + + tail_len = (int)(tail - end); + if (tail_len > 0) + _rtw_memmove(src, src + len, tail_len); + + skb_trim(skb, skb->len - len); + return 0; +} + +static __inline__ unsigned long __nat25_timeout(_adapter *priv) +{ + unsigned long timeout; + + timeout = jiffies - NAT25_AGEING_TIME * HZ; + + return timeout; +} + + +static __inline__ int __nat25_has_expired(_adapter *priv, + struct nat25_network_db_entry *fdb) +{ + if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv))) + return 1; + + return 0; +} + + +static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, + unsigned int *ipAddr) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV4; + _rtw_memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, + unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + _rtw_memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); + _rtw_memcpy(networkAddr + 5, ipxNodeAddr, 6); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, + unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + _rtw_memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); + _rtw_memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2); +} + + +static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, + unsigned short *network, unsigned char *node) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_APPLE; + _rtw_memcpy(networkAddr + 1, (unsigned char *)network, 2); + networkAddr[3] = *node; +} + + +static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, + unsigned char *ac_mac, unsigned short *sid) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_PPPOE; + _rtw_memcpy(networkAddr + 1, (unsigned char *)sid, 2); + _rtw_memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); +} + + +#ifdef CL_IPV6_PASS +static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, + unsigned int *ipAddr) +{ + _rtw_memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV6; + _rtw_memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); +} + + +static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) +{ + while (len > 0) { + if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) + return data + 2; + + len -= (*(data + 1)) * 8; + data += (*(data + 1)) * 8; + } + return NULL; +} + + +static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) +{ + struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; + unsigned char *mac; + + if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { + if (len >= 8) { + mac = scan_tlv(&data[8], len - 8, 1, 1); + if (mac) { + RTW_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + _rtw_memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { + if (len >= 16) { + mac = scan_tlv(&data[16], len - 16, 1, 1); + if (mac) { + RTW_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + _rtw_memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { + if (len >= 24) { + mac = scan_tlv(&data[24], len - 24, 1, 1); + if (mac) { + RTW_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + _rtw_memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { + if (len >= 24) { + mac = scan_tlv(&data[24], len - 24, 2, 1); + if (mac) { + RTW_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + _rtw_memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { + if (len >= 40) { + mac = scan_tlv(&data[40], len - 40, 2, 1); + if (mac) { + RTW_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + _rtw_memcpy(mac, replace_mac, 6); + return 1; + } + } + } + return 0; +} + +#ifdef SUPPORT_RX_UNI2MCAST +static void convert_ipv6_mac_to_mc(struct sk_buff *skb) +{ + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + unsigned char *dst_mac = skb->data; + + /* dst_mac[0] = 0xff; */ + /* dst_mac[1] = 0xff; */ + /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ + dst_mac[0] = 0x33; + dst_mac[1] = 0x33; + _rtw_memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); +#if defined(__LINUX_2_6__) + /*modified by qinjunjie,warning:should not remove next line*/ + skb->pkt_type = PACKET_MULTICAST; +#endif +} +#endif /* CL_IPV6_PASS */ +#endif /* SUPPORT_RX_UNI2MCAST */ + + +static __inline__ int __nat25_network_hash(unsigned char *networkAddr) +{ + if (networkAddr[0] == NAT25_IPV4) { + unsigned long x; + + x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_IPX) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_APPLE) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_PPPOE) { + unsigned long x; + + x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; + + return x & (NAT25_HASH_SIZE - 1); + } +#ifdef CL_IPV6_PASS + else if (networkAddr[0] == NAT25_IPV6) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ + networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ + networkAddr[16]; + + return x & (NAT25_HASH_SIZE - 1); + } +#endif + else { + unsigned long x = 0; + int i; + + for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) + x ^= networkAddr[i]; + + return x & (NAT25_HASH_SIZE - 1); + } +} + + +static __inline__ void __network_hash_link(_adapter *priv, + struct nat25_network_db_entry *ent, int hash) +{ + /* Caller must _rtw_spinlock_bh already! */ + /* _rtw_spinlock_bh(&priv->br_ext_lock); */ + + ent->next_hash = priv->nethash[hash]; + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = &ent->next_hash; + priv->nethash[hash] = ent; + ent->pprev_hash = &priv->nethash[hash]; + + /* _rtw_spinunlock_bh(&priv->br_ext_lock); */ +} + + +static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) +{ + /* Caller must _rtw_spinlock_bh already! */ + /* _rtw_spinlock_bh(&priv->br_ext_lock); */ + + *(ent->pprev_hash) = ent->next_hash; + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = ent->pprev_hash; + ent->next_hash = NULL; + ent->pprev_hash = NULL; + + /* _rtw_spinunlock_bh(&priv->br_ext_lock); */ +} + + +static int __nat25_db_network_lookup_and_replace(_adapter *priv, + struct sk_buff *skb, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + _rtw_spinlock_bh(&priv->br_ext_lock); + + db = priv->nethash[__nat25_network_hash(networkAddr)]; + while (db != NULL) { + if (_rtw_memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + if (!__nat25_has_expired(priv, db)) { + /* replace the destination mac address */ + _rtw_memcpy(skb->data, db->macAddr, ETH_ALEN); + atomic_inc(&db->use_count); + +#ifdef CL_IPV6_PASS + RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + } + _rtw_spinunlock_bh(&priv->br_ext_lock); + return 1; + } + + db = db->next_hash; + } + + _rtw_spinunlock_bh(&priv->br_ext_lock); + return 0; +} + + +static void __nat25_db_network_insert(_adapter *priv, + unsigned char *macAddr, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + int hash; + + _rtw_spinlock_bh(&priv->br_ext_lock); + + hash = __nat25_network_hash(networkAddr); + db = priv->nethash[hash]; + while (db != NULL) { + if (_rtw_memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + _rtw_memcpy(db->macAddr, macAddr, ETH_ALEN); + db->ageing_timer = jiffies; + _rtw_spinunlock_bh(&priv->br_ext_lock); + return; + } + + db = db->next_hash; + } + + db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db)); + if (db == NULL) { + _rtw_spinunlock_bh(&priv->br_ext_lock); + return; + } + + _rtw_memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); + _rtw_memcpy(db->macAddr, macAddr, ETH_ALEN); + atomic_set(&db->use_count, 1); + db->ageing_timer = jiffies; + + __network_hash_link(priv, db, hash); + + _rtw_spinunlock_bh(&priv->br_ext_lock); +} + + +static void __nat25_db_print(_adapter *priv) +{ + + _rtw_spinlock_bh(&priv->br_ext_lock); + +#ifdef BR_EXT_DEBUG + static int counter = 0; + int i, j; + struct nat25_network_db_entry *db; + + counter++; + if ((counter % 16) != 0) + return; + + for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { + db = priv->nethash[i]; + + while (db != NULL) { +#ifdef CL_IPV6_PASS + panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + j++; + + db = db->next_hash; + } + } +#endif + + _rtw_spinunlock_bh(&priv->br_ext_lock); +} + + + + +/* + * NAT2.5 interface + */ + +void nat25_db_cleanup(_adapter *priv) +{ + int i; + + _rtw_spinlock_bh(&priv->br_ext_lock); + + for (i = 0; i < NAT25_HASH_SIZE; i++) { + struct nat25_network_db_entry *f; + f = priv->nethash[i]; + while (f != NULL) { + struct nat25_network_db_entry *g; + + g = f->next_hash; + if (priv->scdb_entry == f) { + _rtw_memset(priv->scdb_mac, 0, ETH_ALEN); + _rtw_memset(priv->scdb_ip, 0, 4); + priv->scdb_entry = NULL; + } + __network_hash_unlink(f); + rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); + + f = g; + } + } + + _rtw_spinunlock_bh(&priv->br_ext_lock); +} + + +void nat25_db_expire(_adapter *priv) +{ + int i; + + _rtw_spinlock_bh(&priv->br_ext_lock); + + /* if(!priv->ethBrExtInfo.nat25_disable) */ + { + for (i = 0; i < NAT25_HASH_SIZE; i++) { + struct nat25_network_db_entry *f; + f = priv->nethash[i]; + + while (f != NULL) { + struct nat25_network_db_entry *g; + g = f->next_hash; + + if (__nat25_has_expired(priv, f)) { + if (atomic_dec_and_test(&f->use_count)) { +#ifdef BR_EXT_DEBUG +#ifdef CL_IPV6_PASS + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10], + f->networkAddr[11], + f->networkAddr[12], + f->networkAddr[13], + f->networkAddr[14], + f->networkAddr[15], + f->networkAddr[16]); +#else + + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10]); +#endif +#endif + if (priv->scdb_entry == f) { + _rtw_memset(priv->scdb_mac, 0, ETH_ALEN); + _rtw_memset(priv->scdb_ip, 0, 4); + priv->scdb_entry = NULL; + } + __network_hash_unlink(f); + rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); + } + } + + f = g; + } + } + } + + _rtw_spinunlock_bh(&priv->br_ext_lock); +} + + +#ifdef SUPPORT_TX_MCAST2UNI +static int checkIPMcAndReplace(_adapter *priv, struct sk_buff *skb, unsigned int *dst_ip) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + int i; + + phead = &priv->asoc_list; + plist = phead->next; + + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (pstat->ipmc_num == 0) + continue; + + for (i = 0; i < MAX_IP_MC_ENTRY; i++) { + if (pstat->ipmc[i].used && _rtw_memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { + _rtw_memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); + return 1; + } + } + } + return 0; +} +#endif + +int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method) +{ + unsigned short protocol; + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + + if (skb == NULL) + return -1; + + if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) + return -1; + + protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + /*---------------------------------------------------*/ + /* Handle IP frame */ + /*---------------------------------------------------*/ + if (protocol == __constant_htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { + DEBUG_WARN("NAT25: malformed IP packet !\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: { + /* some muticast with source IP is all zero, maybe other case is illegal */ + /* in class A, B, C, host address is all zero or all one is illegal */ + if (iph->saddr == 0) + return 0; + RTW_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); + __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); + /* record source IP address and , source mac address into db */ + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: { + RTW_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); +#ifdef SUPPORT_TX_MCAST2UNI + if (priv->pshare->rf_ft_var.mc2u_disable || + ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && + !checkIPMcAndReplace(priv, skb, &iph->daddr)) || + (OPMODE & WIFI_ADHOC_STATE))) +#endif + { + __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); + + if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { + if (*((unsigned char *)&iph->daddr + 3) == 0xff) { + /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ + RTW_INFO("NAT25: Set DA as boardcast\n"); + _rtw_memset(skb->data, 0xff, ETH_ALEN); + } else { + /* forward unknow IP packet to upper TCP/IP */ + RTW_INFO("NAT25: Replace DA with BR's MAC\n"); + if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac + 4)) == 0) { + void netdev_br_init(struct net_device *netdev); + printk("Re-init netdev_br_init() due to br_mac==0!\n"); + netdev_br_init(priv->pnetdev); + } + _rtw_memcpy(skb->data, priv->br_mac, ETH_ALEN); + } + } + } + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle ARP frame */ + /*---------------------------------------------------*/ + else if (protocol == __constant_htons(ETH_P_ARP)) { + struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); + unsigned char *arp_ptr = (unsigned char *)(arp + 1); + unsigned int *sender, *target; + + if (arp->ar_pro != __constant_htons(ETH_P_IP)) { + DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return 0; /* skb_copy for all ARP frame */ + + case NAT25_INSERT: { + RTW_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], + arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); + + /* change to ARP sender mac address to wlan STA address */ + _rtw_memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; + + __nat25_generate_ipv4_network_addr(networkAddr, sender); + + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: { + RTW_INFO("NAT25: Lookup ARP\n"); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; + arp_ptr += (arp->ar_hln + arp->ar_pln); + target = (unsigned int *)arp_ptr; + + __nat25_generate_ipv4_network_addr(networkAddr, target); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + /* change to ARP target mac address to Lookup result */ + arp_ptr = (unsigned char *)(arp + 1); + arp_ptr += (arp->ar_hln + arp->ar_pln); + _rtw_memcpy(arp_ptr, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + /*---------------------------------------------------*/ + /* Handle IPX and Apple Talk frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(ETH_P_IPX)) || + (protocol == __constant_htons(ETH_P_ATALK)) || + (protocol == __constant_htons(ETH_P_AARP))) { + unsigned char ipx_header[2] = {0xFF, 0xFF}; + struct ipxhdr *ipx = NULL; + struct elapaarp *ea = NULL; + struct ddpehdr *ddp = NULL; + unsigned char *framePtr = skb->data + ETH_HLEN; + + if (protocol == __constant_htons(ETH_P_IPX)) { + RTW_INFO("NAT25: Protocol=IPX (Ethernet II)\n"); + ipx = (struct ipxhdr *)framePtr; + } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */ + if (_rtw_memcmp(ipx_header, framePtr, 2)) { + RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n"); + ipx = (struct ipxhdr *)framePtr; + } else { + unsigned char ipx_8022_type = 0xE0; + unsigned char snap_8022_type = 0xAA; + + if (*framePtr == snap_8022_type) { + unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */ + unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */ + unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */ + + framePtr += 3; /* eliminate the 802.2 header */ + + if (_rtw_memcmp(ipx_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + RTW_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n"); + ipx = (struct ipxhdr *)framePtr; + } else if (_rtw_memcmp(aarp_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + ea = (struct elapaarp *)framePtr; + } else if (_rtw_memcmp(ddp_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + ddp = (struct ddpehdr *)framePtr; + } else { + DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], + framePtr[1], framePtr[2], framePtr[3], framePtr[4]); + return -1; + } + } else if (*framePtr == ipx_8022_type) { + framePtr += 3; /* eliminate the 802.2 header */ + + if (_rtw_memcmp(ipx_header, framePtr, 2)) { + RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n"); + ipx = (struct ipxhdr *)framePtr; + } else + return -1; + } + } + } + + /* IPX */ + if (ipx != NULL) { + switch (method) { + case NAT25_CHECK: + if (_rtw_memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { + RTW_INFO("NAT25: Check IPX skb_copy\n"); + return 0; + } + return -1; + + case NAT25_INSERT: { + RTW_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", + ipx->ipx_dest.net, + ipx->ipx_dest.node[0], + ipx->ipx_dest.node[1], + ipx->ipx_dest.node[2], + ipx->ipx_dest.node[3], + ipx->ipx_dest.node[4], + ipx->ipx_dest.node[5], + ipx->ipx_dest.sock, + ipx->ipx_source.net, + ipx->ipx_source.node[0], + ipx->ipx_source.node[1], + ipx->ipx_source.node[2], + ipx->ipx_source.node[3], + ipx->ipx_source.node[4], + ipx->ipx_source.node[5], + ipx->ipx_source.sock); + + if (_rtw_memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { + RTW_INFO("NAT25: Use IPX Net, and Socket as network addr\n"); + + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); + + /* change IPX source node addr to wlan STA address */ + _rtw_memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN); + } else + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); + + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: { + if (_rtw_memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) { + RTW_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); + + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + /* replace IPX destination node addr with Lookup destination MAC addr */ + _rtw_memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); + } else { + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + } + } + return 0; + + default: + return -1; + } + } + + /* AARP */ + else if (ea != NULL) { + /* Sanity check fields. */ + if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { + DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return 0; + + case NAT25_INSERT: { + /* change to AARP source mac address to wlan STA address */ + _rtw_memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN); + + RTW_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); + + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); + + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: { + RTW_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); + + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + /* change to AARP destination mac address to Lookup result */ + _rtw_memcpy(ea->hw_dst, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + + /* DDP */ + else if (ddp != NULL) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: { + RTW_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); + + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); + + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: { + RTW_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); + + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + } + return 0; + + default: + return -1; + } + } + + return -1; + } +#endif + + /*---------------------------------------------------*/ + /* Handle PPPoE frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || + (protocol == __constant_htons(ETH_P_PPP_SES))) { + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + unsigned short *pMagic; + + switch (method) { + case NAT25_CHECK: + if (ph->sid == 0) + return 0; + return 1; + + case NAT25_INSERT: + if (ph->sid == 0) { /* Discovery phase according to tag */ + if (ph->code == PADI_CODE || ph->code == PADR_CODE) { + if (priv->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag, *pOldTag; + unsigned char tag_buf[40]; + int old_tag_len = 0; + + tag = (struct pppoe_tag *)tag_buf; + pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); + if (pOldTag) { /* if SID existed, copy old value and delete it */ + old_tag_len = ntohs(pOldTag->tag_len); + if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { + DEBUG_ERR("SID tag length too long!\n"); + return -1; + } + + _rtw_memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, + pOldTag->tag_data, old_tag_len); + + if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { + DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); + } + + tag->tag_type = PTT_RELAY_SID; + tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); + + /* insert the magic_code+client mac in relay tag */ + pMagic = (unsigned short *)tag->tag_data; + *pMagic = htons(MAGIC_CODE); + _rtw_memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); + + /* Add relay tag */ + if (__nat25_add_pppoe_tag(skb, tag) < 0) + return -1; + + RTW_INFO("NAT25: Insert PPPoE, forward %s packet\n", + (ph->code == PADI_CODE ? "PADI" : "PADR")); + } else { /* not add relay tag */ + if (priv->pppoe_connection_in_progress && + !_rtw_memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) { + DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); + return -2; + } + + if (priv->pppoe_connection_in_progress == 0) + _rtw_memcpy(priv->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); + + priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } else + return -1; + } else { /* session phase */ + RTW_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); + + __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); + + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + + if (!priv->ethBrExtInfo.addPPPoETag && + priv->pppoe_connection_in_progress && + _rtw_memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) + priv->pppoe_connection_in_progress = 0; + } + return 0; + + case NAT25_LOOKUP: + if (ph->code == PADO_CODE || ph->code == PADS_CODE) { + if (priv->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag; + unsigned char *ptr; + unsigned short tagType, tagLen; + int offset = 0; + + ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); + if (ptr == 0) { + DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n"); + return -1; + } + + tag = (struct pppoe_tag *)ptr; + tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); + tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); + + if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { + DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); + return -1; + } + + pMagic = (unsigned short *)tag->tag_data; + if (ntohs(*pMagic) != MAGIC_CODE) { + DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n", + (ph->code == PADO_CODE ? "PADO" : "PADS")); + return -1; + } + + _rtw_memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); + + if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) + offset = TAG_HDR_LEN; + + if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { + DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); + if (offset > 0) + tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); + + RTW_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n", + (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); + } else { /* not add relay tag */ + if (!priv->pppoe_connection_in_progress) { + DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n"); + return -1; + } + _rtw_memcpy(skb->data, priv->pppoe_addr, ETH_ALEN); + priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } else { + if (ph->sid != 0) { + RTW_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); + __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + __nat25_db_print(priv); + } else + return -1; + + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle EAP frame */ + /*---------------------------------------------------*/ + else if (protocol == __constant_htons(0x888e)) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle C-Media proprietary frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(0xe2ae)) || + (protocol == __constant_htons(0xe2af))) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle IPV6 frame */ + /*---------------------------------------------------*/ +#ifdef CL_IPV6_PASS + else if (protocol == __constant_htons(ETH_P_IPV6)) { + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + + if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { + DEBUG_WARN("NAT25: malformed IPv6 packet !\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + if (skb->data[0] & 1) + return 0; + return -1; + + case NAT25_INSERT: { + RTW_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); + + if (!_rtw_memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); + __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); + __nat25_db_print(priv); + + if (iph->nexthdr == IPPROTO_ICMPV6 && + skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { + if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), + skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) { + struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); + hdr->icmp6_cksum = 0; + hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, + iph->payload_len, + IPPROTO_ICMPV6, + csum_partial((__u8 *)hdr, iph->payload_len, 0)); + } + } + } + } + return 0; + + case NAT25_LOOKUP: + RTW_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); + + + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); + if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { +#ifdef SUPPORT_RX_UNI2MCAST + if (iph->daddr.s6_addr[0] == 0xff) + convert_ipv6_mac_to_mc(skb); +#endif + } + return 0; + + default: + return -1; + } + } +#endif /* CL_IPV6_PASS */ + + return -1; +} + + +int nat25_handle_frame(_adapter *priv, struct sk_buff *skb) +{ +#ifdef BR_EXT_DEBUG + if ((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { + panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", + skb->data[0], + skb->data[1], + skb->data[2], + skb->data[3], + skb->data[4], + skb->data[5], + skb->data[6], + skb->data[7], + skb->data[8], + skb->data[9], + skb->data[10], + skb->data[11]); + } +#endif + + if (!(skb->data[0] & 1)) { + int is_vlan_tag = 0, i, retval = 0; + unsigned short vlan_hdr = 0; + + if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { + is_vlan_tag = 1; + vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); + for (i = 0; i < 6; i++) + *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); + skb_pull(skb, 4); + } + + if (!priv->ethBrExtInfo.nat25_disable) { + _rtw_spinlock_bh(&priv->br_ext_lock); + /* + * This function look up the destination network address from + * the NAT2.5 database. Return value = -1 means that the + * corresponding network protocol is NOT support. + */ + if (!priv->ethBrExtInfo.nat25sc_disable && + (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && + _rtw_memcmp(priv->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { + _rtw_memcpy(skb->data, priv->scdb_mac, ETH_ALEN); + + _rtw_spinunlock_bh(&priv->br_ext_lock); + } else { + _rtw_spinunlock_bh(&priv->br_ext_lock); + + retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); + } + } else { + if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && + _rtw_memcmp(priv->br_ip, skb->data + ETH_HLEN + 16, 4)) || + ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && + _rtw_memcmp(priv->br_ip, skb->data + ETH_HLEN + 24, 4))) { + /* for traffic to upper TCP/IP */ + retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); + } + } + + if (is_vlan_tag) { + skb_push(skb, 4); + for (i = 0; i < 6; i++) + *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); + *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); + *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; + } + + if (retval == -1) { + /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ + return -1; + } + } + + return 0; +} + +#if 0 +void mac_clone(_adapter *priv, unsigned char *addr) +{ + struct sockaddr sa; + + _rtw_memcpy(sa.sa_data, addr, ETH_ALEN); + RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + rtl8192cd_set_hwaddr(priv->dev, &sa); +} + + +int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) +{ + if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { + if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ + if (!_rtw_memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && + ((priv->dev->br_port) && + !_rtw_memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { + mac_clone(priv, skb->data + ETH_ALEN); + priv->macclone_completed = 1; + } + } + } + + return 0; +} +#endif /* 0 */ + +#define SERVER_PORT 67 +#define CLIENT_PORT 68 +#define DHCP_MAGIC 0x63825363 +#define BROADCAST_FLAG 0x8000 + +struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; + u_int8_t options[308]; /* 312 - cookie */ +}; + +void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb) +{ + if (skb == NULL) + return; + + if (!priv->ethBrExtInfo.dhcp_bcst_disable) { + unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ + struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if (iph->protocol == IPPROTO_UDP) { /* UDP */ + struct udphdr *udph = (struct udphdr *)((SIZE_PTR)iph + (iph->ihl << 2)); + + if ((udph->source == __constant_htons(CLIENT_PORT)) + && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ + struct dhcpMessage *dhcph = + (struct dhcpMessage *)((SIZE_PTR)udph + sizeof(struct udphdr)); + + if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ + if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ + register int sum = 0; + + RTW_INFO("DHCP: change flag of DHCP request to broadcast.\n"); + /* or BROADCAST flag */ + dhcph->flags |= htons(BROADCAST_FLAG); + /* recalculate checksum */ + sum = ~(udph->check) & 0xffff; + sum += dhcph->flags; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + udph->check = ~sum; + } + } + } + } + } + } +} + + +void *scdb_findEntry(_adapter *priv, unsigned char *macAddr, + unsigned char *ipAddr) +{ + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + struct nat25_network_db_entry *db; + int hash; + + /* _rtw_spinlock_bh(&priv->br_ext_lock); */ + + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); + hash = __nat25_network_hash(networkAddr); + db = priv->nethash[hash]; + while (db != NULL) { + if (_rtw_memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + /* _rtw_spinunlock_bh(&priv->br_ext_lock); */ + return (void *)db; + } + + db = db->next_hash; + } + + /* _rtw_spinunlock_bh(&priv->br_ext_lock); */ + return NULL; +} + +#endif /* CONFIG_BR_EXT */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_btc.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_btc.c new file mode 100644 index 00000000..96d4146f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_btc.c @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright(c) 2013 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifdef CONFIG_BTC + +#include + +#endif /* CONFIG_BTC */ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.c new file mode 100644 index 00000000..b711570d --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.c @@ -0,0 +1,4741 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_CHPLAN_C_ + +#include + +extern struct rtw_regdb_ops regdb_ops; + +u8 rtw_chplan_get_default_regd_2g(u8 id) +{ + if (regdb_ops.get_default_regd_2g) + return regdb_ops.get_default_regd_2g(id); + return RTW_REGD_NA; +} + +#if CONFIG_IEEE80211_BAND_5GHZ +u8 rtw_chplan_get_default_regd_5g(u8 id) +{ + if (regdb_ops.get_default_regd_5g) + return regdb_ops.get_default_regd_5g(id); + return RTW_REGD_NA; +} +#endif + +bool rtw_is_channel_plan_valid(u8 id) +{ + if (regdb_ops.is_domain_code_valid) + return regdb_ops.is_domain_code_valid(id); + return false; +} + +/* + * Search the @param ch in chplan by given @param id + * @id: the given channel plan id + * @ch: the given channel number + * + * return the index of channel_num in channel_set, -1 if not found + */ +static bool rtw_chplan_get_ch(u8 id, u32 ch, u8 *flags) +{ + if (regdb_ops.domain_get_ch) + return regdb_ops.domain_get_ch(id, ch, flags); + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +u8 rtw_chplan_get_default_regd_6g(u8 id) +{ + if (regdb_ops.get_default_regd_6g) + return regdb_ops.get_default_regd_6g(id); + return RTW_REGD_NA; +} + +bool rtw_is_channel_plan_6g_valid(u8 id) +{ + if (regdb_ops.is_domain_code_6g_valid) + return regdb_ops.is_domain_code_6g_valid(id); + return false; +} + +/* + * Search the @param ch in chplan by given @param id + * @id: the given channel plan id + * @ch: the given channel number + * + * return the index of channel_num in channel_set, -1 if not found + */ +static bool rtw_chplan_6g_get_ch(u8 id, u32 ch, u8 *flags) +{ + if (regdb_ops.domain_6g_get_ch) + return regdb_ops.domain_6g_get_ch(id, ch, flags); + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +void rtw_rfctl_addl_ch_disable_conf_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty) +{ + int i; + + rfctl->dis_ch_flags = regsty->dis_ch_flags + #if !CONFIG_DFS + | RTW_CHF_DFS + #endif + ; + + for (i = 0; i < MAX_CHANNEL_NUM_2G_5G; i++) + rfctl->excl_chs[i] = regsty->excl_chs[i]; +#if CONFIG_IEEE80211_BAND_6GHZ + for (i = 0; i < MAX_CHANNEL_NUM_6G; i++) + rfctl->excl_chs_6g[i] = regsty->excl_chs_6g[i]; +#endif +} + +static bool rtw_rfctl_is_excl_chs(struct rf_ctl_t *rfctl, u8 ch) +{ + int i; + + for (i = 0; i < MAX_CHANNEL_NUM_2G_5G; i++) { + if (rfctl->excl_chs[i] == 0) + break; + if (rfctl->excl_chs[i] == ch) + return true; + } + return false; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static bool rtw_rfctl_is_excl_chs_6g(struct rf_ctl_t *rfctl, u8 ch) +{ + int i; + + for (i = 0; i < MAX_CHANNEL_NUM_6G; i++) { + if (rfctl->excl_chs_6g[i] == 0) + break; + if (rfctl->excl_chs_6g[i] == ch) + return true; + } + return false; +} +#endif + +/* + * Check if the @param ch, bw, offset is valid for the given @param id, id_6g + * @ch_set: the given channel set + * @ch: the given channel number + * @bw: the given bandwidth + * @offset: the given channel offset + * + * return valid (1) or not (0) + */ +u8 rtw_chplan_is_bchbw_valid(u8 id, u8 id_6g, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive, struct rf_ctl_t *rfctl) +{ + u8 cch; + u8 *op_chs; + u8 op_ch_num; + u8 op_ch; + u8 valid = 0; + int i; + int ch_idx; + u8 flags; + + cch = rtw_get_center_ch_by_band(band, ch, bw, offset); + + if (!rtw_get_op_chs_by_bcch_bw(band, cch, bw, &op_chs, &op_ch_num)) + goto exit; + + for (i = 0; i < op_ch_num; i++) { + op_ch = *(op_chs + i); + if (0) + RTW_INFO("%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", ch, bw, offset, cch, bw, op_ch); + #if CONFIG_IEEE80211_BAND_6GHZ + if (band == BAND_ON_6G) { + if (!rtw_chplan_6g_get_ch(id_6g, op_ch, &flags) + || (rfctl && (rfctl->dis_ch_flags & flags)) + || (rfctl && rtw_rfctl_is_excl_chs_6g(rfctl, op_ch) == _TRUE)) + break; + } else + #endif + { + if (!rtw_chplan_get_ch(id, op_ch, &flags) + || (rfctl && (rfctl->dis_ch_flags & flags)) + || (rfctl && rtw_rfctl_is_excl_chs(rfctl, op_ch) == _TRUE)) + break; + } + if (flags & RTW_CHF_NO_IR) { + if (!allow_passive + || (!allow_primary_passive && op_ch == ch)) + break; + } + } + + if (op_ch_num != 0 && i == op_ch_num) + valid = 1; + +exit: + return valid; +} + +const char *_regd_src_str[] = { + [REGD_SRC_RTK_PRIV] = "RTK_PRIV", + [REGD_SRC_OS] = "OS", + [REGD_SRC_NUM] = "UNKNOWN", +}; + +static void rtw_chset_apply_from_rtk_priv(struct rtw_chset *chset, u8 chplan, u8 chplan_6g, u8 d_flags) +{ + RT_CHANNEL_INFO *chinfo; + u8 i; + u8 flags; + bool chplan_valid = rtw_is_channel_plan_valid(chplan); +#if CONFIG_IEEE80211_BAND_6GHZ + bool chplan_6g_valid = rtw_is_channel_plan_valid(chplan_6g); +#endif + bool usable_ch; + + RTW_INFO("%s chplan:0x%02X chplan_6g:0x%02X\n", __func__, chplan, chplan_6g); + rtw_warn_on(!chplan_valid); +#if CONFIG_IEEE80211_BAND_6GHZ + rtw_warn_on(!chplan_6g_valid); +#endif + + for (i = 0; i < chset->chs_len; i++) { + chinfo = &chset->chs[i]; + if (chinfo->flags & RTW_CHF_DIS) + continue; + + if (chinfo->band == BAND_ON_24G + #if CONFIG_IEEE80211_BAND_5GHZ + || chinfo->band == BAND_ON_5G + #endif + ) { + if (!chplan_valid) + continue; + usable_ch = rtw_chplan_get_ch(chplan, chinfo->ChannelNum, &flags); + if (usable_ch && (flags & d_flags)) + usable_ch = false; + } + #if CONFIG_IEEE80211_BAND_6GHZ + else if (chinfo->band == BAND_ON_6G) { + if (!chplan_6g_valid) + continue; + usable_ch = rtw_chplan_6g_get_ch(chplan_6g, chinfo->ChannelNum, &flags); + if (usable_ch && (flags & d_flags)) + usable_ch = false; + } + #endif + else + usable_ch = false; + + if (usable_ch) + chinfo->flags |= flags; + else + chinfo->flags = RTW_CHF_DIS; + } +} + +static void rtw_rfctl_chset_apply_regd_reqs(struct rf_ctl_t *rfctl, u8 d_flags, bool req_lock) +{ + struct regd_req_t *req; + _list *cur, *head; + + /* apply regd reqs */ + if (req_lock) + _rtw_mutex_lock_interruptible(&rfctl->regd_req_mutex); + + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (!req->applied) + continue; + + if (req->src == REGD_SRC_RTK_PRIV) { + u8 domain_code_6g = RTW_CHPLAN_6G_NULL; + + #if CONFIG_IEEE80211_BAND_6GHZ + domain_code_6g = req->chplan.domain_code_6g; + #endif + rtw_chset_apply_from_rtk_priv(&rfctl->chset, req->chplan.domain_code, domain_code_6g, d_flags); + } + #ifdef CONFIG_REGD_SRC_FROM_OS + else if (req->src == REGD_SRC_OS) + rtw_chset_apply_from_os(&rfctl->chset, d_flags); + #endif + else + rtw_warn_on(1); + } + + if (req_lock) + _rtw_mutex_unlock(&rfctl->regd_req_mutex); +} + +static void rtw_rfctl_chset_apply_regulatory(struct dvobj_priv *dvobj, bool req_lock) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + struct rtw_chset *chset = &rfctl->chset; + u8 d_band_bmp = 0; + u8 d_flags = rfctl->dis_ch_flags; + RT_CHANNEL_INFO *chinfo; + int i; + + d_band_bmp |= !RFCTL_REG_EN_11A(rfctl) ? BAND_CAP_5G : 0; + + /* reset flags of all channels */ + for (i = 0; i < chset->chs_len; i++) { + chinfo = &chset->chs[i]; + if ((band_to_band_cap(chinfo->band) & d_band_bmp) + || ((chinfo->band == BAND_ON_24G || chinfo->band == BAND_ON_5G) + && rtw_rfctl_is_excl_chs(rfctl, chinfo->ChannelNum) == true) + #if CONFIG_IEEE80211_BAND_6GHZ + || (chinfo->band == BAND_ON_6G + && rtw_rfctl_is_excl_chs_6g(rfctl, chinfo->ChannelNum) == true) + #endif + ) + chinfo->flags = RTW_CHF_DIS; + else + chinfo->flags = 0; + } + + rtw_rfctl_chset_apply_regd_reqs(rfctl, d_flags, req_lock); + + chset->enable_ch_num = 0; + for (i = 0; i < BAND_MAX; i++) + chset->enable_ch_num_of_band[i] = 0; + + for (i = 0; i < chset->chs_len; i++) { + chinfo = &chset->chs[i]; + + chinfo->reg_no_ir = !!(chinfo->flags & RTW_CHF_NO_IR); + + if (chinfo->flags & RTW_CHF_DIS) + continue; + chset->enable_ch_num++; + chset->enable_ch_num_of_band[chinfo->band]++; + + if (chinfo->flags & RTW_CHF_NO_IR && CH_IS_BCN_HINT(chinfo) + && rtw_rfctl_reg_allow_beacon_hint(rfctl) + && rtw_chinfo_allow_beacon_hint(chinfo)) + chinfo->flags &= ~RTW_CHF_NO_IR; + + /* logs for channel with NO_IR but can't be cleared through beacon hint */ + if (chinfo->flags & RTW_CHF_NO_IR) { + if (!rtw_rfctl_reg_allow_beacon_hint(rfctl) || !rtw_chinfo_allow_beacon_hint(chinfo)) + RTW_INFO("band:%s ch%u is NO_IR%s while beacon hint not allowed\n" + , band_str(chinfo->band), chinfo->ChannelNum, chinfo->flags & RTW_CHF_DFS ? " DFS" : ""); + } + } + + if (chset->enable_ch_num) { + char buf[] = "xx,xx,xx"; /* buf for BAND_ON_24G ~ BAND_ON_6G */ + size_t buf_len = strlen(buf) + 1; + char *pos = buf; + + for (i = 0; i < BAND_MAX; i++) + pos += snprintf(pos, buf_len - (pos - buf), "%u,", chset->enable_ch_num_of_band[i]); + if (i) + *(pos - 1) = '\0'; + + RTW_INFO("%s ch num:%d(%s)\n", __func__, chset->enable_ch_num, buf); + } else + RTW_WARN("%s final chset has no channel\n", __func__); +} + +/* domain status specific beacon hint rules */ +#ifndef RTW_CHPLAN_BEACON_HINT_SPECIFIC_COUNTRY +#define RTW_CHPLAN_BEACON_HINT_SPECIFIC_COUNTRY 0 +#endif + +bool rtw_rfctl_reg_allow_beacon_hint(struct rf_ctl_t *rfctl) +{ + return RTW_CHPLAN_BEACON_HINT_SPECIFIC_COUNTRY || RFCTL_REG_WORLDWIDE(rfctl) + || RFCTL_REG_ALPHA2_UNSPEC(rfctl) || RFCTL_REG_INTERSECTED(rfctl); +} + +/* channel specific beacon hint rules */ +#ifndef RTW_CHPLAN_BEACON_HINT_ON_2G_CH_1_11 +#define RTW_CHPLAN_BEACON_HINT_ON_2G_CH_1_11 0 +#endif +#ifndef RTW_CHPLAN_BEACON_HINT_ON_DFS_CH +#define RTW_CHPLAN_BEACON_HINT_ON_DFS_CH 0 +#endif + +bool rtw_chinfo_allow_beacon_hint(struct _RT_CHANNEL_INFO *chinfo) +{ + return (RTW_CHPLAN_BEACON_HINT_ON_2G_CH_1_11 || !(chinfo->band == BAND_ON_24G && chinfo->ChannelNum <= 11)) + && (RTW_CHPLAN_BEACON_HINT_ON_DFS_CH || !(chinfo->flags & RTW_CHF_DFS)); +} + +u8 rtw_process_beacon_hint(struct rf_ctl_t *rfctl, struct wlan_network *network) +{ + u8 act_cnt = 0; + + if (rtw_network_chk_regu_ies(rfctl, network)) { + struct rtw_chset *chset = &rfctl->chset; + WLAN_BSSID_EX *bss = &network->network; + enum band_type band = BSS_EX_OP_BAND(bss); + u8 ch = BSS_EX_OP_CH(bss); + RT_CHANNEL_INFO *chinfo = rtw_chset_get_chinfo_by_bch(chset, band, ch, false); + + if (!chinfo) + goto exit; + + if (rfctl->regd_src == REGD_SRC_RTK_PRIV) { + chinfo->bcn_hint_end_time = rtw_get_current_time() + rtw_ms_to_systime(rfctl->bcn_hint_valid_ms); + if (chinfo->bcn_hint_end_time == RTW_BCN_HINT_STOPPED) + chinfo->bcn_hint_end_time++; + } + + if ((chinfo->flags & RTW_CHF_NO_IR) + && rtw_rfctl_reg_allow_beacon_hint(rfctl) + && rtw_chinfo_allow_beacon_hint(chinfo) + ) { + RTW_INFO("%s: change band:%s ch:%d to active\n", __func__, band_str(band), ch); + chinfo->flags &= ~RTW_CHF_NO_IR; + act_cnt++; + } + } + +exit: + return act_cnt; +} + +/* called at cmd handler */ +void rtw_beacon_hint_ch_change_notifier(struct rf_ctl_t *rfctl) +{ + _adapter *adapter = dvobj_get_primary_adapter(rfctl_to_dvobj(rfctl)); + #ifdef CONFIG_IOCTL_CFG80211 + struct get_chplan_resp *chplan; + + if (rtw_get_chplan_cmd(adapter, RTW_CMDF_DIRECTLY, &chplan) != _SUCCESS + || rtw_regd_change_complete_async(adapter_to_wiphy(adapter), chplan) != _SUCCESS) + rtw_warn_on(1); + #endif + + op_class_pref_apply_regulatory(rfctl, REG_BEACON_HINT); + rtw_nlrtw_reg_beacon_hint_event(adapter); +} + +static void rtw_beacon_hint_expire(struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj; + struct rtw_chset *chset; + RT_CHANNEL_INFO *chinfo; + int i; + bool deactivate = false; + + if (rfctl->regd_src != REGD_SRC_RTK_PRIV) + return; + + dvobj = rfctl_to_dvobj(rfctl); + chset = &rfctl->chset; + + /* don't expire when device is linking/linked/beaconing */ + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) + if (HWBAND_STA_LG_NUM(dvobj, i) || HWBAND_STA_LD_NUM(dvobj, i) || HWBAND_WPS_NUM(dvobj, i) + || HWBAND_AP_NUM(dvobj, i) || HWBAND_MESH_NUM(dvobj, i)|| HWBAND_ADHOC_NUM(dvobj, i)) + break; + if (i < HW_BAND_MAX) + return; + + for (i = 0; i < chset->chs_len; i++) { + chinfo = &chset->chs[i]; + if (!CH_IS_BCN_HINT(chinfo) && !CH_IS_BCN_HINT_STOPPED(chinfo)) { + chinfo->bcn_hint_end_time = RTW_BCN_HINT_STOPPED; + if (chinfo->reg_no_ir && !(chinfo->flags & RTW_CHF_NO_IR)) { + RTW_INFO("%s: change band:%s ch:%d to passive\n", __func__ + , band_str(chinfo->band), chinfo->ChannelNum); + chinfo->flags |= RTW_CHF_NO_IR; + deactivate = true; + } + } + } + + if (deactivate) + rtw_beacon_hint_ch_change_notifier(rfctl); +} + +const char *const _regd_inr_str[] = { + [RTW_REGD_SET_BY_INIT] = "INIT", + [RTW_REGD_SET_BY_USER] = "USER", + [RTW_REGD_SET_BY_COUNTRY_IE] = "COUNTRY_IE", + [RTW_REGD_SET_BY_DRIVER] = "DRIVER", + [RTW_REGD_SET_BY_CORE] = "CORE", + [RTW_REGD_SET_BY_NUM] = "UNKNOWN", +}; + +const char *const _regd_str[] = { + [RTW_REGD_NA] = "NA", + [RTW_REGD_FCC] = "FCC", + [RTW_REGD_MKK] = "MKK", + [RTW_REGD_ETSI] = "ETSI", + [RTW_REGD_IC] = "IC", + [RTW_REGD_KCC] = "KCC", + [RTW_REGD_NCC] = "NCC", + [RTW_REGD_ACMA] = "ACMA", + [RTW_REGD_CHILE] = "CHILE", + [RTW_REGD_MEX] = "MEX", + [RTW_REGD_WW] = "WW", +}; + +const char *const _env_str[] = { + [RTW_ENV_ANY] = "ANY", + [RTW_ENV_INDOOR] = "IN", + [RTW_ENV_OUTDOOR] = "OUT", +}; + +const char *const _rtw_edcca_mode_str[] = { + [RTW_EDCCA_NORM] = "NORMAL", + [RTW_EDCCA_CS] = "CS", + [RTW_EDCCA_ADAPT] = "ADAPT", + [RTW_EDCCA_CBP] = "CBP", +}; + +const char *const _rtw_dfs_regd_str[] = { + [RTW_DFS_REGD_NONE] = "NONE", + [RTW_DFS_REGD_FCC] = "FCC", + [RTW_DFS_REGD_MKK] = "MKK", + [RTW_DFS_REGD_ETSI] = "ETSI", + [RTW_DFS_REGD_KCC] = "KCC", +}; + +const char *const _txpwr_lmt_str[] = { + [TXPWR_LMT_NONE] = "NONE", + [TXPWR_LMT_FCC] = "FCC", + [TXPWR_LMT_MKK] = "MKK", + [TXPWR_LMT_ETSI] = "ETSI", + [TXPWR_LMT_IC] = "IC", + [TXPWR_LMT_KCC] = "KCC", + [TXPWR_LMT_NCC] = "NCC", + [TXPWR_LMT_ACMA] = "ACMA", + [TXPWR_LMT_CHILE] = "CHILE", + [TXPWR_LMT_UKRAINE] = "UKRAINE", + [TXPWR_LMT_MEXICO] = "MEXICO", + [TXPWR_LMT_CN] = "CN", + [TXPWR_LMT_QATAR] = "QATAR", + [TXPWR_LMT_UK] = "UK", + [TXPWR_LMT_THAILAND] = "THAILAND", + [TXPWR_LMT_WW] = "WW", + [TXPWR_LMT_NUM] = NULL, +}; + +const REGULATION_TXPWR_LMT _txpwr_lmt_alternate[] = { + [TXPWR_LMT_NONE] = TXPWR_LMT_NONE, + [TXPWR_LMT_FCC] = TXPWR_LMT_FCC, + [TXPWR_LMT_MKK] = TXPWR_LMT_MKK, + [TXPWR_LMT_ETSI] = TXPWR_LMT_ETSI, + [TXPWR_LMT_WW] = TXPWR_LMT_WW, + [TXPWR_LMT_NUM] = TXPWR_LMT_NUM, + + [TXPWR_LMT_IC] = TXPWR_LMT_FCC, + [TXPWR_LMT_KCC] = TXPWR_LMT_ETSI, + [TXPWR_LMT_NCC] = TXPWR_LMT_FCC, + [TXPWR_LMT_ACMA] = TXPWR_LMT_ETSI, + [TXPWR_LMT_CHILE] = TXPWR_LMT_FCC, + [TXPWR_LMT_UKRAINE] = TXPWR_LMT_ETSI, + [TXPWR_LMT_MEXICO] = TXPWR_LMT_FCC, + [TXPWR_LMT_CN] = TXPWR_LMT_ETSI, + [TXPWR_LMT_QATAR] = TXPWR_LMT_ETSI, + [TXPWR_LMT_UK] = TXPWR_LMT_ETSI, + [TXPWR_LMT_THAILAND] = TXPWR_LMT_ETSI, +}; + +#if CONFIG_IEEE80211_BAND_6GHZ +const char *const _txpwr_lmt_6g_cate_str[] = { + [TXPWR_LMT_6G_CATE_VLP] = "VLP", + [TXPWR_LMT_6G_CATE_LPI] = "LPI", + [TXPWR_LMT_6G_CATE_STD] = "STD", + [TXPWR_LMT_6G_CATE_NUM] = NULL, +}; + +#define TXPWR_LMT_6G_CATE_STR_DECLARE(reg) \ + [TXPWR_LMT_##reg][TXPWR_LMT_6G_CATE_VLP] = #reg"_VLP", \ + [TXPWR_LMT_##reg][TXPWR_LMT_6G_CATE_LPI] = #reg"_LPI", \ + [TXPWR_LMT_##reg][TXPWR_LMT_6G_CATE_STD] = #reg"_STD" + +const char *const _txpwr_lmt_6g_str[][TXPWR_LMT_6G_CATE_NUM] = { + [TXPWR_LMT_NONE][TXPWR_LMT_6G_CATE_VLP] = "NONE", + [TXPWR_LMT_NONE][TXPWR_LMT_6G_CATE_LPI] = "NONE", + [TXPWR_LMT_NONE][TXPWR_LMT_6G_CATE_STD] = "NONE", + [TXPWR_LMT_WW][TXPWR_LMT_6G_CATE_VLP] = "WW", + [TXPWR_LMT_WW][TXPWR_LMT_6G_CATE_LPI] = "WW", + [TXPWR_LMT_WW][TXPWR_LMT_6G_CATE_STD] = "WW", + TXPWR_LMT_6G_CATE_STR_DECLARE(FCC), + TXPWR_LMT_6G_CATE_STR_DECLARE(MKK), + TXPWR_LMT_6G_CATE_STR_DECLARE(ETSI), + TXPWR_LMT_6G_CATE_STR_DECLARE(IC), + TXPWR_LMT_6G_CATE_STR_DECLARE(KCC), + TXPWR_LMT_6G_CATE_STR_DECLARE(NCC), + TXPWR_LMT_6G_CATE_STR_DECLARE(ACMA), + TXPWR_LMT_6G_CATE_STR_DECLARE(CHILE), + TXPWR_LMT_6G_CATE_STR_DECLARE(UKRAINE), + TXPWR_LMT_6G_CATE_STR_DECLARE(MEXICO), + TXPWR_LMT_6G_CATE_STR_DECLARE(CN), + TXPWR_LMT_6G_CATE_STR_DECLARE(QATAR), + TXPWR_LMT_6G_CATE_STR_DECLARE(UK), + TXPWR_LMT_6G_CATE_STR_DECLARE(THAILAND), +}; + +u8 _rtw_env_to_txpwr_lmt_6g_cate_map[RTW_ENV_NUM] = { + [RTW_ENV_ANY] = BIT(TXPWR_LMT_6G_CATE_VLP), + [RTW_ENV_INDOOR] = BIT(TXPWR_LMT_6G_CATE_VLP) | BIT(TXPWR_LMT_6G_CATE_LPI), + [RTW_ENV_OUTDOOR] = BIT(TXPWR_LMT_6G_CATE_VLP), +}; + +#define rtw_env_to_txpwr_lmt_6g_cate_map(env) (((env) >= RTW_ENV_NUM) ? 0 : _rtw_env_to_txpwr_lmt_6g_cate_map[(env)]) + +u8 _reg_info_to_txpwr_lmt_6g_cate_map[] = { + [CIS_6G_REG_IN_AP] = BIT(TXPWR_LMT_6G_CATE_VLP) | BIT(TXPWR_LMT_6G_CATE_LPI), + [CIS_6G_REG_SP_AP] = BIT(TXPWR_LMT_6G_CATE_VLP) | BIT(TXPWR_LMT_6G_CATE_LPI) | BIT(TXPWR_LMT_6G_CATE_STD), + [CIS_6G_REG_VLP_AP] = BIT(TXPWR_LMT_6G_CATE_VLP), + [CIS_6G_REG_IN_EN_AP] = BIT(TXPWR_LMT_6G_CATE_VLP) | BIT(TXPWR_LMT_6G_CATE_LPI), + [CIS_6G_REG_IN_SP_AP] = BIT(TXPWR_LMT_6G_CATE_VLP) | BIT(TXPWR_LMT_6G_CATE_LPI) | BIT(TXPWR_LMT_6G_CATE_STD), +}; + +#define reg_info_to_txpwr_lmt_6g_cate_map(reg_info) (((reg_info) >= CIS_6G_REG_NUM) ? 0 : _reg_info_to_txpwr_lmt_6g_cate_map[(reg_info)]) + +u8 _reg_info_to_chplan_6g_cate_map[] = { + [CIS_6G_REG_IN_AP] = CHPLAN_6G_CATE_LPI, + [CIS_6G_REG_SP_AP] = CHPLAN_6G_CATE_STD, + [CIS_6G_REG_VLP_AP] = CHPLAN_6G_CATE_VLP, + [CIS_6G_REG_IN_EN_AP] = CHPLAN_6G_CATE_LPI, + [CIS_6G_REG_IN_SP_AP] = CHPLAN_6G_CATE_STD, +}; +#define reg_info_to_chplan_6g_cate_map(reg_info) (((reg_info) >= CIS_6G_REG_NUM) ? 0 : _reg_info_to_chplan_6g_cate_map[(reg_info)]) +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +const enum rtw_edcca_mode_t _rtw_regd_to_edcca_mode[RTW_REGD_NUM] = { + [RTW_REGD_NA] = RTW_EDCCA_MODE_NUM, + [RTW_REGD_MKK] = RTW_EDCCA_CS, + [RTW_REGD_ETSI] = RTW_EDCCA_ADAPT, + [RTW_REGD_WW] = RTW_EDCCA_ADAPT, +}; + +#if CONFIG_IEEE80211_BAND_6GHZ +const enum rtw_edcca_mode_t _rtw_regd_to_edcca_mode_6g[RTW_REGD_NUM] = { + [RTW_REGD_NA] = RTW_EDCCA_MODE_NUM, + [RTW_REGD_FCC] = RTW_EDCCA_CBP, + [RTW_REGD_MKK] = RTW_EDCCA_CS, + [RTW_REGD_ETSI] = RTW_EDCCA_ADAPT, + [RTW_REGD_WW] = RTW_EDCCA_CBP, +}; +#endif + +const REGULATION_TXPWR_LMT _rtw_regd_to_txpwr_lmt[] = { + [RTW_REGD_NA] = TXPWR_LMT_NUM, + [RTW_REGD_FCC] = TXPWR_LMT_FCC, + [RTW_REGD_MKK] = TXPWR_LMT_MKK, + [RTW_REGD_ETSI] = TXPWR_LMT_ETSI, + [RTW_REGD_IC] = TXPWR_LMT_IC, + [RTW_REGD_KCC] = TXPWR_LMT_KCC, + [RTW_REGD_NCC] = TXPWR_LMT_NCC, + [RTW_REGD_ACMA] = TXPWR_LMT_ACMA, + [RTW_REGD_CHILE] = TXPWR_LMT_CHILE, + [RTW_REGD_MEX] = TXPWR_LMT_MEXICO, + [RTW_REGD_WW] = TXPWR_LMT_WW, +}; + +char *rtw_get_regd_inr_bmp_str(char *buf, u8 bmp) +{ + char *pos = buf; + int i; + + for (i = 0; i < RTW_REGD_SET_BY_NUM; i++) { + if (!(bmp & BIT(i))) + continue; + pos += snprintf(pos, REGD_INR_BMP_STR_LEN - (pos - buf), "%s%s" + , pos == buf ? "" : " ", regd_inr_str(i)); + if (pos >= buf + REGD_INR_BMP_STR_LEN - 1) + goto exit; + } + if (pos == buf) + buf[0] = '\0'; + +exit: + return buf; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +char *rtw_get_env_bmp_str(char *buf, u8 bmp) +{ + char *pos = buf; + int i; + + for (i = 0; i < RTW_ENV_NUM; i++) { + if (!(bmp & BIT(i))) + continue; + pos += snprintf(pos, ENV_BMP_STR_LEN - (pos - buf), "%s%s" + , pos == buf ? "" : " ", env_str(i)); + if (pos >= buf + ENV_BMP_STR_LEN - 1) + goto exit; + } + if (pos == buf) + buf[0] = '\0'; + +exit: + return buf; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +char *rtw_get_edcca_mode_of_bands_str(char *buf, u8 mode_of_band[]) +{ +#define EDCCA_MODE_SEQ_COMPARE(result, operand) (result == RTW_EDCCA_MODE_NUM ? operand : (operand == RTW_EDCCA_MODE_NUM ? result : (result != operand ? -1 : result))) + + int mode = RTW_EDCCA_MODE_NUM; + char *pos = buf; + + mode = EDCCA_MODE_SEQ_COMPARE(mode, mode_of_band[BAND_ON_24G]); +#if CONFIG_IEEE80211_BAND_5GHZ + mode = EDCCA_MODE_SEQ_COMPARE(mode, mode_of_band[BAND_ON_5G]); +#endif +#if CONFIG_IEEE80211_BAND_6GHZ + mode = EDCCA_MODE_SEQ_COMPARE(mode, mode_of_band[BAND_ON_6G]); +#endif + + if (mode != -1) { /* all available values are the same */ + pos += snprintf(pos, EDCCA_MODE_OF_BANDS_STR_LEN - (pos - buf), "%s(%u)", rtw_edcca_mode_str(mode), mode); + if (pos >= buf + EDCCA_MODE_OF_BANDS_STR_LEN - 1) + goto exit; + } else { + pos += snprintf(pos, EDCCA_MODE_OF_BANDS_STR_LEN - (pos - buf), "%s(%u)", rtw_edcca_mode_str(mode_of_band[BAND_ON_24G]), mode_of_band[BAND_ON_24G]); + if (pos >= buf + EDCCA_MODE_OF_BANDS_STR_LEN - 1) + goto exit; + #if CONFIG_IEEE80211_BAND_5GHZ + pos += snprintf(pos, EDCCA_MODE_OF_BANDS_STR_LEN - (pos - buf), " %s(%u)", rtw_edcca_mode_str(mode_of_band[BAND_ON_5G]), mode_of_band[BAND_ON_5G]); + if (pos >= buf + EDCCA_MODE_OF_BANDS_STR_LEN - 1) + goto exit; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + pos += snprintf(pos, EDCCA_MODE_OF_BANDS_STR_LEN - (pos - buf), " %s(%u)", rtw_edcca_mode_str(mode_of_band[BAND_ON_6G]), mode_of_band[BAND_ON_6G]); + if (pos >= buf + EDCCA_MODE_OF_BANDS_STR_LEN - 1) + goto exit; + #endif + } + +exit: + return buf; +} + +static enum rtw_edcca_mode_t rtw_edcca_mode_get_strictest(enum rtw_edcca_mode_t a, enum rtw_edcca_mode_t b) +{ + if (a >= RTW_EDCCA_MODE_NUM) + return b < RTW_EDCCA_MODE_NUM ? b : RTW_EDCCA_MODE_NUM; + if (b >= RTW_EDCCA_MODE_NUM) + return a; + return rtw_max(a,b); +} + +static void rtw_edcca_mode_update_by_regd_reqs(struct dvobj_priv *dvobj, bool req_lock) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + struct regd_req_t *req; + struct country_chplan *chplan; + _list *cur, *head; + u8 mode[BAND_MAX]; + u8 band, tmp_mode; + char buf[EDCCA_MODE_OF_BANDS_STR_LEN]; + + for (band = 0; band < BAND_MAX; band++) + mode[band] = RTW_EDCCA_MODE_NUM; + + if (req_lock) + _rtw_mutex_lock_interruptible(&rfctl->regd_req_mutex); + + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + chplan = &req->chplan; + cur = get_next(cur); + if (!req->applied) + continue; + + tmp_mode = COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(chplan) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(chplan) : + rtw_regd_to_edcca_mode(rtw_chplan_get_default_regd_2g(chplan->domain_code)); + mode[BAND_ON_24G] = rtw_edcca_mode_get_strictest(mode[BAND_ON_24G], tmp_mode); + + #if CONFIG_IEEE80211_BAND_5GHZ + tmp_mode = COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(chplan) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(chplan) : + rtw_regd_to_edcca_mode(rtw_chplan_get_default_regd_5g(chplan->domain_code)); + mode[BAND_ON_5G] = rtw_edcca_mode_get_strictest(mode[BAND_ON_5G], tmp_mode); + #endif + + #if CONFIG_IEEE80211_BAND_6GHZ + tmp_mode = COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(chplan) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(chplan) : + rtw_regd_to_edcca_mode_6g(rtw_chplan_get_default_regd_6g(chplan->domain_code_6g)); + mode[BAND_ON_6G] = rtw_edcca_mode_get_strictest(mode[BAND_ON_6G], tmp_mode); + #endif + } + + if (req_lock) + _rtw_mutex_unlock(&rfctl->regd_req_mutex); + + rfctl->edcca_mode_2g = mode[BAND_ON_24G]; + #if CONFIG_IEEE80211_BAND_5GHZ + rfctl->edcca_mode_5g = mode[BAND_ON_5G]; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->edcca_mode_6g = mode[BAND_ON_6G]; + #endif + + RTW_PRINT("update edcca_mode:%s\n" + , rtw_get_edcca_mode_of_bands_str(buf, mode) + ); +} + +void rtw_edcca_mode_update(struct dvobj_priv *dvobj, bool req_lock) +{ + struct registry_priv *regsty = dvobj_to_regsty(dvobj); + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + + if (regsty->edcca_mode_sel == RTW_EDCCA_NORM) { + /* force disable */ + rfctl->edcca_mode_2g = RTW_EDCCA_NORM; + #if CONFIG_IEEE80211_BAND_5GHZ + rfctl->edcca_mode_5g = RTW_EDCCA_NORM; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->edcca_mode_6g = RTW_EDCCA_NORM; + #endif + + } else if (regsty->edcca_mode_sel == RTW_EDCCA_CS) { + /* carrier sense */ + rfctl->edcca_mode_2g = RTW_EDCCA_CS; + #if CONFIG_IEEE80211_BAND_5GHZ + rfctl->edcca_mode_5g = RTW_EDCCA_CS; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->edcca_mode_6g = RTW_EDCCA_CS; + #endif + + } else if (regsty->edcca_mode_sel == RTW_EDCCA_ADAPT) { + /* adaptivity */ + rfctl->edcca_mode_2g = RTW_EDCCA_ADAPT; + #if CONFIG_IEEE80211_BAND_5GHZ + rfctl->edcca_mode_5g = RTW_EDCCA_ADAPT; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->edcca_mode_6g = RTW_EDCCA_ADAPT; + #endif + + } else if (regsty->edcca_mode_sel == RTW_EDCCA_CBP) { + /* adaptivity */ + rfctl->edcca_mode_2g = RTW_EDCCA_NORM; + #if CONFIG_IEEE80211_BAND_5GHZ + rfctl->edcca_mode_5g = RTW_EDCCA_NORM; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->edcca_mode_6g = RTW_EDCCA_CBP; + #endif + + } else { + /* by regulatory setting */ + rtw_edcca_mode_update_by_regd_reqs(dvobj, req_lock); + } + + rtw_edcca_hal_update(dvobj); +} + +u8 rtw_get_edcca_mode(struct dvobj_priv *dvobj, enum band_type band) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + u8 edcca_mode = RTW_EDCCA_NORM; + + if (band == BAND_ON_24G) + edcca_mode = rfctl->edcca_mode_2g; + #if CONFIG_IEEE80211_BAND_5GHZ + else if (band == BAND_ON_5G) + edcca_mode = rfctl->edcca_mode_5g; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + else if (band == BAND_ON_6G) + edcca_mode = rfctl->edcca_mode_6g; + #endif + + return edcca_mode; +} + +#if CONFIG_TXPWR_LIMIT +char *rtw_get_txpwr_lmt_name_of_bands_str(char *buf, const char *name_of_band[], u8 unknown_bmp) +{ +#define NAME_DIFF ((void *)1) +/* input comes form organized database, string with same content will not have different pointer */ +#define NAME_SEQ_COMPARE(result, operand) ( \ + (result) == NULL ? (operand) : \ + (operand) == NULL ? (result) : \ + (result) != (operand) ? NAME_DIFF : (result) \ + ) + +#define BOOL_TO_S8(b) ((b) ? 1 : 0) +#define BOOL_S_NONE (-1) +#define BOOL_S_DIFF (-2) +#define BOOL_S_SEQ_COMPARE(result, operand) ( \ + (result) == BOOL_S_NONE ? BOOL_TO_S8(operand) : \ + BOOL_TO_S8(operand) == BOOL_S_NONE ? (result) : \ + (result) != BOOL_TO_S8(operand) ? BOOL_S_DIFF : (result) \ + ) + + const char *name = NULL; + s8 unknown = BOOL_S_NONE; + char *pos = buf; + + name = NAME_SEQ_COMPARE(name, name_of_band[BAND_ON_24G]); + unknown = BOOL_S_SEQ_COMPARE(unknown, !!(unknown_bmp & BIT(BAND_ON_24G))); +#if CONFIG_IEEE80211_BAND_5GHZ + name = NAME_SEQ_COMPARE(name, name_of_band[BAND_ON_5G]); + unknown = BOOL_S_SEQ_COMPARE(unknown, !!(unknown_bmp & BIT(BAND_ON_5G))); +#endif +#if CONFIG_IEEE80211_BAND_6GHZ + name = NAME_SEQ_COMPARE(name, name_of_band[BAND_ON_6G]); + unknown = BOOL_S_SEQ_COMPARE(unknown, !!(unknown_bmp & BIT(BAND_ON_6G))); +#endif + + if (name != NAME_DIFF && unknown != BOOL_S_DIFF) { /* all available values are the same */ + pos += snprintf(pos, TXPWR_NAME_OF_BANDS_STR_LEN - (pos - buf), "%s%s", (unknown_bmp & BIT(BAND_ON_24G)) ? "?" : "", name); + if (pos >= buf + TXPWR_NAME_OF_BANDS_STR_LEN - 1) + goto exit; + } else { + pos += snprintf(pos, TXPWR_NAME_OF_BANDS_STR_LEN - (pos - buf), "%s%s", (unknown_bmp & BIT(BAND_ON_24G)) ? "?" : "", name_of_band[BAND_ON_24G]); + if (pos >= buf + TXPWR_NAME_OF_BANDS_STR_LEN - 1) + goto exit; + #if CONFIG_IEEE80211_BAND_5GHZ + pos += snprintf(pos, TXPWR_NAME_OF_BANDS_STR_LEN - (pos - buf), " %s%s", (unknown_bmp & BIT(BAND_ON_5G)) ? "?" : "", name_of_band[BAND_ON_5G]); + if (pos >= buf + TXPWR_NAME_OF_BANDS_STR_LEN - 1) + goto exit; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + pos += snprintf(pos, TXPWR_NAME_OF_BANDS_STR_LEN - (pos - buf), " %s%s", (unknown_bmp & BIT(BAND_ON_6G)) ? "?" : "", name_of_band[BAND_ON_6G]); + if (pos >= buf + TXPWR_NAME_OF_BANDS_STR_LEN - 1) + goto exit; + #endif + } + +exit: + return buf; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static u8 regd_req_get_6g_cate_map(struct regd_req_t *req) +{ + return req->txpwr_lmt_6g_cate_map; +} +#endif + +static void rtw_txpwr_apply_regd_req_reg_exc(struct rf_ctl_t *rfctl, struct regd_req_t *req + , char *req_6g_name_buf, u8 req_6g_name_bsz + , const char *name_of_band[], u8 *unknown_bmp) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct country_chplan *chplan = &req->chplan; + enum txpwr_lmt_reg_exc_match exc = TXPWR_LMT_REG_EXC_MATCH_NONE; + const char *name = NULL; +#if CONFIG_IEEE80211_BAND_6GHZ + enum txpwr_lmt_reg_exc_match exc_6g = TXPWR_LMT_REG_EXC_MATCH_NONE; + const char *name_6g = NULL; +#endif + u8 band; + + if (*unknown_bmp & (BIT(BAND_ON_24G) | BIT(BAND_ON_5G))) + exc = rtw_txpwr_hal_lmt_reg_exc_search(dvobj, chplan->alpha2, chplan->domain_code, &name); +#if CONFIG_IEEE80211_BAND_6GHZ + if (*unknown_bmp & BIT(BAND_ON_6G)) + exc_6g = rtw_txpwr_hal_lmt_reg_exc_6g_search(dvobj, chplan->alpha2, chplan->domain_code_6g, &name_6g); +#endif + + if (exc + #if CONFIG_IEEE80211_BAND_6GHZ + || exc_6g + #endif + ) { + char exc_msg[] = " country:XX domain:0xGG" + #if CONFIG_IEEE80211_BAND_6GHZ + " domain_6g:0xGG" + #endif + "\0"; + u8 exc_msg_len = sizeof(exc_msg); + char *msg_p = exc_msg; + char buf[TXPWR_NAME_OF_BANDS_STR_LEN]; + + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + + if ((band == BAND_ON_24G || band == BAND_ON_5G) && exc) { + name_of_band[band] = name; + if (strcmp(name, txpwr_lmt_str(TXPWR_LMT_NONE)) == 0 + || strcmp(name, txpwr_lmt_str(TXPWR_LMT_WW)) == 0 + || rtw_txpwr_hal_lmt_reg_search(dvobj, band, name)) + *unknown_bmp &= ~BIT(band); + #if CONFIG_IEEE80211_BAND_6GHZ + } else if (band == BAND_ON_6G && exc_6g) { + if (strcmp(name_6g, txpwr_lmt_str(TXPWR_LMT_NONE)) == 0 + || strcmp(name_6g, txpwr_lmt_str(TXPWR_LMT_WW)) == 0 + ) { + /* known limits without category */ + name_of_band[band] = name_6g; + *unknown_bmp &= ~BIT(band); + } else { + u8 cate_map = regd_req_get_6g_cate_map(req); + int i; + + name_of_band[band] = req_6g_name_buf; + for (i = TXPWR_LMT_6G_CATE_NUM - 1; i >= TXPWR_LMT_6G_CATE_VLP ; i--) { + if (!(cate_map & BIT(i))) + continue; + snprintf(req_6g_name_buf, req_6g_name_bsz, "%s_%s", name_6g, txpwr_lmt_6g_cate_str(i)); + if (rtw_txpwr_hal_lmt_reg_search(dvobj, band, req_6g_name_buf)) { + *unknown_bmp &= ~BIT(band); + break; + } + } + } + #endif + } + } + + if (exc == TXPWR_LMT_REG_EXC_MATCH_COUNTRY + #if CONFIG_IEEE80211_BAND_6GHZ + || exc_6g == TXPWR_LMT_REG_EXC_MATCH_COUNTRY + #endif + ) { + msg_p += snprintf(msg_p, exc_msg_len - (msg_p - exc_msg), " country:"ALPHA2_FMT, ALPHA2_ARG(chplan->alpha2)); + if (msg_p >= exc_msg + exc_msg_len - 1) + goto msg_dump; + } + if (exc == TXPWR_LMT_REG_EXC_MATCH_DOMAIN) { + msg_p += snprintf(msg_p, exc_msg_len - (msg_p - exc_msg), " domain:0x%02x", chplan->domain_code); + if (msg_p >= exc_msg + exc_msg_len - 1) + goto msg_dump; + } + #if CONFIG_IEEE80211_BAND_6GHZ + if (exc_6g == TXPWR_LMT_REG_EXC_MATCH_DOMAIN) { + msg_p += snprintf(msg_p, exc_msg_len - (msg_p - exc_msg), " domain_6g:0x%02x", chplan->domain_code_6g); + if (msg_p >= exc_msg + exc_msg_len - 1) + goto msg_dump; + } + #endif + +msg_dump: + RTW_PRINT("exception%s applied, txpwr_lmt:%s\n", exc_msg + , rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + } +} + +#ifdef CONFIG_REGD_SRC_FROM_OS +static void rtw_txpwr_apply_regd_req_from_os(struct rf_ctl_t *rfctl, struct regd_req_t *req + , const char *req_alpha2_str, char *req_6g_name_buf, u8 req_6g_name_bsz + , const char *name_of_band[], u8 *unknown_bmp) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct country_chplan *chplan = &req->chplan; + + if (rfctl->regd_src == REGD_SRC_OS) { + bool alpha2_is_ww = IS_ALPHA2_WORLDWIDE(req_alpha2_str); + const char *name = NULL; + char buf[TXPWR_NAME_OF_BANDS_STR_LEN]; + u8 band; + + name = alpha2_is_ww ? txpwr_lmt_str(TXPWR_LMT_WW) : req_alpha2_str; + + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + + if (alpha2_is_ww) { + name_of_band[band] = name; + *unknown_bmp &= ~BIT(band); + continue; + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (band == BAND_ON_6G) { + u8 cate_map = regd_req_get_6g_cate_map(req); + int i; + + name_of_band[band] = req_6g_name_buf; + for (i = TXPWR_LMT_6G_CATE_NUM - 1; i >= TXPWR_LMT_6G_CATE_VLP ; i--) { + if (!(cate_map & BIT(i))) + continue; + snprintf(req_6g_name_buf, req_6g_name_bsz, "%s_%s", name, txpwr_lmt_6g_cate_str(i)); + if (rtw_txpwr_hal_lmt_reg_search(dvobj, band, req_6g_name_buf)) { + *unknown_bmp &= ~BIT(band); + break; + } + } + } else + #endif + { + name_of_band[band] = name; + if (rtw_txpwr_hal_lmt_reg_search(dvobj, band, name_of_band[band])) + *unknown_bmp &= ~BIT(band); + } + } + + RTW_PRINT("os country:"ALPHA2_FMT" applied, txpwr_lmt:%s\n" + , ALPHA2_ARG(req_alpha2_str), rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + + if (*unknown_bmp && chplan->domain_code == RTW_CHPLAN_UNSPECIFIED) { + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + name_of_band[band] = txpwr_lmt_str(TXPWR_LMT_WW); + *unknown_bmp &= ~BIT(band); + } + + RTW_PRINT("unsupported os country:"ALPHA2_FMT" applied, txpwr_lmt:%s\n" + , ALPHA2_ARG(req_alpha2_str), rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + } + } +} +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ +static bool rtw_txpwr_search_predef_6g_regd(struct rf_ctl_t *rfctl, struct regd_req_t *req + , u8 txpwr_lmt, const char **name) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + u8 cate_map = regd_req_get_6g_cate_map(req); + int i; + + for (i = TXPWR_LMT_6G_CATE_NUM - 1; i >= TXPWR_LMT_6G_CATE_VLP ; i--) { + if (!(cate_map & BIT(i))) + continue; + *name = txpwr_lmt_6g_str(txpwr_lmt, i); + if (!*name) + continue; + if (rtw_txpwr_hal_lmt_reg_search(dvobj, BAND_ON_6G, *name)) + return true; + } + + return false; +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +static void rtw_txpwr_apply_predefined(struct rf_ctl_t *rfctl, struct regd_req_t *req, enum band_type band, u8 txpwr_lmt + , const char *name_of_band[], u8 *unknown_bmp) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + + if (txpwr_lmt == TXPWR_LMT_NONE || txpwr_lmt == TXPWR_LMT_WW || txpwr_lmt == TXPWR_LMT_NUM) { + name_of_band[band] = txpwr_lmt_str(txpwr_lmt); + *unknown_bmp &= ~BIT(band); + } else if (band == BAND_ON_24G || band == BAND_ON_5G) { + name_of_band[band] = txpwr_lmt_str(txpwr_lmt); + if (name_of_band[band] && rtw_txpwr_hal_lmt_reg_search(dvobj, band, name_of_band[band])) + *unknown_bmp &= ~BIT(band); + #if CONFIG_IEEE80211_BAND_6GHZ + } else if (band == BAND_ON_6G) { + if (rtw_txpwr_search_predef_6g_regd(rfctl, req, txpwr_lmt, &name_of_band[band])) + *unknown_bmp &= ~BIT(band); + #endif + } +} + +static void rtw_txpwr_apply_regd_req_default(struct rf_ctl_t *rfctl, struct regd_req_t *req + , const char *name_of_band[], u8 *unknown_bmp) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct country_chplan *chplan = &req->chplan; + u8 txpwr_lmt[BAND_MAX]; + char buf[TXPWR_NAME_OF_BANDS_STR_LEN]; + u8 band; + bool altenate_applied = 0; + + for (band = 0; band < BAND_MAX; band++) + txpwr_lmt[band] = TXPWR_LMT_NONE; + + if (chplan->txpwr_lmt_override != TXPWR_LMT_DEF) { + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + txpwr_lmt[band] = chplan->txpwr_lmt_override; + rtw_txpwr_apply_predefined(rfctl, req, band, txpwr_lmt[band], name_of_band, unknown_bmp); + } + RTW_PRINT("default country:"ALPHA2_FMT" applied, txpwr_lmt:%s\n" + , ALPHA2_ARG(chplan->alpha2), rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + + } else { + if (*unknown_bmp & (BIT(BAND_ON_24G) | BIT(BAND_ON_5G))) { + txpwr_lmt[BAND_ON_24G] = rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_2g(chplan->domain_code)); + #if CONFIG_IEEE80211_BAND_5GHZ + txpwr_lmt[BAND_ON_5G] = rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_5g(chplan->domain_code)); + #endif + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band)) || (band != BAND_ON_24G && band != BAND_ON_5G)) + continue; + rtw_txpwr_apply_predefined(rfctl, req, band, txpwr_lmt[band], name_of_band, unknown_bmp); + } + RTW_PRINT("default domain:0x%02x applied, txpwr_lmt:%s\n" + , chplan->domain_code, rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (*unknown_bmp & BIT(BAND_ON_6G)) { + txpwr_lmt[BAND_ON_6G] = rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_6g(chplan->domain_code_6g)); + rtw_txpwr_apply_predefined(rfctl, req, BAND_ON_6G, txpwr_lmt[BAND_ON_6G], name_of_band, unknown_bmp); + RTW_PRINT("default domain_6g:0x%02x applied, txpwr_lmt:%s\n" + , chplan->domain_code_6g, rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + } + #endif + } + + if (*unknown_bmp == 0) + return; + + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + if (TXPWR_LMT_ALTERNATE_DEFINED(txpwr_lmt[band])) { + /* + * To support older chips without new predefined txpwr_lmt: + * - use txpwr_lmt_alternate() to get alternate if the selection is not found + */ + altenate_applied = 1; + txpwr_lmt[band] = txpwr_lmt_alternate(txpwr_lmt[band]); + rtw_txpwr_apply_predefined(rfctl, req, band, txpwr_lmt[band], name_of_band, unknown_bmp); + } + } + if (altenate_applied) { + RTW_PRINT("alternate applied, txpwr_lmt:%s\n" + , rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); + if (*unknown_bmp == 0) + return; + } + + for (band = 0; band < BAND_MAX; band++) { + if (!(*unknown_bmp & BIT(band))) + continue; + txpwr_lmt[band] = TXPWR_LMT_WW; + name_of_band[band] = txpwr_lmt_str(txpwr_lmt[band]); + *unknown_bmp &= ~BIT(band); + } + RTW_PRINT("world wide applied, txpwr_lmt:%s\n" + , rtw_get_txpwr_lmt_name_of_bands_str(buf, name_of_band, *unknown_bmp)); +} + +static void rtw_txpwr_apply_regd_req(struct rf_ctl_t *rfctl, struct regd_req_t *req + , char *names_of_band[], int names_of_band_len[]) +{ +#if CONFIG_IEEE80211_BAND_6GHZ +#define REG_6G_NAME_BSZ (16 + 4) /* ex: reg_name(up to 16 char) + "_VLP" */ +#else +#define REG_6G_NAME_BSZ 0 +#endif + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct rtw_chset *chset = &rfctl->chset; + struct country_chplan *chplan = &req->chplan; +#ifdef CONFIG_REGD_SRC_FROM_OS + char req_alpha2_str[3] = {chplan->alpha2[0], chplan->alpha2[1], 0}; +#endif + char req_6g_name_buf[REG_6G_NAME_BSZ]; + const char *name_of_band[BAND_MAX]; + u8 unknown_bmp; /* unknown bitmap of name_of_band */ + u8 band; + + for (band = 0; band < BAND_MAX; band++) + name_of_band[band] = NULL; + + unknown_bmp = 0 + | (chset->chs_of_band[BAND_ON_24G] ? BIT(BAND_ON_24G) : 0) + #if CONFIG_IEEE80211_BAND_5GHZ + | (chset->chs_of_band[BAND_ON_5G] ? BIT(BAND_ON_5G) : 0) + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + | (chset->chs_of_band[BAND_ON_6G] ? BIT(BAND_ON_6G) : 0) + #endif + ; + + /* search from exception mapping */ + rtw_txpwr_apply_regd_req_reg_exc(rfctl, req + , req_6g_name_buf, REG_6G_NAME_BSZ, name_of_band, &unknown_bmp); + if (!unknown_bmp) + goto exit; + +#ifdef CONFIG_REGD_SRC_FROM_OS + rtw_txpwr_apply_regd_req_from_os(rfctl, req, req_alpha2_str + , req_6g_name_buf, REG_6G_NAME_BSZ, name_of_band, &unknown_bmp); + if (!unknown_bmp) + goto exit; +#endif + + /* follow default channel plan mapping */ + rtw_txpwr_apply_regd_req_default(rfctl, req, name_of_band, &unknown_bmp); + +exit: + for (band = 0; band < BAND_MAX; band++) + ustrs_add(&names_of_band[band], &names_of_band_len[band], name_of_band[band]); +} + +void rtw_txpwr_update_cur_lmt_regs(struct dvobj_priv *dvobj, bool req_lock) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + struct regd_req_t *req; + _list *cur, *head; + char *names[BAND_MAX]; + int names_len[BAND_MAX]; + u8 band; + + _rtw_memset(names, 0, sizeof(names)); + _rtw_memset(names_len, 0, sizeof(names_len)); + + if (req_lock) + _rtw_mutex_lock_interruptible(&rfctl->regd_req_mutex); + + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (!req->applied) + continue; + rtw_txpwr_apply_regd_req(rfctl, req, names, names_len); + } + + if (req_lock) + _rtw_mutex_unlock(&rfctl->regd_req_mutex); + + /* set to tx power limit regulations to HAL */ + rtw_txpwr_hal_set_current_lmt_regs_by_name(dvobj, names, names_len); + + for (band = 0; band < BAND_MAX; band++) + if (names[band] && names_len[band]) + rtw_mfree(names[band], names_len[band]); +} +#endif /* CONFIG_TXPWR_LIMIT */ + +static const struct country_chplan world_wide_chplan = + COUNTRY_CHPLAN_ENT(WORLDWIDE_ALPHA2, RTW_CHPLAN_WORLDWIDE, RTW_CHPLAN_6G_WORLDWIDE, DEF, 1, 1, 1, 1, ___); + +#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP +#include "../platform/custom_country_chplan.h" +#elif RTW_DEF_MODULE_REGULATORY_CERT +#include "./def_module_country_chplan.h" +#endif + +/* +* rtw_get_chplan_worldwide - +* @ent: the buf to copy country_chplan entry content +*/ +void rtw_get_chplan_worldwide(struct country_chplan *ent) +{ + _rtw_memcpy(ent, &world_wide_chplan, sizeof(*ent)); +} + +/* +* rtw_get_chplan_from_country - +* @country_code: string of country code +* @ent: the buf to copy country_chplan entry content +* +* Return _TRUE or _FALSE when unsupported country_code is given +*/ +bool rtw_get_chplan_from_country(const char *country_code, struct country_chplan *ent) +{ +#if defined(CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP) || RTW_DEF_MODULE_REGULATORY_CERT + const struct country_chplan *map = NULL; + u16 map_sz = 0; + int i; +#endif + char code[2] = {alpha_to_upper(country_code[0]), alpha_to_upper(country_code[1])}; + +#if defined(CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP) || RTW_DEF_MODULE_REGULATORY_CERT + #ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP + map = CUSTOMIZED_country_chplan_map; + map_sz = sizeof(CUSTOMIZED_country_chplan_map) / sizeof(struct country_chplan); + #else + map_sz = rtw_def_module_country_chplan_map(&map); + #endif + + for (i = 0; i < map_sz; i++) { + if (strncmp(code, map[i].alpha2, 2) == 0) { + if (ent) + _rtw_memcpy(ent, &map[i], sizeof(*ent)); + return true; + } + } + + return false; +#else + if (regdb_ops.get_chplan_from_alpha2) + return regdb_ops.get_chplan_from_alpha2(code, ent); + return false; +#endif +} + +void rtw_chplan_ioctl_input_mapping(u16 *chplan, u16 *chplan_6g) +{ + if (chplan) { + if (*chplan == RTW_CHPLAN_IOCTL_UNSPECIFIED) + *chplan = RTW_CHPLAN_UNSPECIFIED; + else if (*chplan == RTW_CHPLAN_IOCTL_NULL) + *chplan = RTW_CHPLAN_NULL; + } + + if (chplan_6g) { + if (*chplan_6g == RTW_CHPLAN_IOCTL_UNSPECIFIED) + *chplan_6g = RTW_CHPLAN_6G_UNSPECIFIED; + else if (*chplan_6g == RTW_CHPLAN_IOCTL_NULL) + *chplan_6g = RTW_CHPLAN_6G_NULL; + } +} + +bool rtw_chplan_ids_is_world_wide(u8 chplan, u8 chplan_6g) +{ + return !(chplan == RTW_CHPLAN_NULL + #if CONFIG_IEEE80211_BAND_6GHZ + && chplan_6g == RTW_CHPLAN_6G_NULL + #endif + ) + && (chplan == RTW_CHPLAN_WORLDWIDE || chplan == RTW_CHPLAN_NULL) + #if CONFIG_IEEE80211_BAND_6GHZ + && (chplan_6g == RTW_CHPLAN_6G_WORLDWIDE || chplan_6g == RTW_CHPLAN_6G_NULL) + #endif + ; +} + +/* + * Check if the @param ch, bw, offset is valid for the given @param ent + * @ent: the given country chplan ent + * @band: the given band + * @ch: the given channel number + * @bw: the given bandwidth + * @offset: the given channel offset + * @rfctl: refer to addtional ch enable/disable configurations + * + * return valid (1) or not (0) + */ +u8 rtw_country_chplan_is_bchbw_valid(struct country_chplan *ent, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive, struct rf_ctl_t *rfctl) +{ + u8 domain_code_6g = RTW_CHPLAN_6G_NULL; + u8 valid = 0; + + if (band == BAND_ON_5G && !COUNTRY_CHPLAN_EN_11A(ent)) + goto exit; + + if (bw >= CHANNEL_WIDTH_80 && !COUNTRY_CHPLAN_EN_11AC(ent)) + goto exit; + + #if CONFIG_IEEE80211_BAND_6GHZ + domain_code_6g = ent->domain_code_6g; + #endif + + valid = rtw_chplan_is_bchbw_valid(ent->domain_code, domain_code_6g, band, ch, bw, offset + , allow_primary_passive, allow_passive, rfctl); + +exit: + return valid; +} + +static void rtw_country_chplan_get_edcca_mode_of_bands(const struct country_chplan *ent, u8 mode_of_band[]) +{ + mode_of_band[BAND_ON_24G] = + COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(ent) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(ent) : + rtw_regd_to_edcca_mode(rtw_chplan_get_default_regd_2g(ent->domain_code)); + #if CONFIG_IEEE80211_BAND_5GHZ + mode_of_band[BAND_ON_5G] = + COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(ent) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(ent) : + rtw_regd_to_edcca_mode(rtw_chplan_get_default_regd_5g(ent->domain_code)); + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + mode_of_band[BAND_ON_6G] = + COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(ent) != RTW_EDCCA_DEF ? COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(ent) : + rtw_regd_to_edcca_mode_6g(rtw_chplan_get_default_regd_6g(ent->domain_code_6g)); + #endif +} + +static void rtw_country_chplan_get_txpwr_lmt_of_bands(const struct country_chplan *ent, u8 txpwr_lmt_of_band[]) +{ + txpwr_lmt_of_band[BAND_ON_24G] = + ent->txpwr_lmt_override != TXPWR_LMT_DEF ? ent->txpwr_lmt_override : + rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_2g(ent->domain_code)); + #if CONFIG_IEEE80211_BAND_5GHZ + txpwr_lmt_of_band[BAND_ON_5G] = + ent->txpwr_lmt_override != TXPWR_LMT_DEF ? ent->txpwr_lmt_override : + rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_5g(ent->domain_code)); + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + txpwr_lmt_of_band[BAND_ON_6G] = + ent->txpwr_lmt_override != TXPWR_LMT_DEF ? ent->txpwr_lmt_override : + rtw_regd_to_txpwr_lmt(rtw_chplan_get_default_regd_6g(ent->domain_code_6g)); + #endif +} + +#ifdef CONFIG_80211D +static const char *const _cis_status_str[] = { + [COUNTRY_IE_SLAVE_NOCOUNTRY] = "NOCOUNTRY", + [COUNTRY_IE_SLAVE_APPLICABLE] = "APPLICABLE", + [COUNTRY_IE_SLAVE_UNKNOWN] = "UNKNOWN", + [COUNTRY_IE_SLAVE_OPCH_NOEXIST] = "OPCH_NOEXIST", + [COUNTRY_IE_SLAVE_CATE_6G_NS] = "CATE_6G_NS", + [COUNTRY_IE_SLAVE_STATUS_NUM] = "INVALID", +}; + +#define cis_status_str(s) (((s) >= COUNTRY_IE_SLAVE_STATUS_NUM) ? _cis_status_str[COUNTRY_IE_SLAVE_STATUS_NUM] : _cis_status_str[s]) + +const char _rtw_env_char[] = { + [RTW_ENV_ANY] = ' ', + [RTW_ENV_INDOOR] = 'I', + [RTW_ENV_OUTDOOR] = 'O', +}; + +#if CONFIG_IEEE80211_BAND_6GHZ +static const char *const _cis_6g_reg_info_str[] = { + [CIS_6G_REG_IN_AP] = "IN_AP", + [CIS_6G_REG_SP_AP] = "SP_AP", + [CIS_6G_REG_VLP_AP] = "VLP_AP", + [CIS_6G_REG_IN_EN_AP] = "IN_EN_AP", + [CIS_6G_REG_IN_SP_AP] = "IN_SP_AP", + [CIS_6G_REG_NUM] = "RSVD", +}; + +#define cis_6g_reg_info_str(r) (((r) >= CIS_6G_REG_NUM) ? _cis_6g_reg_info_str[CIS_6G_REG_NUM] : _cis_6g_reg_info_str[r]) + +static const enum rtw_env_t _reg_info_to_env[] = { + [CIS_6G_REG_IN_AP] = RTW_ENV_INDOOR, + [CIS_6G_REG_SP_AP] = RTW_ENV_OUTDOOR, + [CIS_6G_REG_VLP_AP] = RTW_ENV_ANY, + [CIS_6G_REG_IN_EN_AP] = RTW_ENV_INDOOR, + [CIS_6G_REG_IN_SP_AP] = RTW_ENV_INDOOR, + [CIS_6G_REG_NUM] = RTW_ENV_ANY, +}; + +#define reg_info_to_env(reg_info) (((reg_info) >= CIS_6G_REG_NUM) ? _reg_info_to_env[CIS_6G_REG_NUM] : _reg_info_to_env[(reg_info)]) +#endif + +void dump_country_ie_slave_records(void *sel, struct rf_ctl_t *rfctl, bool skip_noset) +{ +#define CISR_TITLE_FMT "%-6s %-4s %-4s" +#define CISR_TITLE_ARG , "alpha2", "band", "opch" +#define CISR_VALUE_FMT " "ALPHA2_FMT" %4s %4u" +#define CISR_VALUE_ARG , ALPHA2_ARG(cisr->alpha2), band_str(cisr->band), cisr->opch +#if CONFIG_IEEE80211_BAND_6GHZ +#define CISR_TITLE_FMT_6G " %-3s %-8s" +#define CISR_TITLE_ARG_6G , "env", "6g_reg_i" +#define CISR_VALUE_FMT_6G " %3c %8s" +#define CISR_VALUE_ARG_6G , rtw_env_char(cisr->env), cisr->band == BAND_ON_6G ? cis_6g_reg_info_str(cisr->reg_info) : "" +#else +#define CISR_TITLE_FMT_6G "" +#define CISR_VALUE_FMT_6G "" +#define CISR_TITLE_ARG_6G +#define CISR_VALUE_ARG_6G +#endif +#define CISR_TITLE_FMT_STATUS " %s" +#define CISR_VALUE_FMT_STATUS " %s" +#define CISR_TITLE_ARG_STATUS , "status" +#define CISR_VALUE_ARG_STATUS , cis_status_str(cisr->status) + + struct country_ie_slave_record *cisr; + int i, j; + + RTW_PRINT_SEL(sel, + " " + CISR_TITLE_FMT + CISR_TITLE_FMT_6G + CISR_TITLE_FMT_STATUS + "\n" + CISR_TITLE_ARG + CISR_TITLE_ARG_6G + CISR_TITLE_ARG_STATUS + ); + + for (i = 0; i < CONFIG_IFACE_NUMBER; i++) { + for (j = 0; j < RTW_RLINK_MAX; j++) { + cisr = &rfctl->cisr[i][j]; + if (skip_noset && strncmp(cisr->alpha2, "\x00\x00", 2) == 0) + continue; + + RTW_PRINT_SEL(sel, + "%d %d" + CISR_VALUE_FMT + CISR_VALUE_FMT_6G + CISR_VALUE_FMT_STATUS + "\n" + , i, j + CISR_VALUE_ARG + CISR_VALUE_ARG_6G + CISR_VALUE_ARG_STATUS + ); + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + RTW_PRINT_SEL(sel, "\n"); + RTW_PRINT_SEL(sel, "6g_cate_map_int_link_num:%u\n", rfctl->txpwr_lmt_6g_cate_map_int_link_num); + RTW_PRINT_SEL(sel, "6g_cate_map_int_all_link:0x%02x\n", rfctl->txpwr_lmt_6g_cate_map_int_all_link); +#endif +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static enum rtw_env_t country_str_get_env(const char *country_str) +{ + if (country_str) { + switch (country_str[2]) { + case 'I': + return RTW_ENV_INDOOR; + case 'O': + return RTW_ENV_OUTDOOR; + case ' ': + default: + return RTW_ENV_ANY; + } + } + return RTW_ENV_ANY; +} +#endif + +static enum country_ie_slave_status rtw_get_cisr_from_recv_regu_ies(struct rf_ctl_t *rfctl + , enum band_type band, u8 opch + , const u8 *country_ie, enum country_ie_slave_6g_reg_info reg_info + , struct country_ie_slave_record *cisr) +{ + const char *country_code = country_ie ? country_ie + 2 : NULL; + u8 domain_code_6g = RTW_CHPLAN_6G_NULL; + struct country_chplan *ent = &cisr->chplan; + enum country_ie_slave_status ret; + + _rtw_memcpy(cisr->alpha2, country_code ? country_code : "\x00\x00", 2); + cisr->band = band; + cisr->opch = opch; + +#if CONFIG_IEEE80211_BAND_6GHZ + cisr->env = country_str_get_env(country_code); + cisr->reg_info = reg_info; +#endif + + _rtw_memset(ent, 0, sizeof(*ent)); + + if (!country_code || strncmp(country_code, "XX", 2) == 0) { + ret = COUNTRY_IE_SLAVE_NOCOUNTRY; + goto exit; + } + + if (!rtw_get_chplan_from_country(country_code, ent)) { + ret = COUNTRY_IE_SLAVE_UNKNOWN; + goto exit; + } + + #if CONFIG_IEEE80211_BAND_6GHZ + domain_code_6g = ent->domain_code_6g; + #endif + + if (!rtw_chplan_is_bchbw_valid(ent->domain_code, domain_code_6g, band, opch + , CHANNEL_WIDTH_20, CHAN_OFFSET_NO_EXT, 1, 1, rfctl) + ) { + ret = COUNTRY_IE_SLAVE_OPCH_NOEXIST; + goto exit; + } + +#if CONFIG_IEEE80211_BAND_6GHZ + if (cisr->band == BAND_ON_6G + && !(ent->cate_6g_map & reg_info_to_chplan_6g_cate_map(reg_info)) + ) { + ret = COUNTRY_IE_SLAVE_CATE_6G_NS; + goto exit; + } +#endif + ret = COUNTRY_IE_SLAVE_APPLICABLE; + +exit: + cisr->status = ret; + + return ret; +} +#endif /* CONFIG_80211D */ + +void dump_country_chplan(void *sel, const struct country_chplan *ent, bool regd_info) +{ + char buf[16]; + char *pos = buf; + + if (ent->domain_code == RTW_CHPLAN_UNSPECIFIED) + pos += sprintf(pos, "UNSPEC"); + else + pos += sprintf(pos, "0x%02X", ent->domain_code); + +#if CONFIG_IEEE80211_BAND_6GHZ + if (ent->domain_code_6g == RTW_CHPLAN_6G_UNSPECIFIED) + pos += sprintf(pos, " UNSPEC"); + else + pos += sprintf(pos, " 0x%02X", ent->domain_code_6g); +#endif + + RTW_PRINT_SEL(sel, "\"%c%c\", %s" + , ent->alpha2[0], ent->alpha2[1], buf); + + if (regd_info) { + u8 edcca_mode[BAND_MAX]; + u8 txpwr_lmt[BAND_MAX]; + + rtw_country_chplan_get_edcca_mode_of_bands(ent, edcca_mode); + _RTW_PRINT_SEL(sel, " {%-6s", rtw_edcca_mode_str(edcca_mode[BAND_ON_24G])); + #if CONFIG_IEEE80211_BAND_5GHZ + _RTW_PRINT_SEL(sel, " %-6s", rtw_edcca_mode_str(edcca_mode[BAND_ON_5G])); + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + _RTW_PRINT_SEL(sel, " %-6s", rtw_edcca_mode_str(edcca_mode[BAND_ON_6G])); + #endif + _RTW_PRINT_SEL(sel, "}"); + + rtw_country_chplan_get_txpwr_lmt_of_bands(ent, txpwr_lmt); + _RTW_PRINT_SEL(sel, " {%-8s", txpwr_lmt_str(txpwr_lmt[BAND_ON_24G])); + #if CONFIG_IEEE80211_BAND_5GHZ + _RTW_PRINT_SEL(sel, " %-8s", txpwr_lmt_str(txpwr_lmt[BAND_ON_5G])); + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + _RTW_PRINT_SEL(sel, " %-8s", txpwr_lmt_str(txpwr_lmt[BAND_ON_6G])); + #endif + _RTW_PRINT_SEL(sel, "}"); + } + + _RTW_PRINT_SEL(sel, " %s", COUNTRY_CHPLAN_EN_11BE(ent) ? "be" : " "); + _RTW_PRINT_SEL(sel, " %s", COUNTRY_CHPLAN_EN_11AX(ent) ? "ax" : " "); + _RTW_PRINT_SEL(sel, " %s", COUNTRY_CHPLAN_EN_11AC(ent) ? "ac" : " "); + _RTW_PRINT_SEL(sel, " %s", COUNTRY_CHPLAN_EN_11A(ent) ? "a" : " "); + + #if CONFIG_IEEE80211_BAND_6GHZ + _RTW_PRINT_SEL(sel, " %c%c%c" + , (ent->cate_6g_map & CHPLAN_6G_CATE_STD) ? 'S' : '_' + , (ent->cate_6g_map & CHPLAN_6G_CATE_LPI) ? 'I' : '_' + , (ent->cate_6g_map & CHPLAN_6G_CATE_VLP) ? 'V' : '_' + ); + #endif + + _RTW_PRINT_SEL(sel, "\n"); +} + +void dump_country_chplan_map(void *sel, bool regd_info) +{ + struct country_chplan ent; + u8 code[2]; + +#if RTW_DEF_MODULE_REGULATORY_CERT + RTW_PRINT_SEL(sel, "RTW_DEF_MODULE_REGULATORY_CERT:0x%x\n", RTW_DEF_MODULE_REGULATORY_CERT); +#endif +#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP + RTW_PRINT_SEL(sel, "CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP\n"); +#endif + + rtw_get_chplan_worldwide(&ent); + dump_country_chplan(sel, &ent, regd_info); + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent)) + continue; + + dump_country_chplan(sel, &ent, regd_info); + } + } +} + +void dump_country_list(void *sel) +{ + u8 code[2]; + + RTW_PRINT_SEL(sel, "%s ", WORLDWIDE_ALPHA2); + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, NULL)) + continue; + _RTW_PRINT_SEL(sel, "%c%c ", code[0], code[1]); + } + } + _RTW_PRINT_SEL(sel, "\n"); +} + +void dump_chplan_id_list(void *sel) +{ + u8 id_search_max = 255; + u8 first = 1; + int i; + + for (i = 0; i <= id_search_max; i++) { + if (!rtw_is_channel_plan_valid(i)) + continue; + + if (first) { + RTW_PRINT_SEL(sel, "0x%02X ", i); + first = 0; + } else + _RTW_PRINT_SEL(sel, "0x%02X ", i); + } + if (first == 0) + _RTW_PRINT_SEL(sel, "\n"); +} + +void dump_chplan_country_list(void *sel) +{ + u8 id_search_max = 255; + int i; + + for (i = 0; i <= id_search_max; i++) { + struct country_chplan ent; + u8 code[2]; + u8 first; + + if (!rtw_is_channel_plan_valid(i)) + continue; + + first = 1; + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent) || ent.domain_code != i) + continue; + + if (first) { + RTW_PRINT_SEL(sel, "0x%02X %c%c ", i, code[0], code[1]); + first = 0; + } else + _RTW_PRINT_SEL(sel, "%c%c ", code[0], code[1]); + } + } + if (first == 0) + _RTW_PRINT_SEL(sel, "\n"); + } +} + +#if CONFIG_IEEE80211_BAND_6GHZ +void dump_chplan_6g_id_list(void *sel) +{ + u8 id_search_max = 255; + u8 first = 1; + int i; + + for (i = 0; i <= id_search_max; i++) { + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + + if (first) { + RTW_PRINT_SEL(sel, "0x%02X ", i); + first = 0; + } else + _RTW_PRINT_SEL(sel, "0x%02X ", i); + } + if (first == 0) + _RTW_PRINT_SEL(sel, "\n"); +} + +void dump_chplan_6g_country_list(void *sel) +{ + u8 id_search_max = 255; + int i; + + for (i = 0; i <= id_search_max; i++) { + struct country_chplan ent; + u8 code[2]; + u8 first; + + if (!rtw_is_channel_plan_6g_valid(i)) + continue; + + first = 1; + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + if (!rtw_get_chplan_from_country(code, &ent) || ent.domain_code_6g != i) + continue; + + if (first) { + RTW_PRINT_SEL(sel, "0x%02X %c%c ", i, code[0], code[1]); + first = 0; + } else + _RTW_PRINT_SEL(sel, "%c%c ", code[0], code[1]); + } + } + if (first == 0) + _RTW_PRINT_SEL(sel, "\n"); + } +} +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +#ifdef CONFIG_RTW_DEBUG +void dump_chplan_test(void *sel) +{ + if (regdb_ops.dump_chplan_test) + regdb_ops.dump_chplan_test(sel); +} +#endif /* CONFIG_RTW_DEBUG */ + +void dump_chplan_ver(void *sel) +{ + char buf[CHPLAN_VER_STR_BUF_LEN] = {0}; + + if (regdb_ops.get_ver_str) + regdb_ops.get_ver_str(buf, CHPLAN_VER_STR_BUF_LEN); + RTW_PRINT_SEL(sel, "%s\n", buf); +} + +static struct regd_req_t *rtw_regd_req_alloc(void) +{ + struct regd_req_t *req; + + req = rtw_zmalloc(sizeof(struct regd_req_t)); + if (req) + _rtw_init_listhead(&req->list); + + return req; +} + +static struct regd_req_t *rtw_regd_req_alloc_with_country_chplan(struct country_chplan *ent) +{ + struct regd_req_t *req; + + req = rtw_regd_req_alloc(); + if (req) + _rtw_memcpy(&req->chplan, ent, sizeof(req->chplan)); + + return req; +} + +static void rtw_regd_req_free(struct regd_req_t *req) +{ + rtw_mfree(req, sizeof(*req)); +} + +static void rtw_regd_req_list_insert(struct rf_ctl_t *rfctl, struct regd_req_t *req) +{ + rtw_list_insert_tail(&req->list, &rfctl->regd_req_list); + rfctl->regd_req_num++; +} + +#if defined(CONFIG_80211D) || defined(CONFIG_REGD_SRC_FROM_OS) +static void rtw_regd_req_list_delete(struct rf_ctl_t *rfctl, struct regd_req_t *req) +{ + rtw_list_delete(&req->list); + rfctl->regd_req_num--; +} +#endif + +void rtw_regd_req_list_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty) +{ + _rtw_mutex_init(&rfctl->regd_req_mutex); + _rtw_init_listhead(&rfctl->regd_req_list); + rfctl->init_regd_always_apply = regsty->init_regd_always_apply; + rfctl->user_regd_always_apply = regsty->user_regd_always_apply; +} + +void rtw_regd_req_list_free(struct rf_ctl_t *rfctl) +{ + struct regd_req_t *req; + _list *cur, *head; + + _rtw_mutex_lock_interruptible(&rfctl->regd_req_mutex); + + head = &rfctl->regd_req_list; + cur = get_next(head); + + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + rtw_list_delete(&req->list); + if (req != &rfctl->init_req) + rtw_regd_req_free(req); + } + rfctl->user_req = NULL; + rfctl->regd_req_num = 0; + + _rtw_mutex_unlock(&rfctl->regd_req_mutex); + + _rtw_mutex_free(&rfctl->regd_req_mutex); +} + +void rtw_regd_watchdog_hdl(struct dvobj_priv *dvobj) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + + rtw_beacon_hint_expire(rfctl); + +#ifdef CONFIG_DFS_MASTER + rtw_rfctl_chset_chk_non_ocp_finish(rfctl); +#endif +} + +static enum channel_width rtw_regd_adjust_linking_bw(struct rf_ctl_t *rfctl + , enum band_type band, u8 ch, enum channel_width bw, enum chan_offset offset) +{ +#ifndef DBG_REGD_ADJUST_LINKING_BW +#define DBG_REGD_ADJUST_LINKING_BW 0 +#endif + + struct rtw_chset *chset = &rfctl->chset; + + #if DBG_REGD_ADJUST_LINKING_BW + RTW_INFO("%s %s ch:%u,%u,%u\n" + , __func__, band_str(band), ch, bw, offset); + #endif + + if (bw == CHANNEL_WIDTH_20) + goto exit; + + for (; bw > CHANNEL_WIDTH_20; bw--) { + if (rtw_chset_is_bchbw_non_ocp(chset, band, ch, bw, offset)) { + #if DBG_REGD_ADJUST_LINKING_BW + RTW_INFO("%s %s ch:%u,%u,%u not allowed by non_ocp\n", __func__, band_str(band), ch, bw, offset); + #endif + continue; + } + + if (!rtw_chset_is_bchbw_valid(chset, band, ch, bw, offset, true, true)) { + #if DBG_REGD_ADJUST_LINKING_BW + RTW_INFO("%s %s ch:%u,%u,%u not allowed by chset\n", __func__, band_str(band), ch, bw, offset); + #endif + continue; + } + + break; + } + + if (bw == CHANNEL_WIDTH_20) + offset = CHAN_OFFSET_NO_EXT; + +exit: + rtw_warn_on(!rtw_chset_is_bchbw_valid(chset, band, ch, bw, offset, true, true)); + rtw_warn_on(rtw_chset_is_bchbw_non_ocp(chset, band, ch, bw, offset)); + + return bw; +} + +enum channel_width alink_adjust_linking_bw_by_regd(struct _ADAPTER_LINK *alink + , enum band_type band, u8 ch, enum channel_width bw, enum chan_offset offset) +{ + _adapter *adapter = alink->adapter; + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + return rtw_regd_adjust_linking_bw(rfctl, band, ch, bw, offset); +} + +enum channel_width adapter_adjust_linking_bw_by_regd(_adapter *adapter + , enum band_type band, u8 ch, enum channel_width bw, enum chan_offset offset) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + return rtw_regd_adjust_linking_bw(rfctl, band, ch, bw, offset); +} + +static void rtw_chplan_rtk_priv_domain_code_get_country_chplan(struct country_chplan *chplan + , u8 domain_code, u8 domain_code_6g) +{ + if (rtw_chplan_ids_is_world_wide(domain_code, domain_code_6g)) { + rtw_get_chplan_worldwide(chplan); + chplan->domain_code = domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + chplan->domain_code_6g = domain_code_6g; + #endif + } else { + SET_UNSPEC_ALPHA2(chplan->alpha2); + chplan->domain_code = domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + chplan->domain_code_6g = domain_code_6g; + #endif + + #if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE + chplan->edcca_2g_override = RTW_EDCCA_DEF; + #if CONFIG_IEEE80211_BAND_5GHZ + chplan->edcca_5g_override = RTW_EDCCA_DEF; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + chplan->edcca_6g_override = RTW_EDCCA_DEF; + #endif + #endif + + chplan->txpwr_lmt_override = TXPWR_LMT_DEF; + #ifdef CONFIG_CHPLAN_PROTO_EN + chplan->proto_en = CHPLAN_PROTO_EN_ALL; + #endif + } +} + +static void rtw_rfctl_regd_status_init_by_req(struct rf_ctl_t *rfctl, struct regd_req_t *req) +{ + struct country_chplan *chplan = &req->chplan; + + rfctl->regd_src = req->src; + rfctl->regd_inr_bmp = BIT(req->inr); + _rtw_memcpy(rfctl->alpha2, chplan->alpha2, 2); + rfctl->domain_code = chplan->domain_code; +#if CONFIG_IEEE80211_BAND_6GHZ + rfctl->domain_code_6g = chplan->domain_code_6g; + rfctl->env_bmp = BIT(req->env); +#endif +#ifdef CONFIG_CHPLAN_PROTO_EN + rfctl->proto_en = chplan->proto_en; +#endif +} + +#ifdef CONFIG_80211D +static bool rtw_rfctl_is_init_user_req_world_wide(struct rf_ctl_t *rfctl) +{ + return (!rfctl->user_req && IS_ALPHA2_WORLDWIDE(rfctl->init_req.chplan.alpha2)) /* INIT is WW (when no USER) */ + || (rfctl->user_req && IS_ALPHA2_WORLDWIDE(rfctl->user_req->chplan.alpha2)); /* USER is WW */ +} + +static bool rtw_rfctl_should_cis_enable(struct rf_ctl_t *rfctl) +{ + if (rtw_rfctl_is_disable_sw_channel_plan(rfctl_to_dvobj(rfctl))) + return false; + if (rfctl->cis_en_mode == CISEM_ENABLE) + return true; + if (rfctl->cis_en_mode == CISEM_ENABLE_WW) + return rtw_rfctl_is_init_user_req_world_wide(rfctl); + return false; +} + +static bool rtw_rfctl_update_cis_enabled(struct rf_ctl_t *rfctl, bool init, const char *caller) +{ + bool enabled = rtw_rfctl_should_cis_enable(rfctl); + + if (init || rfctl->cis_enabled != enabled) { + rfctl->cis_enabled = enabled; + RTW_INFO("%s set cis_enabled to %d\n", caller, enabled); + return true; + } + return false; +} + +static bool rtw_rfctl_forbid_unknown_country_opch(bool cis_enable, bool init_user_ww, bool regd_src_os) +{ + return (cis_enable || init_user_ww) && !regd_src_os; +} + +static void rtw_rfctl_update_cisr_collect_mode(struct rf_ctl_t *rfctl, bool init, const char *caller) +{ + bool collect_link_cisr; + bool collect_network_cisr; + bool forbid_unknown_country_opch = rtw_rfctl_forbid_unknown_country_opch( + rfctl->cis_enabled, rtw_rfctl_is_init_user_req_world_wide(rfctl), + RFCTL_REGD_SRC_FROM_OS(rfctl)); + + collect_link_cisr = (rfctl->cis_enabled && !RFCTL_REGD_SRC_FROM_OS(rfctl)) + || rtw_chset_has_6g_enabled(&rfctl->chset); + + collect_network_cisr = (rfctl->cis_enabled && (rfctl->cis_flags & CISF_ENV_BSS)) + || (rtw_txpwr_hal_is_txpwr_limit_needed(rfctl_to_dvobj(rfctl)) + && (forbid_unknown_country_opch || rtw_chset_has_6g_enabled(&rfctl->chset))); + + if (init || rfctl->collect_link_cisr != collect_link_cisr) { + rfctl->collect_link_cisr = collect_link_cisr; + RTW_INFO("%s set collect_link_cisr to %d\n", caller, collect_link_cisr); + } + if (init || rfctl->collect_network_cisr != collect_network_cisr) { + rfctl->collect_network_cisr = collect_network_cisr; + RTW_INFO("%s set collect_network_cisr to %d\n", caller, collect_network_cisr); + } +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static void rtw_rfctl_update_default_chplan_cate_6g_map(struct rf_ctl_t *rfctl, bool init, const char *caller) +{ + struct regd_req_t *user_req = rfctl->user_req; + u8 bmp = 0xFF; + + if (user_req) + bmp &= user_req->chplan.cate_6g_map; + if (!user_req || rfctl->init_regd_always_apply) + bmp &= rfctl->init_req.chplan.cate_6g_map; + + if (init || rfctl->default_chplan_cate_6g_map != bmp) { + rfctl->default_chplan_cate_6g_map = bmp; + RTW_INFO("%s set default_chplan_cate_6g_map to 0x%02x\n", caller, bmp); + if (!bmp && !rfctl->cis_enabled && rtw_txpwr_hal_is_txpwr_limit_needed(rfctl_to_dvobj(rfctl))) + RTW_INFO("%s !cis_enabled, 6G connection not allowed\n", caller); + } +} + +/* +* Update txpwr_lmt_6g_cate_map for +* a. REGD_SRC_RTK_PRIV's INIT/USER req +* b. REGD_SRC_OS's all req +*/ +static void rtw_rfctl_update_regd_req_txpwr_6g_cate_map(struct rf_ctl_t *rfctl) +{ + struct regd_req_t *req; + _list *cur, *head; + + /* apply txpwr lmt 6g cate map of req */ + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + + if (rfctl->regd_src == REGD_SRC_RTK_PRIV) { + /* apply txpwr lmt 6g cate map only for INIT/USER req */ + if (req->inr > RTW_REGD_SET_BY_USER) + continue; + } + + if (rfctl->txpwr_lmt_6g_cate_map_int_link_num) /* from per_link cisr */ + req->txpwr_lmt_6g_cate_map = rfctl->txpwr_lmt_6g_cate_map_int_all_link; + else { + if (req->inr == RTW_REGD_SET_BY_COUNTRY_IE) /* REGD_SRC_OS, without 6G link */ + req->txpwr_lmt_6g_cate_map = BIT(TXPWR_LMT_6G_CATE_VLP); + else /* get from self's env */ + req->txpwr_lmt_6g_cate_map = rtw_env_to_txpwr_lmt_6g_cate_map(req->env); + } + } +} +#endif +#endif /* CONFIG_80211D */ + +/* + * Description: + * Use hardware(efuse), driver parameter(registry) and default channel plan + * to decide which one should be used. + * + * Parameters: + * rfctl pointer of rfctl + * hw_alpha2 country code from HW (efuse/eeprom/mapfile) + * hw_chplan domain code from HW (efuse/eeprom/mapfile) + * hw_chplan_6g 6g domain code from HW (efuse/eeprom/mapfile) + * hw_force_chplan if forcing HW channel plan setting (efuse/eeprom/mapfile) + * will modified tif HW channel plan setting is invlid, will + */ +void rtw_rfctl_decide_init_chplan(struct rf_ctl_t *rfctl, + const char *hw_alpha2, u8 hw_chplan, u8 hw_chplan_6g, u8 hw_force_chplan) +{ + struct registry_priv *regsty; + char *sw_alpha2; + const struct country_chplan *country_ent = NULL; + struct country_chplan ent; + int chplan = -1; + int chplan_6g = -1; + + u8 sw_chplan; + u8 def_chplan = RTW_CHPLAN_WORLDWIDE; /* worldwide, used when HW, SW both invalid */ +#if CONFIG_IEEE80211_BAND_6GHZ + u8 sw_chplan_6g; + u8 def_chplan_6g = RTW_CHPLAN_6G_WORLDWIDE; /* worldwide, used when HW, SW both invalid */ +#endif + + if (hw_alpha2) { + if (strlen(hw_alpha2) != 2 || !is_alpha(hw_alpha2[0]) || is_alpha(hw_alpha2[1])) + RTW_PRINT("%s hw_alpha2 is not valid alpha2\n", __func__); + else if (rtw_get_chplan_from_country(hw_alpha2, &ent)) { + /* get chplan from hw country code, by pass hw chplan setting */ + country_ent = &ent; + chplan = ent.domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + chplan_6g = ent.domain_code_6g; + #endif + goto chk_sw_config; + } else + RTW_PRINT("%s unsupported hw_alpha2:\"%c%c\"\n", __func__, hw_alpha2[0], hw_alpha2[1]); + } + + if (rtw_is_channel_plan_valid(hw_chplan)) + chplan = hw_chplan; + else if (hw_force_chplan == _TRUE) { + RTW_PRINT("%s unsupported hw_chplan:0x%02X\n", __func__, hw_chplan); + /* hw infomaton invalid, refer to sw information */ + hw_force_chplan = _FALSE; + } + +#if CONFIG_IEEE80211_BAND_6GHZ + if (rtw_is_channel_plan_6g_valid(hw_chplan_6g)) + chplan_6g = hw_chplan_6g; + else if (hw_force_chplan == _TRUE) { + RTW_PRINT("%s unsupported hw_chplan_6g:0x%02X\n", __func__, hw_chplan_6g); + /* hw infomaton invalid, refer to sw information */ + hw_force_chplan = _FALSE; + } +#endif + +chk_sw_config: + regsty = dvobj_to_regsty(rfctl_to_dvobj(rfctl)); + + if (hw_force_chplan == _TRUE) + goto done; + + sw_alpha2 = regsty->alpha2; + sw_chplan = regsty->channel_plan; + #if CONFIG_IEEE80211_BAND_6GHZ + sw_chplan_6g = regsty->channel_plan_6g; + #endif + + if (sw_alpha2 && !IS_ALPHA2_UNSPEC(sw_alpha2)) { + if (IS_ALPHA2_WORLDWIDE(sw_alpha2) + || rtw_get_chplan_from_country(sw_alpha2, &ent) + ) { + /* get chplan from sw country code, by pass sw chplan setting */ + if (IS_ALPHA2_WORLDWIDE(sw_alpha2)) + rtw_get_chplan_worldwide(&ent); + country_ent = &ent; + chplan = ent.domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + chplan_6g = ent.domain_code_6g; + #endif + goto done; + } else + RTW_PRINT("%s unsupported sw_alpha2:\"%c%c\"\n", __func__, sw_alpha2[0], sw_alpha2[1]); + } + + if (rtw_is_channel_plan_valid(sw_chplan)) { + /* cancel hw_alpha2 because chplan is specified by sw_chplan */ + country_ent = NULL; + chplan = sw_chplan; + } else if (sw_chplan != RTW_CHPLAN_UNSPECIFIED) + RTW_PRINT("%s unsupported sw_chplan:0x%02X\n", __func__, sw_chplan); + +#if CONFIG_IEEE80211_BAND_6GHZ + if (rtw_is_channel_plan_6g_valid(sw_chplan_6g)) { + /* cancel hw_alpha2 because chplan_6g is specified by sw_chplan_6g */ + country_ent = NULL; + chplan_6g = sw_chplan_6g; + } else if (sw_chplan_6g != RTW_CHPLAN_6G_UNSPECIFIED) + RTW_PRINT("%s unsupported sw_chplan_6g:0x%02X\n", __func__, sw_chplan_6g); +#endif + +done: + if (chplan == -1) { + RTW_PRINT("%s use def_chplan:0x%02X\n", __func__, def_chplan); + chplan = def_chplan; + } else + RTW_PRINT("%s chplan:0x%02X\n", __func__, chplan); + +#if CONFIG_IEEE80211_BAND_6GHZ + if (chplan_6g == -1) { + RTW_PRINT("%s use def_chplan_6g:0x%02X\n", __func__, def_chplan_6g); + chplan_6g = def_chplan_6g; + } else + RTW_PRINT("%s chplan_6g:0x%02X\n", __func__, chplan_6g); +#endif + + if (!country_ent) + rtw_chplan_rtk_priv_domain_code_get_country_chplan(&ent, chplan, chplan_6g); + else { + RTW_PRINT("%s country code:\"%c%c\"\n", __func__ + , country_ent->alpha2[0], country_ent->alpha2[1]); + } + +#if CONFIG_IEEE80211_BAND_6GHZ + RTW_PRINT("%s env:%s\n", __func__, env_str(regsty->env)); +#endif + + rfctl->disable_sw_chplan = hw_force_chplan; + + rfctl->init_req.src = REGD_SRC_RTK_PRIV; + rfctl->init_req.inr = RTW_REGD_SET_BY_INIT; +#if CONFIG_IEEE80211_BAND_6GHZ + rfctl->init_req.env = regsty->env; +#endif + rfctl->init_req.applied = true; + _rtw_memcpy(&rfctl->init_req.chplan, &ent, sizeof(ent)); + rtw_regd_req_list_insert(rfctl, &rfctl->init_req); + + rtw_rfctl_regd_status_init_by_req(rfctl, &rfctl->init_req); +} + +void rtw_rfctl_apply_init_chplan(struct rf_ctl_t *rfctl, bool req_lock) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + + rtw_edcca_mode_update(dvobj, req_lock); + rtw_rfctl_chset_apply_regulatory(dvobj, req_lock); + +#ifdef CONFIG_80211D + rtw_rfctl_update_cis_enabled(rfctl, true, __func__); + rtw_rfctl_update_cisr_collect_mode(rfctl, true, __func__); + rfctl->init_user_req_is_ww = rtw_rfctl_is_init_user_req_world_wide(rfctl); + #if CONFIG_IEEE80211_BAND_6GHZ + rtw_rfctl_update_default_chplan_cate_6g_map(rfctl, true, __func__); + rtw_rfctl_update_regd_req_txpwr_6g_cate_map(rfctl); + #endif +#endif +} + +bool rtw_rfctl_is_disable_sw_channel_plan(struct dvobj_priv *dvobj) +{ + return dvobj_to_rfctl(dvobj)->disable_sw_chplan; +} + +static void get_str_of_set_chplan_keys(char *buf, u8 buf_len, struct SetChannelPlan_param *param) +{ + char *pos = buf; + +#ifdef CONFIG_80211D +#if CONFIG_IEEE80211_BAND_6GHZ +#define CHPLAN_KEYS_FMT_80211D_6G " env:%s reg_info:%s" +#define CHPLAN_KEYS_ARG_80211D_6G , env_str(param->cisr.env), cis_6g_reg_info_str(param->cisr.reg_info) +#else +#define CHPLAN_KEYS_FMT_80211D_6G +#define CHPLAN_KEYS_ARG_80211D_6G +#endif + + if (param->regd_src == REGD_SRC_RTK_PRIV && param->inr == RTW_REGD_SET_BY_COUNTRY_IE) { + if (param->has_cisr) { + pos += snprintf(pos, buf_len - (pos - buf), "alid:%c alpha2:"ALPHA2_FMT + CHPLAN_KEYS_FMT_80211D_6G + " %s" + , param->cisr_alink_id >= RTW_RLINK_MAX ? '-' : '0' + param->cisr_alink_id + , ALPHA2_ARG(param->cisr.alpha2) + CHPLAN_KEYS_ARG_80211D_6G + , cis_status_str(param->cisr.status)); + } else + *buf = '\0'; + } else +#endif + { + if (param->has_country) + pos += snprintf(pos, buf_len - (pos - buf), "alpha2:"ALPHA2_FMT, ALPHA2_ARG(param->country_ent.alpha2)); + else { + if (param->channel_plan == RTW_CHPLAN_UNSPECIFIED) + pos += snprintf(pos, buf_len - (pos - buf), "chplan:UNSPEC"); + else + pos += snprintf(pos, buf_len - (pos - buf), "chplan:0x%02X", param->channel_plan); + + #if CONFIG_IEEE80211_BAND_6GHZ + if (param->channel_plan_6g == RTW_CHPLAN_6G_UNSPECIFIED) + pos += snprintf(pos, buf_len - (pos - buf), " chplan_6g:UNSPEC"); + else + pos += snprintf(pos, buf_len - (pos - buf), " chplan_6g:0x%02X", param->channel_plan_6g); + #endif + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (param->env < RTW_ENV_NUM) + pos += snprintf(pos, buf_len - (pos - buf), " env:%s", env_str(param->env)); + else + pos += snprintf(pos, buf_len - (pos - buf), " env:UNSPEC"); + #endif + } +} + +#define EXCL_CHS_STR_LEN (MAX_CHANNEL_NUM_2G_5G * 4) +#define EXCL_CHS_6G_STR_LEN (MAX_CHANNEL_NUM_6G * 4) +#if defined(CONFIG_RTW_DEBUG) || defined(CONFIG_PROC_DEBUG) +static char *get_str_of_u8_array(char *buf, size_t buf_len, u8 array[], size_t array_len, char delim, bool zero_end) +{ + char *pos = buf; + char d_str[2] = {delim, '\0'}; + int i; + + for (i = 0; i < array_len && (!zero_end || array[i]); i++) { + pos += snprintf(pos, buf_len - (pos - buf), "%s%u" + , pos == buf ? "" : d_str, array[i]); + if (pos >= buf + buf_len - 1) + break; + } + if (pos == buf) + buf[0] = '\0'; + + return buf; +} +#endif + +#define RTW_PRIV_USER_SET_DOMAIN BIT0 +#define RTW_PRIV_USER_SET_DOMAIN_6G BIT1 +#define RTW_PRIV_USER_SET_COUNTRY BIT2 +#define RTW_PRIV_USER_SET_ENV BIT3 + +static int rtw_chplan_rtk_priv_req_prehdl_domain_code(struct rf_ctl_t *rfctl, struct SetChannelPlan_param *param, const char *caller) +{ + if (param->priv_user_set_bmp & RTW_PRIV_USER_SET_DOMAIN) { + /* disallow invalid input */ + if (!rtw_is_channel_plan_valid(param->channel_plan)) { + RTW_WARN("%s invalid chplan:0x%02X\n", caller, param->channel_plan); + return _FAIL; + } + } else { + /* use original value when unspecified */ + if (rfctl->user_req) + param->channel_plan = rfctl->user_req->chplan.domain_code; + else + param->channel_plan = rfctl->init_req.chplan.domain_code; + } + +#if CONFIG_IEEE80211_BAND_6GHZ + if (param->priv_user_set_bmp & RTW_PRIV_USER_SET_DOMAIN_6G) { + if (!rtw_is_channel_plan_6g_valid(param->channel_plan_6g)) { + RTW_WARN("%s invalid chplan_6g:0x%02X\n", caller, param->channel_plan_6g); + return _FAIL; + } + } else { + /* use original value when unspecified */ + if (rfctl->user_req) + param->channel_plan_6g = rfctl->user_req->chplan.domain_code_6g; + else + param->channel_plan_6g = rfctl->init_req.chplan.domain_code_6g; + } +#endif + + return _SUCCESS; +} + +static void rtw_chplan_rtk_priv_req_prehdl_country_ent(struct rf_ctl_t *rfctl, struct SetChannelPlan_param *param) +{ + if (!param->has_country) { + struct country_chplan *ent = ¶m->country_ent; + + if (!(param->priv_user_set_bmp & (RTW_PRIV_USER_SET_DOMAIN | RTW_PRIV_USER_SET_DOMAIN_6G))) { + /* no domain/_6g specified, keep original country setting */ + if (rfctl->user_req) + _rtw_memcpy(ent, &rfctl->user_req->chplan, sizeof(*ent)); + else + _rtw_memcpy(ent, &rfctl->init_req.chplan, sizeof(*ent)); + } else { + /* set world wide or unspecified */ + u8 chplan_6g = RTW_CHPLAN_6G_NULL; + + #if CONFIG_IEEE80211_BAND_6GHZ + chplan_6g = param->channel_plan_6g; + #endif + + rtw_chplan_rtk_priv_domain_code_get_country_chplan(ent, param->channel_plan, chplan_6g); + } + + param->has_country = 1; + } +} + +static void rtw_chplan_rtk_priv_req_prehdl_confs(struct rf_ctl_t *rfctl, struct chplan_confs *confs, const char *caller) +{ + if (confs->set_types & BIT(CHPLAN_CONFS_DIS_CH_FLAGS)) { + #if !CONFIG_DFS + /* force disable DFS channel because no DFS capability */ + confs->dis_ch_flags |= RTW_CHF_DFS; + #endif + if (rfctl->dis_ch_flags != confs->dis_ch_flags) { + char buf[RTW_CH_FLAGS_STR_LEN]; + + rfctl->dis_ch_flags = confs->dis_ch_flags; + RTW_INFO("%s set dis_ch_flags to %s\n", caller + , rtw_get_ch_flags_str(buf, confs->dis_ch_flags, ',')); + } else + confs->set_types &= ~BIT(CHPLAN_CONFS_DIS_CH_FLAGS); + } + + if (confs->set_types & BIT(CHPLAN_CONFS_EXCL_CHS)) { + if (_rtw_memcmp(rfctl->excl_chs, confs->excl_chs, sizeof(rfctl->excl_chs)) == _FALSE) { + char buf[EXCL_CHS_STR_LEN]; + + _rtw_memcpy(rfctl->excl_chs, confs->excl_chs, sizeof(rfctl->excl_chs)); + + RTW_INFO("%s set excl_chs to %s\n", caller + , get_str_of_u8_array(buf, sizeof(buf), confs->excl_chs, MAX_CHANNEL_NUM_2G_5G, ',', true)); + } else + confs->set_types &= ~BIT(CHPLAN_CONFS_EXCL_CHS); + } + +#if CONFIG_IEEE80211_BAND_6GHZ + if (confs->set_types & BIT(CHPLAN_CONFS_EXCL_CHS_6G)) { + if (_rtw_memcmp(rfctl->excl_chs_6g, confs->excl_chs_6g, sizeof(rfctl->excl_chs_6g)) == _FALSE) { + char buf[EXCL_CHS_6G_STR_LEN]; + + _rtw_memcpy(rfctl->excl_chs_6g, confs->excl_chs_6g, sizeof(rfctl->excl_chs_6g)); + + RTW_INFO("%s set excl_chs_6g to %s\n", caller + , get_str_of_u8_array(buf, sizeof(buf), confs->excl_chs_6g, MAX_CHANNEL_NUM_6G, ',', true)); + } else + confs->set_types &= ~BIT(CHPLAN_CONFS_EXCL_CHS_6G); + } +#endif + + if (confs->set_types & BIT(CHPLAN_CONFS_INIT_REGD_ALWAYS_APPLY)) { + bool val_changed = false; + + if (rfctl->init_regd_always_apply != confs->init_regd_always_apply) { + rfctl->init_regd_always_apply = confs->init_regd_always_apply; + val_changed = true; + RTW_INFO("%s set init_regd_always_apply to %d\n" + , caller, confs->init_regd_always_apply); + } + + if (!val_changed || rfctl->regd_src != REGD_SRC_RTK_PRIV + || rfctl->regd_req_num == 1 /* only INIT */ + ) + confs->set_types &= ~BIT(CHPLAN_CONFS_INIT_REGD_ALWAYS_APPLY); + } + + if (confs->set_types & BIT(CHPLAN_CONFS_USER_REGD_ALWAYS_APPLY)) { + bool val_changed = false; + + if (rfctl->user_regd_always_apply != confs->user_regd_always_apply) { + rfctl->user_regd_always_apply = confs->user_regd_always_apply; + val_changed = true; + RTW_INFO("%s set user_regd_always_apply to %d\n" + , caller, confs->user_regd_always_apply); + } + + if (!val_changed || rfctl->regd_src != REGD_SRC_RTK_PRIV + || !rfctl->user_req + || rfctl->regd_req_num == 2 /* only INIT & USER */ + ) + confs->set_types &= ~BIT(CHPLAN_CONFS_USER_REGD_ALWAYS_APPLY); + } + + if (confs->set_types & BIT(CHPLAN_CONFS_BCN_HINT_VALID_MS)) { + if (rfctl->bcn_hint_valid_ms != confs->bcn_hint_valid_ms) { + rfctl->bcn_hint_valid_ms = confs->bcn_hint_valid_ms; + RTW_INFO("%s set bcn_hint_valid_ms to %u\n", caller, confs->bcn_hint_valid_ms); + } + confs->set_types &= ~BIT(CHPLAN_CONFS_BCN_HINT_VALID_MS); /* setting done here */ + } + +#ifdef CONFIG_80211D + #ifdef CONFIG_REGD_SRC_FROM_OS + if (RFCTL_REGD_SRC_FROM_OS(rfctl)) { + /* regd_src from OS has its own 802.11d behavior, do not allow change */ + confs->set_types &= ~(BIT(CHPLAN_CONFS_CIS_EN_MODE) + | BIT(CHPLAN_CONFS_CIS_FLAGS) + | BIT(CHPLAN_CONFS_CIS_EN_ROLE) + | BIT(CHPLAN_CONFS_CIS_EN_IFBMP) + | BIT(CHPLAN_CONFS_CIS_SCAN_INT_MS) + ); + } + #endif + if (confs->set_types & BIT(CHPLAN_CONFS_CIS_EN_MODE)) { + if (CIS_EN_MODE_IS_VALID(confs->cis_en_mode) + && rfctl->cis_en_mode != confs->cis_en_mode + ) { + rfctl->cis_en_mode = confs->cis_en_mode; + RTW_INFO("%s set cis_en_mode to %u\n", caller, confs->cis_en_mode); + } else + confs->set_types &= ~BIT(CHPLAN_CONFS_CIS_EN_MODE); + } + + if (confs->set_types & BIT(CHPLAN_CONFS_CIS_FLAGS)) { + if (confs->cis_flags & ~CISF_VALIDS) { + RTW_WARN("%s cis_flags:0x%02x has undefined bits, apply valid bits only\n", caller, confs->cis_flags); + confs->cis_flags &= CISF_VALIDS; + } + if (rfctl->cis_flags != confs->cis_flags) { + rfctl->cis_flags = confs->cis_flags; + RTW_INFO("%s set cis_flags to 0x%02x\n", caller, confs->cis_flags); + } else + confs->set_types &= ~BIT(CHPLAN_CONFS_CIS_FLAGS); + } + + if (confs->set_types & BIT(CHPLAN_CONFS_CIS_EN_ROLE)) { + if (rfctl->cis_en_role != confs->cis_en_role) { + rfctl->cis_en_role = confs->cis_en_role; + RTW_INFO("%s set cis_en_role to 0x%02x\n", caller, confs->cis_en_role); + } + confs->set_types &= ~BIT(CHPLAN_CONFS_CIS_EN_ROLE); /* setting done here */ + } + + if (confs->set_types & BIT(CHPLAN_CONFS_CIS_EN_IFBMP)) { + if (rfctl->cis_en_ifbmp != confs->cis_en_ifbmp) { + rfctl->cis_en_ifbmp = confs->cis_en_ifbmp; + RTW_INFO("%s set cis_en_ifbmp to 0x%02x\n", caller, confs->cis_en_ifbmp); + } + confs->set_types &= ~BIT(CHPLAN_CONFS_CIS_EN_IFBMP); /* setting done here */ + } + + if (confs->set_types & BIT(CHPLAN_CONFS_CIS_SCAN_INT_MS)) { + if (rfctl->cis_scan_int_ms != confs->cis_scan_int_ms) { + rfctl->cis_scan_int_ms = confs->cis_scan_int_ms; + RTW_INFO("%s set cis_scan_int_ms to %u\n", caller, confs->cis_scan_int_ms); + } + confs->set_types &= ~BIT(CHPLAN_CONFS_CIS_SCAN_INT_MS); /* setting done here */ + } +#endif +} + +static bool rtw_chplan_rtk_priv_req_prehdl_user(struct rf_ctl_t *rfctl, struct SetChannelPlan_param *param, const char *caller) +{ + bool effected = false; + + if (param->channel_plan != RTW_CHPLAN_UNSPECIFIED) + param->priv_user_set_bmp |= RTW_PRIV_USER_SET_DOMAIN; + if (param->has_country) + param->priv_user_set_bmp |= RTW_PRIV_USER_SET_COUNTRY; +#if CONFIG_IEEE80211_BAND_6GHZ + if (param->channel_plan_6g != RTW_CHPLAN_6G_UNSPECIFIED) + param->priv_user_set_bmp |= RTW_PRIV_USER_SET_DOMAIN_6G; + if (param->env < RTW_ENV_NUM) + param->priv_user_set_bmp |= RTW_PRIV_USER_SET_ENV; +#endif + + if (!param->priv_user_set_bmp && !param->confs.set_types) { + /* meaningless input */ + RTW_WARN("%s meaningless input\n", caller); + goto exit; + } + + /* check input parameter */ + if (rtw_chplan_rtk_priv_req_prehdl_domain_code(rfctl, param, __func__) != _SUCCESS) + goto exit; + + if (param->priv_user_set_bmp & (RTW_PRIV_USER_SET_DOMAIN | RTW_PRIV_USER_SET_DOMAIN_6G + | RTW_PRIV_USER_SET_COUNTRY | RTW_PRIV_USER_SET_ENV) + ) { + rtw_chplan_rtk_priv_req_prehdl_country_ent(rfctl, param); + + /* allows only one user request */ + if (!rfctl->user_req) { + rfctl->user_req = rtw_regd_req_alloc_with_country_chplan(¶m->country_ent); + if (rfctl->user_req) { + rfctl->user_req->src = param->regd_src; + rfctl->user_req->inr = param->inr; + #if CONFIG_IEEE80211_BAND_6GHZ + if (param->env >= RTW_ENV_NUM) /* no env specified by first user_req, get from init_req */ + rfctl->user_req->env = rfctl->init_req.env; + else { + rfctl->user_req->env = param->env; + if (rfctl->init_req.env == param->env) + param->priv_user_set_bmp &= ~RTW_PRIV_USER_SET_ENV; + } + #endif + rtw_regd_req_list_insert(rfctl, rfctl->user_req); + effected = true; + } else + rtw_warn_on(1); + } else { + if (!_rtw_memcmp(&rfctl->user_req->chplan, ¶m->country_ent, sizeof(param->country_ent))) { + _rtw_memcpy(&rfctl->user_req->chplan, ¶m->country_ent, sizeof(param->country_ent)); + effected = true; + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (param->env < RTW_ENV_NUM && rfctl->user_req->env != param->env) { + rfctl->user_req->env = param->env; + effected = true; + } else + param->priv_user_set_bmp &= ~RTW_PRIV_USER_SET_ENV; + #endif + } + } + + /* check and update confs */ + rtw_chplan_rtk_priv_req_prehdl_confs(rfctl, ¶m->confs, caller); + +exit: + return effected || param->confs.set_types; +} + +#ifdef CONFIG_80211D +#if CONFIG_IEEE80211_BAND_6GHZ +static u8 cisr_get_txpwr_lmt_6g_cate_map(struct country_ie_slave_record *cisr) +{ + if (cisr->band == BAND_ON_6G) { + if (!IS_6G_REG_INFO_RSVD(cisr->reg_info)) + return reg_info_to_txpwr_lmt_6g_cate_map(cisr->reg_info); + return BIT(TXPWR_LMT_6G_CATE_VLP); + } + return 0; +} +#endif + +enum cisr_match { + CISR_MATCH = 0, /* identically match */ + CISR_MATCH_CHPLAN = 1, /* same chplan result (including txpwr_lmt_6g_cate_bmp) */ + CISR_DIFF /* different (not above cases) */ +}; + +static enum cisr_match rtw_cisr_compare(struct country_ie_slave_record *a, struct country_ie_slave_record *b) +{ + if (_rtw_memcmp(a, b, sizeof(*a)) == true) + return CISR_MATCH; + if (_rtw_memcmp(&a->chplan, &b->chplan, sizeof(a->chplan)) == true + #if CONFIG_IEEE80211_BAND_6GHZ + && cisr_get_txpwr_lmt_6g_cate_map(a) == cisr_get_txpwr_lmt_6g_cate_map(b) + #endif + ) + return CISR_MATCH_CHPLAN; + return CISR_DIFF; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static void rtw_rfctl_update_6g_cate_map_int_all_link(struct rf_ctl_t *rfctl) +{ + struct regd_req_t *user_req = rfctl->user_req; + int i, j; + u8 bmp; + u8 applied_link_num; + bool include_nocountry = !rfctl->cis_enabled; /* if cis is not enabled, include nocountry directly */ + +search: + bmp = 0; + applied_link_num = 0; + for (i = 0; i < CONFIG_IFACE_NUMBER; i++) { + for (j = 0; j < RTW_RLINK_MAX; j++) { + if (rfctl->cisr[i][j].band != BAND_ON_6G + || (!include_nocountry && rfctl->cisr[i][j].status == COUNTRY_IE_SLAVE_NOCOUNTRY)) + continue; + + if (bmp == 0) + bmp = cisr_get_txpwr_lmt_6g_cate_map(&rfctl->cisr[i][j]); + else + bmp &= cisr_get_txpwr_lmt_6g_cate_map(&rfctl->cisr[i][j]); + + applied_link_num++; + } + } + + if (!applied_link_num && !include_nocountry) { + /* if no applied link, include 6G link with NOCOUNTRY status*/ + include_nocountry = true; + goto search; + } + + rfctl->txpwr_lmt_6g_cate_map_int_all_link = bmp; + rfctl->txpwr_lmt_6g_cate_map_int_link_num = applied_link_num; +} + +static void rtw_rfctl_get_txpwr_lmt_6g_cate_map_from_init_user(struct rf_ctl_t *rfctl + , enum rtw_env_t *r_env, enum country_ie_slave_6g_reg_info *r_reg_info + , u8 *r_txpwr_lmt_6g_cate_map) +{ + struct regd_req_t *user_req = rfctl->user_req; + enum rtw_env_t env = RTW_ENV_NUM; + u8 bmp; + + if (user_req) + env = user_req->env; + if (!user_req || rfctl->init_regd_always_apply) { + if (env == RTW_ENV_NUM || rfctl->init_req.env == RTW_ENV_ANY) + env = rfctl->init_req.env; + else if (env != rfctl->init_req.env) + env = RTW_ENV_ANY; + } + + bmp = rtw_env_to_txpwr_lmt_6g_cate_map(env); + + *r_env = env; + *r_reg_info = CIS_6G_REG_RSVD; + *r_txpwr_lmt_6g_cate_map = bmp; +} +#endif /*CONFIG_IEEE80211_BAND_6GHZ */ + +static bool rtw_chplan_update_per_link_cisr(struct rf_ctl_t *rfctl, u8 iface_id + , u8 cisr_alink_id, struct country_ie_slave_record *cisr) +{ + struct country_ie_slave_record ori_cisr_cont[RTW_RLINK_MAX]; + u8 alink_id_s, alink_id_e, alink_id; + int i, j; + bool effected = false; + + if (cisr_alink_id < RTW_RLINK_MAX) { + /* specific alink */ + alink_id_s = cisr_alink_id; + alink_id_e = alink_id_s + 1; + } else { + /* all alinks of specific iface */ + alink_id_s = 0; + alink_id_e = RTW_RLINK_MAX; + } + + /* compare original record with same iface_id & spcified alink_id range */ + for (alink_id = alink_id_s; alink_id < alink_id_e; alink_id++) + if (rtw_cisr_compare(&rfctl->cisr[iface_id][alink_id], cisr) != CISR_MATCH) + break; + if (alink_id >= alink_id_e) { + /* record no change */ + goto exit; + } + + /* backup original content */ + for (alink_id = alink_id_s; alink_id < alink_id_e; alink_id++) + _rtw_memcpy(&ori_cisr_cont[alink_id], &rfctl->cisr[iface_id][alink_id], sizeof(ori_cisr_cont[alink_id])); + + /* update record */ + for (alink_id = alink_id_s; alink_id < alink_id_e; alink_id++) + _rtw_memcpy(&rfctl->cisr[iface_id][alink_id], cisr, sizeof(*cisr)); + + /* compare original record with same iface_id & spcified alink_id range for chplan change */ + for (alink_id = alink_id_s; alink_id < alink_id_e; alink_id++) + if (rtw_cisr_compare(&ori_cisr_cont[alink_id], cisr) > CISR_MATCH_CHPLAN) + break; + if (alink_id >= alink_id_e) { + /* chplan no change */ + goto exit; + } + +#if CONFIG_IEEE80211_BAND_6GHZ + rtw_rfctl_update_6g_cate_map_int_all_link(rfctl); +#endif + + effected = true; + +exit: + return effected; +} + +static bool rtw_regd_req_list_add_country_ie_req(struct rf_ctl_t *rfctl + , struct country_ie_slave_record *cisr, bool link) +{ + struct country_chplan *chplan = &cisr->chplan; + struct regd_req_t *req; + _list *cur, *head; + bool insert = false; +#if CONFIG_IEEE80211_BAND_6GHZ + enum rtw_env_t env; + enum country_ie_slave_6g_reg_info reg_info; + u8 txpwr_lmt_6g_cate_map; + + if (link) { + env = cisr->env; + reg_info = cisr->reg_info; + txpwr_lmt_6g_cate_map = cisr_get_txpwr_lmt_6g_cate_map(cisr); + } else { + /* ENV_BSS doesn't affect env and reg_info, assign value acording to per link status or init/user req */ + if (rfctl->txpwr_lmt_6g_cate_map_int_link_num) { + env = RTW_ENV_NUM; + reg_info = CIS_6G_REG_RSVD; + txpwr_lmt_6g_cate_map = rfctl->txpwr_lmt_6g_cate_map_int_all_link; + } else { + rtw_rfctl_get_txpwr_lmt_6g_cate_map_from_init_user(rfctl + , &env, ®_info, &txpwr_lmt_6g_cate_map); + } + } +#endif + + head = &rfctl->regd_req_list; + cur = get_next(head); + while (rtw_end_of_queue_search(head, cur) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + if (req->inr == RTW_REGD_SET_BY_COUNTRY_IE + && _rtw_memcmp(&req->chplan, chplan, sizeof(*chplan)) == true + #if CONFIG_IEEE80211_BAND_6GHZ + /* only compare txpwr_lmt_6g_cate_map */ + && req->txpwr_lmt_6g_cate_map == txpwr_lmt_6g_cate_map + #endif + ) { + req->ref_cnt++; + break; + } + cur = get_next(cur); + } + if (rtw_end_of_queue_search(head, cur)) { + req = rtw_regd_req_alloc_with_country_chplan(chplan); + if (req) { + req->src = REGD_SRC_RTK_PRIV; + req->inr = RTW_REGD_SET_BY_COUNTRY_IE; + #if CONFIG_IEEE80211_BAND_6GHZ + req->env = env; + req->reg_info = reg_info; + req->txpwr_lmt_6g_cate_map = txpwr_lmt_6g_cate_map; + #endif + req->ref_cnt = 1; + rtw_regd_req_list_insert(rfctl, req); + insert = true; + } else + rtw_warn_on(1); + } + + return insert; +} + +static bool rtw_regd_req_list_add_country_ie_req_from_per_link_cisr(struct rf_ctl_t *rfctl) +{ + int i, j; + bool effected = false; + + for (i = 0; i < CONFIG_IFACE_NUMBER; i++) { + for (j = 0; j < RTW_RLINK_MAX; j++) { + if (rfctl->cisr[i][j].status != COUNTRY_IE_SLAVE_APPLICABLE) + continue; + effected |= rtw_regd_req_list_add_country_ie_req(rfctl, &rfctl->cisr[i][j], true); + } + } + + return effected; +} + +static bool rtw_regd_req_list_add_country_ie_req_from_scanned_network_cisr(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + struct mlme_priv *mlme = &adapter->mlmepriv; + _queue *queue = &mlme->scanned_queue; + _list *list, *head; + struct wlan_network *scanned; + bool effected = false; + + _rtw_spinlock_bh(&queue->lock); + + head = get_list_head(queue); + list = get_next(head); + while (!rtw_end_of_queue_search(head, list)) { + scanned = LIST_CONTAINOR(list, struct wlan_network, list); + list = get_next(list); + + if (scanned->cisr.status != COUNTRY_IE_SLAVE_APPLICABLE) + continue; + effected |= rtw_regd_req_list_add_country_ie_req(rfctl, &scanned->cisr, false); + } + + _rtw_spinunlock_bh(&queue->lock); + + return effected; +} + +static void rtw_regd_req_list_clear_ref_cnt_by_inr(struct rf_ctl_t *rfctl, enum rtw_regd_inr inr) +{ + struct regd_req_t *req; + _list *cur, *head; + + head = &rfctl->regd_req_list; + cur = get_next(head); + while (rtw_end_of_queue_search(head, cur) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (req->inr == inr) + req->ref_cnt = 0; + } +} + +static bool rtw_regd_req_list_clear_zero_ref_req_by_inr(struct rf_ctl_t *rfctl, enum rtw_regd_inr inr) +{ + struct regd_req_t *req; + _list *cur, *head; + bool del = false; + + head = &rfctl->regd_req_list; + cur = get_next(head); + while (rtw_end_of_queue_search(head, cur) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (req->inr == inr && req->ref_cnt == 0) { + rtw_regd_req_list_delete(rfctl, req); + rtw_regd_req_free(req); + del = true; + } + } + return del; +} + +static bool rtw_chplan_rtk_priv_req_prehdl_country_ie(_adapter *adapter, struct SetChannelPlan_param *param, const char *caller) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + struct chplan_confs *confs = ¶m->confs; + u16 apply_confs_bmp = BIT(CHPLAN_CONFS_CIS_EN_MODE) | BIT(CHPLAN_CONFS_CIS_FLAGS); + bool confs_change = confs->set_types & apply_confs_bmp; + bool effected = false; + + if (param->has_cisr) { + bool per_link_cisr_changed; + + #ifdef CONFIG_RTW_DEBUG + if (rtw_drv_log_level >= _DRV_DEBUG_) { + RTW_PRINT("%s cisr before\n", __func__); + dump_country_ie_slave_records(RTW_DBGDUMP, rfctl, 0); + } + #endif + + per_link_cisr_changed = rtw_chplan_update_per_link_cisr(rfctl + , adapter->iface_id, param->cisr_alink_id, ¶m->cisr); + if (!per_link_cisr_changed && !confs_change) + goto exit; + + if (!rfctl->cis_enabled || rfctl->regd_src != REGD_SRC_RTK_PRIV) + effected = per_link_cisr_changed; + } + + if (param->has_cisr) { + #ifdef CONFIG_RTW_DEBUG + if (rtw_drv_log_level >= _DRV_DEBUG_) { + RTW_PRINT("%s cisr after\n", __func__); + dump_country_ie_slave_records(RTW_DBGDUMP, rfctl, 0); + } + #endif + } + + if (rfctl->regd_src == REGD_SRC_RTK_PRIV) { + rtw_regd_req_list_clear_ref_cnt_by_inr(rfctl, RTW_REGD_SET_BY_COUNTRY_IE); + + if (rfctl->cis_enabled) { + effected |= rtw_regd_req_list_add_country_ie_req_from_per_link_cisr(rfctl); + if (rfctl->cis_flags & CISF_ENV_BSS) + effected |= rtw_regd_req_list_add_country_ie_req_from_scanned_network_cisr(adapter); + } + + effected |= rtw_regd_req_list_clear_zero_ref_req_by_inr(rfctl, RTW_REGD_SET_BY_COUNTRY_IE); + } + confs->set_types &= ~apply_confs_bmp; + +exit: + return effected; +} +#endif /* CONFIG_80211D */ + +#ifdef CONFIG_REGD_SRC_FROM_OS +static bool rtw_chplan_req_prehdl_from_os(_adapter *adapter, struct SetChannelPlan_param *param, const char *caller) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + bool effected = false; + struct regd_req_t *req; + _list *cur, *head; + +#ifdef CONFIG_80211D + /* adjust cis settings */ + rfctl->cis_en_mode = rtw_os_get_cis_en_mode(adapter); + rfctl->cis_flags = 0; + rfctl->cis_en_role = COUNTRY_IE_SLAVE_EN_ROLE_STA | COUNTRY_IE_SLAVE_EN_ROLE_GC; + rfctl->cis_en_ifbmp = 0xFF; + rtw_rfctl_update_cis_enabled(rfctl, false, __func__); + rtw_rfctl_update_cisr_collect_mode(rfctl, false, __func__); +#endif + + /* + * two reqs only: + * 1. init req and + * 2. another recent req + */ + #if CONFIG_IEEE80211_BAND_6GHZ + if (param->inr == RTW_REGD_SET_BY_USER + && param->channel_plan == RTW_CHPLAN_UNSPECIFIED + && param->channel_plan_6g == RTW_CHPLAN_6G_UNSPECIFIED + && !param->has_country + ) { + /* special OS-USER req to set default environment */ + if (param->env < RTW_ENV_NUM) { + bool has_country_ie = false; + bool non_country_ie_env_changed = false; + + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (req->inr != RTW_REGD_SET_BY_COUNTRY_IE) { + if (req->env != param->env) { + req->env = param->env; + non_country_ie_env_changed = true; + } + } else + has_country_ie = true; + } + if (!has_country_ie && non_country_ie_env_changed) { + effected = true; + goto exit; + } + } + goto exit; + } else + #endif + { + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (req->inr == RTW_REGD_SET_BY_INIT) + continue; + if (req->inr == RTW_REGD_SET_BY_USER) + rfctl->user_req = NULL; + rtw_regd_req_list_delete(rfctl, req); + rtw_regd_req_free(req); + } + + req = rtw_regd_req_alloc_with_country_chplan(¶m->country_ent); + if (req) { + req->src = param->regd_src; + req->inr = param->inr; + #if CONFIG_IEEE80211_BAND_6GHZ + if (req->inr == RTW_REGD_SET_BY_COUNTRY_IE && param->env < RTW_ENV_NUM) + req->env = param->env; + else + req->env = rfctl->init_req.env; + #endif + rtw_regd_req_list_insert(rfctl, req); + if (req->inr == RTW_REGD_SET_BY_USER) + rfctl->user_req = req; + } else { + rtw_warn_on(1); + goto exit; + } + } + + effected = true; + +exit: + return effected; +} +#endif /* CONFIG_REGD_SRC_FROM_OS */ + +static bool rtw_chplan_req_prehdl(_adapter *adapter, struct SetChannelPlan_param *param, const char *caller) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + bool effected = false; + char buf[64]; + + get_str_of_set_chplan_keys(buf, 64, param); + RTW_INFO("%s iface_id:%u src:%s inr:%s %s\n", caller, adapter->iface_id + , regd_src_str(param->regd_src), regd_inr_str(param->inr), buf); + + if (param->inr == RTW_REGD_SET_BY_INIT) { + /* init should not done here */ + rtw_warn_on(1); + goto exit; + } + + if (param->regd_src == REGD_SRC_RTK_PRIV) { + if (param->inr == RTW_REGD_SET_BY_USER) { + #ifdef CONFIG_80211D + struct chplan_confs *confs = ¶m->confs; + #endif + + if (!rtw_chplan_rtk_priv_req_prehdl_user(rfctl, param, __func__)) + goto exit; + + #ifdef CONFIG_80211D + /* + * rfctl.regd_src is not allowed to change from REGD_SRC_OS to REGD_SRC_RTK_PRIV + * get new status and update to rfctl.cis_enabled here is safe and necessary for logic below + */ + if (rtw_rfctl_update_cis_enabled(rfctl, false, __func__)) { + rtw_rfctl_update_cisr_collect_mode(rfctl, false, __func__); + /* enable status change */ + confs->set_types |= BIT(CHPLAN_CONFS_CIS_EN_MODE); + } + + if ((confs->set_types & BIT(CHPLAN_CONFS_CIS_FLAGS)) + || (confs->set_types & BIT(CHPLAN_CONFS_CIS_EN_MODE)) + || (param->priv_user_set_bmp & RTW_PRIV_USER_SET_ENV) + ) { + if (!rtw_chplan_rtk_priv_req_prehdl_country_ie(adapter, param, __func__) + && !confs->set_types && !param->priv_user_set_bmp) + goto exit; + } + #endif + } + #ifdef CONFIG_80211D + else if (param->inr == RTW_REGD_SET_BY_COUNTRY_IE) { + if (!rtw_chplan_rtk_priv_req_prehdl_country_ie(adapter, param, __func__)) + goto exit; + } + #endif + else { + rtw_warn_on(1); + goto exit; + } + } +#ifdef CONFIG_REGD_SRC_FROM_OS + else if (param->regd_src == REGD_SRC_OS) { + if (!rtw_chplan_req_prehdl_from_os(adapter, param, caller)) + goto exit; + } +#endif + else { + rtw_warn_on(1); + goto exit; + } + + effected = true; + +exit: +#ifdef CONFIG_80211D + rfctl->init_user_req_is_ww = rtw_rfctl_is_init_user_req_world_wide(rfctl); + #if CONFIG_IEEE80211_BAND_6GHZ + rtw_rfctl_update_default_chplan_cate_6g_map(rfctl, false, caller); + rtw_rfctl_update_regd_req_txpwr_6g_cate_map(rfctl); + #endif +#endif + + return effected; +} + +static void rtw_rfctl_regd_req_sel_and_status_update(struct rf_ctl_t *rfctl) +{ + struct regd_req_t *req; + struct country_chplan *chplan; + _list *cur, *head; + enum regd_src_t applied_src = REGD_SRC_NUM; + enum rtw_regd_inr applied_inr = RTW_REGD_SET_BY_NUM; + + /* decide applied_src (highest src) */ + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (applied_src == REGD_SRC_NUM || req->src > applied_src) + applied_src = req->src; + } + + /* decide applied_inr (highest inr) */ + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + if (req->src != applied_src) + continue; + if (applied_inr == RTW_REGD_SET_BY_NUM || req->inr > applied_inr) + applied_inr = req->inr; + } + + rfctl->regd_src = REGD_SRC_NUM; + head = &rfctl->regd_req_list; + cur = get_next(head); + while ((rtw_end_of_queue_search(head, cur)) == _FALSE) { + req = LIST_CONTAINOR(cur, struct regd_req_t, list); + cur = get_next(cur); + + /* mark req with different src as not applied*/ + if (applied_src != req->src) { + req->applied = false; + continue; + } + /* mark req with target inr or always_apply INIT/USER req as applied*/ + req->applied = applied_inr == req->inr + || (req->inr == RTW_REGD_SET_BY_INIT && rfctl->init_regd_always_apply) + || (req->inr == RTW_REGD_SET_BY_USER && rfctl->user_regd_always_apply); + if (!req->applied) + continue; + + chplan = &req->chplan; + if (rfctl->regd_src == REGD_SRC_NUM) { + /* first applied req */ + rtw_rfctl_regd_status_init_by_req(rfctl, req); + + } else if (rfctl->regd_src == req->src) { + rfctl->regd_inr_bmp |= BIT(req->inr); + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->env_bmp |= BIT(req->env); + #endif + if (_rtw_memcmp(rfctl->alpha2, chplan->alpha2, 2) != _TRUE + || rfctl->domain_code != chplan->domain_code + #if CONFIG_IEEE80211_BAND_6GHZ + || rfctl->domain_code_6g != chplan->domain_code_6g + #endif + ) + SET_INTERSECTEDC_ALPHA2(rfctl->alpha2); + if (rfctl->domain_code != chplan->domain_code) + rfctl->domain_code = RTW_CHPLAN_UNSPECIFIED; + #if CONFIG_IEEE80211_BAND_6GHZ + if (rfctl->domain_code_6g != chplan->domain_code_6g) + rfctl->domain_code_6g = RTW_CHPLAN_UNSPECIFIED; + #endif + #ifdef CONFIG_CHPLAN_PROTO_EN + rfctl->proto_en &= chplan->proto_en; + #endif + } else { + RTW_WARN("%s req->src:%s != applied src:%s\n", __func__, regd_src_str(req->src), regd_src_str(rfctl->regd_src)); + rtw_warn_on(1); + } + } + + #ifdef CONFIG_80211D + if (rtw_rfctl_update_cis_enabled(rfctl, false, __func__)) + rtw_rfctl_update_cisr_collect_mode(rfctl, false, __func__); + #endif +} + +#if defined(CONFIG_AP_MODE) && CONFIG_AP_REGU_FORBID +bool rtw_rfctl_is_regu_forbid_bss(struct rf_ctl_t *rfctl, enum band_type band) +{ + if (!rtw_txpwr_hal_is_txpwr_limit_needed(rfctl_to_dvobj(rfctl))) + return false; + + /* forbid before 6G AP regulatory ready */ + return band == BAND_ON_6G; +} + +static void rtw_bss_regu_status_update(struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + u8 band_idx; + + /* TODO: update possible AP cate */ + + for (band_idx = HW_BAND_0; band_idx < HW_BAND_MAX; band_idx++) { + _adapter *iface; + struct _ADAPTER_LINK *alink; + int i, j; + bool forbid; + u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp_by_hwband(dvobj, band_idx); + u8 forbid_cnt = 0; + bool sta_link = false; + + /* loop all bss to apply regu status (reg_info, forbid) */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface || !(ifbmp_m & BIT(iface->iface_id))) + continue; + + for (j = 0; j < ADAPTER_GET_LINK_NUM(iface); j++) { + alink = GET_LINK(iface, j); + if (ALINK_GET_HWBAND(alink) != band_idx) + continue; + + forbid = rtw_rfctl_is_regu_forbid_bss(rfctl, ALINK_GET_BAND(alink)); + if (forbid) + forbid_cnt++; + + /* TODO: update reg_info for 6G AP */ + + /* update forbid status */ + rtw_ap_link_regu_forbid_apply(alink, forbid, false); + } + } + + if (!forbid_cnt || DEV_MCC_CAPABLE(dvobj)) + continue; + + /* check if having sta link exist */ + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (!iface || (ifbmp_m & BIT(iface->iface_id)) || !rtw_is_adapter_up(iface)) + continue; + + for (j = 0; j < ADAPTER_GET_LINK_NUM(iface); j++) { + alink = GET_LINK(iface, j); + if (ALINK_GET_HWBAND(alink) != band_idx) + continue; + if (rfctl->cisr[i][j].opch) { + sta_link = true; + i = dvobj->iface_nums; + break; + } + } + } + + if (!sta_link) { + /* no sta link, trigger bss ch select to get out of forbid status */ + _adapter *m_iface = rtw_mi_get_ap_mesh_iface_by_hwband(dvobj, band_idx); + u8 ifbmp_s = rtw_mi_get_lgd_sta_ifbmp_by_hwband(dvobj, band_idx); + + RTW_INFO(FUNC_HWBAND_FMT" trigger ch select for forbid bss\n", FUNC_HWBAND_ARG(band_idx)); + + if (!m_iface) { + rtw_warn_on(1); + continue; + } + + rtw_change_bss_bchbw_cmd(m_iface, RTW_CMDF_DIRECTLY + , ifbmp_m, ifbmp_s, REQ_BAND_NONE, REQ_CH_NONE, REQ_BW_ORI, REQ_OFFSET_NONE); + } + } +} +#endif /* defined(CONFIG_AP_MODE) && CONFIG_AP_REGU_FORBID */ + +u8 rtw_set_chplan_hdl(_adapter *adapter, u8 *pbuf) +{ + struct SetChannelPlan_param *param; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); +#ifdef CONFIG_IOCTL_CFG80211 + struct get_chplan_resp *chplan; +#endif + + if (!pbuf) + return H2C_PARAMETERS_ERROR; + + param = (struct SetChannelPlan_param *)pbuf; + + _rtw_mutex_lock_interruptible(&rfctl->regd_req_mutex); + + if (!rtw_chplan_req_prehdl(adapter, param, __func__)) { + _rtw_mutex_unlock(&rfctl->regd_req_mutex); + goto exit; + } + + rtw_rfctl_regd_req_sel_and_status_update(rfctl); + +#if CONFIG_TXPWR_LIMIT + rtw_txpwr_update_cur_lmt_regs(dvobj, false); +#endif + + rtw_edcca_mode_update(dvobj, false); + + rtw_rfctl_chset_apply_regulatory(dvobj, false); +#ifdef CONFIG_80211D + rtw_rfctl_update_cisr_collect_mode(rfctl, false, __func__); +#endif + + _rtw_mutex_unlock(&rfctl->regd_req_mutex); + + op_class_pref_apply_regulatory(rfctl, REG_CHANGE); + init_channel_list(adapter); + +#ifdef CONFIG_IOCTL_CFG80211 + if (rtw_get_chplan_cmd(adapter, RTW_CMDF_DIRECTLY, &chplan) == _SUCCESS) { + if (!param->rtnl_lock_needed) + rtw_regd_change_complete_sync(adapter_to_wiphy(adapter), chplan, 0); + else + rtw_warn_on(rtw_regd_change_complete_async(adapter_to_wiphy(adapter), chplan) != _SUCCESS); + } else + rtw_warn_on(1); +#endif + + rtw_nlrtw_reg_change_event(adapter); + + if (rtw_txpwr_hal_get_pwr_lmt_en(dvobj) && rtw_hw_is_init_completed(dvobj)) + rtw_update_txpwr_level(dvobj, HW_BAND_MAX); + +exit: + +#if defined(CONFIG_AP_MODE) && CONFIG_AP_REGU_FORBID + rtw_bss_regu_status_update(rfctl); +#endif + + return H2C_SUCCESS; +} + +static u8 _rtw_set_chplan_cmd(_adapter *adapter, int flags + , u8 chplan, u8 chplan_6g, const struct country_chplan *country_ent + , enum rtw_env_t env, enum regd_src_t regd_src, enum rtw_regd_inr inr + , const struct country_ie_slave_record *cisr, u8 cisr_alink_id + , struct chplan_confs *confs) +{ + struct cmd_obj *cmdobj; + struct SetChannelPlan_param *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; +#ifdef PLATFORM_LINUX + bool rtnl_lock_needed = rtw_rtnl_lock_needed(adapter_to_dvobj(adapter)); +#endif + u8 res = _SUCCESS; + + /* check if allow software config */ + if (rtw_rfctl_is_disable_sw_channel_plan(adapter_to_dvobj(adapter)) == _TRUE) { + res = _FAIL; + goto exit; + } + + if (country_ent) { + /* if country_entry is provided, replace chplan */ + chplan = country_ent->domain_code; + #if CONFIG_IEEE80211_BAND_6GHZ + chplan_6g = country_ent->domain_code_6g; + #endif + } + + /* prepare cmd parameter */ + parm = rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + parm->regd_src = regd_src; + parm->inr = inr; + if (country_ent) { + _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent)); + parm->has_country = true; + } + parm->channel_plan = chplan; +#if CONFIG_IEEE80211_BAND_6GHZ + parm->channel_plan_6g = chplan_6g; + parm->env = env; +#endif +#ifdef CONFIG_80211D + if (cisr) { + _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr)); + parm->cisr_alink_id = cisr_alink_id; + parm->has_cisr = true; + } +#endif + + if (confs) + _rtw_memcpy(&parm->confs, confs, sizeof(parm->confs)); + +#ifdef PLATFORM_LINUX + if (flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK)) + parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */ + else + parm->rtnl_lock_needed = 1; /* asynchronous call, always needed */ +#endif + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm)) + res = _FAIL; + rtw_mfree(parm, sizeof(*parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree(parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_CHANPLAN); + CMD_OBJ_SET_HWBAND(cmdobj, HW_BAND_0); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + + /* allow set channel plan when cmd_thread is not running */ + if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + parm = rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + parm->regd_src = regd_src; + parm->inr = inr; + if (country_ent) { + _rtw_memcpy(&parm->country_ent, country_ent, sizeof(parm->country_ent)); + parm->has_country = true; + } + parm->channel_plan = chplan; + #if CONFIG_IEEE80211_BAND_6GHZ + parm->channel_plan_6g = chplan_6g; + parm->env = env; + #endif + #ifdef CONFIG_80211D + if (cisr) { + _rtw_memcpy(&parm->cisr, cisr, sizeof(*cisr)); + parm->cisr_alink_id = cisr_alink_id; + parm->has_cisr = true; + } + #endif + if (confs) + _rtw_memcpy(&parm->confs, confs, sizeof(parm->confs)); + #ifdef PLATFORM_LINUX + parm->rtnl_lock_needed = rtnl_lock_needed; /* synchronous call, follow caller's */ + #endif + + if (H2C_SUCCESS != rtw_set_chplan_hdl(adapter, (u8 *)parm)) + res = _FAIL; + else + res = _SUCCESS; + rtw_mfree(parm, sizeof(*parm)); + } + } + +exit: + return res; +} + +u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 chplan_6g + , enum rtw_env_t env, enum rtw_regd_inr inr) +{ + return _rtw_set_chplan_cmd(adapter, flags + , chplan, chplan_6g, NULL, env + , REGD_SRC_RTK_PRIV, inr + , NULL, RTW_RLINK_MAX + , NULL); +} + +u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code + , enum rtw_env_t env, enum rtw_regd_inr inr) +{ + struct country_chplan ent; + + if (IS_ALPHA2_WORLDWIDE(country_code)) { + rtw_get_chplan_worldwide(&ent); + goto cmd; + } + + if (is_alpha(country_code[0]) == _FALSE + || is_alpha(country_code[1]) == _FALSE + ) { + RTW_PRINT("%s input country_code is not alpha2\n", __func__); + return _FAIL; + } + + if (!rtw_get_chplan_from_country(country_code, &ent)) { + RTW_PRINT("%s unsupported country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]); + return _FAIL; + } + +cmd: + RTW_PRINT("%s country_code:\"%c%c\"\n", __func__, country_code[0], country_code[1]); + + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, env + , REGD_SRC_RTK_PRIV, inr + , NULL, RTW_RLINK_MAX + , NULL); +} + +#if CONFIG_IEEE80211_BAND_6GHZ +u8 rtw_set_env_cmd(_adapter *adapter, int flags, enum rtw_env_t env + , enum regd_src_t regd_src, enum rtw_regd_inr inr) +{ + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, NULL, env + , regd_src, inr + , NULL, RTW_RLINK_MAX + , NULL); +} +#endif + +u8 rtw_set_chplan_confs_cmd(_adapter *adapter, int flags, struct chplan_confs *confs) +{ + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, NULL, RTW_ENV_NUM + , REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_USER + , NULL, RTW_RLINK_MAX + , confs); +} + +#ifdef CONFIG_PROC_DEBUG +static const char *const chplan_confs_type_str[] = { + [CHPLAN_CONFS_DIS_CH_FLAGS] = "dis_ch_flags", + [CHPLAN_CONFS_EXCL_CHS] = "excl_chs", + [CHPLAN_CONFS_EXCL_CHS_6G] = "excl_chs_6g", + [CHPLAN_CONFS_INIT_REGD_ALWAYS_APPLY] = "init_regd_always_apply", + [CHPLAN_CONFS_USER_REGD_ALWAYS_APPLY] = "user_regd_always_apply", + [CHPLAN_CONFS_BCN_HINT_VALID_MS] = "bcn_hint_valid_ms", + [CHPLAN_CONFS_CIS_EN_MODE] = "cis_en_mode", + [CHPLAN_CONFS_CIS_FLAGS] = "cis_flags", + [CHPLAN_CONFS_CIS_EN_IFBMP] = "cis_en_ifbmp", + [CHPLAN_CONFS_CIS_EN_ROLE] = "cis_en_role", + [CHPLAN_CONFS_CIS_SCAN_INT_MS] = "cis_scan_int_ms", +}; + +static enum chplan_confs_type get_chplan_confs_type_from_str(const char *str, size_t str_len) +{ + u8 i; + + for (i = 0; i < CHPLAN_CONFS_NUM; i++) + if (str_len == strlen(chplan_confs_type_str[i]) + && strncmp(str, chplan_confs_type_str[i], str_len) == 0) + return i; + return CHPLAN_CONFS_NUM; +} + +static void rtw_parse_chplan_confs_type_arg_str(struct chplan_confs *confs, enum chplan_confs_type type, char *str) +{ + if (type == CHPLAN_CONFS_DIS_CH_FLAGS) { + confs->set_types |= BIT(type); + if (strlen(str)) { + char *c; + enum rtw_ch_type ch_type; + + for (c = strsep(&str, ","); c; c = strsep(&str, ",")) { + ch_type = get_ch_type_from_str(c, strlen(c)); + if (ch_type != RTW_CHT_NUM) + confs->dis_ch_flags |= BIT(ch_type); + } + } + + } else if (type == CHPLAN_CONFS_EXCL_CHS) { + confs->set_types |= BIT(type); + if (strlen(str)) { + char *c; + int ch, ch_num = 0; + + for (c = strsep(&str, ","); c && ch_num < MAX_CHANNEL_NUM_2G_5G; c = strsep(&str, ",")) { + if (sscanf(c, "%d", &ch) == 1 && ch > 0 && ch < 256) + confs->excl_chs[ch_num++] = ch; + } + } + +#if CONFIG_IEEE80211_BAND_6GHZ + } else if (type == CHPLAN_CONFS_EXCL_CHS_6G) { + confs->set_types |= BIT(type); + if (strlen(str)) { + char *c; + int ch, ch_num = 0; + + for (c = strsep(&str, ","); c && ch_num < MAX_CHANNEL_NUM_6G; c = strsep(&str, ",")) { + if (sscanf(c, "%d", &ch) == 1 && ch > 0 && ch < 256) + confs->excl_chs_6g[ch_num++] = ch; + } + } +#endif + + } else if (type == CHPLAN_CONFS_INIT_REGD_ALWAYS_APPLY) { + if (strlen(str)) { + int val; + + if (sscanf(str, "%d", &val) == 1) { + confs->set_types |= BIT(type); + confs->init_regd_always_apply = !!val; + } + } + + } else if (type == CHPLAN_CONFS_USER_REGD_ALWAYS_APPLY) { + if (strlen(str)) { + int val; + + if (sscanf(str, "%d", &val) == 1) { + confs->set_types |= BIT(type); + confs->user_regd_always_apply = !!val; + } + } + + } else if (type == CHPLAN_CONFS_BCN_HINT_VALID_MS) { + if (strlen(str)) { + u32 ms; + + if (sscanf(str, "%u", &ms) == 1) { + confs->set_types |= BIT(type); + confs->bcn_hint_valid_ms = ms; + } + } + +#ifdef CONFIG_80211D + } else if (type == CHPLAN_CONFS_CIS_EN_MODE) { + if (strlen(str)) { + u8 mode; + + if (sscanf(str, "%hhu", &mode) == 1) { + confs->set_types |= BIT(type); + confs->cis_en_mode = mode; + } + } + + } else if (type == CHPLAN_CONFS_CIS_FLAGS) { + if (strlen(str)) { + u8 flags; + + if (sscanf(str, "%hhx", &flags) == 1) { + confs->set_types |= BIT(type); + confs->cis_flags = flags; + } + } + + } else if (type == CHPLAN_CONFS_CIS_EN_ROLE) { + if (strlen(str)) { + u8 role; + + if (sscanf(str, "%hhx", &role) == 1) { + confs->set_types |= BIT(type); + confs->cis_en_role = role; + } + } + + } else if (type == CHPLAN_CONFS_CIS_EN_IFBMP) { + if (strlen(str)) { + u8 ifbmp; + + if (sscanf(str, "%hhx", &ifbmp) == 1) { + confs->set_types |= BIT(type); + confs->cis_en_ifbmp = ifbmp; + } + } + + } else if (type == CHPLAN_CONFS_CIS_SCAN_INT_MS) { + if (strlen(str)) { + u32 ms; + + if (sscanf(str, "%u", &ms) == 1) { + confs->set_types |= BIT(type); + confs->cis_scan_int_ms = ms; + } + } +#endif /* CONFIG_80211D */ + + } +} + +u16 rtw_parse_chplan_confs_cmd_str(struct chplan_confs *confs, char *str) +{ + char *next = str, *c, *equal; + enum chplan_confs_type type; + + _rtw_memset(confs, 0, sizeof(*confs)); + + for (c = strsep(&next, " \t\n\r"); c; c = strsep(&next, " \t\n\r")) { + equal = strchr(c, '='); + if (!equal || c == equal) + continue; + type = get_chplan_confs_type_from_str(c, equal - c); + if (type == CHPLAN_CONFS_NUM) + continue; + rtw_parse_chplan_confs_type_arg_str(confs, type, equal + 1); + } + + return confs->set_types; +} +#endif /* CONFIG_PROC_DEBUG */ + +#ifdef CONFIG_80211D +u8 rtw_alink_apply_recv_regu_ies_cmd(struct _ADAPTER_LINK *alink, int flags, enum band_type band,u8 opch + , const u8 *country_ie, enum country_ie_slave_6g_reg_info reg_info) +{ + struct country_ie_slave_record cisr; + + rtw_get_cisr_from_recv_regu_ies(adapter_to_rfctl(alink->adapter), band, opch + , country_ie, reg_info + , &cisr); + + return _rtw_set_chplan_cmd(alink->adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, NULL, RTW_ENV_NUM + , REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE + , &cisr, rtw_adapter_link_get_id(alink) + , NULL); +} + +u8 rtw_apply_recv_regu_ies_cmd(_adapter *adapter, int flags, enum band_type band,u8 opch + , const u8 *country_ie, enum country_ie_slave_6g_reg_info reg_info) +{ + struct country_ie_slave_record cisr; + + rtw_get_cisr_from_recv_regu_ies(adapter_to_rfctl(adapter), band, opch + , country_ie, reg_info + , &cisr); + + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, NULL, RTW_ENV_NUM + , REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE + , &cisr, RTW_RLINK_MAX + , NULL); +} + +u8 rtw_apply_scan_network_country_ie_cmd(_adapter *adapter, int flags) +{ + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, NULL, RTW_ENV_NUM + , REGD_SRC_RTK_PRIV, RTW_REGD_SET_BY_COUNTRY_IE + , NULL, RTW_RLINK_MAX + , NULL); +} +#endif /* CONFIG_80211D */ + +#ifdef CONFIG_REGD_SRC_FROM_OS +u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code + , u8 dfs_region, enum rtw_env_t env, enum rtw_regd_inr inr) +{ + struct country_chplan ent; + struct country_chplan rtk_ent; + bool rtk_ent_exist; + + rtk_ent_exist = rtw_get_chplan_from_country(country_code, &rtk_ent); + + _rtw_memcpy(ent.alpha2, country_code, 2); + + /* + * Regulation follows OS, the internal txpwr limit selection is searched by alpha2 + * "00" => WW, others use string mapping + * When no matching txpwr limit selection is found, use + * 1. txpwr lmit selection associated with alpha2 inside driver regulation database + * 2. WW when driver has no support of this alpha2 + */ + + ent.domain_code = rtk_ent_exist ? rtk_ent.domain_code : RTW_CHPLAN_UNSPECIFIED; + #if CONFIG_IEEE80211_BAND_6GHZ + ent.domain_code_6g = rtk_ent_exist ? rtk_ent.domain_code_6g : RTW_CHPLAN_6G_UNSPECIFIED; + #endif + + #if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE + ent.edcca_2g_override = rtk_ent_exist ? rtk_ent.edcca_2g_override : RTW_EDCCA_ADAPT; + #if CONFIG_IEEE80211_BAND_5GHZ + ent.edcca_5g_override = rtk_ent_exist ? rtk_ent.edcca_5g_override : RTW_EDCCA_ADAPT; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + ent.edcca_6g_override = rtk_ent_exist ? rtk_ent.edcca_6g_override : RTW_EDCCA_ADAPT; + #endif + #endif + + ent.txpwr_lmt_override = rtk_ent_exist ? rtk_ent.txpwr_lmt_override : TXPWR_LMT_DEF; + #ifdef CONFIG_CHPLAN_PROTO_EN + ent.proto_en = CHPLAN_PROTO_EN_ALL; + #endif + + /* TODO: dfs_region */ + + return _rtw_set_chplan_cmd(adapter, flags + , RTW_CHPLAN_UNSPECIFIED, RTW_CHPLAN_6G_UNSPECIFIED, &ent, env + , REGD_SRC_OS, inr + , NULL, RTW_RLINK_MAX + , NULL); +} +#endif /* CONFIG_REGD_SRC_FROM_OS */ + +u8 rtw_get_chplan_hdl(_adapter *adapter, u8 *pbuf) +{ + struct get_channel_plan_param *param; + struct get_chplan_resp *chplan; + struct rf_ctl_t *rfctl; + struct rtw_chset *chset; +#if CONFIG_TXPWR_LIMIT + char *tl_reg_names[BAND_MAX]; + int tl_reg_names_len[BAND_MAX]; +#endif + int tl_reg_names_len_total = 0; + int i; + + if (!pbuf) + return H2C_PARAMETERS_ERROR; + + rfctl = adapter_to_rfctl(adapter); + chset = adapter_to_chset(adapter); + param = (struct get_channel_plan_param *)pbuf; + +#if CONFIG_TXPWR_LIMIT + rtw_txpwr_hal_get_current_lmt_regs_name(adapter_to_dvobj(adapter), tl_reg_names, tl_reg_names_len); + for (i = 0; i < BAND_MAX; i++) + tl_reg_names_len_total += tl_reg_names_len[i]; +#endif + + chplan = rtw_vmalloc(sizeof(struct get_chplan_resp) + sizeof(RT_CHANNEL_INFO) * chset->chs_len + tl_reg_names_len_total); + if (!chplan) + return H2C_CMD_FAIL; + + chplan->regd_src = rfctl->regd_src; + chplan->regd_inr_bmp = rfctl->regd_inr_bmp; + + chplan->alpha2[0] = rfctl->alpha2[0]; + chplan->alpha2[1] = rfctl->alpha2[1]; + + chplan->channel_plan = rfctl->domain_code; +#if CONFIG_IEEE80211_BAND_6GHZ + chplan->chplan_6g = rfctl->domain_code_6g; + chplan->env_bmp = rfctl->env_bmp; +#endif +#if CONFIG_TXPWR_LIMIT + chplan->txpwr_lmt_names_len_total = tl_reg_names_len_total; + for (i = 0; i < BAND_MAX; i++) { + if (i == 0) + chplan->txpwr_lmt_names[i] = ((u8 *)(chplan->chs)) + sizeof(RT_CHANNEL_INFO) * chset->chs_len; + else + chplan->txpwr_lmt_names[i] = chplan->txpwr_lmt_names[i - 1] + chplan->txpwr_lmt_names_len[i - 1]; + + chplan->txpwr_lmt_names_len[i] = tl_reg_names_len[i]; + if (tl_reg_names[i] && tl_reg_names_len[i]) { + _rtw_memcpy((void *)chplan->txpwr_lmt_names[i], tl_reg_names[i], tl_reg_names_len[i]); + rtw_mfree(tl_reg_names[i], tl_reg_names_len[i]); + } + } +#endif + chplan->edcca_mode_2g = rfctl->edcca_mode_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + chplan->edcca_mode_5g = rfctl->edcca_mode_5g; +#endif +#if CONFIG_IEEE80211_BAND_6GHZ + chplan->edcca_mode_6g = rfctl->edcca_mode_6g; +#endif +#ifdef CONFIG_DFS_MASTER + chplan->dfs_domain = rtw_rfctl_get_dfs_domain(rfctl); +#endif + + chplan->proto_en = 0 + #ifdef CONFIG_CHPLAN_PROTO_EN + | rfctl->proto_en + #endif + ; + + chplan->confs.dis_ch_flags = rfctl->dis_ch_flags; + _rtw_memcpy(chplan->confs.excl_chs, rfctl->excl_chs, MAX_CHANNEL_NUM_2G_5G); +#if CONFIG_IEEE80211_BAND_6GHZ + _rtw_memcpy(chplan->confs.excl_chs_6g, rfctl->excl_chs_6g, MAX_CHANNEL_NUM_6G); +#endif + chplan->confs.init_regd_always_apply = rfctl->init_regd_always_apply; + chplan->confs.user_regd_always_apply = rfctl->user_regd_always_apply; + chplan->confs.bcn_hint_valid_ms = rfctl->bcn_hint_valid_ms; +#ifdef CONFIG_80211D + chplan->confs.cis_en_mode = rfctl->cis_en_mode; + chplan->confs.cis_flags = rfctl->cis_flags; + chplan->confs.cis_en_role = rfctl->cis_en_role; + chplan->confs.cis_en_ifbmp = rfctl->cis_en_ifbmp; + chplan->confs.cis_scan_int_ms = rfctl->cis_scan_int_ms; +#endif + + chplan->chs_len = chset->chs_len; + _rtw_memcpy(chplan->chs, chset->chs, sizeof(RT_CHANNEL_INFO) * chset->chs_len); + param->chplan = chplan; + + return H2C_SUCCESS; +} + +void rtw_get_chplan_callback(_adapter *adapter, struct cmd_obj *cmdobj) +{ + struct get_channel_plan_param *param = (struct get_channel_plan_param *)cmdobj->parmbuf; + + cmdobj->sctx_rsp_buf = param->chplan; +} + +u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **chplan) +{ + struct cmd_obj *cmdobj; + struct get_channel_plan_param *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _FAIL; + + if (!(flags & (RTW_CMDF_DIRECTLY | RTW_CMDF_WAIT_ACK))) { + rtw_warn_on(1); + goto exit; + } + + /* prepare cmd parameter */ + parm = rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) + goto exit; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm)) { + *chplan = parm->chplan; + res = _SUCCESS; + } + rtw_mfree((u8 *)parm, sizeof(*parm)); + } else { /* case of RTW_CMDF_WAIT_ACK */ + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_GET_CHANPLAN); + CMD_OBJ_SET_HWBAND(cmdobj, HW_BAND_0); + cmdobj->no_io = true; + + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + cmdobj->sctx_rsp_buf_free = (void *)rtw_free_get_chplan_resp; + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_DONE_SUCCESS) + *chplan = sctx.rsp; + else + res = _FAIL; + } + + /* allow get channel plan when cmd_thread is not running */ + if (res != _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + parm = rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) + goto exit; + + if (H2C_SUCCESS == rtw_get_chplan_hdl(adapter, (u8 *)parm)) { + *chplan = parm->chplan; + res = _SUCCESS; + } + + rtw_mfree((u8 *)parm, sizeof(*parm)); + } + } + +exit: + return res; +} + +void rtw_free_get_chplan_resp(struct get_chplan_resp *chplan) +{ + size_t sz = sizeof(struct get_chplan_resp) + sizeof(RT_CHANNEL_INFO) * chplan->chs_len + #if CONFIG_TXPWR_LIMIT + + chplan->txpwr_lmt_names_len_total + #endif + ; + + rtw_vmfree(chplan, sz); +} + +bool rtw_network_chk_opch_status(struct rf_ctl_t *rfctl + , struct wlan_network *network) +{ + RT_CHANNEL_INFO *chinfo; + bool ret = false; + + chinfo = rtw_chset_get_chinfo_by_bch(&rfctl->chset + , BSS_EX_OP_BAND(&network->network), BSS_EX_OP_CH(&network->network), false); + if (!chinfo) + goto exit; + + if (CH_IS_NON_OCP(chinfo)) + goto exit; + + ret = true; + +exit: + return ret; +} + +#ifdef CONFIG_80211D +static bool rtw_iface_accept_country_ie(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (!(BIT(adapter->iface_id) & rfctl->cis_en_ifbmp)) + return false; + if (!MLME_IS_STA(adapter)) + return false; + if (!MLME_IS_GC(adapter)) { + if (!(rfctl->cis_en_role & COUNTRY_IE_SLAVE_EN_ROLE_STA)) + return false; + } else { + if (!(rfctl->cis_en_role & COUNTRY_IE_SLAVE_EN_ROLE_GC)) + return false; + } + return true; +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static enum country_ie_slave_6g_reg_info rtw_ies_get_6g_reg_info(const u8 *ies, uint ies_len) +{ + const u8 *he_op_ie; + sint he_op_ielen; + + he_op_ie = rtw_get_ext_ie(ies, WLAN_EID_EXTENSION_HE_OPERATION, &he_op_ielen, ies_len); + if (he_op_ie && he_op_ielen >= 1 + HE_OPER_PARAMS_LEN && GET_HE_OP_PARA_6GHZ_OP_INFO_PRESENT(he_op_ie + 3)) { + u8 offset = HE_OPER_PARAMS_LEN + HE_OPER_BSS_COLOR_INFO_LEN + HE_OPER_BASIC_MCS_LEN + + (GET_HE_OP_PARA_VHT_OP_INFO_PRESENT(he_op_ie + 3) ? HE_OPER_VHT_OPER_INFO_LEN : 0) + + (GET_HE_OP_PARA_CO_HOSTED_BSS(he_op_ie + 3) ? HE_OPER_MAX_COHOST_BSSID_LEN : 0); + + if (he_op_ielen >= offset) + return GET_HE_OP_INFO_REG_INFO(he_op_ie + 3 + offset); + } + return CIS_6G_REG_RSVD; +} +#endif + +void rtw_alink_joinbss_update_regulatory(struct _ADAPTER_LINK *alink, const WLAN_BSSID_EX *network) +{ + _adapter *adapter = alink->adapter; + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (rfctl->collect_link_cisr) { + u8 iface_id = adapter->iface_id; + u8 alink_id = rtw_adapter_link_get_id(alink); + const u8 *country_ie = NULL; + sint country_ie_len = 0; + enum country_ie_slave_6g_reg_info reg_info = CIS_6G_REG_RSVD; + + if (rtw_iface_accept_country_ie(adapter)) { + country_ie = rtw_get_ie(BSS_EX_TLV_IES(network) + , WLAN_EID_COUNTRY, &country_ie_len, BSS_EX_TLV_IES_LEN(network)); + if (country_ie) { + if (country_ie_len < 3) { + country_ie = NULL; + country_ie_len = 0; + } else + country_ie_len += 2; + } + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (BSS_EX_OP_BAND(network) == BAND_ON_6G) + reg_info = rtw_ies_get_6g_reg_info(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network)); + #endif + + if (country_ie) { + rtw_buf_update(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id], country_ie, country_ie_len); + } else { + rtw_buf_free(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id]); + } + + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->recv_6g_reg_info[iface_id][alink_id] = reg_info; + #endif + + if (rtw_alink_apply_recv_regu_ies_cmd(alink, RTW_CMDF_DIRECTLY + , BSS_EX_OP_BAND(network), BSS_EX_OP_CH(network), country_ie, reg_info) != _SUCCESS) + RTW_WARN(FUNC_ADPT_FMT" id:%u rtw_alink_apply_recv_regu_ies_cmd() fail\n", FUNC_ADPT_ARG(adapter), alink_id); + } +} + +static void _rtw_alink_leavebss_update_regulatory(_adapter *adapter, u8 alink_id) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (rfctl->collect_link_cisr) { + u8 iface_id = adapter->iface_id; + + if (alink_id < RTW_RLINK_MAX) { + struct _ADAPTER_LINK * alink = GET_LINK(adapter, alink_id); + + rtw_buf_free(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id]); + if (rtw_alink_apply_recv_regu_ies_cmd(alink, RTW_CMDF_DIRECTLY, 0, 0, NULL, CIS_6G_REG_RSVD) != _SUCCESS) + RTW_WARN(FUNC_ADPT_FMT" id:%u rtw_alink_apply_recv_regu_ies_cmd() fail\n", FUNC_ADPT_ARG(adapter), alink_id); + } else { + u8 i; + + for (i = 0; i < RTW_RLINK_MAX; i++) + rtw_buf_free(&rfctl->recv_country_ie[iface_id][i] + , &rfctl->recv_country_ie_len[iface_id][i]); + if (rtw_apply_recv_regu_ies_cmd(adapter, RTW_CMDF_DIRECTLY, 0, 0, NULL, CIS_6G_REG_RSVD) != _SUCCESS) + RTW_WARN(FUNC_ADPT_FMT" rtw_apply_recv_regu_ies_cmd() fail\n", FUNC_ADPT_ARG(adapter)); + } + } +} + +void rtw_alink_leavebss_update_regulatory(struct _ADAPTER_LINK * alink) +{ + _rtw_alink_leavebss_update_regulatory(alink->adapter, rtw_adapter_link_get_id(alink)); +} + +void rtw_alink_csa_update_regulatory(struct _ADAPTER_LINK *alink, enum band_type req_band, u8 req_ch) +{ + _adapter *adapter = alink->adapter; + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (rfctl->collect_link_cisr) { + u8 iface_id = adapter->iface_id; + u8 alink_id = rtw_adapter_link_get_id(alink); + + if (rtw_alink_apply_recv_regu_ies_cmd(alink, RTW_CMDF_DIRECTLY + , req_band, req_ch, rfctl->recv_country_ie[iface_id][alink_id] + , RFCTL_RECV_6G_REG_INFO(rfctl, iface_id, alink_id)) != _SUCCESS) + RTW_WARN(FUNC_ADPT_FMT" id:%u rtw_alink_apply_recv_regu_ies_cmd() fail\n", FUNC_ADPT_ARG(adapter), alink_id); + } +} + +void alink_process_regu_ies(struct _ADAPTER_LINK *alink, u8 *ies, uint ies_len) +{ + _adapter *adapter = alink->adapter; + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + u8 iface_id; + u8 alink_id; + +#ifdef CONFIG_ECSA_PHL + /* don't process country ie when under CSA processing */ + if (rtw_mr_is_ecsa_running(adapter)) + return; +#endif + + iface_id = adapter->iface_id; + alink_id = rtw_adapter_link_get_id(alink); + + if (rfctl->collect_link_cisr) { + const u8 *country_ie = NULL; + sint country_ie_len = 0; + bool country_ie_changed; + bool country_str_changed = false; + enum country_ie_slave_6g_reg_info reg_info = CIS_6G_REG_RSVD; + bool reg_info_changed = false; + + if (rtw_iface_accept_country_ie(adapter)) { + country_ie = rtw_get_ie(ies, WLAN_EID_COUNTRY, &country_ie_len, ies_len); + if (country_ie) { + if (country_ie_len < 3) { + country_ie = NULL; + country_ie_len = 0; + } else + country_ie_len += 2; + } + } + country_ie_changed = ((!!rfctl->recv_country_ie[iface_id][alink_id]) ^ (!!country_ie)) + || rfctl->recv_country_ie_len[iface_id][alink_id] != country_ie_len + || _rtw_memcmp(rfctl->recv_country_ie[iface_id][alink_id], country_ie, country_ie_len) == _FALSE; + + #if CONFIG_IEEE80211_BAND_6GHZ + if (ALINK_GET_BAND(alink) == BAND_ON_6G) + reg_info = rtw_ies_get_6g_reg_info(ies, ies_len); + reg_info_changed = rfctl->recv_6g_reg_info[iface_id][alink_id] != reg_info; + #endif + + if (!country_ie_changed && !reg_info_changed) + return; + + if (country_ie_changed) { + country_str_changed = ((!!rfctl->recv_country_ie[iface_id][alink_id]) ^ (!!country_ie)) + || (country_ie && _rtw_memcmp(rfctl->recv_country_ie[iface_id][alink_id] + 2, country_ie + 2, 3)); + if (!country_ie) { + rtw_buf_free(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id]); + } else { + rtw_buf_update(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id], country_ie, country_ie_len); + } + } + + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->recv_6g_reg_info[iface_id][alink_id] = reg_info; + #endif + + if (country_str_changed /* for now only country str is used */ + || reg_info_changed + ) { + RTW_INFO(FUNC_ADPT_FMT" id:%u%s%s changed\n", FUNC_ADPT_ARG(adapter), alink_id + , country_str_changed ? " country_str" : "" + #if CONFIG_IEEE80211_BAND_6GHZ + , reg_info_changed ? " 6g_reg_info" : "" + #else + , "" + #endif + ); + rtw_alink_apply_recv_regu_ies_cmd(alink, 0, ALINK_GET_BAND(alink), ALINK_GET_CH(alink) + , rfctl->recv_country_ie[iface_id][alink_id], RFCTL_RECV_6G_REG_INFO(rfctl, iface_id, alink_id)); + } + } + else if (rfctl->recv_country_ie[iface_id][alink_id]) { + rtw_buf_free(&rfctl->recv_country_ie[iface_id][alink_id] + , &rfctl->recv_country_ie_len[iface_id][alink_id]); + #if CONFIG_IEEE80211_BAND_6GHZ + rfctl->recv_6g_reg_info[iface_id][alink_id] = CIS_6G_REG_RSVD; + #endif + rtw_alink_apply_recv_regu_ies_cmd(alink, 0, ALINK_GET_BAND(alink), ALINK_GET_CH(alink), NULL, CIS_6G_REG_RSVD); + } +} + +void rtw_joinbss_update_regulatory(_adapter *adapter, const WLAN_BSSID_EX *network) +{ + rtw_alink_joinbss_update_regulatory(GET_PRIMARY_LINK(adapter), network); +} + +void rtw_leavebss_update_regulatory(_adapter *adapter) +{ + _rtw_alink_leavebss_update_regulatory(adapter, RTW_RLINK_MAX); +} + +void rtw_csa_update_regulatory(_adapter *adapter, enum band_type req_band, u8 req_ch) +{ + rtw_alink_csa_update_regulatory(GET_PRIMARY_LINK(adapter), req_band, req_ch); +} + +void process_regu_ies(_adapter *adapter, u8 *ies, uint ies_len) +{ + alink_process_regu_ies(GET_PRIMARY_LINK(adapter), ies, ies_len); +} + +bool rtw_update_scanned_network_cisr(struct rf_ctl_t *rfctl, struct wlan_network *network) +{ + if (rfctl->collect_network_cisr) { + const u8 *country_ie = NULL; + sint country_ie_len = 0; + enum country_ie_slave_6g_reg_info reg_info = CIS_6G_REG_RSVD; + struct country_ie_slave_record *cisr = &network->cisr; + struct country_chplan *chplan = &network->cisr.chplan; + struct country_chplan ori_chplan; + + _rtw_memcpy(&ori_chplan, chplan, sizeof(*chplan)); + + country_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_COUNTRY, &country_ie_len, BSS_EX_TLV_IES_LEN(&network->network)); + if (country_ie) { + if (country_ie_len < 3) + country_ie = NULL; + } + + #if CONFIG_IEEE80211_BAND_6GHZ + if (BSS_EX_OP_BAND(&network->network) == BAND_ON_6G) + reg_info = rtw_ies_get_6g_reg_info(BSS_EX_TLV_IES(&network->network), BSS_EX_TLV_IES_LEN(&network->network)); + #endif + + rtw_get_cisr_from_recv_regu_ies(rfctl + , BSS_EX_OP_BAND(&network->network), BSS_EX_OP_CH(&network->network) + , country_ie, reg_info, cisr); + + return _rtw_memcmp(&ori_chplan, chplan, sizeof(*chplan)) == _TRUE ? false : true; + } + else if (network->cisr.alpha2[0] != '\0' || network->cisr.alpha2[1] != '\0') { + network->cisr.alpha2[0] = network->cisr.alpha2[1] = '\0'; + network->cisr.band = BSS_EX_OP_BAND(&network->network); + network->cisr.opch = BSS_EX_OP_CH(&network->network); + #if CONFIG_IEEE80211_BAND_6GHZ + network->cisr.reg_info = CIS_6G_REG_RSVD; + #endif + network->cisr.status = COUNTRY_IE_SLAVE_NOCOUNTRY; + return true; + } + + return false; +} + +bool rtw_network_chk_regu_ies(struct rf_ctl_t *rfctl, struct wlan_network *network) +{ + bool forbid_unknown_country_opch; + bool ret = false; + + if (!rtw_txpwr_hal_is_txpwr_limit_needed(rfctl_to_dvobj(rfctl))) + goto bypass; + +#if CONFIG_IEEE80211_BAND_6GHZ + if (network->cisr.band == BAND_ON_6G) { + /* forbid before std-client ready */ + if (network->cisr.reg_info == CIS_6G_REG_SP_AP + || network->cisr.reg_info == CIS_6G_REG_IN_SP_AP) + goto exit; + + if (!rfctl->cis_enabled + || network->cisr.status == COUNTRY_IE_SLAVE_NOCOUNTRY + || network->cisr.status == COUNTRY_IE_SLAVE_UNKNOWN + ) { + if (!(rfctl->default_chplan_cate_6g_map & reg_info_to_chplan_6g_cate_map(network->cisr.reg_info))) + goto exit; + } else { + if (network->cisr.status == COUNTRY_IE_SLAVE_CATE_6G_NS) + goto exit; + } + } +#endif + + forbid_unknown_country_opch = rtw_rfctl_forbid_unknown_country_opch( + rfctl->cis_enabled, rfctl->init_user_req_is_ww, RFCTL_REGD_SRC_FROM_OS(rfctl)); + if (forbid_unknown_country_opch) { + if (network->cisr.status == COUNTRY_IE_SLAVE_UNKNOWN + || network->cisr.status == COUNTRY_IE_SLAVE_OPCH_NOEXIST) + goto exit; + } + +bypass: + ret = true; + +exit: + return ret; +} + +void rtw_rfctl_cis_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty) +{ +#if CONFIG_IEEE80211_BAND_6GHZ + int i, j; +#endif + + rfctl->cis_en_mode = regsty->country_ie_slave_en_mode; + if (!CIS_EN_MODE_IS_VALID(rfctl->cis_en_mode)) { + RTW_WARN("%s cis_en_mode %u is not supported, set to disable\n", __func__, rfctl->cis_en_mode); + rfctl->cis_en_mode = CISEM_DISABLE; + } + + rfctl->cis_flags = regsty->country_ie_slave_flags; + if (rfctl->cis_flags & ~CISF_VALIDS) { + RTW_WARN("%s cis_flags:0x%02x has undefined bits, apply valid bits only\n", __func__, rfctl->cis_flags); + rfctl->cis_flags &= CISF_VALIDS; + } + + rfctl->cis_en_role = regsty->country_ie_slave_en_role; + rfctl->cis_en_ifbmp = regsty->country_ie_slave_en_ifbmp; + rfctl->cis_scan_int_ms = regsty->country_ie_slave_scan_int_ms; + +#if CONFIG_IEEE80211_BAND_6GHZ + for (i = 0; i < CONFIG_IFACE_NUMBER; i++) { + for (j = 0; j < RTW_RLINK_MAX; j++) { + rfctl->recv_6g_reg_info[i][j] = CIS_6G_REG_RSVD; + rfctl->cisr[i][j].reg_info = CIS_6G_REG_RSVD; + } + } +#endif +} + +void rtw_rfctl_cis_deinit(struct rf_ctl_t *rfctl) +{ + int i, j; + + for (i = 0; i < CONFIG_IFACE_NUMBER; i++) + for (j = 0; j < RTW_RLINK_MAX; j++) + rtw_buf_free(&rfctl->recv_country_ie[i][j], &rfctl->recv_country_ie_len[i][j]); +} +#endif /* CONFIG_80211D */ + +#ifdef CONFIG_PROC_DEBUG +void dump_cur_chplan_confs(void *sel, struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct get_chplan_resp *chplan; + struct chplan_confs *confs; + size_t buf_len = rtw_max(RTW_CH_FLAGS_STR_LEN, EXCL_CHS_STR_LEN); + char *buf; + +#if CONFIG_IEEE80211_BAND_6GHZ + buf_len = rtw_max(buf_len, EXCL_CHS_6G_STR_LEN); +#endif + + buf = rtw_vmalloc(buf_len); + if (!buf) + return; + + if (rtw_get_chplan_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_WAIT_ACK, &chplan) == _FAIL) + goto free_buf; + + confs = &chplan->confs; + + RTW_PRINT_SEL(sel, "dis_ch_flags=%s\n", rtw_get_ch_flags_str(buf, confs->dis_ch_flags, ',')); + RTW_PRINT_SEL(sel, "excl_chs=%s\n" + , get_str_of_u8_array(buf, buf_len, confs->excl_chs, MAX_CHANNEL_NUM_2G_5G, ',', true)); +#if CONFIG_IEEE80211_BAND_6GHZ + RTW_PRINT_SEL(sel, "excl_chs_6g=%s\n" + , get_str_of_u8_array(buf, buf_len, confs->excl_chs_6g, MAX_CHANNEL_NUM_6G, ',', true)); +#endif + RTW_PRINT_SEL(sel, "init_regd_always_apply=%d\n", confs->init_regd_always_apply); + RTW_PRINT_SEL(sel, "user_regd_always_apply=%d\n", confs->user_regd_always_apply); + RTW_PRINT_SEL(sel, "bcn_hint_valid_ms=%u\n", confs->bcn_hint_valid_ms); +#ifdef CONFIG_80211D + RTW_PRINT_SEL(sel, "cis_en_mode=%u\n", confs->cis_en_mode); + RTW_PRINT_SEL(sel, "cis_flags=0x%02x\n", confs->cis_flags); + RTW_PRINT_SEL(sel, "cis_en_role=0x%02x\n", confs->cis_en_role); + RTW_PRINT_SEL(sel, "cis_en_ifbmp=0x%02x\n", confs->cis_en_ifbmp); + RTW_PRINT_SEL(sel, "cis_scan_int_ms=%u\n", confs->cis_scan_int_ms); +#endif + + rtw_free_get_chplan_resp(chplan); + +free_buf: + rtw_vmfree(buf, buf_len); +} + +static void dump_chplan_regd_inrs(void *sel, struct get_chplan_resp *chplan) +{ + char buf[REGD_INR_BMP_STR_LEN]; + + RTW_PRINT_SEL(sel, "regd_inr:%s\n", rtw_get_regd_inr_bmp_str(buf, chplan->regd_inr_bmp)); +} + +#if CONFIG_IEEE80211_BAND_6GHZ +static void dump_chplan_envs(void *sel, struct get_chplan_resp *chplan) +{ + char buf[REGD_INR_BMP_STR_LEN]; + + RTW_PRINT_SEL(sel, "env:%s\n", rtw_get_env_bmp_str(buf, chplan->env_bmp)); +} +#endif + +#if CONFIG_TXPWR_LIMIT +static void dump_chplan_txpwr_lmt_regs(void *sel, struct get_chplan_resp *chplan) +{ + int band; + const char *names, *name; + int names_len; + + for (band = 0; band < BAND_MAX; band++) { + names = chplan->txpwr_lmt_names[band]; + names_len = chplan->txpwr_lmt_names_len[band]; + + RTW_PRINT_SEL(sel, "txpwr_lmt[%s]:", band_str(band)); + ustrs_for_each_str(names, names_len, name) + _RTW_PRINT_SEL(sel, "%s%s", name == names ? "" : " ", name); + _RTW_PRINT_SEL(sel, "\n"); + } +} +#endif + +static void dump_chplan_edcca_modes(void *sel, struct get_chplan_resp *chplan) +{ + u8 mode[BAND_MAX]; + char buf[EDCCA_MODE_OF_BANDS_STR_LEN]; + + mode[BAND_ON_24G] = chplan->edcca_mode_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + mode[BAND_ON_5G] = chplan->edcca_mode_5g; +#endif +#if CONFIG_IEEE80211_BAND_6GHZ + mode[BAND_ON_6G] = chplan->edcca_mode_6g; +#endif + + RTW_PRINT_SEL(sel, "edcca_mode:%s\n", rtw_get_edcca_mode_of_bands_str(buf, mode)); +} + +static void dump_addl_ch_disable_conf(void *sel, struct get_chplan_resp *chplan) +{ + struct chplan_confs *confs = &chplan->confs; + int i; + + if (confs->dis_ch_flags) { + char buf[RTW_CH_FLAGS_STR_LEN]; + + RTW_PRINT_SEL(sel, "dis_ch_flags:%s\n", rtw_get_ch_flags_str(buf, confs->dis_ch_flags, ' ')); + } + + if (confs->excl_chs[0] != 0) { + char buf[EXCL_CHS_STR_LEN]; + + RTW_PRINT_SEL(sel, "excl_chs:%s\n" + , get_str_of_u8_array(buf, sizeof(buf), confs->excl_chs, MAX_CHANNEL_NUM_2G_5G, ' ', true)); + } + +#if CONFIG_IEEE80211_BAND_6GHZ + for (i = 0; i < MAX_CHANNEL_NUM_6G; i++) + if (confs->excl_chs_6g[i] != 0) + break; + + if (confs->excl_chs_6g[0] != 0) { + char buf[EXCL_CHS_6G_STR_LEN]; + + RTW_PRINT_SEL(sel, "excl_chs_6g:%s\n" + , get_str_of_u8_array(buf, sizeof(buf), confs->excl_chs_6g, MAX_CHANNEL_NUM_6G, ' ', true)); + } +#endif +} + +void dump_cur_country(void *sel, struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct get_chplan_resp *chplan; + + if (rtw_get_chplan_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_WAIT_ACK, &chplan) == _FAIL) + return; + + RTW_PRINT_SEL(sel, "%c%c\n", chplan->alpha2[0], chplan->alpha2[1]); + + rtw_free_get_chplan_resp(chplan); +} + +void dump_cur_chplan(void *sel, struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct get_chplan_resp *chplan; + + if (rtw_get_chplan_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_WAIT_ACK, &chplan) == _FAIL) + return; + + RTW_PRINT_SEL(sel, "regd_src:%s(%d)\n", regd_src_str(chplan->regd_src), chplan->regd_src); + dump_chplan_regd_inrs(sel, chplan); + + RTW_PRINT_SEL(sel, "alpha2:%c%c\n", chplan->alpha2[0], chplan->alpha2[1]); + +#ifdef CONFIG_80211BE_EHT + RTW_PRINT_SEL(sel, "be:%d\n", (chplan->proto_en & CHPLAN_PROTO_EN_BE) ? 1 : 0); +#endif +#ifdef CONFIG_80211AX_HE + RTW_PRINT_SEL(sel, "ax:%d\n", (chplan->proto_en & CHPLAN_PROTO_EN_AX) ? 1 : 0); +#endif +#ifdef CONFIG_80211AC_VHT + RTW_PRINT_SEL(sel, "ac:%d\n", (chplan->proto_en & CHPLAN_PROTO_EN_AC) ? 1 : 0); +#endif +#if CONFIG_IEEE80211_BAND_5GHZ + RTW_PRINT_SEL(sel, "a:%d\n", (chplan->proto_en & CHPLAN_PROTO_EN_A) ? 1 : 0); +#endif + + if (chplan->channel_plan == RTW_CHPLAN_UNSPECIFIED) + RTW_PRINT_SEL(sel, "chplan:UNSPEC\n"); + else + RTW_PRINT_SEL(sel, "chplan:0x%02X\n", chplan->channel_plan); + +#if CONFIG_IEEE80211_BAND_6GHZ + if (chplan->chplan_6g == RTW_CHPLAN_6G_UNSPECIFIED) + RTW_PRINT_SEL(sel, "chplan_6g:UNSPEC\n"); + else + RTW_PRINT_SEL(sel, "chplan_6g:0x%02X\n", chplan->chplan_6g); + + dump_chplan_envs(sel, chplan); +#endif + +#if CONFIG_TXPWR_LIMIT + dump_chplan_txpwr_lmt_regs(sel, chplan); +#endif + + dump_chplan_edcca_modes(sel, chplan); + +#ifdef CONFIG_DFS_MASTER + RTW_PRINT_SEL(sel, "dfs_domain:%s(%u)\n", rtw_dfs_regd_str(chplan->dfs_domain), chplan->dfs_domain); +#endif + + dump_addl_ch_disable_conf(sel, chplan); + + dump_chinfos(sel, chplan->chs, chplan->chs_len); + + rtw_free_get_chplan_resp(chplan); +} + +#if CONFIG_IEEE80211_BAND_6GHZ +void dump_cur_env(void *sel, struct rf_ctl_t *rfctl) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct get_chplan_resp *chplan; + + if (rtw_get_chplan_cmd(dvobj_get_primary_adapter(dvobj), RTW_CMDF_WAIT_ACK, &chplan) == _FAIL) + return; + + dump_chplan_envs(sel, chplan); + + rtw_free_get_chplan_resp(chplan); +} +#endif +#endif /* CONFIG_PROC_DEBUG */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.h b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.h new file mode 100644 index 00000000..0bcd88cb --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chplan.h @@ -0,0 +1,685 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_CHPLAN_H__ +#define __RTW_CHPLAN_H__ + +#define RTW_CHPLAN_IOCTL_NULL 0xFFFE /* special value by ioctl: null(empty) chplan */ +#define RTW_CHPLAN_IOCTL_UNSPECIFIED 0xFFFF /* special value by ioctl: no change (keep original) */ + +#define RTW_CHPLAN_NULL 0x0A +#define RTW_CHPLAN_WORLDWIDE 0x7F +#define RTW_CHPLAN_UNSPECIFIED 0xFF +#define RTW_CHPLAN_6G_NULL 0x00 +#define RTW_CHPLAN_6G_WORLDWIDE 0x7F +#define RTW_CHPLAN_6G_UNSPECIFIED 0xFF + +u8 rtw_chplan_get_default_regd_2g(u8 id); +#if CONFIG_IEEE80211_BAND_5GHZ +u8 rtw_chplan_get_default_regd_5g(u8 id); +#endif +bool rtw_is_channel_plan_valid(u8 id); + +#if CONFIG_IEEE80211_BAND_6GHZ +u8 rtw_chplan_get_default_regd_6g(u8 id); +bool rtw_is_channel_plan_6g_valid(u8 id); +#endif + +void rtw_rfctl_addl_ch_disable_conf_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty); + +u8 rtw_chplan_is_bchbw_valid(u8 id, u8 id_6g, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive, struct rf_ctl_t *rfctl); + +enum regd_src_t { + REGD_SRC_RTK_PRIV = 0, /* Regulatory settings from Realtek framework (Realtek defined or customized) */ + REGD_SRC_OS = 1, /* Regulatory settings from OS */ + REGD_SRC_NUM, +}; + +#define regd_src_is_valid(src) ((src) < REGD_SRC_NUM) + +extern const char *_regd_src_str[]; +#define regd_src_str(src) ((src) >= REGD_SRC_NUM ? _regd_src_str[REGD_SRC_NUM] : _regd_src_str[src]) + +bool rtw_rfctl_reg_allow_beacon_hint(struct rf_ctl_t *rfctl); +bool rtw_chinfo_allow_beacon_hint(struct _RT_CHANNEL_INFO *chinfo); +u8 rtw_process_beacon_hint(struct rf_ctl_t *rfctl, struct wlan_network *network); +void rtw_beacon_hint_ch_change_notifier(struct rf_ctl_t *rfctl); + +#define ALPHA2_FMT "%c%c" +#define ALPHA2_ARG(a2) ((is_alpha(a2[0]) || is_decimal(a2[0])) ? a2[0] : '-'), ((is_alpha(a2[1]) || is_decimal(a2[1])) ? a2[1] : '-') + +#define WORLDWIDE_ALPHA2 "00" +#define UNSPEC_ALPHA2 "99" +#define INTERSECTED_ALPHA2 "98" + +#define IS_ALPHA2_WORLDWIDE(_alpha2) (strncmp(_alpha2, WORLDWIDE_ALPHA2, 2) == 0) +#define IS_ALPHA2_UNSPEC(_alpha2) (strncmp(_alpha2, UNSPEC_ALPHA2, 2) == 0) +#define IS_ALPHA2_INTERSECTED(_alpha2) (strncmp(_alpha2, INTERSECTED_ALPHA2, 2) == 0) +#define SET_UNSPEC_ALPHA2(_alpha2) do { _rtw_memcpy(_alpha2, UNSPEC_ALPHA2, 2); } while (0) +#define SET_INTERSECTEDC_ALPHA2(_alpha2) do { _rtw_memcpy(_alpha2, INTERSECTED_ALPHA2, 2); } while (0) + +enum rtw_regd_inr { + RTW_REGD_SET_BY_INIT = 0, + RTW_REGD_SET_BY_USER = 1, + RTW_REGD_SET_BY_COUNTRY_IE = 2, + + /* below is not used for REGD_SRC_RTK_PRIV */ + RTW_REGD_SET_BY_DRIVER = 3, + RTW_REGD_SET_BY_CORE = 4, + + RTW_REGD_SET_BY_NUM, +}; + +extern const char *const _regd_inr_str[]; +#define regd_inr_str(inr) (((inr) >= RTW_REGD_SET_BY_NUM) ? _regd_inr_str[RTW_REGD_SET_BY_NUM] : _regd_inr_str[(inr)]) + +enum rtw_regd { + RTW_REGD_NA = 0, + RTW_REGD_FCC = 1, + RTW_REGD_MKK = 2, + RTW_REGD_ETSI = 3, + RTW_REGD_IC = 4, + RTW_REGD_KCC = 5, + RTW_REGD_NCC = 6, + RTW_REGD_ACMA = 7, + RTW_REGD_CHILE = 8, + RTW_REGD_MEX = 9, + RTW_REGD_WW, + RTW_REGD_NUM, +}; + +extern const char *const _regd_str[]; +#define regd_str(regd) (((regd) >= RTW_REGD_NUM) ? _regd_str[RTW_REGD_NA] : _regd_str[(regd)]) + +enum rtw_env_t { + RTW_ENV_ANY = 0, + RTW_ENV_INDOOR = 1, + RTW_ENV_OUTDOOR = 2, + RTW_ENV_NUM, +}; + +extern const char *const _env_str[]; +#define env_str(env) (((env) >= RTW_ENV_NUM) ? _env_str[RTW_ENV_ANY] : _env_str[(env)]) + +enum rtw_edcca_mode_t { + RTW_EDCCA_NORM = 0, /* normal */ + RTW_EDCCA_CS = 1, /* carrier sense */ + RTW_EDCCA_ADAPT = 2, /* adaptivity */ + RTW_EDCCA_CBP = 3, /* contention based protocol */ + RTW_EDCCA_MODE_NUM, + RTW_EDCCA_DEF = RTW_EDCCA_MODE_NUM, /* default (ref to domain code), used at country chplan map's override field */ + RTW_EDCCA_AUTO = 0xFF, /* follow channel plan */ +}; + +extern const char *const _rtw_edcca_mode_str[]; +#define rtw_edcca_mode_str(mode) (((mode) >= RTW_EDCCA_MODE_NUM) ? _rtw_edcca_mode_str[RTW_EDCCA_NORM] : _rtw_edcca_mode_str[(mode)]) + +enum rtw_dfs_regd { + RTW_DFS_REGD_NONE = 0, + RTW_DFS_REGD_FCC = 1, + RTW_DFS_REGD_MKK = 2, + RTW_DFS_REGD_ETSI = 3, + RTW_DFS_REGD_KCC = 4, + RTW_DFS_REGD_NUM, + RTW_DFS_REGD_AUTO = 0xFF, /* follow channel plan */ +}; + +#define RTW_DFS_REGD_IS_UNKNOWN(regd) ((regd) == RTW_DFS_REGD_NONE || (regd) >= RTW_DFS_REGD_NUM) + +extern const char *const _rtw_dfs_regd_str[]; +#define rtw_dfs_regd_str(region) (((region) >= RTW_DFS_REGD_NUM) ? _rtw_dfs_regd_str[RTW_DFS_REGD_NONE] : _rtw_dfs_regd_str[(region)]) + +typedef enum _REGULATION_TXPWR_LMT { + TXPWR_LMT_NONE = 0, /* no limit */ + TXPWR_LMT_FCC = 1, + TXPWR_LMT_MKK = 2, + TXPWR_LMT_ETSI = 3, + TXPWR_LMT_IC = 4, + TXPWR_LMT_KCC = 5, + TXPWR_LMT_NCC = 6, + TXPWR_LMT_ACMA = 7, + TXPWR_LMT_CHILE = 8, + TXPWR_LMT_UKRAINE = 9, + TXPWR_LMT_MEXICO = 10, + TXPWR_LMT_CN = 11, + TXPWR_LMT_QATAR = 12, + TXPWR_LMT_UK = 13, + TXPWR_LMT_THAILAND = 14, + TXPWR_LMT_WW, /* smallest of all available limit, keep last */ + + TXPWR_LMT_NUM, + TXPWR_LMT_DEF = TXPWR_LMT_NUM, /* default (ref to domain code), used at country chplan map's override field */ +} REGULATION_TXPWR_LMT; + +extern const char *const _txpwr_lmt_str[]; +#define txpwr_lmt_str(regd) (((regd) >= TXPWR_LMT_NUM) ? _txpwr_lmt_str[TXPWR_LMT_NUM] : _txpwr_lmt_str[(regd)]) + +extern const REGULATION_TXPWR_LMT _txpwr_lmt_alternate[]; +#define txpwr_lmt_alternate(ori) (((ori) > TXPWR_LMT_NUM) ? _txpwr_lmt_alternate[TXPWR_LMT_WW] : _txpwr_lmt_alternate[(ori)]) + +#define TXPWR_LMT_ALTERNATE_DEFINED(txpwr_lmt) (txpwr_lmt_alternate(txpwr_lmt) != txpwr_lmt) + +#if CONFIG_IEEE80211_BAND_6GHZ +enum txpwr_lmt_6g_cate_t { + TXPWR_LMT_6G_CATE_VLP, + TXPWR_LMT_6G_CATE_LPI, + TXPWR_LMT_6G_CATE_STD, + TXPWR_LMT_6G_CATE_NUM, +}; + +extern const char *const _txpwr_lmt_6g_cate_str[]; +#define txpwr_lmt_6g_cate_str(cate) (((cate) >= TXPWR_LMT_6G_CATE_NUM) ? _txpwr_lmt_6g_cate_str[TXPWR_LMT_6G_CATE_NUM] : _txpwr_lmt_6g_cate_str[(cate)]) + +extern const char *const _txpwr_lmt_6g_str[][TXPWR_LMT_6G_CATE_NUM]; +#define txpwr_lmt_6g_str(regd, cate) (((regd) >= TXPWR_LMT_NUM || (cate) >= TXPWR_LMT_6G_CATE_NUM) ? _txpwr_lmt_str[TXPWR_LMT_NUM] : _txpwr_lmt_6g_str[(regd)][(cate)]) +#endif /* CONFIG_IEEE80211_BAND_6GHZ */ + +extern const enum rtw_edcca_mode_t _rtw_regd_to_edcca_mode[RTW_REGD_NUM]; +#define rtw_regd_to_edcca_mode(regd) (((regd) >= RTW_REGD_NUM) ? RTW_EDCCA_NORM : _rtw_regd_to_edcca_mode[(regd)]) + +#if CONFIG_IEEE80211_BAND_6GHZ +extern const enum rtw_edcca_mode_t _rtw_regd_to_edcca_mode_6g[RTW_REGD_NUM]; +#define rtw_regd_to_edcca_mode_6g(regd) (((regd) >= RTW_REGD_NUM) ? RTW_EDCCA_NORM : _rtw_regd_to_edcca_mode_6g[(regd)]) +#endif + +extern const REGULATION_TXPWR_LMT _rtw_regd_to_txpwr_lmt[]; +#define rtw_regd_to_txpwr_lmt(regd) (((regd) >= RTW_REGD_NUM) ? TXPWR_LMT_WW : _rtw_regd_to_txpwr_lmt[(regd)]) + +#define REGD_INR_BMP_STR_LEN (33) +char *rtw_get_regd_inr_bmp_str(char *buf, u8 bmp); + +#define ENV_BMP_STR_LEN (11) +char *rtw_get_env_bmp_str(char *buf, u8 bmp); + +#define EDCCA_MODE_OF_BANDS_STR_LEN (((6 + 3 + 1) * BAND_MAX) + 1) +char *rtw_get_edcca_mode_of_bands_str(char *buf, u8 mode_of_band[]); +void rtw_edcca_mode_update(struct dvobj_priv *dvobj, bool req_lock); +u8 rtw_get_edcca_mode(struct dvobj_priv *dvobj, enum band_type band); + +#if CONFIG_TXPWR_LIMIT +#define TXPWR_NAME_OF_BANDS_STR_LEN (((1 + 8 + 1) * BAND_MAX) + (4 * CONFIG_IEEE80211_BAND_6GHZ) + 1) +char *rtw_get_txpwr_lmt_name_of_bands_str(char *buf, const char *name_of_band[], u8 unknown_bmp); +void rtw_txpwr_update_cur_lmt_regs(struct dvobj_priv *dvobj, bool req_lock); +#endif + +#define CHPLAN_PROTO_EN_A BIT0 +#define CHPLAN_PROTO_EN_AC BIT1 +#define CHPLAN_PROTO_EN_AX BIT2 +#define CHPLAN_PROTO_EN_BE BIT3 +#define CHPLAN_PROTO_EN_ALL 0xFF + +#if defined(CONFIG_80211BE_EHT) || defined(CONFIG_80211AX_HE) || defined(CONFIG_80211AC_VHT) || CONFIG_IEEE80211_BAND_5GHZ +#define CONFIG_CHPLAN_PROTO_EN +#endif + +#define CHPLAN_6G_CATE_VLP BIT0 +#define CHPLAN_6G_CATE_LPI BIT1 +#define CHPLAN_6G_CATE_STD BIT2 + +struct country_chplan { + char alpha2[2]; + + u8 domain_code; +#if CONFIG_IEEE80211_BAND_6GHZ + u8 domain_code_6g; +#endif + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE + /* will override edcca mode get by domain code (/6g) */ + u8 edcca_2g_override:3; + #if CONFIG_IEEE80211_BAND_5GHZ + u8 edcca_5g_override:3; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + u8 edcca_6g_override:3; + #endif +#endif + + /* will override txpwr_lmt get by domain code (/6g) */ + u8 txpwr_lmt_override; + +#ifdef CONFIG_CHPLAN_PROTO_EN + u8 proto_en; +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + u8 cate_6g_map; +#endif +}; + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_2G_OVERRIDE(_val) , .edcca_2g_override = (_val) +#else +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_2G_OVERRIDE(_val) +#endif + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE && CONFIG_IEEE80211_BAND_5GHZ +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_5G_OVERRIDE(_val) , .edcca_5g_override = (_val) +#else +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_5G_OVERRIDE(_val) +#endif + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE && CONFIG_IEEE80211_BAND_6GHZ +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_6G_OVERRIDE(_val) , .edcca_6g_override = (_val) +#else +#define COUNTRY_CHPLAN_ASSIGN_EDCCA_6G_OVERRIDE(_val) +#endif + +#define CHPLAN_6G_CATE_MAP____ 0 +#define CHPLAN_6G_CATE_MAP___V CHPLAN_6G_CATE_VLP +#define CHPLAN_6G_CATE_MAP__I_ CHPLAN_6G_CATE_LPI +#define CHPLAN_6G_CATE_MAP__IV (CHPLAN_6G_CATE_LPI | CHPLAN_6G_CATE_VLP) +#define CHPLAN_6G_CATE_MAP_S__ CHPLAN_6G_CATE_STD +#define CHPLAN_6G_CATE_MAP_S_V (CHPLAN_6G_CATE_STD | CHPLAN_6G_CATE_VLP) +#define CHPLAN_6G_CATE_MAP_SI_ (CHPLAN_6G_CATE_STD | CHPLAN_6G_CATE_LPI) +#define CHPLAN_6G_CATE_MAP_SIV (CHPLAN_6G_CATE_STD | CHPLAN_6G_CATE_LPI | CHPLAN_6G_CATE_VLP) + +#if CONFIG_IEEE80211_BAND_6GHZ +#define COUNTRY_CHPLAN_ASSIGN_CHPLAN_6G(_val) , .domain_code_6g = (_val) +#define COUNTRY_CHPLAN_ASSIGN_6G_CATE_MAP(_val) , .cate_6g_map = CHPLAN_6G_CATE_MAP_##_val +#else +#define COUNTRY_CHPLAN_ASSIGN_CHPLAN_6G(_val) +#define COUNTRY_CHPLAN_ASSIGN_6G_CATE_MAP(_val) +#endif + +#ifdef CONFIG_CHPLAN_PROTO_EN +#define COUNTRY_CHPLAN_ASSIGN_PROTO_EN(_val) , .proto_en = (_val) +#else +#define COUNTRY_CHPLAN_ASSIGN_PROTO_EN(_val) +#endif + +#define COUNTRY_CHPLAN_ENT_ARGC_9(_alpha2, _chplan, _chplan_6g, _txpwr_lmt_override, _en_11be, _en_11ax, _en_11ac, _en_11a, _cate_6g_map) \ + { \ + .alpha2 = (_alpha2), .domain_code = (_chplan) \ + COUNTRY_CHPLAN_ASSIGN_CHPLAN_6G(_chplan_6g) \ + COUNTRY_CHPLAN_ASSIGN_EDCCA_2G_OVERRIDE(RTW_EDCCA_DEF) \ + COUNTRY_CHPLAN_ASSIGN_EDCCA_5G_OVERRIDE(RTW_EDCCA_DEF) \ + COUNTRY_CHPLAN_ASSIGN_EDCCA_6G_OVERRIDE(RTW_EDCCA_DEF) \ + , .txpwr_lmt_override = TXPWR_LMT_##_txpwr_lmt_override \ + COUNTRY_CHPLAN_ASSIGN_PROTO_EN( \ + (_en_11be ? CHPLAN_PROTO_EN_BE : 0) | (_en_11ax ? CHPLAN_PROTO_EN_AX : 0) \ + | (_en_11ac ? CHPLAN_PROTO_EN_AC : 0) | (_en_11a ? CHPLAN_PROTO_EN_A : 0)) \ + COUNTRY_CHPLAN_ASSIGN_6G_CATE_MAP(_cate_6g_map) \ + } + +#define COUNTRY_CHPLAN_ENT_ARGC_7(_alpha2, _chplan, _chplan_6g, _txpwr_lmt_override, _en_11ax, _en_11ac, _en_11a) \ + COUNTRY_CHPLAN_ENT_ARGC_9(_alpha2, _chplan, _chplan_6g, _txpwr_lmt_override, 0, _en_11ax, _en_11ac, _en_11a, ___) + +#define __COUNTRY_CHPLAN_ENT_HDL(argc9, argc8, argc7, argc6, argc5, argc4, argc3, argc2, argc1, hdl, ...) hdl + +#define COUNTRY_CHPLAN_ENT(...) \ + __COUNTRY_CHPLAN_ENT_HDL(__VA_ARGS__, \ + COUNTRY_CHPLAN_ENT_ARGC_9, \ + macro_argc8, \ + COUNTRY_CHPLAN_ENT_ARGC_7, \ + macro_argc6, \ + macro_argc5, \ + macro_argc4, \ + macro_argc3, \ + macro_argc2, \ + macro_argc1) \ + (__VA_ARGS__) + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE +#define COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(_ent) (_ent)->edcca_2g_override +#else +#define COUNTRY_CHPLAN_EDCCA_2G_OVERRIDE(_ent) RTW_EDCCA_DEF +#endif + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE && CONFIG_IEEE80211_BAND_5GHZ +#define COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(_ent) (_ent)->edcca_5g_override +#else +#define COUNTRY_CHPLAN_EDCCA_5G_OVERRIDE(_ent) RTW_EDCCA_DEF +#endif + +#if CONFIG_COUNTRY_CHPLAN_EDCCA_OVERRIDE && CONFIG_IEEE80211_BAND_6GHZ +#define COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(_ent) (_ent)->edcca_6g_override +#else +#define COUNTRY_CHPLAN_EDCCA_6G_OVERRIDE(_ent) RTW_EDCCA_DEF +#endif + +#if CONFIG_IEEE80211_BAND_5GHZ +#define COUNTRY_CHPLAN_EN_11A(_ent) (((_ent)->proto_en & CHPLAN_PROTO_EN_A) ? true : false) +#else +#define COUNTRY_CHPLAN_EN_11A(_ent) false +#endif + +#ifdef CONFIG_80211AC_VHT +#define COUNTRY_CHPLAN_EN_11AC(_ent) (((_ent)->proto_en & CHPLAN_PROTO_EN_AC) ? true : false) +#else +#define COUNTRY_CHPLAN_EN_11AC(_ent) false +#endif + +#ifdef CONFIG_80211AX_HE +#define COUNTRY_CHPLAN_EN_11AX(_ent) (((_ent)->proto_en & CHPLAN_PROTO_EN_AX) ? true : false) +#else +#define COUNTRY_CHPLAN_EN_11AX(_ent) false +#endif + +#ifdef CONFIG_80211BE_EHT +#define COUNTRY_CHPLAN_EN_11BE(_ent) (((_ent)->proto_en & CHPLAN_PROTO_EN_BE) ? true : false) +#else +#define COUNTRY_CHPLAN_EN_11BE(_ent) false +#endif + +void rtw_get_chplan_worldwide(struct country_chplan *ent); +bool rtw_get_chplan_from_country(const char *country_code, struct country_chplan *ent); + +void rtw_chplan_ioctl_input_mapping(u16 *chplan, u16 *chplan_6g); +bool rtw_chplan_ids_is_world_wide(u8 chplan, u8 chplan_6g); + +u8 rtw_country_chplan_is_bchbw_valid(struct country_chplan *ent, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive, struct rf_ctl_t *rfctl); + +enum country_ie_slave_en_mode { + CISEM_DISABLE = 0, /* disable */ + CISEM_ENABLE = 1, /* enable */ + CISEM_ENABLE_WW = 2, /* enable when INIT/USER set world wide mode */ + CISEM_NUM, +}; + +#define CIS_EN_MODE_IS_VALID(mode) ((mode) < CISEM_NUM) + +enum country_ie_slave_flags { + _CISF_RSVD_0 = BIT0, /* deprecated BIT0 */ + CISF_ENV_BSS = BIT1, /* if not set, consider IEs of associated BSSs only */ + + CISF_VALIDS = CISF_ENV_BSS, +}; + +enum country_ie_slave_6g_reg_info { + CIS_6G_REG_IN_AP = 0, + CIS_6G_REG_SP_AP = 1, + CIS_6G_REG_VLP_AP = 2, + CIS_6G_REG_IN_EN_AP = 3, + CIS_6G_REG_IN_SP_AP = 4, + CIS_6G_REG_NUM, + CIS_6G_REG_RSVD = CIS_6G_REG_NUM, +}; + +#define IS_6G_REG_INFO_RSVD(reg) ((reg) >= CIS_6G_REG_NUM) + +enum country_ie_slave_status { + COUNTRY_IE_SLAVE_NOCOUNTRY = 0, /* no country IE or 'XX' alpha2 */ + COUNTRY_IE_SLAVE_APPLICABLE = 1, + COUNTRY_IE_SLAVE_UNKNOWN = 2, /* unknown country */ + COUNTRY_IE_SLAVE_OPCH_NOEXIST = 3, /* bss's op ch not exist */ + COUNTRY_IE_SLAVE_CATE_6G_NS = 4, /* 6G category not support */ + + COUNTRY_IE_SLAVE_STATUS_NUM, +}; + +struct country_ie_slave_record { + char alpha2[2]; /* country code get from connected AP of STA ifaces, "\x00\x00" is not set */ + enum band_type band; + u8 opch; +#if CONFIG_IEEE80211_BAND_6GHZ + enum rtw_env_t env; + enum country_ie_slave_6g_reg_info reg_info; +#endif + enum country_ie_slave_status status; + struct country_chplan chplan; +}; + +#ifdef CONFIG_80211D +extern const char _rtw_env_char[]; +#define rtw_env_char(e) (((e) >= RTW_ENV_NUM) ? _rtw_env_char[RTW_ENV_ANY] : _rtw_env_char[e]) + +void dump_country_ie_slave_records(void *sel, struct rf_ctl_t *rfctl, bool skip_noset); +#endif + +void dump_country_chplan(void *sel, const struct country_chplan *ent, bool regd_info); +void dump_country_chplan_map(void *sel, bool regd_info); +void dump_country_list(void *sel); +void dump_chplan_id_list(void *sel); +void dump_chplan_country_list(void *sel); +#if CONFIG_IEEE80211_BAND_6GHZ +void dump_chplan_6g_id_list(void *sel); +void dump_chplan_6g_country_list(void *sel); +#endif +#ifdef CONFIG_RTW_DEBUG +void dump_chplan_test(void *sel); +#endif +void dump_chplan_ver(void *sel); + +struct regd_req_t { + _list list; + int ref_cnt; /* used by RTK_PRIV's COUNTRY_IE req */ + bool applied; + + enum regd_src_t src; + enum rtw_regd_inr inr; +#if CONFIG_IEEE80211_BAND_6GHZ + enum rtw_env_t env; + enum country_ie_slave_6g_reg_info reg_info; + u8 txpwr_lmt_6g_cate_map; +#endif + + struct country_chplan chplan; +}; + +void rtw_regd_req_list_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty); +void rtw_regd_req_list_free(struct rf_ctl_t *rfctl); + +void rtw_regd_watchdog_hdl(struct dvobj_priv *dvobj); + +struct _ADAPTER_LINK; +enum channel_width alink_adjust_linking_bw_by_regd(struct _ADAPTER_LINK *alink + , enum band_type band, u8 ch, enum channel_width bw, enum chan_offset offset); +enum channel_width adapter_adjust_linking_bw_by_regd(_adapter *adapter + , enum band_type band, u8 ch, enum channel_width bw, enum chan_offset offset); + +void rtw_rfctl_decide_init_chplan(struct rf_ctl_t *rfctl, + const char *hw_alpha2, u8 hw_chplan, u8 hw_chplan_6g, u8 hw_force_chplan); +void rtw_rfctl_apply_init_chplan(struct rf_ctl_t *rfctl, bool req_lock); + +bool rtw_rfctl_is_disable_sw_channel_plan(struct dvobj_priv *dvobj); + +#define alink_regu_block_tx(alink) (LINK_MLME_IS_REGU_FORBID(alink) || alink_is_tx_blocked_by_ch_waiting(alink)) +#define adapter_regu_block_tx(adapter) alink_regu_block_tx(GET_PRIMARY_LINK(adapter)) + +#if defined(CONFIG_AP_MODE) && CONFIG_AP_REGU_FORBID +bool rtw_rfctl_is_regu_forbid_bss(struct rf_ctl_t *rfctl, enum band_type band); +#else +#define rtw_rfctl_is_regu_forbid_bss(rfctl, band) false +#endif + +enum chplan_confs_type { + CHPLAN_CONFS_DIS_CH_FLAGS, + CHPLAN_CONFS_EXCL_CHS, + CHPLAN_CONFS_EXCL_CHS_6G, + CHPLAN_CONFS_INIT_REGD_ALWAYS_APPLY, + CHPLAN_CONFS_USER_REGD_ALWAYS_APPLY, + CHPLAN_CONFS_BCN_HINT_VALID_MS, + CHPLAN_CONFS_CIS_EN_MODE, + CHPLAN_CONFS_CIS_FLAGS, + CHPLAN_CONFS_CIS_EN_ROLE, + CHPLAN_CONFS_CIS_EN_IFBMP, + CHPLAN_CONFS_CIS_SCAN_INT_MS, + CHPLAN_CONFS_NUM, +}; + +struct chplan_confs { + u16 set_types; /* bitmap of chplan_confs_type */ + u8 dis_ch_flags; + u8 excl_chs[MAX_CHANNEL_NUM_2G_5G]; +#if CONFIG_IEEE80211_BAND_6GHZ + u8 excl_chs_6g[MAX_CHANNEL_NUM_6G]; +#endif + bool init_regd_always_apply; + bool user_regd_always_apply; + u32 bcn_hint_valid_ms; +#ifdef CONFIG_80211D + u8 cis_en_mode; + u8 cis_flags; + u8 cis_en_role; + u8 cis_en_ifbmp; + u32 cis_scan_int_ms; +#endif +}; + +struct SetChannelPlan_param { + enum regd_src_t regd_src; + enum rtw_regd_inr inr; + struct country_chplan country_ent; + bool has_country; + u8 channel_plan; +#if CONFIG_IEEE80211_BAND_6GHZ + u8 channel_plan_6g; + enum rtw_env_t env; +#endif + /* used for regd_src == RTK_PRIV and inr == USER, bitmap of RTW_PRIV_USER_SET_XXX */ + u8 priv_user_set_bmp; + +#ifdef CONFIG_80211D + /* used for regd_src == RTK_PRIV and inr == COUNTRY_IE */ + struct country_ie_slave_record cisr; + u8 cisr_alink_id; + bool has_cisr; +#endif + + struct chplan_confs confs; + +#ifdef PLATFORM_LINUX + bool rtnl_lock_needed; +#endif +}; + +u8 rtw_set_chplan_hdl(_adapter *adapter, u8 *pbuf); + +u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 chplan_6g + , enum rtw_env_t env, enum rtw_regd_inr inr); +u8 rtw_set_country_cmd(_adapter *adapter, int flags, const char *country_code + , enum rtw_env_t env, enum rtw_regd_inr inr); +#if CONFIG_IEEE80211_BAND_6GHZ +u8 rtw_set_env_cmd(_adapter *adapter, int flags, enum rtw_env_t env + , enum regd_src_t regd_src, enum rtw_regd_inr inr); +#endif +#ifdef CONFIG_80211D +u8 rtw_alink_apply_recv_regu_ies_cmd(struct _ADAPTER_LINK *alink, int flags, enum band_type band,u8 opch + , const u8 *country_ie, enum country_ie_slave_6g_reg_info reg_info); +u8 rtw_apply_recv_regu_ies_cmd(_adapter *adapter, int flags, enum band_type band,u8 opch + , const u8 *country_ie, enum country_ie_slave_6g_reg_info reg_info); +u8 rtw_apply_scan_network_country_ie_cmd(_adapter *adapter, int flags); +#endif +#ifdef CONFIG_REGD_SRC_FROM_OS +u8 rtw_sync_os_regd_cmd(_adapter *adapter, int flags, const char *country_code + , u8 dfs_region, enum rtw_env_t env, enum rtw_regd_inr inr); +#endif +u8 rtw_set_chplan_confs_cmd(_adapter *adapter, int flags, struct chplan_confs *confs); +#ifdef CONFIG_PROC_DEBUG +u16 rtw_parse_chplan_confs_cmd_str(struct chplan_confs *confs, char *str); +#endif + +struct get_chplan_resp { + enum regd_src_t regd_src; + u8 regd_inr_bmp; + char alpha2[2]; + u8 channel_plan; +#if CONFIG_IEEE80211_BAND_6GHZ + u8 chplan_6g; + u8 env_bmp; +#endif + +#if CONFIG_TXPWR_LIMIT + /* point to content of txpwr_lmt_names of specific band (after content of chset) */ + const char *txpwr_lmt_names[BAND_MAX]; + int txpwr_lmt_names_len[BAND_MAX]; + int txpwr_lmt_names_len_total; /* ease for free operation */ +#endif + u8 edcca_mode_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 edcca_mode_5g; +#endif +#if CONFIG_IEEE80211_BAND_6GHZ + u8 edcca_mode_6g; +#endif +#ifdef CONFIG_DFS_MASTER + u8 dfs_domain; +#endif + u8 proto_en; + + struct chplan_confs confs; + + u8 chs_len; + RT_CHANNEL_INFO chs[0]; +}; + +struct get_channel_plan_param { + struct get_chplan_resp *chplan; +}; + +u8 rtw_get_chplan_hdl(_adapter *adapter, u8 *pbuf); +struct cmd_obj; +void rtw_get_chplan_callback(_adapter *adapter, struct cmd_obj *cmdobj); + +u8 rtw_get_chplan_cmd(_adapter *adapter, int flags, struct get_chplan_resp **chplan); +void rtw_free_get_chplan_resp(struct get_chplan_resp *chplan); + +bool rtw_network_chk_opch_status(struct rf_ctl_t *rfctl, struct wlan_network *network); + +#ifdef CONFIG_80211D +void rtw_alink_joinbss_update_regulatory(struct _ADAPTER_LINK *alink, const WLAN_BSSID_EX *network); +void rtw_alink_leavebss_update_regulatory(struct _ADAPTER_LINK * alink); +void rtw_alink_csa_update_regulatory(struct _ADAPTER_LINK *alink, enum band_type req_band, u8 req_ch); +void alink_process_regu_ies(struct _ADAPTER_LINK *alink, u8 *ies, uint ies_len); + +void rtw_joinbss_update_regulatory(_adapter *adapter, const WLAN_BSSID_EX *network); +void rtw_leavebss_update_regulatory(_adapter *adapter); +void rtw_csa_update_regulatory(_adapter *adapter, enum band_type req_band, u8 req_ch); +void process_regu_ies(_adapter *adapter, u8 *ies, uint ies_len); + +bool rtw_update_scanned_network_cisr(struct rf_ctl_t *rfctl, struct wlan_network *network); +bool rtw_network_chk_regu_ies(struct rf_ctl_t *rfctl, struct wlan_network *network); + +void rtw_rfctl_cis_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty); +void rtw_rfctl_cis_deinit(struct rf_ctl_t *rfctl); +#else +#define rtw_network_chk_regu_ies(rfctl, network) true +#endif /* CONFIG_80211D */ + +#ifdef CONFIG_PROC_DEBUG +void dump_cur_chplan_confs(void *sel, struct rf_ctl_t *rfctl); +void dump_cur_country(void *sel, struct rf_ctl_t *rfctl); +void dump_cur_chplan(void *sel, struct rf_ctl_t *rfctl); +#if CONFIG_IEEE80211_BAND_6GHZ +void dump_cur_env(void *sel, struct rf_ctl_t *rfctl); +#endif +#endif /* CONFIG_PROC_DEBUG */ + +#define CHPLAN_VER_STR_BUF_LEN 64 + +struct rtw_regdb_ops { + u8 (*get_default_regd_2g)(u8 id); +#if CONFIG_IEEE80211_BAND_5GHZ + u8 (*get_default_regd_5g)(u8 id); +#endif + bool (*is_domain_code_valid)(u8 id); + bool (*domain_get_ch)(u8 id, u32 ch, u8 *flags); +#if CONFIG_IEEE80211_BAND_6GHZ + u8 (*get_default_regd_6g)(u8 id); + bool (*is_domain_code_6g_valid)(u8 id); + bool (*domain_6g_get_ch)(u8 id, u32 ch, u8 *flags); +#endif + + bool (*get_chplan_from_alpha2)(const char *alpha2, struct country_chplan *ent); + +#ifdef CONFIG_RTW_DEBUG + void (*dump_chplan_test)(void *sel); +#endif + void (*get_ver_str)(char *buf, size_t buf_len); +}; + +#endif /* __RTW_CHPLAN_H__ */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.c new file mode 100644 index 00000000..2cd409f4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.c @@ -0,0 +1,382 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_CHSET_C_ + +#include + +const char *const _rtw_ch_type_str[] = { + [RTW_CHT_DIS] = "DIS", + [RTW_CHT_NO_IR] = "NO_IR", + [RTW_CHT_DFS] = "DFS", + [RTW_CHT_NO_HT40U] = "NO_40M+", + [RTW_CHT_NO_HT40L] = "NO_40M-", + [RTW_CHT_NO_80MHZ] = "NO_80M", + [RTW_CHT_NO_160MHZ] = "NO_160M", + [RTW_CHT_NUM] = "UNKNOWN", +}; + +enum rtw_ch_type get_ch_type_from_str(const char *str, size_t str_len) +{ + u8 i; + + for (i = 0; i < RTW_CHT_NUM; i++) + if (str_len == strlen(rtw_ch_type_str(i)) + && strncmp(str, rtw_ch_type_str(i), str_len) == 0) + return i; + return RTW_CHT_NUM; +} + +char *rtw_get_ch_flags_str(char *buf, u8 flags, char delim) +{ + char *pos = buf; + char d_str[2] = {delim, '\0'}; + int i; + + for (i = 0; i < RTW_CHT_NUM; i++) { + if (!(flags & BIT(i))) + continue; + pos += snprintf(pos, RTW_CH_FLAGS_STR_LEN - (pos - buf), "%s%s" + , pos == buf ? "" : d_str, rtw_ch_type_str(i)); + if (pos >= buf + RTW_CH_FLAGS_STR_LEN - 1) + break; + } + if (pos == buf) + *buf = '\0'; + + return buf; +} + +int rtw_chset_init(struct rtw_chset *chset, u8 band_bmp) +{ + u8 ch_num = 0; + int band, i; + + _rtw_memset(chset->chs, 0, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); + + for (band = 0; band < BAND_MAX; band++) { + u8 center_ch_num; + u8 (*center_chs)(u8, u8); + + if (!(band_bmp & band_to_band_cap(band))) + continue; + + center_ch_num = center_chs_num_of_band[band](CHANNEL_WIDTH_20); + center_chs = center_chs_of_band[band]; + + chset->chs_of_band[band] = &chset->chs[ch_num]; + chset->chs_len_of_band[band] = 0; + + for (i = 0; i < center_ch_num; i++) { + chset->chs[ch_num].band = band; + chset->chs[ch_num].ChannelNum = center_chs(CHANNEL_WIDTH_20, i); + chset->chs_len_of_band[band]++;; + ch_num++; + } + } + + chset->chs_len = ch_num; + + return _SUCCESS; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +/* + * Search enabled channel with the @param ch in given @param ch_set + * @ch_set: the given channel set + * @ch: the given channel number + * + * return the index of channel_num in channel_set, -1 if not found + */ +RTW_FUNC_2G_5G_ONLY static int _rtw_chset_search_ch(const struct rtw_chset *chset, u32 ch, bool include_dis) +{ + int i; + + if (ch == 0) + return -1; + + for (i = 0; i < chset->chs_len; i++) { + if (ch == chset->chs[i].ChannelNum + && (include_dis || !(chset->chs[i].flags & RTW_CHF_DIS))) + return i; + } + + return -1; +} + +RTW_FUNC_2G_5G_ONLY int rtw_chset_search_ch(const struct rtw_chset *chset, u32 ch) +{ + return _rtw_chset_search_ch(chset, ch, false); +} +#endif + +/* + * Search enabled channel with the @param ch of @param band in given @param ch_set + * @ch_set: the given channel set + * @band: the given band + * @ch: the given channel number + * + * return the index of channel_num in channel_set, -1 if not found + */ +static int _rtw_chset_search_bch(const struct rtw_chset *chset, enum band_type band, u32 ch, bool include_dis) +{ + int i; + + if (ch == 0) + return -1; + + for (i = 0; i < chset->chs_len; i++) { + if (band == chset->chs[i].band && ch == chset->chs[i].ChannelNum + && (include_dis || !(chset->chs[i].flags & RTW_CHF_DIS))) + return i; + } + + return -1; +} + +int rtw_chset_search_bch(const struct rtw_chset *chset, enum band_type band, u32 ch) +{ + return _rtw_chset_search_bch(chset, band, ch, false); +} + +RT_CHANNEL_INFO *rtw_chset_get_chinfo_by_bch(struct rtw_chset *chset, enum band_type band, u32 ch, bool include_dis) +{ + int i = _rtw_chset_search_bch(chset, band, ch, include_dis); + + return i >= 0 ? &chset->chs[i] : NULL; +} + +/* + * Check if the @param ch, bw, offset is valid for the given @param ch_set + * @ch_set: the given channel set + * @ch: the given channel number + * @bw: the given bandwidth + * @offset: the given channel offset + * + * return valid (1) or not (0) + */ +static u8 _rtw_chset_is_bchbw_valid(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive) +{ + u8 cch; + u8 *op_chs; + u8 op_ch_num; + u8 valid = 0; + int i; + int ch_idx; + + cch = rtw_get_center_ch_by_band(band, ch, bw, offset); + + if (!rtw_get_op_chs_by_bcch_bw(band, cch, bw, &op_chs, &op_ch_num)) + goto exit; + + for (i = 0; i < op_ch_num; i++) { + if (0) + RTW_INFO("%u,%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", band, ch, bw, offset, cch, bw, *(op_chs + i)); + ch_idx = rtw_chset_search_bch(chset, band, *(op_chs + i)); + if (ch_idx == -1) + break; + if (!allow_passive && chset->chs[ch_idx].flags & RTW_CHF_NO_IR) { + /* all sub chs are passive is not allowed and one of sub ch is NO_IR */ + if (!allow_primary_passive) /* even primary ch is not allow to be NO_IR */ + break; + if (chset->chs[ch_idx].ChannelNum != ch) /* allow primary ch NO_IR, but this is not primary ch */ + break; + } + if (bw >= CHANNEL_WIDTH_40) { + if ((chset->chs[ch_idx].flags & RTW_CHF_NO_HT40U) && i % 2 == 0) + break; + if ((chset->chs[ch_idx].flags & RTW_CHF_NO_HT40L) && i % 2 == 1) + break; + } + if (bw >= CHANNEL_WIDTH_80 && (chset->chs[ch_idx].flags & RTW_CHF_NO_80MHZ)) + break; + if (bw >= CHANNEL_WIDTH_160 && (chset->chs[ch_idx].flags & RTW_CHF_NO_160MHZ)) + break; + } + + if (op_ch_num != 0 && i == op_ch_num) + valid = 1; + +exit: + return valid; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +RTW_FUNC_2G_5G_ONLY u8 rtw_chset_is_chbw_valid(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset, bool allow_primary_passive, bool allow_passive) +{ + return _rtw_chset_is_bchbw_valid(chset, rtw_is_2g_ch(ch) ? BAND_ON_24G : BAND_ON_5G, ch, bw, offset, allow_primary_passive, allow_passive); +} +#endif + +u8 rtw_chset_is_bchbw_valid(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive) +{ + return _rtw_chset_is_bchbw_valid(chset, band, ch, bw, offset, allow_primary_passive, allow_passive); +} + +/** + * rtw_chset_sync_bchbw - obey g_ch, adjust g_bw, g_offset, bw, offset to fit in channel plan + * @ch_set: channel plan to check + * @req_ch: pointer of the request ch, may be modified further + * @req_bw: pointer of the request bw, may be modified further + * @req_offset: pointer of the request offset, may be modified further + * @g_ch: pointer of the ongoing group ch + * @g_bw: pointer of the ongoing group bw, may be modified further + * @g_offset: pointer of the ongoing group offset, may be modified further + * @allow_primary_passive: if allow passive primary ch when deciding chbw + * @allow_passive: if allow passive ch (not primary) when deciding chbw + */ +void rtw_chset_sync_bchbw(const struct rtw_chset *chset, enum band_type *req_band, u8 *req_ch, u8 *req_bw, u8 *req_offset + , enum band_type *g_band, u8 *g_ch, u8 *g_bw, u8 *g_offset, bool allow_primary_passive, bool allow_passive) +{ + enum band_type r_band; + u8 r_ch, r_bw, r_offset; + enum band_type u_band; + u8 u_ch, u_bw, u_offset; + u8 cur_bw = *req_bw; + + while (1) { + r_band = *req_band; + r_ch = *req_ch; + r_bw = cur_bw; + r_offset = *req_offset; + u_band = *g_band; + u_ch = *g_ch; + u_bw = *g_bw; + u_offset = *g_offset; + + rtw_sync_bchbw(&r_band, &r_ch, &r_bw, &r_offset, &u_band, &u_ch, &u_bw, &u_offset); + + if (rtw_chset_is_bchbw_valid(chset, r_band, r_ch, r_bw, r_offset, allow_primary_passive, allow_passive)) + break; + if (cur_bw == CHANNEL_WIDTH_20) { + rtw_warn_on(1); + break; + } + cur_bw--; + }; + + *req_band = r_band; + *req_ch = r_ch; + *req_bw = r_bw; + *req_offset = r_offset; + *g_band = u_band; + *g_ch = u_ch; + *g_bw = u_bw; + *g_offset = u_offset; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +RTW_FUNC_2G_5G_ONLY void rtw_chset_sync_chbw(const struct rtw_chset *chset, u8 *req_ch, u8 *req_bw, u8 *req_offset + , u8 *g_ch, u8 *g_bw, u8 *g_offset, bool allow_primary_passive, bool allow_passive) +{ + enum band_type band = rtw_is_2g_ch(*g_ch) ? BAND_ON_24G : BAND_ON_5G; /* follow g_ch's band */ + + rtw_chset_sync_bchbw(chset, &band, req_ch, req_bw, req_offset, &band, g_ch, g_bw, g_offset, allow_primary_passive, allow_passive); +} +#endif + +u8 *rtw_chset_set_spt_chs_ie(struct rtw_chset *chset, u8 *buf_pos, uint *buf_len) +{ + u8 i = 0; + u8 fch = 0, lch = 0, ch; + u8 *cont = buf_pos + 2; + RT_CHANNEL_INFO *chinfo; + + while (i < chset->chs_len) { + chinfo = &chset->chs[i++]; + + if (chinfo->flags & RTW_CHF_DIS) + continue; + + #if CONFIG_IEEE80211_BAND_6GHZ + /* don't appnd 6G chs now, how to distinguish 2G/5G chs with 6G? */ + if (chinfo->band == BAND_ON_6G) + continue; + #endif + + ch = chinfo->ChannelNum; + if (fch == 0) { + fch = ch; + lch = ch; + continue; + } + + if (lch + 1 != ch) { + *cont = fch; + *(cont + 1) = lch - fch + 1; + cont += 2; + fch = ch; + } + lch = ch; + } + if (fch) { + /* last subband */ + *cont = fch; + *(cont + 1) = lch - fch + 1; + cont += 2; + } + + if (cont > buf_pos + 2) { + *buf_pos = WLAN_EID_SUPPORTED_CHANNELS; + *(buf_pos + 1) = cont - buf_pos - 2; + *buf_len += cont - buf_pos; + return cont; + } + return buf_pos; +} + +#ifdef CONFIG_PROC_DEBUG +void dump_chinfos(void *sel, const RT_CHANNEL_INFO *chinfos, u8 chinfo_num) +{ + u32 bhint_sec; + char bhint_buf[8]; + u16 non_ocp_sec; + char non_ocp_buf[8]; + char flags_buf[RTW_CH_FLAGS_STR_LEN]; + u8 enable_ch_num = 0; + u8 i; + + RTW_PRINT_SEL(sel, "%-3s %-4s %-5s %-4s flags\n", "ch", "freq", "bhint", "nocp"); + + for (i = 0; i < chinfo_num; i++) { + if (chinfos[i].flags & RTW_CHF_DIS) + continue; + enable_ch_num++; + + bhint_sec = 0; + if (CH_IS_BCN_HINT(&chinfos[i])) { + bhint_sec = rtw_systime_to_ms(chinfos[i].bcn_hint_end_time - rtw_get_current_time()) / 1000; + if (bhint_sec > 99999) + bhint_sec = 99999; + } + snprintf(bhint_buf, 8, "%d", bhint_sec); + + non_ocp_sec = 0; + #ifdef CONFIG_DFS_MASTER + if (CH_IS_NON_OCP(&chinfos[i])) + non_ocp_sec = rtw_systime_to_ms(chinfos[i].non_ocp_end_time - rtw_get_current_time()) / 1000; + #endif + snprintf(non_ocp_buf, 8, "%d", non_ocp_sec); + + RTW_PRINT_SEL(sel, "%3u %4u %5s %4s %s\n" + , chinfos[i].ChannelNum, rtw_bch2freq(chinfos[i].band, chinfos[i].ChannelNum) + , bhint_buf, non_ocp_buf, rtw_get_ch_flags_str(flags_buf, chinfos[i].flags, ' ') + ); + } + + RTW_PRINT_SEL(sel, "total ch number:%d\n", enable_ch_num); +} +#endif /* CONFIG_PROC_DEBUG */ \ No newline at end of file diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.h b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.h new file mode 100644 index 00000000..1e253b07 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_chset.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_CHSET_H__ +#define __RTW_CHSET_H__ + +enum rtw_ch_type { + RTW_CHT_DIS = 0, + RTW_CHT_NO_IR = 1, + RTW_CHT_DFS = 2, + RTW_CHT_NO_HT40U = 3, + RTW_CHT_NO_HT40L = 4, + RTW_CHT_NO_80MHZ = 5, + RTW_CHT_NO_160MHZ = 6, + RTW_CHT_NUM, +}; + +extern const char *const _rtw_ch_type_str[]; +#define rtw_ch_type_str(type) (((type) >= RTW_CHT_NUM) ? _rtw_ch_type_str[RTW_CHT_NUM] : _rtw_ch_type_str[(type)]) + +enum rtw_ch_type get_ch_type_from_str(const char *str, size_t str_len); + +enum { + RTW_CHF_DIS = BIT(RTW_CHT_DIS), + RTW_CHF_NO_IR = BIT(RTW_CHT_NO_IR), + RTW_CHF_DFS = BIT(RTW_CHT_DFS), + RTW_CHF_NO_HT40U = BIT(RTW_CHT_NO_HT40U), + RTW_CHF_NO_HT40L = BIT(RTW_CHT_NO_HT40L), + RTW_CHF_NO_80MHZ = BIT(RTW_CHT_NO_80MHZ), + RTW_CHF_NO_160MHZ = BIT(RTW_CHT_NO_160MHZ), +}; + +#define RTW_CH_FLAGS_STR_LEN (45) +char *rtw_get_ch_flags_str(char *buf, u8 flags, char delim); + +/* The channel information about this channel including joining, scanning, and power constraints. */ +typedef struct _RT_CHANNEL_INFO { + u8 band; /* enum band_type */ + u8 ChannelNum; /* The channel number. */ + + /* + * Bitmap and its usage: + * RTW_CHF_DIS, RTW_CHF_NO_IR, RTW_CHF_DFS: is used to check for status + * RTW_CHF_NO_HT40U, RTW_CHF_NO_HT40L, RTW_CHF_NO_80MHZ, RTW_CHF_NO_160MHZ: extra bandwidth limitation (ex: from regulatory) + */ + u8 flags; + + bool reg_no_ir; + systime bcn_hint_end_time; + +#ifdef CONFIG_FIND_BEST_CHANNEL + u32 rx_count; +#endif + +#if CONFIG_IEEE80211_BAND_5GHZ && CONFIG_DFS + #ifdef CONFIG_DFS_MASTER + bool cac_done; + systime non_ocp_end_time; + #endif +#endif + + u8 hidden_bss_cnt; /* per scan count */ + +#if defined(CONFIG_IOCTL_CFG80211) && !RTW_PER_ADAPTER_WIPHY + void *os_chan; +#endif +} RT_CHANNEL_INFO, *PRT_CHANNEL_INFO; + +#define RTW_BCN_HINT_STOPPED 0 /* used by bcn_hint_end_time time stamps */ +#define CH_IS_BCN_HINT_STOPPED(rt_ch_info) ((rt_ch_info)->bcn_hint_end_time == RTW_BCN_HINT_STOPPED) +#define CH_IS_BCN_HINT(rt_ch_info) (!CH_IS_BCN_HINT_STOPPED(rt_ch_info) && rtw_time_after((rt_ch_info)->bcn_hint_end_time, rtw_get_current_time())) + +struct rtw_chset { + RT_CHANNEL_INFO chs[MAX_CHANNEL_NUM]; + u8 chs_len; + RT_CHANNEL_INFO *chs_of_band[BAND_MAX]; + u8 chs_len_of_band[BAND_MAX]; + u8 enable_ch_num; + u8 enable_ch_num_of_band[BAND_MAX]; +}; + +int rtw_chset_init(struct rtw_chset *chset, u8 band_bmp); + +RTW_FUNC_2G_5G_ONLY int rtw_chset_search_ch(const struct rtw_chset *chset, u32 ch); +RTW_FUNC_2G_5G_ONLY u8 rtw_chset_is_chbw_valid(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive); +RTW_FUNC_2G_5G_ONLY void rtw_chset_sync_chbw(const struct rtw_chset *chset, u8 *req_ch, u8 *req_bw, u8 *req_offset + , u8 *g_ch, u8 *g_bw, u8 *g_offset, bool allow_primary_passive, bool allow_passive); +int rtw_chset_search_bch(const struct rtw_chset *chset, enum band_type band, u32 ch); +RT_CHANNEL_INFO *rtw_chset_get_chinfo_by_bch(struct rtw_chset *chset, enum band_type band, u32 ch, bool include_dis); +u8 rtw_chset_is_bchbw_valid(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset + , bool allow_primary_passive, bool allow_passive); +void rtw_chset_sync_bchbw(const struct rtw_chset *chset, enum band_type *req_band, u8 *req_ch, u8 *req_bw, u8 *req_offset + , enum band_type *g_band, u8 *g_ch, u8 *g_bw, u8 *g_offset, bool allow_primary_passive, bool allow_passive); + +#if CONFIG_IEEE80211_BAND_6GHZ +#define rtw_chset_has_6g_enabled(chset) (!!(chset)->enable_ch_num_of_band[BAND_ON_6G]) +#else +#define rtw_chset_has_6g_enabled(chset) false +#endif + +u8 *rtw_chset_set_spt_chs_ie(struct rtw_chset *chset, u8 *buf_pos, uint *buf_len); + +#ifdef CONFIG_PROC_DEBUG +void dump_chinfos(void *sel, const RT_CHANNEL_INFO *chinfos, u8 chinfo_num); +#endif + +#endif /* __RTW_CHSET_H__ */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_cmd.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_cmd.c new file mode 100755 index 00000000..87a16b3b --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_cmd.c @@ -0,0 +1,5453 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2023 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_CMD_C_ + +#include + +#ifndef DBG_CMD_EXECUTE + #define DBG_CMD_EXECUTE 0 +#endif + +/* +Caller and the rtw_cmd_thread can protect cmd_q by spin_lock. +No irqsave is necessary. +*/ +u32 rtw_init_cmd_priv(struct dvobj_priv *dvobj) +{ + u32 res = _SUCCESS; + struct cmd_priv *pcmdpriv = &dvobj->cmdpriv; + + pcmdpriv->dvobj = dvobj; + #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ + _rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0); + _rtw_init_sema(&(pcmdpriv->start_cmdthread_sema), 0); + _rtw_init_queue(&(pcmdpriv->cmd_queue)); + #endif + + pcmdpriv->cmd_seq = 1; + pcmdpriv->cmd_issued_cnt = 0; + + _rtw_mutex_init(&pcmdpriv->sctx_mutex); + + ATOMIC_SET(&pcmdpriv->event_seq, 0); + pcmdpriv->evt_done_cnt = 0; + + return res; + +} + +void rtw_free_cmd_priv(struct dvobj_priv *dvobj) +{ + struct cmd_priv *pcmdpriv = &dvobj->cmdpriv; + + #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ + _rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock)); + _rtw_free_sema(&(pcmdpriv->cmd_queue_sema)); + _rtw_free_sema(&(pcmdpriv->start_cmdthread_sema)); + #endif + + _rtw_mutex_free(&pcmdpriv->sctx_mutex); +} + +static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) +{ + u8 bAllow = _FALSE; /* set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE */ + struct dvobj_priv *dvobj = pcmdpriv->dvobj; + + + if (cmd_obj->cmdcode == CMD_SET_CHANPLAN) + bAllow = _TRUE; + + if (cmd_obj->no_io) + bAllow = _TRUE; + + return _SUCCESS; +} + +/* +Calling Context: + +rtw_enqueue_cmd can only be called between kernel thread, +since only spin_lock is used. + +ISR/Call-Back functions can't call this sub-function. + +*/ +#ifdef DBG_CMD_QUEUE +extern u8 dump_cmd_id; +#endif + +#if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ +static sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head) +{ + unsigned long sp_flags; + + if (obj == NULL) + goto exit; + + /* _rtw_spinlock_bh(&queue->lock); */ + _rtw_spinlock_irq(&queue->lock, &sp_flags); + + if (to_head) + rtw_list_insert_head(&obj->list, &queue->queue); + else + rtw_list_insert_tail(&obj->list, &queue->queue); + +#ifdef DBG_CMD_QUEUE + if (dump_cmd_id) { + RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode); + if (obj->cmdcode == CMD_SET_MLME_EVT) { + if (obj->parmbuf) { + struct rtw_evt_header *evt_hdr = (struct rtw_evt_header *)(obj->parmbuf); + RTW_INFO("evt_hdr->id:%d\n", evt_hdr->id); + } + } + if (obj->cmdcode == CMD_SET_DRV_EXTRA) { + if (obj->parmbuf) { + struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf); + RTW_INFO("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id); + } + } + } + + if (queue->queue.prev->next != &queue->queue) { + RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__, + &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next); + + RTW_INFO("==========%s============\n", __FUNCTION__); + RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj); + RTW_INFO("padapter: %p\n", obj->padapter); + RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode); + RTW_INFO("res: %d\n", obj->res); + RTW_INFO("parmbuf: %p\n", obj->parmbuf); + RTW_INFO("cmdsz: %d\n", obj->cmdsz); + RTW_INFO("rsp: %p\n", obj->rsp); + RTW_INFO("rspsz: %d\n", obj->rspsz); + RTW_INFO("sctx: %p\n", obj->sctx); + RTW_INFO("list->next: %p\n", obj->list.next); + RTW_INFO("list->prev: %p\n", obj->list.prev); + } +#endif /* DBG_CMD_QUEUE */ + + /* _rtw_spinunlock_bh(&queue->lock); */ + _rtw_spinunlock_irq(&queue->lock, &sp_flags); + +exit: + + + return _SUCCESS; +} +#else +static sint _rtw_enqueue_cmd(struct cmd_obj *obj, bool to_head) +{ + u32 res; + + res = rtw_enqueue_phl_cmd(obj); + +#ifdef DBG_CMD_QUEUE + if (dump_cmd_id) { + RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode); + if (obj->cmdcode == CMD_SET_MLME_EVT) { + if (obj->parmbuf) { + struct rtw_evt_header *evt_hdr = (struct rtw_evt_header *)(obj->parmbuf); + RTW_INFO("evt_hdr->id:%d\n", evt_hdr->id); + } + } + if (obj->cmdcode == CMD_SET_DRV_EXTRA) { + if (obj->parmbuf) { + struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf); + RTW_INFO("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id); + } + } + } +#endif /* DBG_CMD_QUEUE */ + return res; +} +#endif + +u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) +{ + int res = _FAIL; + + if (cmd_obj == NULL) + goto exit; + + res = rtw_cmd_filter(pcmdpriv, cmd_obj); + if (_FAIL == res) { + if (cmd_obj->cmdcode == CMD_SET_DRV_EXTRA) { + struct drvextra_cmd_parm *extra_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; + + if (extra_parm->pbuf && extra_parm->size > 0) + rtw_mfree(extra_parm->pbuf, extra_parm->size); + } +#ifdef CONFIG_80211BE_EHT + else if (cmd_obj->cmdcode == CMD_SET_MLME_EVT) { + struct rtw_evt_header *hdr = + (struct rtw_evt_header*)cmd_obj->parmbuf; + + hdr = (struct rtw_evt_header*)cmd_obj->parmbuf; + if (hdr && hdr->id == EVT_JOINBSS) { + struct wlan_network *network = + (struct wlan_network *)(cmd_obj->parmbuf + sizeof(*hdr)); + if (network && network->network.is_mld) { + rtw_free_cloned_mld_network(network->network.mld_network); + cmd_obj->parmbuf = NULL; + } + } + } +#endif + rtw_free_cmd_obj(cmd_obj); + goto exit; + } + + + res = _rtw_enqueue_cmd(cmd_obj, 0); + #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ + if (res == _SUCCESS) + _rtw_up_sema(&pcmdpriv->cmd_queue_sema); + #endif + +exit: + return res; +} + +#if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ +struct cmd_obj *_rtw_dequeue_cmd(_queue *queue) +{ + struct cmd_obj *obj; + unsigned long sp_flags; + + /* _rtw_spinlock_bh(&(queue->lock)); */ + _rtw_spinlock_irq(&queue->lock, &sp_flags); + +#ifdef DBG_CMD_QUEUE + if (queue->queue.prev->next != &queue->queue) { + RTW_INFO("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__, + &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next); + } +#endif /* DBG_CMD_QUEUE */ + + + if (rtw_is_list_empty(&(queue->queue))) + obj = NULL; + else { + obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list); + +#ifdef DBG_CMD_QUEUE + if (queue->queue.prev->next != &queue->queue) { + RTW_INFO("==========%s============\n", __FUNCTION__); + RTW_INFO("head:%p,obj_addr:%p\n", &queue->queue, obj); + RTW_INFO("padapter: %p\n", obj->padapter); + RTW_INFO("cmdcode: 0x%02x\n", obj->cmdcode); + RTW_INFO("res: %d\n", obj->res); + RTW_INFO("parmbuf: %p\n", obj->parmbuf); + RTW_INFO("cmdsz: %d\n", obj->cmdsz); + RTW_INFO("rsp: %p\n", obj->rsp); + RTW_INFO("rspsz: %d\n", obj->rspsz); + RTW_INFO("sctx: %p\n", obj->sctx); + RTW_INFO("list->next: %p\n", obj->list.next); + RTW_INFO("list->prev: %p\n", obj->list.prev); + } + + if (dump_cmd_id) { + RTW_INFO("%s===> cmdcode:0x%02x\n", __FUNCTION__, obj->cmdcode); + if (obj->cmdcode == CMD_SET_DRV_EXTRA) { + if (obj->parmbuf) { + struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)(obj->parmbuf); + printk("pdrvextra_cmd_parm->ec_id:0x%02x\n", pdrvextra_cmd_parm->ec_id); + } + } + + } +#endif /* DBG_CMD_QUEUE */ + + rtw_list_delete(&obj->list); + } + + /* _rtw_spinunlock_bh(&(queue->lock)); */ + _rtw_spinunlock_irq(&queue->lock, &sp_flags); + + + return obj; +} + +struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv) +{ + struct cmd_obj *cmd_obj; + + cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue); + + return cmd_obj; +} +#endif +void rtw_free_cmd_obj(struct cmd_obj *pcmd) +{ + if (pcmd->parmbuf != NULL) { + /* free parmbuf in cmd_obj */ + rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz); + } + if (pcmd->rsp != NULL) { + if (pcmd->rspsz != 0) { + /* free rsp in cmd_obj */ + rtw_mfree((unsigned char *)pcmd->rsp, pcmd->rspsz); + } + } + + /* free cmd_obj */ + rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj)); +} +void rtw_run_cmd(_adapter *padapter, struct cmd_obj *pcmd, bool discard) +{ + u8 ret; + systime cmd_start_time; + u32 cmd_process_time; + u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf); + void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd); + struct cmd_priv *pcmdpriv = &(adapter_to_dvobj(padapter)->cmdpriv); + struct drvextra_cmd_parm *extra_parm = NULL; + + cmd_start_time = rtw_get_current_time(); + pcmdpriv->cmd_issued_cnt++; + + if (discard) + goto post_process; + + if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) { + RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode); + pcmd->res = H2C_PARAMETERS_ERROR; + goto post_process; + } + + cmd_hdl = wlancmds[pcmd->cmdcode].cmd_hdl; + if (!cmd_hdl) { + RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode); + pcmd->res = H2C_PARAMETERS_ERROR; + goto post_process; + } + + if (DBG_CMD_EXECUTE) + RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd) + , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : "")); + + ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf); + pcmd->res = ret; + + pcmdpriv->cmd_seq++; + +post_process: + pcmd->sctx_rsp_buf = NULL; /* init to NULL, may point to buffer allocated in cmd_thread after callback */ + + /* call callback function for post-processed */ + if (pcmd->cmdcode < (sizeof(wlancmds) / sizeof(struct rtw_cmd))) + pcmd_callback = wlancmds[pcmd->cmdcode].callback; + else + pcmd_callback = NULL; + + if (pcmd_callback) + pcmd_callback(pcmd->padapter, pcmd); + + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (pcmd->sctx) { + if (0) + RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter)); + if (pcmd->res == H2C_SUCCESS) { + if (pcmd->sctx_rsp_buf) + pcmd->sctx->rsp = pcmd->sctx_rsp_buf; + rtw_sctx_done(&pcmd->sctx); + } else + rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); + } else { + if (pcmd->sctx_rsp_buf && pcmd->sctx_rsp_buf_free) { + if (0) + RTW_PRINT(FUNC_ADPT_FMT" free pcmd->sctx_rsp_buf\n", FUNC_ADPT_ARG(pcmd->padapter)); + pcmd->sctx_rsp_buf_free(pcmd->sctx_rsp_buf); + } + } + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + + cmd_process_time = rtw_get_passing_time_ms(cmd_start_time); + if (cmd_process_time > 1000) { + RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time); + if (0) + rtw_warn_on(1); + } + + rtw_free_cmd_obj(pcmd); +} +#if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/ +void rtw_stop_cmd_thread(_adapter *adapter) +{ + if (adapter->cmdThread) { + _rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema); + rtw_thread_stop(adapter->cmdThread); + adapter->cmdThread = NULL; + } +} + +thread_return rtw_cmd_thread(thread_context context) +{ + u8 ret; + struct cmd_obj *pcmd; + u8 *pcmdbuf, *prspbuf; + systime cmd_start_time; + u32 cmd_process_time; + u8(*cmd_hdl)(_adapter *padapter, u8 *pbuf); + void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd); + _adapter *padapter = (_adapter *)context; + struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); + struct drvextra_cmd_parm *extra_parm = NULL; + unsigned long sp_flags; + + rtw_thread_enter("RTW_CMD_THREAD"); + + pcmdbuf = pcmdpriv->cmd_buf; + prspbuf = pcmdpriv->rsp_buf; + ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE); + _rtw_up_sema(&pcmdpriv->start_cmdthread_sema); + + + while (1) { + if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) { + RTW_PRINT(FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter)); + break; + } + + if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter))) { + RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n", + FUNC_ADPT_ARG(padapter), + dev_is_drv_stopped(adapter_to_dvobj(padapter)) ? "True" : "False", + dev_is_surprise_removed(adapter_to_dvobj(padapter)) ? "True" : "False"); + break; + } + + _rtw_spinlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags); + if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) { + /* RTW_INFO("%s: cmd queue is empty!\n", __func__); */ + _rtw_spinunlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags); + continue; + } + _rtw_spinunlock_irq(&pcmdpriv->cmd_queue.lock, &sp_flags); + +_next: + if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter))) { + RTW_PRINT("%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n", + __func__ + , dev_is_drv_stopped(adapter_to_dvobj(padapter)) ? "True" : "False" + , dev_is_surprise_removed(adapter_to_dvobj(padapter)) ? "True" : "False" + , __LINE__); + break; + } + + pcmd = rtw_dequeue_cmd(pcmdpriv); + if (!pcmd) { + continue; + } + + cmd_start_time = rtw_get_current_time(); + pcmdpriv->cmd_issued_cnt++; + + if (pcmd->cmdsz > MAX_CMDSZ) { + RTW_ERR("%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ); + pcmd->res = H2C_PARAMETERS_ERROR; + goto post_process; + } + + if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) { + RTW_ERR("%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode); + pcmd->res = H2C_PARAMETERS_ERROR; + goto post_process; + } + + cmd_hdl = wlancmds[pcmd->cmdcode].cmd_hdl; + if (!cmd_hdl) { + RTW_ERR("%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode); + pcmd->res = H2C_PARAMETERS_ERROR; + goto post_process; + } + + if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) { + pcmd->res = H2C_DROPPED; + if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) { + extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; + if (extra_parm && extra_parm->pbuf && extra_parm->size > 0) + rtw_mfree(extra_parm->pbuf, extra_parm->size); + } + goto post_process; + } + + if (DBG_CMD_EXECUTE) + RTW_INFO(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd) + , pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : "")); + + _rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); + ret = cmd_hdl(pcmd->padapter, pcmdbuf); + pcmd->res = ret; + + pcmdpriv->cmd_seq++; + +post_process: + + _rtw_mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)); + if (pcmd->sctx) { + if (0) + RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter)); + if (pcmd->res == H2C_SUCCESS) + rtw_sctx_done(&pcmd->sctx); + else + rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR); + } + _rtw_mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); + + cmd_process_time = rtw_get_passing_time_ms(cmd_start_time); + if (cmd_process_time > 1000) { + RTW_INFO(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time); + if (0) + rtw_warn_on(1); + } + + /* call callback function for post-processed */ + if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) + pcmd_callback = wlancmds[pcmd->cmdcode].callback; + else + pcmd_callback = NULL; + + if (pcmd_callback == NULL) { + rtw_free_cmd_obj(pcmd); + } else { + /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL) */ + pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */ + } + + flush_signals_thread(); + + goto _next; + + } + + /* to avoid enqueue cmd after free all cmd_obj */ + ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE); + + /* free all cmd_obj resources */ + do { + pcmd = rtw_dequeue_cmd(pcmdpriv); + if (pcmd == NULL) + break; + + if (0) + RTW_INFO("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd)); + + if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) { + extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf; + if (extra_parm->pbuf && extra_parm->size > 0) + rtw_mfree(extra_parm->pbuf, extra_parm->size); + } + + _rtw_mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)); + if (pcmd->sctx) { + if (0) + RTW_PRINT(FUNC_ADPT_FMT" pcmd->sctx\n", FUNC_ADPT_ARG(pcmd->padapter)); + rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_DROP); + } + _rtw_mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex)); + + rtw_free_cmd_obj(pcmd); + } while (1); + + RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter)); + + rtw_thread_wait_stop(); + + return 0; +} +#endif + +void rtw_readtssi_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd) +{ + + rtw_mfree((unsigned char *) pcmd->parmbuf, pcmd->cmdsz); + rtw_mfree((unsigned char *) pcmd, sizeof(struct cmd_obj)); + +#ifdef CONFIG_MP_INCLUDED + if (padapter->registrypriv.mp_mode == 1) + padapter->mppriv.workparam.bcompleted = _TRUE; +#endif + +} + +static u8 rtw_createbss_cmd(_adapter *adapter, int flags, bool adhoc + , u8 ifbmp, u8 excl_ifbmp, s8 req_band, s16 req_ch, s8 req_bw, s8 req_offset, u8 is_change_chbw) +{ + struct cmd_obj *cmdobj; + struct createbss_parm *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 res = _SUCCESS; + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(adapter); + + if (req_ch > 0 && req_bw >= 0 && req_offset >= 0) { + if (!rtw_chset_is_bchbw_valid(adapter_to_chset(adapter), req_band, req_ch, req_bw, req_offset, 0, 0)) { + res = _FAIL; + goto exit; + } + } + + /* prepare cmd parameter */ + parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + + if (adhoc) { + /* for now, adhoc doesn't support ch,bw,offset request */ + parm->adhoc = 1; + } else { + parm->adhoc = 0; + parm->ifbmp = ifbmp; + parm->excl_ifbmp = excl_ifbmp; + parm->req_band = req_band; + parm->req_ch = req_ch; + parm->req_bw = req_bw; + parm->req_offset = req_offset; + parm->ifbmp_ch_changed = 0; + parm->ch_to_set = 0; + parm->bw_to_set = 0; + parm->offset_to_set = 0; + parm->is_change_chbw = is_change_chbw; + } + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm)) + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_CREATE_BSS); + cmdobj->band_idx = padapter_link->wrlink->hw_band; + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + } + +exit: + return res; +} + +inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags) +{ + return rtw_createbss_cmd(adapter, flags + , 1 + , 0, 0, REQ_BAND_NONE + , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* for now, adhoc doesn't support ch,bw,offset request */ + , _FALSE + ); +} + +inline u8 rtw_startbss_cmd(_adapter *adapter, int flags) +{ + return rtw_createbss_cmd(adapter, flags + , 0 + , BIT(adapter->iface_id), 0, REQ_BAND_NONE + , 0, REQ_BW_NONE, REQ_OFFSET_NONE /* excute entire AP setup cmd */ + , _FALSE + ); +} + +inline u8 rtw_change_bss_bchbw_cmd(_adapter *adapter, int flags + , u32 iflbmp, u32 excl_iflbmp, s8 req_band, s16 req_ch, s8 req_bw, s8 req_offset) +{ + /* single link only */ + return rtw_createbss_cmd(adapter, flags + , 0 + , iflbmp_to_ifbmp(iflbmp), iflbmp_to_ifbmp(excl_iflbmp), req_band + , req_ch, req_bw, req_offset + , _TRUE + ); +} + +u8 rtw_joinbss_cmd(_adapter *padapter, struct wlan_network *pnetwork) +{ + u8 res = _SUCCESS; + WLAN_BSSID_EX *psecnetwork; + struct cmd_obj *pcmd; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct joinbss_parm *param; + NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode; + + rtw_led_control(padapter, LED_CTL_START_TO_LINK); + + pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmd == NULL) { + res = _FAIL; + goto exit; + } + pcmd->padapter = padapter; + + /* for hidden ap to set fw_state here */ + if (!MLME_IS_STA(padapter) || !MLME_IS_ADHOC(padapter)) { + switch (ndis_network_mode) { + case Ndis802_11IBSS: + set_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE); + break; + + case Ndis802_11Infrastructure: + set_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE); + break; + + default: + rtw_warn_on(1); + break; + } + } + + param = rtw_malloc(sizeof(struct joinbss_parm)); + if (param == NULL) { + if (pcmd != NULL) + rtw_mfree(pcmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + _rtw_memset(¶m->network, 0, sizeof(WLAN_BSSID_EX)); + _rtw_memcpy(¶m->network, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network)); + + init_h2fwcmd_w_parm_no_rsp(pcmd, param, CMD_JOINBSS); + + res = rtw_enqueue_cmd(pcmdpriv, pcmd); + +exit: + return res; +} + +#ifdef CONFIG_STA_CMD_DISPR +/* for sta_mode only */ +static u8 sta_disassoc_cmd(struct _ADAPTER *a, u32 deauth_timeout_ms, int flags) +{ + struct cmd_priv *cmdpriv = &adapter_to_dvobj(a)->cmdpriv; + struct cmd_obj *cmd = NULL; + struct disconnect_parm *param = NULL; + struct submit_ctx sctx; + enum rtw_phl_status status; + int ret; + u8 res = _FAIL; + + + if (!MLME_IS_ASOC(a)) + return _SUCCESS; + + param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param)); + if (!param) { + RTW_ERR(FUNC_ADPT_FMT ": alloc param FAIL!", FUNC_ADPT_ARG(a)); + goto exit; + } + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmd)); + if (!cmd) { + RTW_ERR(FUNC_ADPT_FMT ": alloc cmd FAIL!", FUNC_ADPT_ARG(a)); + rtw_mfree((u8 *)param, sizeof(*param)); + goto exit; + } + + param->deauth_timeout_ms = deauth_timeout_ms; + init_h2fwcmd_w_parm_no_rsp(cmd, param, CMD_DISCONNECT); + cmd->padapter = a; + if (flags & RTW_CMDF_WAIT_ACK) { + cmd->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + + status = rtw_disconnect_cmd(a, cmd); + if (status != RTW_PHL_STATUS_SUCCESS) { + rtw_mfree((u8 *)param, sizeof(*param)); + rtw_mfree((u8 *)cmd, sizeof(*cmd)); + if (status == RTW_PHL_STATUS_RESOURCE) { + RTW_INFO(FUNC_ADPT_FMT ": disconnect is on-going%s...\n", + FUNC_ADPT_ARG(a), + (flags & RTW_CMDF_WAIT_ACK) ? ", wait to complete" : ""); + if (flags & RTW_CMDF_WAIT_ACK) { + if (rtw_disconnect_wait_complete(a, deauth_timeout_ms)) { + res = _SUCCESS; + } else { + RTW_WARN(FUNC_ADPT_FMT ": Fail to wait disconnect complete!\n", + FUNC_ADPT_ARG(a)); + } + } else { + res = _SUCCESS; + } + } else { + RTW_ERR(FUNC_ADPT_FMT ": send disconnect cmd FAIL!(0x%x)\n", + FUNC_ADPT_ARG(a), status); + } + goto exit; + } + res = _SUCCESS; + + if (flags & RTW_CMDF_WAIT_ACK) { + ret = rtw_sctx_wait(&sctx, __func__); + if (ret == _FAIL) + res = _FAIL; + _rtw_spinlock_bh(&a->disconnect_lock); + if (a->discon_cmd) { + a->discon_cmd->sctx = NULL; + /* + * a->discon_param would be + * freed by disconnect cmd dispatcher. + */ + } + _rtw_spinunlock_bh(&a->disconnect_lock); + } + +exit: + return res; +} +#endif /* CONFIG_STA_CMD_DISPR */ + +u8 rtw_disassoc_cmd(_adapter *padapter, u32 deauth_timeout_ms, int flags) /* for sta_mode */ +{ + struct cmd_obj *cmdobj = NULL; + struct disconnect_parm *param = NULL; + struct cmd_priv *cmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + + struct submit_ctx sctx; + u8 res = _SUCCESS; + + +#ifdef CONFIG_STA_CMD_DISPR + if (MLME_IS_STA(padapter)) + return sta_disassoc_cmd(padapter, deauth_timeout_ms, flags); +#endif /* CONFIG_STA_CMD_DISPR */ + + /* prepare cmd parameter */ + param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param)); + if (param == NULL) { + res = _FAIL; + goto exit; + } + param->deauth_timeout_ms = deauth_timeout_ms; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS) + res = _FAIL; + rtw_mfree((u8 *)param, sizeof(*param)); + + } else { + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)param, sizeof(*param)); + goto exit; + } + cmdobj->padapter = padapter; + init_h2fwcmd_w_parm_no_rsp(cmdobj, param, CMD_DISCONNECT); + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + if (res == _FAIL) { + RTW_ERR(FUNC_ADPT_FMT ": enqueue disconnect cmd FAIL!\n", + FUNC_ADPT_ARG(padapter)); + goto exit; + } + if (flags & RTW_CMDF_WAIT_ACK) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&cmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&cmdpriv->sctx_mutex); + } + } + +exit: + return res; +} + + +u8 rtw_stop_ap_cmd(_adapter *adapter, u8 flags) +{ +#ifdef CONFIG_AP_MODE + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != stop_ap_hdl(adapter)) + res = _FAIL; + } else { + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + + parm->ec_id = STOP_AP_WK_CID; + parm->type = 0; + parm->size = 0; + parm->pbuf = NULL; + + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + } + } +exit: + return res; +#endif +} + +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT +u8 rtw_tx_control_cmd(_adapter *adapter) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + + u8 res = _SUCCESS; + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL){ + res = _FAIL; + goto exit; + } + cmd->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = TBTX_CONTROL_TX_WK_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; +} +#endif + +u8 rtw_setopmode_cmd(_adapter *adapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, u8 flags) +{ + struct cmd_obj *cmdobj; + struct setopmode_parm *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + /* prepare cmd parameter */ + parm = (struct setopmode_parm *)rtw_zmalloc(sizeof(*parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + parm->mode = (u8)networktype; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != setopmode_hdl(adapter, (u8 *)parm)) + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_OPMODE); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + } + } + +exit: + return res; +} + +#ifdef CONFIG_CMD_DISP +u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue) +{ + struct set_stakey_parm setstakey_para; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct _ADAPTER_LINK *padapter_link = sta->padapter_link; + struct link_security_priv *lsecuritypriv = &padapter_link->securitypriv; + u8 key_len =16; + u8 res = _SUCCESS; + + _rtw_memset(&setstakey_para, 0, sizeof(struct set_stakey_parm)); + _rtw_memcpy(setstakey_para.addr, sta->phl_sta->mac_addr, ETH_ALEN); + + if (MLME_IS_STA(padapter)) + setstakey_para.algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; + else + GET_ENCRY_ALGO(psecuritypriv, sta, setstakey_para.algorithm, _FALSE); + + if ((setstakey_para.algorithm == _GCMP_256_) || (setstakey_para.algorithm == _CCMP_256_)) + key_len = 32; + + if (key_type == GROUP_KEY) { + _rtw_memcpy(&setstakey_para.key, &lsecuritypriv->dot118021XGrpKey[lsecuritypriv->dot118021XGrpKeyid].skey, key_len); + setstakey_para.gk = 1; + setstakey_para.keyid = (u8)lsecuritypriv->dot118021XGrpKeyid; + } else if (key_type == UNICAST_KEY) + _rtw_memcpy(&setstakey_para.key, &sta->dot118021x_UncstKey, key_len); +#ifdef CONFIG_TDLS + else if (key_type == TDLS_KEY) { + _rtw_memcpy(&setstakey_para.key, sta->tpk.tk, key_len); + setstakey_para.algorithm = (u8)sta->dot118021XPrivacy; + } +#endif /* CONFIG_TDLS */ + + /* jeff: set this becasue at least sw key is ready */ + padapter->securitypriv.busetkipkey = _TRUE; + + if (enqueue) { + set_stakey_hdl(padapter, &setstakey_para, PHL_CMD_NO_WAIT, 0); + } else { + set_stakey_hdl(padapter, &setstakey_para, PHL_CMD_DIRECTLY, 0); + } +exit: + return res; +} + +u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue) +{ + struct cmd_obj *cmd; + struct set_stakey_parm *psetstakey_para; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct set_stakey_rsp *psetstakey_rsp = NULL; + s16 cam_id = 0; + u8 res = _SUCCESS; + + if (!sta) { + RTW_ERR("%s sta == NULL\n", __func__); + goto exit; + } + + if (!enqueue) + rtw_hw_del_all_key(padapter, sta, PHL_CMD_DIRECTLY, 0); + else + rtw_hw_del_all_key(padapter, sta, PHL_CMD_NO_WAIT, 0); + +exit: + + + return res; +} +#else /* CONFIG_FSM */ +u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue) +{ + struct cmd_obj *pcmd; + struct set_stakey_parm *psetstakey_para; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct set_stakey_rsp *psetstakey_rsp = NULL; + + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; + u8 key_len =16; + u8 res = _SUCCESS; + + + psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); + if (psetstakey_para == NULL) { + res = _FAIL; + goto exit; + } + + _rtw_memcpy(psetstakey_para->addr, sta->phl_sta->mac_addr, ETH_ALEN); + + if (MLME_IS_STA(padapter)) + psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm; + else + GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE); + + if ((psetstakey_para->algorithm == _GCMP_256_) || (psetstakey_para->algorithm == _CCMP_256_)) + key_len = 32; + + if (key_type == GROUP_KEY) { + _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, key_len); + psetstakey_para->gk = 1; + } else if (key_type == UNICAST_KEY) + _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, key_len); +#ifdef CONFIG_TDLS + else if (key_type == TDLS_KEY) { + _rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, key_len); + psetstakey_para->algorithm = (u8)sta->dot118021XPrivacy; + } +#endif /* CONFIG_TDLS */ + + /* jeff: set this becasue at least sw key is ready */ + padapter->securitypriv.busetkipkey = _TRUE; + + if (enqueue) { + pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmd == NULL) { + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + res = _FAIL; + goto exit; + } + pcmd->padapter = padapter; + + psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp)); + if (psetstakey_rsp == NULL) { + rtw_mfree((u8 *) pcmd, sizeof(struct cmd_obj)); + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + res = _FAIL; + goto exit; + } + + init_h2fwcmd_w_parm_no_rsp(pcmd, psetstakey_para, CMD_SET_STAKEY); + pcmd->rsp = (u8 *) psetstakey_rsp; + pcmd->rspsz = sizeof(struct set_stakey_rsp); + res = rtw_enqueue_cmd(pcmdpriv, pcmd); + } else { + set_stakey_hdl(padapter, (u8 *)psetstakey_para); + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + } +exit: + return res; +} + +u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue) +{ + struct cmd_obj *cmd; + struct set_stakey_parm *psetstakey_para; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct set_stakey_rsp *psetstakey_rsp = NULL; + s16 cam_id = 0; + u8 res = _SUCCESS; + + if (!sta) { + RTW_ERR("%s sta == NULL\n", __func__); + goto exit; + } + + if (!enqueue) { + rtw_hw_del_all_key(padapter, sta, PHL_CMD_DIRECTLY, 0); + } else { + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + + psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); + if (psetstakey_para == NULL) { + rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp)); + if (psetstakey_rsp == NULL) { + rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)psetstakey_para, sizeof(struct set_stakey_parm)); + res = _FAIL; + goto exit; + } + + init_h2fwcmd_w_parm_no_rsp(cmd, psetstakey_para, CMD_SET_STAKEY); + cmd->rsp = (u8 *) psetstakey_rsp; + cmd->rspsz = sizeof(struct set_stakey_rsp); + + _rtw_memcpy(psetstakey_para->addr, sta->phl_sta->mac_addr, ETH_ALEN); + + psetstakey_para->algorithm = _NO_PRIVACY_; + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + + } + +exit: + + + return res; +} +#endif + +u8 rtw_addbareq_cmd(_adapter *padapter, u8 tid, u8 *addr) +{ + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct cmd_obj *cmd; + struct addBaReq_parm *paddbareq_parm; + + u8 res = _SUCCESS; + + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm)); + if (paddbareq_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + paddbareq_parm->tid = tid; + _rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN); + + init_h2fwcmd_w_parm_no_rsp(cmd, paddbareq_parm, CMD_ADD_BAREQ); + + /* RTW_INFO("rtw_addbareq_cmd, tid=%d\n", tid); */ + + /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; +} + +u8 rtw_addbarsp_cmd(_adapter *padapter, u8 *addr, u16 tid, + struct ADDBA_request *paddba_req, u8 status, + u16 size, u16 start_seq) +{ + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct cmd_obj *cmd; + struct addBaRsp_parm *paddBaRsp_parm; + u8 res = _SUCCESS; + + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + paddBaRsp_parm = (struct addBaRsp_parm *)rtw_zmalloc(sizeof(struct addBaRsp_parm)); + + if (paddBaRsp_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + _rtw_memcpy(paddBaRsp_parm->addr, addr, ETH_ALEN); + _rtw_memcpy(&(paddBaRsp_parm->preq), paddba_req, sizeof(struct ADDBA_request)); + paddBaRsp_parm->tid = tid; + paddBaRsp_parm->status = status; + paddBaRsp_parm->size = size; + paddBaRsp_parm->start_seq = start_seq; + + init_h2fwcmd_w_parm_no_rsp(cmd, paddBaRsp_parm, CMD_ADD_BARSP); + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + + + return res; +} + +u8 rtw_delba_cmd(struct _ADAPTER *a, u8 *addr, u16 tid) +{ + struct cmd_priv *cmdpriv = &adapter_to_dvobj(a)->cmdpriv; + struct cmd_obj *cmd = NULL; + struct addBaReq_parm *parm = NULL; + + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (!cmd) + return _FAIL; + cmd->padapter = a; + + parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm)); + if (!parm) { + rtw_mfree(cmd, sizeof(struct cmd_obj)); + return _FAIL; + } + + parm->tid = tid; + _rtw_memcpy(parm->addr, addr, ETH_ALEN); + init_h2fwcmd_w_parm_no_rsp(cmd, parm, CMD_DELBA); + + return rtw_enqueue_cmd(cmdpriv, cmd); +} + +/* add for CONFIG_IEEE80211W, none 11w can use it */ +u8 rtw_reset_securitypriv_cmd(_adapter *padapter) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + u8 res = _SUCCESS; + + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + + /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; + +} + +void free_assoc_resources_hdl(_adapter *padapter, u8 lock_scanned_queue) +{ + rtw_free_assoc_resources(padapter, lock_scanned_queue); +} + +u8 rtw_free_assoc_resources_cmd(_adapter *padapter, u8 lock_scanned_queue, int flags) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + if (flags & RTW_CMDF_DIRECTLY) { + free_assoc_resources_hdl(padapter, lock_scanned_queue); + } + else { + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; + pdrvextra_cmd_parm->type = lock_scanned_queue; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + if (flags & RTW_CMDF_WAIT_ACK) { + cmd->sctx = &sctx; + rtw_sctx_init(&sctx, 2000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmd->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + } + } +exit: + return res; + +} +#if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/ +u8 rtw_dynamic_chk_wk_cmd(_adapter *padapter) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + u8 res = _SUCCESS; + + + /* only primary padapter does this cmd */ + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + + /* rtw_enqueue_cmd(pcmdpriv, ph2c); */ + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; +} +#endif + +u8 rtw_set_chbw_cmd(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + struct rtw_chan_def *chdef, u8 flags, enum rfk_tri_type rt_type) +{ + struct cmd_obj *pcmdobj; + struct set_ch_parm *set_ch_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + + RTW_INFO(FUNC_NDEV_FMT" band:%d, ch:%u, bw:%u, ch_offset:%u\n", + FUNC_NDEV_ARG(padapter->pnetdev), + chdef->band, chdef->chan, chdef->bw, chdef->offset); + + /* check input parameter */ + + /* prepare cmd parameter */ + set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm)); + if (set_ch_parm == NULL) { + res = _FAIL; + goto exit; + } + set_ch_parm->band = chdef->band; + set_ch_parm->ch = chdef->chan; + set_ch_parm->bw = chdef->bw; + set_ch_parm->ch_offset = chdef->offset; + set_ch_parm->rt_type = rt_type; + set_ch_parm->link_idx = padapter_link->wrlink->id; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != rtw_set_chbw_hdl(padapter, (u8 *)set_ch_parm)) + res = _FAIL; + + rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmdobj == NULL) { + rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm)); + res = _FAIL; + goto exit; + } + pcmdobj->padapter = padapter; + + init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, CMD_SET_CHANNEL); + + if (flags & RTW_CMDF_WAIT_ACK) { + pcmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + pcmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + } + } + + /* do something based on res... */ +exit: + RTW_INFO(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res); + return res; +} + +#ifdef CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD +u8 rtw_led_blink_cmd(_adapter *padapter, void *pLed) +{ + struct cmd_obj *pcmdobj; + struct LedBlink_param *ledBlink_param; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + u8 res = _SUCCESS; + + pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmdobj == NULL) { + res = _FAIL; + goto exit; + } + pcmdobj->padapter = padapter; + + ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param)); + if (ledBlink_param == NULL) { + rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + ledBlink_param->pLed = pLed; + + init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, CMD_LEDBLINK); + res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); + +exit: + return res; +} +#endif /*CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD*/ + +u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option, u8 flags) +{ + u8 res = _SUCCESS; +#ifdef CONFIG_TDLS + struct cmd_obj *pcmdobj; + struct TDLSoption_param *TDLSoption; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + struct submit_ctx sctx; + + pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmdobj == NULL) { + res = _FAIL; + goto exit; + } + pcmdobj->padapter = padapter; + + TDLSoption = (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param)); + if (TDLSoption == NULL) { + rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + _rtw_spinlock_bh(&(padapter->tdlsinfo.cmd_lock)); + if (addr != NULL) + _rtw_memcpy(TDLSoption->addr, addr, 6); + TDLSoption->option = option; + _rtw_spinunlock_bh(&(padapter->tdlsinfo.cmd_lock)); + init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, CMD_TDLS); + + if (flags & RTW_CMDF_WAIT_ACK) { + pcmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 3000); + } + + res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + pcmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + +exit: +#endif /* CONFIG_TDLS */ + + return res; +} + +u8 rtw_ssmps_wk_hdl(_adapter *adapter, struct ssmps_cmd_parm *ssmp_param) +{ + u8 res = _SUCCESS; + struct sta_info *sta = ssmp_param->sta; + u8 smps = ssmp_param->smps; + + if (sta == NULL) + return _FALSE; + + if (smps) + rtw_ssmps_enter(adapter, sta); + else + rtw_ssmps_leave(adapter, sta); + return res; +} + +u8 rtw_ssmps_wk_cmd(_adapter *adapter, struct sta_info *sta, u8 smps, u8 enqueue) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *cmd_parm; + struct ssmps_cmd_parm *ssmp_param; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 res = _SUCCESS; + + if (enqueue) { + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + cmdobj->padapter = adapter; + + cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + ssmp_param = (struct ssmps_cmd_parm *)rtw_zmalloc(sizeof(struct ssmps_cmd_parm)); + if (ssmp_param == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + ssmp_param->smps = smps; + ssmp_param->sta = sta; + + cmd_parm->ec_id = SSMPS_WK_CID; + cmd_parm->type = 0; + cmd_parm->size = sizeof(struct ssmps_cmd_parm); + cmd_parm->pbuf = (u8 *)ssmp_param; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + } else { + struct ssmps_cmd_parm tmp_ssmp_param; + + tmp_ssmp_param.smps = smps; + tmp_ssmp_param.sta = sta; + rtw_ssmps_wk_hdl(adapter, &tmp_ssmp_param); + } + +exit: + return res; +} + +#ifdef CONFIG_SUPPORT_STATIC_SMPS +u8 _ssmps_chk_by_tp(_adapter *adapter) +{ + u8 enter_smps = _FALSE; + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct sta_priv *pstapriv = &adapter->stapriv; + struct sta_info *psta; + u32 tx_tp_mbits, rx_tp_mbits; + + if (!MLME_IS_STA(adapter) || + !rtw_hw_is_mimo_support(adapter) || + !pmlmeext->ssmps_en || + (pmlmeext->chandef.chan > 14) + ) + return enter_smps; + + psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); + if (psta == NULL) { + RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter)); + rtw_warn_on(1); + return enter_smps; + } + /*TODO*/ + if (psta->phl_sta->asoc_cap.nss_tx == 1) + return enter_smps; + + tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10; + rx_tp_mbits = psta->sta_stats.rx_tp_kbits >> 10; + + #ifdef DBG_STATIC_SMPS + if (pmlmeext->ssmps_test) { + enter_smps = (pmlmeext->ssmps_test_en == 1) ? _TRUE : _FALSE; + } + else + #endif + { + if ((tx_tp_mbits <= pmlmeext->ssmps_tx_tp_th) && + (rx_tp_mbits <= pmlmeext->ssmps_rx_tp_th)) + enter_smps = _TRUE; + else + enter_smps = _FALSE; + } + + if (1) { + RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d], rx_tp:%d [%d] , SSMPS enter :%s\n", + FUNC_ADPT_ARG(adapter), + tx_tp_mbits, pmlmeext->ssmps_tx_tp_th, + rx_tp_mbits, pmlmeext->ssmps_rx_tp_th, + (enter_smps == _TRUE) ? "True" : "False"); + #ifdef DBG_STATIC_SMPS + RTW_INFO(FUNC_ADPT_FMT" test:%d test_en:%d\n", + FUNC_ADPT_ARG(adapter), + pmlmeext->ssmps_test, + pmlmeext->ssmps_test_en); + #endif + } + + if (enter_smps) { + if (psta->phl_sta->sm_ps != SM_PS_STATIC) + rtw_ssmps_enter(adapter, psta); + } else { + if (psta->phl_sta->sm_ps != SM_PS_DISABLE) + rtw_ssmps_leave(adapter, psta); + else { + u8 ps_change = _FALSE; + + if (enter_smps && psta->phl_sta->sm_ps != SM_PS_STATIC) + ps_change = _TRUE; + else if (!enter_smps && psta->phl_sta->sm_ps != SM_PS_DISABLE) + ps_change = _TRUE; + + if (ps_change) + rtw_ssmps_wk_cmd(adapter, psta, enter_smps, 1); + } + } + + return enter_smps; +} +#endif /*CONFIG_SUPPORT_STATIC_SMPS*/ + +#ifdef CONFIG_CTRL_TXSS_BY_TP +void rtw_ctrl_txss_update(_adapter *adapter, struct sta_info *sta) +{ + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + pmlmeext->txss_bk = sta->phl_sta->asoc_cap.nss_rx; +} + +u8 rtw_ctrl_txss(_adapter *adapter, struct sta_info *sta, bool tx_1ss) +{ + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter); + u8 lps_changed = _FALSE; + u8 rst = _SUCCESS; + + if (pmlmeext->txss_1ss == tx_1ss) + return _FALSE; + /* + if (pwrpriv->bLeisurePs && pwrpriv->pwr_mode != PM_PS_MODE_ACTIVE) { + lps_changed = _TRUE; + LPS_Leave(adapter, "LPS_CTRL_TXSS"); + } + */ + + RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] set tx to %d ss\n", + ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr), + (tx_1ss) ? 1 : rtw_get_sta_tx_nss(adapter, sta)); + + /*update ra*/ + if (tx_1ss) + sta->phl_sta->asoc_cap.nss_rx = 1; + else + sta->phl_sta->asoc_cap.nss_rx = pmlmeext->txss_bk; + rtw_sta_hal_ra_mask_update_cmd(adapter, sta, RTW_CMDF_DIRECTLY); + + /*configure trx mode*/ + /*rtw_phydm_trx_cfg(adapter, tx_1ss);*/ + pmlmeext->txss_1ss = tx_1ss; + /* + if (lps_changed) + LPS_Enter(adapter, "LPS_CTRL_TXSS"); + */ + + return rst; +} + +u8 rtw_ctrl_txss_wk_hdl(_adapter *adapter, struct txss_cmd_parm *txss_param) +{ + if (!txss_param->sta) + return _FALSE; + + return rtw_ctrl_txss(adapter, txss_param->sta, txss_param->tx_1ss); +} + +u8 rtw_ctrl_txss_wk_cmd(_adapter *adapter, struct sta_info *sta, bool tx_1ss, u8 flag) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *cmd_parm; + struct txss_cmd_parm *txss_param; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + txss_param = (struct txss_cmd_parm *)rtw_zmalloc(sizeof(struct txss_cmd_parm)); + if (txss_param == NULL) { + res = _FAIL; + goto exit; + } + + txss_param->tx_1ss = tx_1ss; + txss_param->sta = sta; + + if (flag & RTW_CMDF_DIRECTLY) { + res = rtw_ctrl_txss_wk_hdl(adapter, txss_param); + rtw_mfree((u8 *)txss_param, sizeof(*txss_param)); + } else { + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + cmdobj->padapter = adapter; + + cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (cmd_parm == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + cmd_parm->ec_id = TXSS_WK_CID; + cmd_parm->type = 0; + cmd_parm->size = sizeof(struct txss_cmd_parm); + cmd_parm->pbuf = (u8 *)txss_param; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA); + + if (flag & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + if (res == _SUCCESS && (flag & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + } + +exit: + return res; +} + +void rtw_ctrl_tx_ss_by_tp(_adapter *adapter) +{ + bool tx_1ss = _FALSE; /*change tx from 2ss to 1ss*/ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct sta_priv *pstapriv = &adapter->stapriv; + struct sta_info *psta; + u32 tx_tp_mbits; + + if (!MLME_IS_STA(adapter) || + !rtw_hw_is_mimo_support(adapter) || + !pmlmeext->txss_ctrl_en + ) + return; + + psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); + if (psta == NULL) { + RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter)); + rtw_warn_on(1); + return; + } + + tx_tp_mbits = psta->sta_stats.tx_tp_kbits >> 10; + if (tx_tp_mbits >= pmlmeext->txss_tp_th) { + tx_1ss = _FALSE; + } else { + if (pmlmeext->txss_tp_chk_cnt && --pmlmeext->txss_tp_chk_cnt) + tx_1ss = _FALSE; + else + tx_1ss = _TRUE; + } + + if (1) { + RTW_INFO(FUNC_ADPT_FMT" tx_tp:%d [%d] tx_1ss(%d):%s\n", + FUNC_ADPT_ARG(adapter), + tx_tp_mbits, pmlmeext->txss_tp_th, + pmlmeext->txss_tp_chk_cnt, + (tx_1ss == _TRUE) ? "True" : "False"); + } + + if (pmlmeext->txss_1ss != tx_1ss) + rtw_ctrl_txss(adapter, psta, tx_1ss); +} +#ifdef DBG_CTRL_TXSS +void dbg_ctrl_txss(_adapter *adapter, bool tx_1ss) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct sta_priv *pstapriv = &adapter->stapriv; + struct sta_info *psta; + + if (!MLME_IS_STA(adapter) || + !rtw_hw_is_mimo_support(adapter) + ) + return; + + psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); + if (psta == NULL) { + RTW_ERR(ADPT_FMT" sta == NULL\n", ADPT_ARG(adapter)); + rtw_warn_on(1); + return; + } + + rtw_ctrl_txss(adapter, psta, tx_1ss); +} +#endif +#endif /*CONFIG_CTRL_TXSS_BY_TP*/ + +u8 traffic_status_watchdog(_adapter *padapter) +{ + u8 bEnterPS = _FALSE; + u16 BusyThresholdHigh; + u16 BusyThresholdLow; + u16 BusyThreshold; + u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE; + u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE; + + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); +#ifdef CONFIG_TDLS + struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo); + struct tdls_txmgmt txmgmt; + u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_TRAFFIC_PROTECT + RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo; +#endif + +#ifdef CONFIG_BTC + if (padapter->registrypriv.wifi_spec != 1) { + BusyThresholdHigh = 25; + BusyThresholdLow = 10; + } else +#endif /* CONFIG_BTC */ + { + BusyThresholdHigh = 100; + BusyThresholdLow = 75; + } + BusyThreshold = BusyThresholdHigh; + + + /* */ + /* Determine if our traffic is busy now */ + /* */ + if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) + /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { + /* if we raise bBusyTraffic in last watchdog, using lower threshold. */ + if (pmlmepriv->LinkDetectInfo.bBusyTraffic) + BusyThreshold = BusyThresholdLow; + + if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) { + bBusyTraffic = _TRUE; + + if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) + bRxBusyTraffic = _TRUE; + else + bTxBusyTraffic = _TRUE; + } + + /* Higher Tx/Rx data. */ + if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 || + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) { + bHigherBusyTraffic = _TRUE; + + if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) + bHigherBusyRxTraffic = _TRUE; + else + bHigherBusyTxTraffic = _TRUE; + } + +#ifdef CONFIG_TRAFFIC_PROTECT +#define TX_ACTIVE_TH 10 +#define RX_ACTIVE_TH 20 +#define TRAFFIC_PROTECT_PERIOD_MS 4500 + + if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH + || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) { + + RTW_INFO(FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n", + FUNC_ADPT_ARG(padapter), + TRAFFIC_PROTECT_PERIOD_MS, + link_detect->NumTxOkInPeriod, + link_detect->NumRxUnicastOkInPeriod); + + rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS); + } +#endif + +#ifdef CONFIG_TDLS +#ifdef CONFIG_TDLS_AUTOSETUP + /* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */ + if (rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_TDLS) == _TRUE) { + if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) { + _rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN); + issue_tdls_dis_req(padapter, &txmgmt); + } + ptdlsinfo->watchdog_count++; + } +#endif /* CONFIG_TDLS_AUTOSETUP */ +#endif /* CONFIG_TDLS */ + +#ifdef CONFIG_SUPPORT_STATIC_SMPS + _ssmps_chk_by_tp(padapter); +#endif +#ifdef CONFIG_CTRL_TXSS_BY_TP + rtw_ctrl_tx_ss_by_tp(padapter); +#endif + + } + +#if 0 + session_tracker_chk_cmd(padapter, NULL); +#endif + +#ifdef CONFIG_BEAMFORMING +#ifdef RTW_WKARD_TX_DISABLE_BFEE + /*For each padapter*/ + rtw_core_bf_watchdog(padapter); +#endif +#endif + + pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0; + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0; + pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; + pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic; + pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic; + pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic; + pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; + pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; + pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; + + return bEnterPS; + +} + + +/* for 11n Logo 4.2.31/4.2.32 */ +void dynamic_update_bcn_check(_adapter *padapter) +{ + struct registry_priv *pregistrypriv = &padapter->registrypriv; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + + if (!padapter->registrypriv.wifi_spec) + return; + + if (!pregistrypriv->ht_enable || !is_supported_ht(pregistrypriv->wireless_mode)) + return; + + if (!MLME_IS_AP(padapter)) + return; + + if (pmlmeext->bstart_bss) { + /* In 10 * 2 = 20s, there are no legacy AP, update HT info */ + static u8 count = 1; + + if (count % 10 == 0) { + count = 1; +#ifdef CONFIG_80211N_HT + if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc) + && _FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) { + + if (rtw_ht_operation_update(padapter, padapter_link) > 0) + { + rtw_update_beacon(padapter, padapter_link, + _HT_CAPABILITY_IE_, NULL, _FALSE, 0); + rtw_update_beacon(padapter, padapter_link, + _HT_ADD_INFO_IE_, NULL, _TRUE, 0); + } + } +#endif /* CONFIG_80211N_HT */ + } + +#ifdef CONFIG_80211N_HT + /* In 2s, there are any legacy AP, update HT info, and then reset count */ + + if (_FALSE != ATOMIC_READ(&pmlmepriv->olbc) + && _FALSE != ATOMIC_READ(&pmlmepriv->olbc_ht)) { + + if (rtw_ht_operation_update(padapter, padapter_link) > 0) + { + rtw_update_beacon(padapter, padapter_link, + _HT_CAPABILITY_IE_, NULL, _FALSE, 0); + rtw_update_beacon(padapter, padapter_link, + _HT_ADD_INFO_IE_, NULL, _TRUE, 0); + + } + ATOMIC_SET(&pmlmepriv->olbc, _FALSE); + ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE); + count = 0; + } +#endif /* CONFIG_80211N_HT */ + count ++; + } +} + +struct turbo_edca_setting{ + u32 edca_ul; /* uplink, tx */ + u32 edca_dl; /* downlink, rx */ +}; + +#define TURBO_EDCA_ENT(UL, DL) {UL, DL} + +#define TURBO_EDCA_MODE_NUM 8 +static struct turbo_edca_setting ctrl_turbo_edca[TURBO_EDCA_MODE_NUM] = { + /* { UL, DL } */ + TURBO_EDCA_ENT(0x5e431c, 0x431c), /* mode 0 */ + + TURBO_EDCA_ENT(0x431c, 0x431c), /* mode 1 */ + + TURBO_EDCA_ENT(0x5e431c, 0x5e431c), /* mode 2 */ + + TURBO_EDCA_ENT(0x5ea42b, 0x5ea42b), /* mode 3 */ + + TURBO_EDCA_ENT(0x5ea42b, 0x431c), /* mode 4 */ + + TURBO_EDCA_ENT(0x6ea42b, 0x6ea42b), /* mode 5 */ + + TURBO_EDCA_ENT(0xa42b, 0xa42b), /* mode 6 */ + + TURBO_EDCA_ENT(0x5e431c, 0xa42b), /* mode 7 */ +}; + +void rtw_turbo_edca(_adapter *padapter) +{ + struct registry_priv *pregpriv = &padapter->registrypriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj); + u32 edca_be_ul = padapter->last_edca; + u32 edca_be_dl = padapter->last_edca; + u32 ac_parm = padapter->last_edca; + u8 ac; + u8 is_linked = _FALSE; + /* ToDo CONFIG_RTW_MLD: currently primary link only */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + u8 set_edca = _FALSE; + + if (padapter->dis_turboedca == DIS_TURBO) + return; + + #ifdef CONFIG_THERMAL_PROTECT + if (phl_com->drv_mode == RTW_DRV_MODE_HIGH_THERMAL) { + padapter->edca_reset = _TRUE; + return; + } + #endif/*CONFIG_THERMAL_PROTECT*/ + + if (padapter->edca_reset == _TRUE ) { + padapter->edca_reset = _FALSE; + set_edca = _TRUE; + } + + if (rtw_mi_check_status(padapter, MI_ASSOC)) + is_linked = _TRUE; + + if (is_linked != _TRUE) + return; + + if (pregpriv->wifi_spec == 1) + return; + + /* keep this condition at last check */ + if (padapter->dis_turboedca == DIS_TURBO_USE_MANUAL) { + if (padapter->edca_param_mode < TURBO_EDCA_MODE_NUM) { + + struct turbo_edca_setting param; + + param = ctrl_turbo_edca[padapter->edca_param_mode]; + edca_be_ul = param.edca_ul; + edca_be_dl = param.edca_dl; + } else { + edca_be_ul = padapter->edca_param_mode; + edca_be_dl = padapter->edca_param_mode; + } + } + + if (phl_com->phl_stats.tx_traffic.lvl == RTW_TFC_HIGH) + ac_parm = edca_be_ul; + else if (phl_com->phl_stats.tx_traffic.lvl != RTW_TFC_HIGH) + ac_parm = edca_be_dl; + else + return; + + if ((padapter->last_edca != ac_parm) || (set_edca == _TRUE)) { + ac = 0; + /*RTW_INFO("%s, edca(0x%08x), lvl(%d), sts(%d)\n", __func__, ac_parm, + phl_com->phl_stats.tx_traffic.lvl, phl_com->phl_stats.tx_traffic.sts);*/ + rtw_hw_set_edca(padapter, padapter_link, ac, ac_parm); + padapter->last_edca = ac_parm; + } +} + +u32 rtw_get_turbo_edca(_adapter *padapter, u8 aifs, u8 ecwmin, u8 ecwmax, u8 txop) +{ + struct registry_priv *pregpriv = &padapter->registrypriv; + u32 ret = 0; + u8 decide_txop = txop; + u8 default_txop = 0x5e; + u32 ac_parm = padapter->last_edca; + u8 ac = 0;/*BE*/ + + if (padapter->dis_turboedca == DIS_TURBO) + return ret; + + if (pregpriv->wifi_spec == 1) + return ret; + + if (default_txop > txop) + decide_txop = default_txop; + else + decide_txop = txop; + + ac_parm = aifs | (ecwmin << 8) | (ecwmax << 12) | (decide_txop << 16); + + return ac_parm; + +} + +void rtw_iface_dynamic_chk_wk_hdl(_adapter *padapter) +{ + rtw_turbo_edca(padapter); + + /* for debug purpose */ + _linked_info_dump(padapter); +} + +void rtw_dynamic_chk_wk_hdl(_adapter *padapter) +{ + rtw_mi_dynamic_chk_wk_hdl(padapter); + + + /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */ + { +#ifdef DBG_RX_COUNTER_DUMP + rtw_dump_rx_counters(padapter); +#endif + } + +#ifdef CONFIG_RTW_MULTI_AP + rtw_ch_util_rpt(padapter); +#endif + +#ifdef CONFIG_IPS_CHECK_IN_WD + /* always call rtw_ps_processor() at last one. */ + rtw_ps_processor(padapter); +#endif +} + +void rtw_dynamic_chk_wk_sw_hdl(_adapter *padapter) +{ +#ifdef CONFIG_RTW_MULTI_AP + rtw_ch_util_rpt(padapter); +#endif + + rtw_edcca_hal_update(adapter_to_dvobj(padapter)); +} + +void rtw_dynamic_chk_wk_hw_hdl(_adapter *padapter) +{ + rtw_mi_dynamic_chk_wk_hdl(padapter); + + /* if(check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)==_FALSE) */ + { +#ifdef DBG_RX_COUNTER_DUMP + rtw_dump_rx_counters(padapter); +#endif + } + +#ifdef CONFIG_IPS_CHECK_IN_WD + /* always call rtw_ps_processor() at last one. */ + rtw_ps_processor(padapter); +#endif + +#ifdef RTW_DETECT_HANG + rtw_is_hang_check(padapter); +#endif +} + +/* add for CONFIG_IEEE80211W, none 11w can use it */ +void reset_securitypriv_hdl(_adapter *padapter) +{ + rtw_reset_securitypriv(padapter); +} + +#ifdef CONFIG_IOCTL_CFG80211 +#if 0 /*!CONFIG_PHL_ARCH*/ +static u8 _p2p_roch_cmd(_adapter *adapter + , u64 cookie, struct wireless_dev *wdev + , struct ieee80211_channel *ch, enum nl80211_channel_type ch_type + , unsigned int duration + , u8 flags +) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct p2p_roch_parm *roch_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 cancel = duration ? 0 : 1; + u8 res = _SUCCESS; + + roch_parm = (struct p2p_roch_parm *)rtw_zmalloc(sizeof(struct p2p_roch_parm)); + if (roch_parm == NULL) { + res = _FAIL; + goto exit; + } + + roch_parm->cookie = cookie; + roch_parm->wdev = wdev; + if (!cancel) { + _rtw_memcpy(&roch_parm->ch, ch, sizeof(struct ieee80211_channel)); + roch_parm->ch_type = ch_type; + roch_parm->duration = duration; + } + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != p2p_protocol_wk_hdl(adapter, cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK, (u8 *)roch_parm)) + res = _FAIL; + rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm)); + res = _FAIL; + goto exit; + } + + parm->ec_id = P2P_PROTO_WK_CID; + parm->type = cancel ? P2P_CANCEL_RO_CH_WK : P2P_RO_CH_WK; + parm->size = sizeof(*roch_parm); + parm->pbuf = (u8 *)roch_parm; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)roch_parm, sizeof(*roch_parm)); + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + } + +exit: + return res; +} +#endif /*!CONFIG_PHL_ARCH*/ + +inline u8 rtw_mgnt_tx_cmd(_adapter *adapter, u8 tx_band, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack, u8 flags) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct mgnt_tx_parm *mgnt_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + mgnt_parm = (struct mgnt_tx_parm *)rtw_zmalloc(sizeof(struct mgnt_tx_parm)); + if (mgnt_parm == NULL) { + res = _FAIL; + goto exit; + } + + mgnt_parm->tx_band = tx_band; + mgnt_parm->tx_ch = tx_ch; + mgnt_parm->no_cck = no_cck; + mgnt_parm->buf = buf; + mgnt_parm->len = len; + mgnt_parm->wait_ack = wait_ack; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != rtw_mgnt_tx_handler(adapter, (u8 *)mgnt_parm)) + res = _FAIL; + rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm)); + res = _FAIL; + goto exit; + } + + parm->ec_id = MGNT_TX_WK_CID; + parm->type = 0; + parm->size = sizeof(*mgnt_parm); + parm->pbuf = (u8 *)mgnt_parm; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)mgnt_parm, sizeof(*mgnt_parm)); + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + } + +exit: + return res; +} +#endif + +#ifdef CONFIG_AP_MODE + +static void rtw_chk_hi_queue_hdl(_adapter *padapter) +{ + struct sta_info *psta_bmc; + struct sta_priv *pstapriv = &padapter->stapriv; + systime start = rtw_get_current_time(); + u8 empty = _FALSE; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + psta_bmc = rtw_get_bcmc_stainfo(padapter, padapter_link); + if (!psta_bmc) + return; + + rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); + + while (_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms()) { + rtw_msleep_os(100); + rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); + } + + if (psta_bmc->sleepq_len == 0) { + if (empty == _SUCCESS) { + bool update_tim = _FALSE; + + if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) + update_tim = _TRUE; + + rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0); + rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0); + + if (update_tim == _TRUE) + _update_beacon(padapter, padapter_link, + _TIM_IE_, NULL, _TRUE, 0,"bmc sleepq and HIQ empty"); + } else /* re check again */ + rtw_chk_hi_queue_cmd(padapter); + + } + +} + +u8 rtw_chk_hi_queue_cmd(_adapter *padapter) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + u8 res = _SUCCESS; + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; + +} +#endif /* CONFIG_AP_MODE */ + +#if 0 /*def RTW_PHL_DBG_CMD*/ + +u8 sample_txwd[] = +{ +/*dword 00*/ 0x80, 0x00, 0x40, 0x00, +/*dword 01*/ 0x00, 0x00, 0x00, 0x00, +/*dword 02*/ 0xF2, 0x05, 0x00, 0x00, +/*dword 03*/ 0x3E, 0x11, 0x00, 0x00, +/*dword 04*/ 0x00, 0x00, 0x00, 0x00, +/*dword 05*/ 0x00, 0x00, 0x00, 0x00, +/*dword 06*/ 0x00, 0x07, 0x9B, 0x63, +/*dword 07*/ 0x3F, 0x00, 0x00, 0x00, +/*dword 08*/ 0x00, 0x00, 0x00, 0x00, +/*dword 09*/ 0x00, 0x00, 0x00, 0x00, +/*dword 10*/ 0x0C, 0x00, 0x00, 0x00, +/*dword 11*/ 0x00, 0x00, 0x00, 0x00, +}; + +#define WD_SPEC(_name, _idx_dw, _bit_start, _bit_end) { \ + .name = (_name), \ + .idx_dw = (_idx_dw), \ + .bit_start = (_bit_start), \ + .bit_end = (_bit_end) \ +} + +struct parse_wd { + char name[32]; + u8 idx_dw; + u8 bit_start; + u8 bit_end; +}; + +#define MAX_PHL_CMD_LEN 200 +#define MAX_PHL_CMD_NUM 10 +#define MAX_PHL_CMD_STR_LEN 200 + +char *get_next_para_str(char *para) +{ + return (para+MAX_PHL_CMD_STR_LEN); +} + +static struct parse_wd parse_txwd_8852ae_full[] = { + WD_SPEC("EN_HWSEQ_MODE" , 0, 0, 1), + WD_SPEC("HW_SSN_SEL" , 0, 2, 3), + WD_SPEC("SMH_EN" , 0, 4, 4), + WD_SPEC("HWAMSDU" , 0, 5, 5), + WD_SPEC("HW_AES_IV" , 0, 6, 6), + WD_SPEC("WD page" , 0, 7, 7), + WD_SPEC("CHK_EN" , 0, 8, 8), + WD_SPEC("WP_INT" , 0, 9, 9), + WD_SPEC("STF mode" , 0, 10, 10), + WD_SPEC("HEADERwLLC_LEN" , 0, 11, 15), + WD_SPEC("CHANNEL_DMA" , 0, 16, 19), + WD_SPEC("FW_download" , 0, 20, 20), + WD_SPEC("PKT_OFFSET" , 0, 21, 21), + WD_SPEC("WDINFO_EN" , 0, 22, 22), + WD_SPEC("MOREDATA" , 0, 23, 23), + WD_SPEC("WP_OFFSET" , 0, 24, 31), + + WD_SPEC("SHCUT_CAMID" , 1, 0, 7), + WD_SPEC("DMA_TXAGG_NUM" , 1, 8, 15), + WD_SPEC("PLD(Packet ID)" , 1, 16, 31), + + WD_SPEC("TXPKTSIZE" , 2, 0, 13), + WD_SPEC("RU_TC" , 2, 14, 16), + WD_SPEC("QSEL" , 2, 17, 22), + WD_SPEC("TID_indicate" , 2, 23, 23), + WD_SPEC("MACID" , 2, 24, 30), + WD_SPEC("RSVD" , 2, 31, 31), + + WD_SPEC("Wifi_SEQ" , 3, 0, 11), + WD_SPEC("AGG_EN" , 3, 12, 12), + WD_SPEC("BK" , 3, 13, 13), + WD_SPEC("RTS_TC" , 3, 14, 19), + WD_SPEC("DATA_TC" , 3, 20, 25), + WD_SPEC("MU_2nd_TC" , 3, 26, 28), + WD_SPEC("MU_TC" , 3, 29, 31), + + WD_SPEC("TIMESTAMP" , 4, 0, 15), + WD_SPEC("AES_IV_L" , 4, 16, 31), + + WD_SPEC("AES_IV_H" , 5, 0, 31), + + WD_SPEC("MBSSID" , 6, 0, 3), + WD_SPEC("Multiport_ID" , 6, 4, 6), + WD_SPEC("RSVD" , 6, 7, 7), + WD_SPEC("DATA_BW_ER" , 6, 8, 8), + WD_SPEC("DISRTSFB" , 6, 9, 9), + WD_SPEC("DISDATAFB" , 6, 10, 10), + WD_SPEC("DATA_LDPC" , 6, 11, 11), + WD_SPEC("DATA_STBC" , 6, 12, 13), + WD_SPEC("DATA_DCM" , 6, 14, 14), + WD_SPEC("DATA_ER" , 6, 15, 15), + WD_SPEC("DataRate" , 6, 16, 24), + WD_SPEC("GI_LTF" , 6, 25, 27), + WD_SPEC("DATA_BW" , 6, 28, 29), + WD_SPEC("USERATE_SEL" , 6, 30, 30), + WD_SPEC("ACK_CH_INFO" , 6, 31, 31), + + WD_SPEC("MAX_AGG_NUM" , 7, 0, 7), + WD_SPEC("BCN_SRCH_SEQ" , 7, 8, 9), + WD_SPEC("NAVUSEHDR" , 7, 10, 10), + WD_SPEC("BMC" , 7, 11, 11), + WD_SPEC("A_CTRL_BQR" , 7, 12, 12), + WD_SPEC("A_CTRL_UPH" , 7, 13, 13), + WD_SPEC("A_CTRL_BSR" , 7, 14, 14), + WD_SPEC("A_CTRL_CAS" , 7, 15, 15), + WD_SPEC("DATA_RTY_LOWEST_RATE" , 7, 16, 24), + WD_SPEC("DATA_TXCNT_LMT" , 7, 25, 30), + WD_SPEC("DATA_TXCNT_LMT_SEL" , 7, 31, 31), + + WD_SPEC("SEC_CAM_IDX" , 8, 0, 7), + WD_SPEC("SEC_HW_ENC" , 8, 8, 8), + WD_SPEC("SECTYPE" , 8, 9, 12), + WD_SPEC("lifetime_sel" , 8, 13, 15), + WD_SPEC("RSVD" , 8, 16, 16), + WD_SPEC("FORCE_TXOP" , 8, 17, 17), + WD_SPEC("AMPDU_DENSITY" , 8, 18, 20), + WD_SPEC("LSIG_TXOP_EN" , 8, 21, 21), + WD_SPEC("TXPWR_OFSET_TYPE" , 8, 22, 24), + WD_SPEC("RSVD" , 8, 25, 25), + WD_SPEC("obw_cts2self_dup_type" , 8, 26, 29), + WD_SPEC("RSVD" , 8, 30, 31), + + WD_SPEC("Signaling_TA_PKT_EN" , 9, 0, 0), + WD_SPEC("NDPA" , 9, 1, 2), + WD_SPEC("SND_PKT_SEL" , 9, 3, 5), + WD_SPEC("SIFS_Tx" , 9, 6, 6), + WD_SPEC("HT_DATA_SND" , 9, 7, 7), + WD_SPEC("RSVD" , 9, 8, 8), + WD_SPEC("RTT_EN" , 9, 9, 9), + WD_SPEC("SPE_RPT" , 9, 10, 10), + WD_SPEC("BT_NULL" , 9, 11, 11), + WD_SPEC("TRI_FRAME" , 9, 12, 12), + WD_SPEC("NULL_1" , 9, 13, 13), + WD_SPEC("NULL_0" , 9, 14, 14), + WD_SPEC("RAW" , 9, 15, 15), + WD_SPEC("Group_bit" , 9, 16, 23), + WD_SPEC("RSVD" , 9, 24, 25), + WD_SPEC("BCNPKT_TSF_CTRL" , 9, 26, 26), + WD_SPEC("Signaling_TA_PKT_SC" , 9, 27, 30), + WD_SPEC("FORCE_BSS_CLR" , 9, 31, 31), + + WD_SPEC("SW_DEFINE" , 10, 0, 3), + WD_SPEC("RSVD" , 10, 4, 26), + WD_SPEC("RTS_EN" , 10, 27, 27), + WD_SPEC("CTS2SELF" , 10, 28, 28), + WD_SPEC("CCA_RTS" , 10, 29, 30), + WD_SPEC("HW_RTS_EN" , 10, 31, 31), + + WD_SPEC("RSVD" , 11, 0, 3), + WD_SPEC("NDPA_duration" , 11, 4, 26), +}; + +static struct parse_wd parse_rxwd_8852ae[] = { + WD_SPEC("PKT_LEN" , 0, 0, 13), + WD_SPEC("SHIFT" , 0, 14, 15), + WD_SPEC("WL_HD_IV_LEN" , 0, 16, 21), + WD_SPEC("BB_SEL" , 0, 22, 22), + WD_SPEC("MAC_INFO_VLD" , 0, 23, 23), + WD_SPEC("RPKT_TYPE" , 0, 24, 27), + WD_SPEC("DRV_INFO_SIZE" , 0, 28, 30), + WD_SPEC("LONG_RXD" , 0, 31, 31), + + WD_SPEC("PPDU_TYPE" , 1, 0, 3), + WD_SPEC("PPDU_CNT" , 1, 4, 6), + WD_SPEC("SR_EN" , 1, 7, 7), + WD_SPEC("USER_ID" , 1, 8, 15), + WD_SPEC("RX_DATARATE" , 1, 16, 24), + WD_SPEC("RX_GI_LTF" , 1, 25, 27), + WD_SPEC("NON_SRG_PPDU" , 1, 28, 28), + WD_SPEC("INTER_PPDU" , 1, 29, 29), + WD_SPEC("BW" , 1, 30, 31), + + WD_SPEC("FREERUN_CNT" , 2, 0, 31), + + WD_SPEC("A1_MATCH" , 3, 1, 1), + WD_SPEC("SW_DEC" , 3, 2, 2), + WD_SPEC("HW_DEC" , 3, 3, 3), + WD_SPEC("AMPDU" , 3, 4, 4), + WD_SPEC("AMPDU_END_PKT" , 3, 5, 5), + WD_SPEC("AMSDU" , 3, 6, 6), + WD_SPEC("AMSDU_CUT" , 3, 7, 7), + WD_SPEC("LAST_MSDU" , 3, 8, 8), + WD_SPEC("BYPASS" , 3, 9, 9), + WD_SPEC("CRC32" , 3, 10, 10), + WD_SPEC("MAGIC_WAKE" , 3, 11, 11), + WD_SPEC("UNICAST_WAKE" , 3, 12, 12), + WD_SPEC("PATTERN_WAKE" , 3, 13, 13), + WD_SPEC("GET_CH_INFO" , 3, 14, 14), + WD_SPEC("RX_STATISTICS" , 3, 15, 15), + WD_SPEC("PATTERN_IDX" , 3, 16, 20), + WD_SPEC("TARGET_IDC" , 3, 21, 23), + WD_SPEC("CHKSUM_OFFLOAD_EN" , 3, 24, 24), + WD_SPEC("WITH_LLC" , 3, 25, 25), + WD_SPEC("RSVD" , 3, 26, 31), + + WD_SPEC("TYPE" , 4, 0, 1), + WD_SPEC("MC" , 4, 2, 2), + WD_SPEC("BC" , 4, 3, 3), + WD_SPEC("MD" , 4, 4, 4), + WD_SPEC("MF" , 4, 5, 5), + WD_SPEC("PWR" , 4, 6, 6), + WD_SPEC("QOS" , 4, 7, 7), + WD_SPEC("TID" , 4, 8, 11), + WD_SPEC("EOSP" , 4, 12, 12), + WD_SPEC("HTC" , 4, 13, 13), + WD_SPEC("QNULL" , 4, 14, 14), + WD_SPEC("RSVD" , 4, 15, 15), + WD_SPEC("SEQ" , 4, 16, 27), + WD_SPEC("FRAG" , 4, 28, 31), + + WD_SPEC("SEC_CAM_IDX" , 5, 0, 7), + WD_SPEC("ADDR_CAM" , 5, 8, 15), + WD_SPEC("MAC_ID" , 5, 16, 23), + WD_SPEC("RX_PL_ID" , 5, 24, 27), + WD_SPEC("ADDR_CAM_VLD" , 5, 28, 28), + WD_SPEC("ADDR_FWD_EN" , 5, 29, 29), + WD_SPEC("RX_PL_MATCH" , 5, 30, 30), + WD_SPEC("RSVD" , 5, 31, 31), +}; + + +enum WD_TYPE { + TXWD_INFO = 0, + TXWD_INFO_BODY, + RXWD, + +}; + +u32 get_txdesc_element_val(u32 val_dw, u8 bit_start, u8 bit_end) +{ + u32 mask = 0; + u32 i = 0; + + if(bit_start>31 + || bit_end>31 + || (bit_start>bit_end)){ + printk("[%s] error %d %d\n", __FUNCTION__, bit_start, bit_end); + return 0; + } + + for(i = bit_start; i<=bit_end; i++){ + mask |= (1<>bit_start); +} + + +void parse_wd_8852ae(_adapter *adapter, u32 type, u32 idx_wd, u8 *wd) +{ + u32 i, val = 0; + u32 cur_dw = 0xFF; + u32 idx, val_dw = 0; + u32 array_size = 0; + struct parse_wd *parser = NULL; + + if(wd==NULL) + return; + + if(type == TXWD_INFO_BODY){ + parser = parse_txwd_8852ae_full; + array_size = ARRAY_SIZE(parse_txwd_8852ae_full); + } + else if(type == RXWD){ + parser = parse_rxwd_8852ae; + array_size = ARRAY_SIZE(parse_rxwd_8852ae); + } + + for(i = 0; i>>> WD[%03d].dw%02d = 0x%08x \n", idx_wd, cur_dw, val_dw); + } + + val = get_txdesc_element_val(val_dw, + parser[i].bit_start, parser[i].bit_end); + + printk("%s[%d:%d] = (0x%x)\n", + parser[i].name, + parser[i].bit_end, parser[i].bit_start, val); + } + printk("\n"); + +} + + +void compare_wd_8852ae(_adapter *adapter, u32 type, u8 *wd1, u8 *wd2) +{ + u32 i, val1, val2 = 0; + u32 cur_dw = 0xFF; + u32 idx, val_dw1, val_dw2 = 0; + u32 array_size = 0; + struct parse_wd *parser = NULL; + + if((wd1==NULL) ||(wd2==NULL)) + return; + + if(type == TXWD_INFO_BODY){ + parser = parse_txwd_8852ae_full; + array_size = ARRAY_SIZE(parse_txwd_8852ae_full); + } + + for(i = 0; icore_logs; + u32 idx = 0; + + printk("drvTx MAP"); + for(idx=0; idxdrvTx[idx]; + if(idx >= log->txCnt_all) + break; + printk("[drvTx %03d]\n", idx); + printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]); + } + + printk("========= \n\n"); + printk("phlTx MAP"); + for(idx=0; idxphlTx[idx]; + u32 idx1 = 0; + if(idx >= log->txCnt_phl) + break; + printk("[phlTx %03d]\n", idx); + printk("type=%d totalSz=%d fragNum=%d\n", record->type, record->totalSz, record->fragNum); + for(idx1=0; idx1fragNum; idx1++){ + printk("frag#%d: len=%d virtaddr=%p \n", idx1, + record->fragLen[idx1], record->virtAddr[idx1]); + printk("frag#%d: phyAddrH=%d phyAddrL=%p \n", idx1, + record->phyAddrH[idx1], record->phyAddrL[idx1]); + } + } + + printk("========= \n\n"); + printk("TxRcycle MAP"); + for(idx=0; idxtxRcycle[idx]; + u32 idx1 = 0; + if(idx >= log->txCnt_recycle) + break; + printk("[TxRcycle %03d]\n", idx); + printk("type=%d totalSz=%d fragNum=%d\n", record->type, record->totalSz, record->fragNum); + for(idx1=0; idx1fragNum; idx1++){ + printk("frag#%d: len=%d virtaddr=%p \n", idx1, + record->fragLen[idx1], record->virtAddr[idx1]); + printk("frag#%d: phyAddrH=%d phyAddrL=%p \n", idx1, + record->phyAddrH[idx1], record->phyAddrL[idx1]); + } + } +} + +void core_dump_map_rx(_adapter *adapter) +{ + struct core_logs *log = &adapter->core_logs; + u32 idx = 0; + + printk("drvRx MAP"); + for(idx=0; idxdrvRx[idx]; + if(idx >= log->rxCnt_all) + break; + printk("[drvRx %03d]\n", idx); + printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]); + printk("wl_seq=%d wl_type=0x%x wl_subtype=0x%x\n", record->wl_seq, record->wl_type, record->wl_subtype); + } + + printk("========= \n\n"); + printk("phlRx MAP"); + for(idx=0; idxphlRx[idx]; + if(idx >= log->rxCnt_phl) + break; + printk("[phlRx %03d]\n", idx); + printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]); + } + + printk("========= \n\n"); + printk("rxRcycle MAP"); + for(idx=0; idxrxRcycle[idx]; + if(idx >= log->rxCnt_recycle) + break; + printk("[rxRcycle %03d]\n", idx); + printk("type=%d totalSz=%d virtAddr=%p\n", record->type, record->totalSz, record->virtAddr[0]); + } + +} + + +void core_dump_record(_adapter *adapter, u8 dump_type) +{ + struct core_logs *log = &adapter->core_logs; + u32 idx = 0; + + printk("txCnt_all: %d (%d) \n", log->txCnt_all, log->txCnt_all%CORE_LOG_NUM); + printk("txCnt_data: %d \n", log->txCnt_data); + printk("txCnt_mgmt: %d \n", log->txCnt_mgmt); + printk("txCnt_phl: %d (%d), Sz=%d \n", log->txCnt_phl, log->txCnt_phl%CORE_LOG_NUM, log->txSize_phl); + printk("txCnt_recycle: %d (%d), Sz=%d \n", log->txCnt_recycle, log->txCnt_recycle%CORE_LOG_NUM, log->txSize_recycle); + + printk("rxCnt_all: %d (%d) \n", log->rxCnt_all, log->rxCnt_all%CORE_LOG_NUM); + printk("rxCnt_data: %d (retry=%d)\n", log->rxCnt_data, log->rxCnt_data_retry); + printk("rxCnt_mgmt: %d \n", log->rxCnt_mgmt); + printk("rxCnt_phl: %d (%d), Sz=%d \n", log->rxCnt_phl, log->rxCnt_phl%CORE_LOG_NUM, log->rxSize_phl); + printk("rxCnt_recycle: %d (%d), Sz=%d\n", log->rxCnt_recycle, log->rxCnt_recycle%CORE_LOG_NUM, log->rxSize_recycle); +#ifdef CONFIG_RTW_CORE_RXSC + printk("enable_rxsc: %d \n", adapter->enable_rxsc); + printk("rxCnt_data: orig=%d shortcut=%d(ratio=%d)\n", + log->rxCnt_data_orig, log->rxCnt_data_shortcut, + log->rxCnt_data_shortcut*100/(log->rxCnt_data_orig+log->rxCnt_data_shortcut)); + printk("rxCnt_coreInd: %d \n", log->rxCnt_coreInd); +#endif + + if(dump_type == REC_DUMP_TX){ + core_dump_map_tx(adapter); + } + else if(dump_type == REC_DUMP_RX){ + core_dump_map_rx(adapter); + } + else if(dump_type == REC_DUMP_ALL){ + core_dump_map_tx(adapter); + core_dump_map_rx(adapter); + } +} + +void core_add_record(_adapter *adapter, u8 type, void *p) +{ + struct core_logs *log = &adapter->core_logs; + + if(!adapter->record_enable) + return; + + if(type == REC_TX_DATA){ + u32 idx = log->txCnt_all%CORE_LOG_NUM; + struct core_record *record = &(log->drvTx[idx]); + struct sk_buff *skb = p; + + log->txCnt_data++; + record->type = type; + record->totalSz = skb->len; + record->virtAddr[0] = skb->data; + } + + if(type == REC_TX_MGMT){ + u32 idx = log->txCnt_all%CORE_LOG_NUM; + struct core_record *record = &(log->drvTx[idx]); + struct xmit_frame *pxframe = p; + + log->txCnt_mgmt++; + record->type = type; + record->totalSz = pxframe->attrib.pktlen; + record->virtAddr[0] = pxframe->buf_addr; + } + + if(type == REC_TX_PHL || type == REC_TX_PHL_RCC){ + u32 idx = 0; + struct core_record *record = NULL; + struct rtw_xmit_req *txreq = p; + + if(type == REC_TX_PHL){ + idx = log->txCnt_phl%CORE_LOG_NUM; + record = &(log->phlTx[idx]); + log->txCnt_phl++; + } + + if(type == REC_TX_PHL_RCC){ + idx = log->txCnt_recycle%CORE_LOG_NUM; + record = &(log->txRcycle[idx]); + log->txCnt_recycle++; + } + + record->type = type; + record->totalSz = 0; + record->fragNum = txreq->pkt_cnt; + + { + struct rtw_pkt_buf_list *pkt_list =(struct rtw_pkt_buf_list *)txreq->pkt_list; + u32 idx1 = 0; + for(idx1=0; idx1pkt_cnt; idx1++){ + if(idx1 >= MAX_FRAG){ + printk("!! WARN[%s][%d] type=%d frag>= %d \n", + __FUNCTION__, __LINE__, type, MAX_FRAG); + break; + } + record->totalSz += pkt_list->length; + record->fragLen[idx1] = pkt_list->length; + record->virtAddr[idx1] = pkt_list->vir_addr; + record->phyAddrL[idx1] = pkt_list->phy_addr_l; + record->phyAddrH[idx1] = pkt_list->phy_addr_h; + pkt_list++; + } + } + + if(type == REC_TX_PHL) + log->txSize_phl += record->totalSz; + else if(type == REC_TX_PHL_RCC) + log->txSize_recycle += record->totalSz; + + } + + if(type == REC_RX_PHL || type == REC_RX_PHL_RCC){ + u32 idx = 0; + struct core_record *record = NULL; + struct rtw_recv_pkt *rx_req = p; + struct rtw_pkt_buf_list *pkt = rx_req->pkt_list; + + if(type == REC_RX_PHL){ + idx = log->rxCnt_phl%CORE_LOG_NUM; + record = &(log->phlRx[idx]); + log->rxCnt_phl++; + } + + if(type == REC_RX_PHL_RCC){ + idx = log->rxCnt_recycle%CORE_LOG_NUM; + record = &(log->rxRcycle[idx]); + log->rxCnt_recycle++; + } + + record->type = type; + record->totalSz = pkt->length; + record->virtAddr[0] = pkt->vir_addr; + + if(type == REC_RX_PHL) + log->rxSize_phl += record->totalSz; + else if(type == REC_RX_PHL_RCC) + log->rxSize_recycle += record->totalSz; + } + + if(type == REC_RX_DATA || type == REC_RX_MGMT){ + u32 idx = log->rxCnt_all%CORE_LOG_NUM; + struct core_record *record = &(log->drvRx[idx]); + union recv_frame *prframe = p; + struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; + + if(type == REC_RX_DATA){ + log->rxCnt_data++; + } + + if(type == REC_RX_MGMT){ + log->rxCnt_mgmt++; + } + + record->type = type; + record->totalSz = prframe->u.hdr.len; + record->virtAddr[0] = prframe->u.hdr.rx_data; + + record->wl_seq = pattrib->seq_num; + record->wl_type = pattrib->wl_type; + record->wl_subtype = pattrib->wl_subtype; + + } + + if(type == REC_RX_DATA_RETRY){ + log->rxCnt_data_retry++; + } + + log->txCnt_all = log->txCnt_mgmt + log->txCnt_data; + log->rxCnt_all = log->rxCnt_mgmt + log->rxCnt_data; +} + + +void phl_dump_map_tx(_adapter *adapter) +{ + struct phl_logs *log = &adapter->phl_logs; + u32 idx = 0; + + printk("txBd MAP"); + for(idx=0; idxtxBd[idx]; + if(idx >= log->txCnt_bd) + break; + printk("[txBd %03d]\n", idx); + { + u8 *tmp=record->bd_buf; + u32 len = record->bd_len; + u32 idx1 = 0; + if(tmp == NULL) + break; + for(idx1=0; idx1txWd[idx]; + if(idx >= log->txCnt_wd) + break; + printk("[txWd %03d]\n", idx); + { + u8 *tmp=record->wd_buf; + u32 len = record->wd_len; + u32 idx1 = 0; + if(tmp == NULL) + break; + for(idx1=0; idx1wd_buf); + //compare_wd_8852ae(adapter, TXWD_INFO_BODY, record->wd_buf, sample_txwd); + } + + printk("========= \n\n"); + printk("wpRecycle MAP"); + for(idx=0; idxwpRecycle[idx]; + if(idx >= log->txCnt_recycle) + break; + printk("[txRecycle %03d]\n", idx); + printk("wp_seq=%d \n", record->wp_seq); + } +} + +void phl_dump_map_rx(_adapter *adapter) +{ + struct phl_logs *log = &adapter->phl_logs; + u32 idx = 0; + + printk("rxPciMap MAP"); + for(idx=0; idxrxPciMap[idx]; + if(idx >= log->rxCnt_map) + break; + printk("[rxPciMap %03d]\n", idx); + printk("phyAddrL=%p len=%d\n", record->phyAddrL, record->map_len); + } + + + printk("========= \n\n"); + printk("rxPciUnmap MAP"); + for(idx=0; idxrxPciUnmap[idx]; + if(idx >= log->rxCnt_unmap) + break; + printk("[rxPciUnmap %03d]\n", idx); + printk("phyAddrL=%p len=%d\n", record->phyAddrL, record->map_len); + } + + printk("========= \n\n"); + printk("rxWd MAP"); + for(idx=0; idxrxWd[idx]; + if(idx >= log->rxCnt_wd) + break; + printk("[rxWd %03d]\n", idx); + { + u8 *tmp = record->wd_buf; + u32 len = record->wd_len; + u32 idx1 = 0; + if(tmp == NULL) + break; + for(idx1=0; idx1wd_buf); + } + + printk("========= \n\n"); + printk("rxAmpdu MAP"); + for(idx=0; idx= log->rxCnt_ampdu) + break; + printk("[rxAmpdu %03d] = %d\n", idx, log->rxAmpdu[idx]); + } + +} + +void phl_dump_record(_adapter *adapter, u8 dump_type) +{ + struct phl_logs *log = &adapter->phl_logs; + u32 idx = 0; + + printk("txBd: %d (%d) \n", log->txCnt_bd, log->txCnt_bd%CORE_LOG_NUM); + printk("txWd: %d (%d) \n", log->txCnt_wd, log->txCnt_wd%CORE_LOG_NUM); + printk("wpCnt_recycle: %d (%d) \n", log->txCnt_recycle, log->txCnt_recycle%CORE_LOG_NUM); + + printk("rxMap: %d (%d), Sz=%d \n", log->rxCnt_map, log->rxCnt_map%CORE_LOG_NUM, log->rxSize_map); + printk("rxUnmap: %d (%d), Sz=%d \n", log->rxCnt_unmap, log->txCnt_wd%CORE_LOG_NUM, log->rxSize_map); + printk("rxWd: %d (%d) \n", log->rxCnt_wd, log->rxCnt_wd%CORE_LOG_NUM); + printk("rxCnt_ampdu: %d (%d) \n", log->rxCnt_ampdu, log->rxCnt_ampdu%CORE_LOG_NUM); + + if(dump_type == REC_DUMP_TX) + phl_dump_map_tx(adapter); + else if(dump_type == REC_DUMP_RX) + phl_dump_map_rx(adapter); + else if(dump_type == REC_DUMP_ALL){ + phl_dump_map_tx(adapter); + phl_dump_map_rx(adapter); + } +} + +u32 tmp_rx_last_ppdu = 0; + +void phl_add_record(void *d, u8 type, void *p, u32 num) +{ + struct dvobj_priv *pobj = (struct dvobj_priv *)d; + _adapter *adapter = dvobj_get_primary_adapter(pobj); + struct phl_logs *log = &adapter->phl_logs; + + if(!adapter->record_enable) + return; + + if(type == REC_TXWD){ + u32 idx = log->txCnt_wd%CORE_LOG_NUM; + struct record_txwd *record = &(log->txWd[idx]); + + log->txCnt_wd++; + record->wd_len = num; + memset((u8 *)record->wd_buf, 0, MAX_TXWD_SIZE); + memcpy((u8 *)record->wd_buf, p, num); + } + + if(type == REC_TXBD){ + u32 idx = log->txCnt_bd%CORE_LOG_NUM; + struct record_txbd *record = &(log->txBd[idx]); + + log->txCnt_bd++; + record->bd_len = num; + memset((u8 *)record->bd_buf, 0, MAX_TXBD_SIZE); + memcpy((u8 *)record->bd_buf, p, num); + } + + if(type == REC_WP_RCC){ + u32 idx = log->txCnt_recycle%CORE_LOG_NUM; + struct record_wp_rcc *record = &(log->wpRecycle[idx]); + + log->txCnt_recycle++; + record->wp_seq = num; + } + + if(type == REC_RX_MAP || type == REC_RX_UNMAP){ + struct record_pci *record = NULL; + if(type == REC_RX_MAP) { + u32 idx = log->rxCnt_map%CORE_LOG_NUM; + record = &(log->rxPciMap[idx]); + log->rxCnt_map++; + log->rxSize_map+=num; + } + else if(type == REC_RX_UNMAP) { + u32 idx = log->rxCnt_unmap%CORE_LOG_NUM; + record = &(log->rxPciUnmap[idx]); + log->rxCnt_unmap++; + log->rxSize_map+=num; + } + record->phyAddrL = p; + record->map_len = num; + } + + if(type == REC_RXWD){ + u32 idx = log->rxCnt_wd%CORE_LOG_NUM; + struct record_rxwd *record = &(log->rxWd[idx]); + + log->rxCnt_wd++; + record->wd_len = num; + memset((u8 *)record->wd_buf, 0, MAX_RXWD_SIZE); + memcpy((u8 *)record->wd_buf, p, num); + } + + if(type == REC_RX_AMPDU){ + u32 idx = 0; + + if(log->rxCnt_ampdu == 0 && (log->rxAmpdu[0] == 0)) + tmp_rx_last_ppdu = num; + + if(tmp_rx_last_ppdu != num){ + tmp_rx_last_ppdu = num; + + log->rxCnt_ampdu ++; + idx = log->rxCnt_ampdu%CORE_LOG_NUM; + log->rxAmpdu[idx] = 1; + } + else{ + idx = log->rxCnt_ampdu%CORE_LOG_NUM; + log->rxAmpdu[idx]++; + } +} + +} + +void core_cmd_record_trx(_adapter *adapter, void *cmd_para, u32 para_num) +{ + u32 idx = 0; + char *para = (char *)cmd_para; + + if(para_num<=0) + return; + + if(!strcmp(para, "start")){ + u8 *log = NULL; + log = (u8*)&adapter->core_logs; + memset(log, 0, sizeof(struct core_logs)); + log = (u8*)&adapter->phl_logs; + memset(log, 0, sizeof(struct phl_logs)); + adapter->record_enable = 1; + }else if(!strcmp(para, "stop")){ + adapter->record_enable = 0; + }else if(!strcmp(para, "dump")){ + u32 dump_type = 0; + para=get_next_para_str(para); + sscanf(para, "%d", &dump_type); + phl_dump_record(adapter, (u8)dump_type); + } +} + +void reset_txforce_para(_adapter *adapter) +{ + adapter->txForce_rate = INV_TXFORCE_VAL; + adapter->txForce_agg = INV_TXFORCE_VAL; + adapter->txForce_aggnum = INV_TXFORCE_VAL; + adapter->txForce_gi = INV_TXFORCE_VAL; +} + +void core_cmd_txforce(_adapter *adapter, void *cmd_para, u32 para_num) +{ + u32 idx = 0; + char *para = (char *)cmd_para; + bool is_txforce_apply = true; + + if (para_num <= 0) + return; + + if (!strcmp(para, "start")) { + adapter->txForce_enable = 1; + reset_txforce_para(adapter); + } else if(!strcmp(para, "stop")) { + adapter->txForce_enable = 0; + reset_txforce_para(adapter); + } else if (!strcmp(para, "rate")) { + u32 rate = 0; + para = get_next_para_str(para); + sscanf(para, "%x", &rate); + adapter->txForce_rate = rate; + } else if (!strcmp(para, "agg")) { + u32 agg = 0; + para = get_next_para_str(para); + sscanf(para, "%x", &agg); + adapter->txForce_agg = agg; + } else if (!strcmp(para, "aggnum")) { + u32 aggnum = 0; + para = get_next_para_str(para); + sscanf(para, "%d", &aggnum); + adapter->txForce_aggnum = aggnum; + } else if (!strcmp(para, "gi")) { + u32 gi = 0; + para = get_next_para_str(para); + sscanf(para, "%d", &gi); + adapter->txForce_gi = gi; + } else if (!strcmp(para, "macid")) { + + } else if (!strcmp(para, "retry")) { + + } else { + is_txforce_apply = false; + } + +#ifdef CONFIG_CORE_TXSC + if (is_txforce_apply) + txsc_clear(adapter); +#endif +} + +#ifdef CONFIG_RTW_CORE_RXSC +void core_cmd_rxsc(_adapter *adapter, void *cmd_para, u32 para_num) +{ + u32 idx = 0; + char *para = (char *)cmd_para; + + printk("core_cmd_rxsc \n"); + + if(para_num<=0) + return; + + if(!strcmp(para, "enable")){ + printk("enable"); + adapter->enable_rxsc = 1; + }else if(!strcmp(para, "disable")){ + printk("disable"); + adapter->enable_rxsc = 0; + }else if(!strcmp(para, "dump")){ + struct core_logs *log = &adapter->core_logs; + printk("dump"); + printk("enable_rxsc: %d \n", adapter->enable_rxsc); + printk("rxCnt_data: orig=%d shortcut=%d(ratio=%d)\n", + log->rxCnt_data_orig, log->rxCnt_data_shortcut, + log->rxCnt_data_shortcut*100/(log->rxCnt_data_orig+log->rxCnt_data_shortcut)); + } + +} +#endif + +void core_sniffer_rx(_adapter *adapter, u8 *pkt, u32 pktlen) +{ + struct sk_buff* pskb = NULL; + + if(!adapter->sniffer_enable) + return; + + if(pkt==NULL) + return; + + pskb = dev_alloc_skb(pktlen+200); + + if(pskb == NULL){ + return; +} + + _rtw_memcpy(pskb->data, pkt, pktlen); + pskb->len = pktlen; + + skb_reset_mac_header(pskb); + pskb->dev = adapter->pnetdev; + pskb->dev->type = ARPHRD_IEEE80211; + pskb->ip_summed = CHECKSUM_UNNECESSARY; + pskb->pkt_type = PACKET_OTHERHOST; + pskb->protocol = htons(ETH_P_802_2); + netif_receive_skb(pskb); + + return; +} + +void core_cmd_sniffer(_adapter *adapter, void *cmd_para, u32 para_num) + { + u32 idx=0; + char *para = (char *)cmd_para; + + if(para_num<=0) + return; + + if(!strcmp(para, "start")){ + adapter->sniffer_enable = 1; + }else if(!strcmp(para, "stop")){ + adapter->sniffer_enable = 0; + } +} + + +#define LEN_TEST_BUF 2000 +u8 test_buf[LEN_TEST_BUF]; + +#ifdef CONFIG_PCI_HCI +#include +#endif + +#include "../phl/phl_headers.h" +#include "../phl/phl_api.h" +#include "../phl/hal_g6/hal_api_mac.h" +#include "../phl/hal_g6/mac/mac_reg.h" + + +#define SHOW_REG32(adapter, reg) \ + do { \ + printk("\t%04X = %08X\n", \ + (reg), rtw_phl_read32(adapter->dvobj->phl, reg)); \ + } while (0) + +#define SHOW_REG32_MSG(adapter, reg, msg) \ + do { \ + printk("\t%04X = %08X - %s\n", \ + (reg), rtw_phl_read32(adapter->dvobj->phl, reg), msg); \ + } while (0) + +#define SHOW_REG16(adapter, reg) \ + do { \ + printk("\t%04X = %04X\n", \ + (reg), rtw_phl_read16(adapter->dvobj->phl, reg)); \ + } while (0) + +#define SHOW_REG16_MSG(adapter, reg, msg) \ + do { \ + printk("\t%04X = %04X - %s\n", \ + (reg), rtw_phl_read16(adapter->dvobj->phl, reg), msg); \ + } while (0) + + +static inline void _show_RX_counter(_adapter *adapter) +{ + /* Show RX PPDU counters */ + int i; + u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL); + static const char *cnt_name[] = {"Invalid packet", + "RE-CCA", + "RX FIFO overflow", + "RX packet full drop", + "RX packet dma OK", + "UD 0", + "UD 1", + "UD 2", + "UD 3", + "continuous FCS error", + "RX packet filter drop", + "CSI packet DMA OK", + "CSI packet DMA drop", + "RX MAC stop" + }; + + printk("CMAC0 RX PPDU Counters @%04X:\n", R_AX_RX_DBG_CNT_SEL); + reg32 &= ~(B_AX_RX_CNT_IDX_MSK << B_AX_RX_CNT_IDX_SH); + for (i = 30; i < 44; i++) { + rtw_phl_write32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL, + reg32 | (i << B_AX_RX_CNT_IDX_SH)); + printk(" %02X: %d - %s\n", i, + ( + ( rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL) + >> B_AX_RX_DBG_CNT_SH) + & B_AX_RX_DBG_CNT_MSK), + cnt_name[i - 30]); + } + + reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1); + printk("CMAC1 RX PPDU Counters @%04X:\n", R_AX_RX_DBG_CNT_SEL_C1); + reg32 &= ~(B_AX_RX_CNT_IDX_MSK << B_AX_RX_CNT_IDX_SH); + for (i = 30; i < 44; i++) { + rtw_phl_write32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1, + reg32 | (i << B_AX_RX_CNT_IDX_SH)); + printk(" %02X: %d - %s\n", i, + ( + ( rtw_phl_read32(adapter->dvobj->phl, R_AX_RX_DBG_CNT_SEL_C1) + >> B_AX_RX_DBG_CNT_SH) + & B_AX_RX_DBG_CNT_MSK), + cnt_name[i - 30]); + } +} /* _show_RX_counter */ + +void _show_TX_dbg_status(_adapter *adapter) +{ + u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, 0x9F1C); + printk("TX Debug: 0x%08X\n", reg32); +} + +void _show_BCN_dbg_status(_adapter *adapter) +{ + SHOW_REG32_MSG(adapter, R_AX_PORT_CFG_P0, "PORT_CFG_P0"); + SHOW_REG32_MSG(adapter, R_AX_TBTT_PROHIB_P0, "TBTT_PROHIB_P0"); + SHOW_REG32_MSG(adapter, R_AX_EN_HGQ_NOLIMIT, "EN_HGQ_NOLIMIT"); + SHOW_REG32_MSG(adapter, R_AX_TBTT_AGG_P0, "TBTT_AGG_P0"); + + SHOW_REG32_MSG(adapter, R_AX_PORT_CFG_P0_C1, "PORT_CFG_P0_C1"); + SHOW_REG32_MSG(adapter, R_AX_TBTT_PROHIB_P0_C1, "TBTT_PROHIB_P0_C1"); + SHOW_REG32_MSG(adapter, R_AX_EN_HGQ_NOLIMIT_C1, "EN_HGQ_NOLIMIT_C1"); + SHOW_REG32_MSG(adapter, R_AX_TBTT_AGG_P0_C1, "TBTT_AGG_P0_C1"); + + SHOW_REG32_MSG(adapter, R_AX_WCPU_FW_CTRL, "R_AX_WCPU_FW_CTRL"); +} + + +void core_cmd_dump_debug(_adapter *adapter, void *cmd_para, u32 para_num) +{ + printk("TX path registers: \n"); + + SHOW_REG32_MSG(adapter, R_AX_RXQ_RXBD_IDX, "RX_BD_IDX"); + SHOW_REG32_MSG(adapter, R_AX_RPQ_RXBD_IDX, "RP_BD_IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH0_TXBD_IDX, "ACH0 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH1_TXBD_IDX, "ACH1 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH2_TXBD_IDX, "ACH2 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH3_TXBD_IDX, "ACH3 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH4_TXBD_IDX, "ACH4 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH5_TXBD_IDX, "ACH5 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH6_TXBD_IDX, "ACH6 IDX"); + SHOW_REG32_MSG(adapter, R_AX_ACH7_TXBD_IDX, "ACH7 IDX"); + SHOW_REG32_MSG(adapter, R_AX_CH8_TXBD_IDX, "CH8 IDX"); + SHOW_REG32_MSG(adapter, R_AX_CH9_TXBD_IDX, "CH9 IDX"); + SHOW_REG32_MSG(adapter, R_AX_CH10_TXBD_IDX, "CH10 IDX"); + SHOW_REG32_MSG(adapter, R_AX_CH11_TXBD_IDX, "CH11 IDX"); + SHOW_REG32_MSG(adapter, R_AX_CH12_TXBD_IDX, "CH12 IDX"); +#ifdef R_AX_PCIE_DBG_CTRL + SHOW_REG32_MSG(adapter, R_AX_PCIE_DBG_CTRL, "DBG_CTRL"); +#else + SHOW_REG32_MSG(adapter, 0x11C0, "DBG_CTRL"); +#endif + SHOW_REG32_MSG(adapter, R_AX_DBG_ERR_FLAG, "DBG_ERR"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_HIMR00, "IMR0"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_HISR00, "ISR0"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_HIMR10, "IMR1"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_HISR10, "IMR1"); + SHOW_REG16_MSG(adapter, R_AX_ACH0_BDRAM_RWPTR, "CH0"); + SHOW_REG16_MSG(adapter, R_AX_ACH1_BDRAM_RWPTR, "CH1"); + SHOW_REG16_MSG(adapter, R_AX_ACH2_BDRAM_RWPTR, "CH2"); + SHOW_REG16_MSG(adapter, R_AX_ACH3_BDRAM_RWPTR, "CH3"); + SHOW_REG16_MSG(adapter, R_AX_ACH4_BDRAM_RWPTR, "CH4"); + SHOW_REG16_MSG(adapter, R_AX_ACH5_BDRAM_RWPTR, "CH5"); + SHOW_REG16_MSG(adapter, R_AX_ACH6_BDRAM_RWPTR, "CH6"); + SHOW_REG16_MSG(adapter, R_AX_ACH7_BDRAM_RWPTR, "CH7"); + SHOW_REG16_MSG(adapter, R_AX_CH8_BDRAM_RWPTR, "CH8"); + SHOW_REG16_MSG(adapter, R_AX_CH9_BDRAM_RWPTR, "CH9"); + SHOW_REG16_MSG(adapter, R_AX_CH10_BDRAM_RWPTR, "CH10"); + SHOW_REG16_MSG(adapter, R_AX_CH11_BDRAM_RWPTR, "CH11"); + SHOW_REG16_MSG(adapter, R_AX_CH12_BDRAM_RWPTR, "CH12"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_STOP1, "DMA_STOP1"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_BUSY1, "DMA_BUSY1"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_STOP2, "DMA_STOP2"); + SHOW_REG32_MSG(adapter, R_AX_PCIE_DMA_BUSY2, "DMA_BUSY2"); + SHOW_REG32(adapter, 0x8840); + SHOW_REG32(adapter, 0x8844); + SHOW_REG32(adapter, 0x8854); + SHOW_REG16(adapter, 0xCA22); + SHOW_REG32(adapter, 0x8AA8); + + /* Show TX PPDU counters */ + do { + int i; + u32 reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT); + + printk("CMAC0 TX PPDU Counters @%04X:\n", R_AX_TX_PPDU_CNT); + + reg32 &= ~(B_AX_PPDU_CNT_IDX_MSK << B_AX_PPDU_CNT_IDX_SH); + for (i = 0; i < 11; i++) { + rtw_phl_write32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT, + reg32 | (i << B_AX_PPDU_CNT_IDX_SH)); + printk(" %02X: %d\n", i, + ( + ( rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT) + >> B_AX_TX_PPDU_CNT_SH) + & B_AX_TX_PPDU_CNT_MSK)); + } + + reg32 = rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1); + + printk("CMAC1 TX PPDU Counters @%04X:\n", R_AX_TX_PPDU_CNT_C1); + + reg32 &= ~(B_AX_PPDU_CNT_IDX_MSK << B_AX_PPDU_CNT_IDX_SH); + for (i = 0; i < 11; i++) { + rtw_phl_write32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1, + reg32 | (i << B_AX_PPDU_CNT_IDX_SH)); + printk(" %02X: %d\n", i, + ( + ( rtw_phl_read32(adapter->dvobj->phl, R_AX_TX_PPDU_CNT_C1) + >> B_AX_TX_PPDU_CNT_SH) + & B_AX_TX_PPDU_CNT_MSK)); + } + } while (0); + + /* Show RX PPDU counters */ + _show_RX_counter(adapter); + + _show_TX_dbg_status(adapter); + + _show_BCN_dbg_status(adapter); + +} + +void core_cmd_dump_reg(_adapter *adapter, void *cmd_para, u32 para_num) +{ + u32 *para = (u32 *)cmd_para; + void *phl = adapter->dvobj->phl; + u32 reg_start, reg_end; + u32 idx = 0; + + reg_start = para[0]; + reg_end = reg_start + para[1]; + + while(1) { + if((reg_start>=reg_end) || (reg_start >= 0xffff)) + break; + + printk("[%04x] %08x %08x %08x %08x \n", + reg_start, + rtw_phl_read32(phl, reg_start), rtw_phl_read32(phl, reg_start+4), + rtw_phl_read32(phl, reg_start+8), rtw_phl_read32(phl, reg_start+12)); + + reg_start+=16; + } +} + +void core_cmd_dump_cnt(_adapter *adapter, void *cmd_para, u32 para_num) +{ + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter); + struct xmit_priv *pxmitpriv = &adapter->xmitpriv; + char *para = (char *)cmd_para; + int i = 0; + + RTW_PRINT("\n"); + RTW_PRINT(" cur_tx_tp: %d\n", pdvobjpriv->traffic_stat.cur_tx_tp); + #if 0 + RTW_PRINT(" core_tx_pkts: %lld\n", pxmitpriv->core_tx_pkts); + RTW_PRINT(" core_tx_drop: %lld\n", pxmitpriv->core_tx_drop); + for (i = 0; i < 10; i++) + if (pxmitpriv->core_tx_abort[i] != 0) + RTW_PRINT(" core_tx_abort[%d]: %lld\n", i, pxmitpriv->core_tx_abort[i]); + #endif + /* XMITFRAME */ + RTW_PRINT("[XMITFRAME]\n"); + RTW_PRINT(" free_cnt: %d\n", pxmitpriv->free_xmitframe_cnt); + RTW_PRINT(" full_cnt: %d\n", pxmitpriv->full_xmitframe_cnt); + + /* TXREQ */ + RTW_PRINT("[TXREQ]\n"); + RTW_PRINT(" free_cnt: %d\n", adapter->free_txreq_cnt); + RTW_PRINT(" full_cnt: %d\n", adapter->txreq_full_cnt); +} + +#ifdef CONFIG_CORE_TXSC +void core_cmd_txsc(_adapter *adapter, void *cmd_para, u32 para_num) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct xmit_priv *pxmitpriv = &adapter->xmitpriv; + u32 idx = 0; + char *para = (char *)cmd_para; + u32 value = 0; + + if (para_num <= 0) + return; + + if (!strcmp(para, "enable")) { + u8 old_value = pxmitpriv->txsc_enable; + para = get_next_para_str(para); + sscanf(para, "%d", &value); + + RTW_PRINT("[txsc] enable:%d\n", value); + if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { + pxmitpriv->txsc_enable = value; + #ifdef CONFIG_TXSC_AMSDU + if (pxmitpriv->txsc_enable == 0) + pxmitpriv->txsc_amsdu_enable = 0; + #endif + } else + RTW_PRINT("[TXSC][WARNING] only AP mode support tx shortcut now !!\n"); + + if (value != old_value) + txsc_clear(adapter); + } else if (!strcmp(para, "debug")) { + + RTW_PRINT("[txsc] debug info\n"); + txsc_dump(adapter); + + } else if (!strcmp(para, "clear")) { + + RTW_PRINT("[TXSC] clear shortcut\n"); + txsc_clear(adapter); + } +} + +void core_cmd_debug(_adapter *adapter, void *cmd_para, u32 para_num) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + u32 idx = 0; + char *para = (char *)cmd_para; + u32 value = 0; + + if (para_num <= 0) + return; + + if (!strcmp(para, "mdata")) { + extern u8 DBG_PRINT_MDATA_ONCE; + DBG_PRINT_MDATA_ONCE = 1; + } else if (!strcmp(para, "txreq")) { + extern u8 DBG_PRINT_TXREQ_ONCE; + DBG_PRINT_TXREQ_ONCE = 1; + } + #if 0 + else if (!strcmp(para, "haldata")) { + extern u8 DBG_PRINT_PKTINFO_ONCE; + DBG_PRINT_PKTINFO_ONCE = 1; + } else if (!strcmp(para, "wdpage")) { + extern u8 DBG_PRINT_WDPAGE_ONCE; + DBG_PRINT_WDPAGE_ONCE = 1; + } + #endif + +} + +#ifdef CONFIG_TXSC_AMSDU +void amsdu_clear(_adapter *padapter) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + int i; + + RTW_PRINT("[amsdu] clear amsdu counter\n"); + + for (i = 0; i < 4; i++) { + pxmitpriv->cnt_txsc_amsdu_enq[i] = 0; + pxmitpriv->cnt_txsc_amsdu_enq_abort[i] = 0; + pxmitpriv->cnt_txsc_amsdu_deq[i] = 0; + } + pxmitpriv->cnt_txsc_amsdu_deq_empty = 0; + pxmitpriv->cnt_txsc_amsdu_timeout_deq_empty = 0; + + for (i = 0; i < MAX_TXSC_SKB_NUM; i++) { + pxmitpriv->cnt_txsc_amsdu_dump[i] = 0; + pxmitpriv->cnt_txsc_amsdu_timeout_dump[i] = 0; + } + for(i = 0; i < ARRAY_SIZE(pxmitpriv->cnt_txsc_amsdu_timeout_ok); i++) { + pxmitpriv->cnt_txsc_amsdu_timeout_ok[i] = 0; + pxmitpriv->cnt_txsc_amsdu_timeout_fail[i] = 0; + } +} + +void amsdu_dump(_adapter *padapter) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct sta_info *psta = NULL; + u8 i; + + RTW_PRINT("[amsdu] txsc amsdu enable: %d\n", pxmitpriv->txsc_amsdu_enable); + RTW_PRINT("[amsdu] amsdu num: %d\n", padapter->tx_amsdu); + RTW_PRINT("[amsdu] amsdu rate: %d\n", padapter->tx_amsdu_rate); + RTW_PRINT("[amsdu] txsc_amsdu_force_num: %d\n", pxmitpriv->txsc_amsdu_force_num); + RTW_PRINT("[amsdu] amsdu max num: %d\n", MAX_TXSC_SKB_NUM); + RTW_PRINT("[amsdu] amsdu max queue num: %d\n", MAX_AMSDU_ENQ_NUM); + + RTW_PRINT("\n"); + for (i = 0; i < 4; i++) { + RTW_PRINT("[amsdu] cnt_enq[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_enq[i]); + RTW_PRINT("[amsdu] cnt_deq[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_deq[i]); + RTW_PRINT("[amsdu] cnt_abort[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_enq_abort[i]); + } + + RTW_PRINT("\n"); + for (i = 0; i < MAX_TXSC_SKB_NUM; i++) { + if (pxmitpriv->cnt_txsc_amsdu_dump[i] > 0) + RTW_PRINT("[amsdu] cnt_dump[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_dump[i]); + } + RTW_PRINT("[amsdu] cnt_deq_empty: %lld\n", pxmitpriv->cnt_txsc_amsdu_deq_empty); + RTW_PRINT("[amsdu] cnt_enq_ps: %lld\n", pxmitpriv->cnt_txsc_amsdu_enq_ps); + RTW_PRINT("[amsdu] cnt_deq_ps: %lld\n", pxmitpriv->cnt_txsc_amsdu_deq_ps); + + RTW_PRINT("\n"); + for (i = 0; i < MAX_TXSC_SKB_NUM; i++) { + if (pxmitpriv->cnt_txsc_amsdu_timeout_dump[i] > 0) + RTW_PRINT("[amsdu] cnt_to_dump[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_timeout_dump[i]); + } + RTW_PRINT("[amsdu] cnt_to_deq_empty: %lld\n", pxmitpriv->cnt_txsc_amsdu_timeout_deq_empty); + + RTW_PRINT("\n"); + for (i = 0; i < ARRAY_SIZE(pxmitpriv->cnt_txsc_amsdu_timeout_ok); i++) { + if (pxmitpriv->cnt_txsc_amsdu_timeout_ok[i] > 0) + RTW_PRINT("[amsdu] cnt_to_ok[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_timeout_ok[i]); + if (pxmitpriv->cnt_txsc_amsdu_timeout_fail[i] > 0) + RTW_PRINT("[amsdu] cnt_to_fail[%d]: %lld\n", i, pxmitpriv->cnt_txsc_amsdu_timeout_fail[i]); + } + + RTW_PRINT("\n"); + for (i = 0; i < pstapriv->max_aid; i++) { + psta = pstapriv->sta_aid[i]; + if (!psta) + continue; + + RTW_PRINT("[%d] STA[%02x:%02x:%02x:%02x:%02x:%02x]->txq[ac]\n txsc_amsdu_num:%d, txsc_amsdu_max:%d\n", i, + psta->phl_sta->mac_addr[0], psta->phl_sta->mac_addr[1], psta->phl_sta->mac_addr[2], + psta->phl_sta->mac_addr[3], psta->phl_sta->mac_addr[4], psta->phl_sta->mac_addr[5], + psta->txsc_amsdu_num, psta->txsc_amsdu_max); + for (i = 0; i < 4; i++) + RTW_PRINT(" amsdu_txq[%d]: cnt:%d, rptr:%d, wptr:%d\n", + i, psta->amsdu_txq[i].cnt, psta->amsdu_txq[i].rptr, psta->amsdu_txq[i].wptr); + RTW_PRINT("\n"); + } +} + +void core_cmd_amsdu(_adapter *adapter, void *cmd_para, u32 para_num) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct xmit_priv *pxmitpriv = &adapter->xmitpriv; + u32 idx = 0; + char *para = (char *)cmd_para; + u32 value = 0; + + if (para_num <= 0) + return; + + if (!strcmp(para, "enable")) { + para = get_next_para_str(para); + sscanf(para, "%d", &value); + + RTW_PRINT("[amsdu] set txsc_amsdu_enable:%d\n", value); + + if (value == 1) { + pxmitpriv->txsc_enable = 0; + txsc_clear(adapter); + pxmitpriv->txsc_enable = 1; + RTW_PRINT("[txsc] set txsc_enable:%d\n", pxmitpriv->txsc_enable); + } else if(value == 0) { + txsc_clear(adapter); + amsdu_clear(adapter); + } + + pxmitpriv->txsc_amsdu_enable = value; + if (pxmitpriv->txsc_amsdu_enable) + rtw_phl_write32(adapter->dvobj->phl, 0x9b00, 0); + else + rtw_phl_write32(adapter->dvobj->phl, 0x9b00, 0x7); + + } else if (!strcmp(para, "num") ) { + para = get_next_para_str(para); + sscanf(para, "%d", &value); + + if (value > MAX_TXSC_SKB_NUM) { + value = MAX_TXSC_SKB_NUM; + RTW_PRINT("[amsdu] error !!! amsdu num should not over %d\n", MAX_TXSC_SKB_NUM); + } + + RTW_PRINT("[amsdu] set tx_amsdu num:%d\n", value); + adapter->tx_amsdu = value; + + } else if (!strcmp(para, "tp")) { + para = get_next_para_str(para); + sscanf(para, "%d", &value); + + RTW_PRINT("[amsdu] set tx_amsdu_rate:%d\n", value); + adapter->tx_amsdu_rate = value; + + } else if(!strcmp(para, "debug")) { + + RTW_PRINT("[amsdu] show info\n"); + amsdu_dump(adapter); + } else if (!strcmp(para, "force_num")) { + + para = get_next_para_str(para); + sscanf(para, "%d", &value); + if (value > MAX_TXSC_SKB_NUM) + value = MAX_TXSC_SKB_NUM; + + RTW_PRINT("[amsdu] set txsc_amsdu_force_num:%d\n", value); + + pxmitpriv->txsc_amsdu_force_num = value; + } +} +#endif/* CONFIG_TXSC_AMSDU */ +#endif /* CONFIG_CORE_TXSC */ + + +enum _CORE_CMD_PARA_TYPE { + CMD_PARA_DEC = 0, + CMD_PARA_HEX, + CMD_PARA_STR, +}; + +struct test_cmd_list { + const char *name; + void (*fun)(_adapter *, void *, u32); + enum _CORE_CMD_PARA_TYPE para_type; +}; + +void test_dump_dec(_adapter *adapter, void *cmd_para, u32 para_num) +{ + u32 idx = 0; + u32 *para = (u32 *)cmd_para; + DBGP("para_num=%d\n", para_num); + + for(idx=0; idx 0){ + tmp = strsep(&buf, ","); + + if(tmp){ + if(type == CMD_PARA_HEX) + sscanf(tmp, "%x", para); + else if(type == CMD_PARA_DEC) + sscanf(tmp, "%d", para); + para += 1; + *num = *num+1; + } + else + return; + + if(buf && (len>strlen(tmp))) + get_all_cmd_para_value(adapter, buf, strlen(buf), para, type, num); + else + return; + } + } + +void get_all_cmd_para_str(_adapter *adapter, char *buf, u32 len, char *para, u8 type, u32* num) +{ + u8 *tmp = NULL; + + if(!buf || !len) + return; + + DBGP("type=%d buf=%s para=%p num=%d\n", type, buf, para, *num); + + if(len > 0){ + tmp = strsep(&buf, ","); + + if(tmp){ + strcpy(para, tmp); + para += MAX_PHL_CMD_STR_LEN; + *num = *num+1; + } + else + return; + + if(buf && (len>strlen(tmp))) + get_all_cmd_para_str(adapter, buf, strlen(buf), para, type, num); + else + return; + } + } + +struct test_cmd_list core_test_cmd_list[] = { + {"dec", test_dump_dec, CMD_PARA_DEC}, + {"hex", test_dump_hex, CMD_PARA_HEX}, + {"str", test_dump_str, CMD_PARA_STR}, + {"dump_reg", core_cmd_dump_reg, CMD_PARA_HEX}, + {"dump_debug", core_cmd_dump_debug, CMD_PARA_DEC}, + {"record", core_cmd_record_trx, CMD_PARA_STR}, + {"txforce", core_cmd_txforce, CMD_PARA_STR}, + {"sniffer", core_cmd_sniffer, CMD_PARA_STR}, +#ifdef CONFIG_RTW_CORE_RXSC + {"rxsc", core_cmd_rxsc, CMD_PARA_STR}, +#endif + {"dump_cnt", core_cmd_dump_cnt, CMD_PARA_STR}, +#ifdef CONFIG_CORE_TXSC + {"txsc", core_cmd_txsc, CMD_PARA_STR}, + {"debug", core_cmd_debug, CMD_PARA_STR}, +#ifdef CONFIG_TXSC_AMSDU + {"amsdu", core_cmd_amsdu, CMD_PARA_STR}, +#endif /* CONFIG_TXSC_AMSDU */ +#endif /* CONFIG_CORE_TXSC */ +}; + +void core_cmd_phl_handler(_adapter *adapter, char *extra) +{ + u32 para[MAX_PHL_CMD_NUM]={0}; + char para_str[MAX_PHL_CMD_NUM][MAX_PHL_CMD_STR_LEN]={{0}}; + char *cmd_name, *cmd_para = NULL; + struct test_cmd_list *cmd = core_test_cmd_list; + u32 array_size = ARRAY_SIZE(core_test_cmd_list); + u32 i = 0; + + _rtw_memset(para, 0x0, sizeof(para)); + _rtw_memset(para_str, 0x0, sizeof(para_str)); + + cmd_name = strsep(&extra, ","); + + if(!cmd_name){ + for(i = 0; iname); + return; + } + + for(i = 0; iname, cmd_name)){ + void *cmd_para = NULL; + u32 cmd_para_num = 0; + if(cmd->para_type == CMD_PARA_DEC || cmd->para_type == CMD_PARA_HEX){ + cmd_para = para; + if(extra) + get_all_cmd_para_value(adapter, extra, strlen(extra), para, cmd->para_type, &cmd_para_num); + } + else{ + cmd_para = para_str; + if(extra) + get_all_cmd_para_str(adapter, extra, strlen(extra), para_str, cmd->para_type, &cmd_para_num); + } + + cmd->fun(adapter, cmd_para, cmd_para_num); + break; + } + } + +} + +#endif + +u8 rtw_test_h2c_cmd(_adapter *adapter, u8 *buf, u8 len) +{ + struct cmd_obj *pcmdobj; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + u8 *ph2c_content; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 res = _SUCCESS; + + pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmdobj == NULL) { + res = _FAIL; + goto exit; + } + pcmdobj->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + ph2c_content = rtw_zmalloc(len); + if (ph2c_content == NULL) { + rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = TEST_H2C_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = len; + pdrvextra_cmd_parm->pbuf = ph2c_content; + + _rtw_memcpy(ph2c_content, buf, len); + + init_h2fwcmd_w_parm_no_rsp(pcmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, pcmdobj); + +exit: + return res; +} + +#ifdef CONFIG_MP_INCLUDED +static s32 rtw_mp_cmd_hdl(_adapter *padapter, u8 mp_cmd_id) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + int ret = H2C_SUCCESS; + uint status = _FALSE; + struct mp_priv *pmppriv = &padapter->mppriv; + struct rtw_test_module_info test_module_info; + struct rtw_mp_test_rpt my_mp_test_rpt; + + if (mp_cmd_id == MP_START) { + if (padapter->registrypriv.mp_mode == 0) { + + test_module_info.tm_mode = RTW_DRV_MODE_MP; + test_module_info.tm_type = RTW_TEST_SUB_MODULE_MP; + pmppriv->keep_ips_status = dvobj->phl_com->dev_sw_cap.ps_cap.ips_en; + pmppriv->keep_lps_status = dvobj->phl_com->dev_sw_cap.ps_cap.lps_en; + dvobj->phl_com->dev_sw_cap.ps_cap.ips_en = PS_OP_MODE_DISABLED; + dvobj->phl_com->dev_sw_cap.ps_cap.lps_en = PS_OP_MODE_DISABLED; + + rtw_phl_test_submodule_init(dvobj->phl_com, &test_module_info); +#ifdef CONFIG_BTC + if (dvobj->phl_com->dev_cap.btc_mode == BTC_MODE_NORMAL ||\ + dvobj->phl_com->dev_cap.btc_mode == BTC_MODE_BT) { + + pmppriv->mp_keep_btc_mode = dvobj->phl_com->dev_cap.btc_mode; + rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SWITCH_BT_PATH); + RTW_INFO("config BTC to WL Only\n"); + } +#endif + rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_PHY_INDEX); + status = rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_START_DUT); + + if (status == _TRUE) { + padapter->registrypriv.mp_mode = 1; + MPT_InitializeAdapter(padapter, 1); + } + } + + if (padapter->registrypriv.mp_mode == 0) { + ret = H2C_REJECTED; + goto exit; + } + + if (padapter->mppriv.mode == MP_OFF) { + if (mp_start_test(padapter) == _FAIL) { + ret = H2C_REJECTED; + goto exit; + } + padapter->mppriv.mode = MP_ON; + } + padapter->mppriv.bmac_filter = _FALSE; + + } else if (mp_cmd_id == MP_STOP) { + if (padapter->registrypriv.mp_mode == 1) { + + status = rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_STOP_DUT); + RTW_INFO("RTW_MP_CONFIG_CMD_STOP_DUT %s\n", status == _TRUE ? "ok" : "fail"); + rtw_phl_test_get_rpt(dvobj->phl_com, (u8*)&my_mp_test_rpt, sizeof(my_mp_test_rpt)); + + if (my_mp_test_rpt.status == _TRUE) + RTW_INFO("TM Sub finished OK!!!\n"); +#ifdef CONFIG_BTC + if (pmppriv->mp_keep_btc_mode != BTC_MODE_MAX) { + pmppriv->btc_path = pmppriv->mp_keep_btc_mode; + rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SWITCH_BT_PATH); + } +#endif + test_module_info.tm_mode = RTW_DRV_MODE_NORMAL; + test_module_info.tm_type = RTW_TEST_SUB_MODULE_MP; + dvobj->phl_com->dev_sw_cap.ps_cap.ips_en = pmppriv->keep_ips_status; + dvobj->phl_com->dev_sw_cap.ps_cap.lps_en = pmppriv->keep_lps_status; + + rtw_phl_test_submodule_deinit(dvobj->phl_com, &test_module_info); + + MPT_DeInitAdapter(padapter); + padapter->registrypriv.mp_mode = 0; + } + + if (padapter->mppriv.mode != MP_OFF) { + mp_stop_test(padapter); + padapter->mppriv.mode = MP_OFF; + } + + } else { + RTW_INFO(FUNC_ADPT_FMT"invalid id:%d\n", FUNC_ADPT_ARG(padapter), mp_cmd_id); + ret = H2C_PARAMETERS_ERROR; + rtw_warn_on(1); + } + +exit: + return ret; +} + +u8 rtw_mp_cmd(_adapter *adapter, u8 mp_cmd_id, u8 flags) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + + parm->ec_id = MP_CMD_WK_CID; + parm->type = mp_cmd_id; + parm->size = 0; + parm->pbuf = NULL; + + if (flags & RTW_CMDF_DIRECTLY) { + /* no need to enqueue, do the cmd hdl directly and free cmd parameter */ + if (H2C_SUCCESS != rtw_mp_cmd_hdl(adapter, mp_cmd_id)) + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + if (flags & RTW_CMDF_WAIT_ACK) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + } + +exit: + return res; +} +#endif /*CONFIG_MP_INCLUDED*/ + +#ifdef CONFIG_RTW_CUSTOMER_STR +static s32 rtw_customer_str_cmd_hdl(_adapter *adapter, u8 write, const u8 *cstr) +{ + int ret = H2C_SUCCESS; + + if (write) + ret = rtw_hal_h2c_customer_str_write(adapter, cstr); + else + ret = rtw_hal_h2c_customer_str_req(adapter); + + return ret == _SUCCESS ? H2C_SUCCESS : H2C_REJECTED; +} + +static u8 rtw_customer_str_cmd(_adapter *adapter, u8 write, const u8 *cstr) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + u8 *str = NULL; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + + if (write) { + str = rtw_zmalloc(RTW_CUSTOMER_STR_LEN); + if (str == NULL) { + rtw_mfree((u8 *)parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + } + + parm->ec_id = CUSTOMER_STR_WK_CID; + parm->type = write; + parm->size = write ? RTW_CUSTOMER_STR_LEN : 0; + parm->pbuf = write ? str : NULL; + + if (write) + _rtw_memcpy(str, cstr, RTW_CUSTOMER_STR_LEN); + + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + if (write) + rtw_mfree(str, RTW_CUSTOMER_STR_LEN); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, 2 * 1000); + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + + if (res == _SUCCESS) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&pcmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&pcmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + +exit: + return res; +} + +inline u8 rtw_customer_str_req_cmd(_adapter *adapter) +{ + return rtw_customer_str_cmd(adapter, 0, NULL); +} + +inline u8 rtw_customer_str_write_cmd(_adapter *adapter, const u8 *cstr) +{ + return rtw_customer_str_cmd(adapter, 1, cstr); +} +#endif /* CONFIG_RTW_CUSTOMER_STR */ + +u8 rtw_c2h_wk_cmd(_adapter *padapter, u8 *pbuf, u16 length, u8 type) +{ + struct cmd_obj *cmd; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + u8 *extra_cmd_buf; + u8 res = _SUCCESS; + + cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmd == NULL) { + res = _FAIL; + goto exit; + } + cmd->padapter = padapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + extra_cmd_buf = rtw_zmalloc(length); + if (extra_cmd_buf == NULL) { + rtw_mfree((u8 *)cmd, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + _rtw_memcpy(extra_cmd_buf, pbuf, length); + pdrvextra_cmd_parm->ec_id = C2H_WK_CID; + pdrvextra_cmd_parm->type = type; + pdrvextra_cmd_parm->size = length; + pdrvextra_cmd_parm->pbuf = extra_cmd_buf; + + init_h2fwcmd_w_parm_no_rsp(cmd, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmd); + +exit: + return res; +} + +#define C2H_TYPE_PKT 1 +inline u8 rtw_c2h_packet_wk_cmd(_adapter *adapter, u8 *c2h_evt, u16 length) +{ + return rtw_c2h_wk_cmd(adapter, c2h_evt, length, C2H_TYPE_PKT); +} + +static u8 _rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms) +{ + struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct cmd_obj *cmdobj; + struct RunInThread_param *parm; + struct submit_ctx sctx; + s32 res = _SUCCESS; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (NULL == cmdobj) { + res = _FAIL; + goto exit; + } + cmdobj->padapter = adapter; + + parm = (struct RunInThread_param *)rtw_zmalloc(sizeof(struct RunInThread_param)); + if (NULL == parm) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + parm->func = func; + parm->context = context; + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_RUN_INTHREAD); + + if (timeout_ms >= 0) { + cmdobj->sctx = &sctx; + rtw_sctx_init(&sctx, timeout_ms); + } + + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + + if (res == _SUCCESS && timeout_ms >= 0) { + rtw_sctx_wait(&sctx, __func__); + _rtw_mutex_lock_interruptible(&cmdpriv->sctx_mutex); + if (sctx.status == RTW_SCTX_SUBMITTED) + cmdobj->sctx = NULL; + _rtw_mutex_unlock(&cmdpriv->sctx_mutex); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + +exit: + return res; +} +u8 rtw_run_in_thread_cmd(_adapter *adapter, void (*func)(void *), void *context) +{ + return _rtw_run_in_thread_cmd(adapter, func, context, -1); +} + +u8 rtw_run_in_thread_cmd_wait(_adapter *adapter, void (*func)(void *), void *context, s32 timeout_ms) +{ + return _rtw_run_in_thread_cmd(adapter, func, context, timeout_ms); +} + + +u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port) +{ + struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *cmd_parm; + struct st_cmd_parm *st_parm; + u8 res = _SUCCESS; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + cmdobj->padapter = adapter; + + cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (cmd_parm == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm)); + if (st_parm == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + st_parm->cmd = cmd; + st_parm->sta = sta; + if (cmd != ST_CMD_CHK) { + _rtw_memcpy(&st_parm->local_naddr, local_naddr, 4); + _rtw_memcpy(&st_parm->local_port, local_port, 2); + _rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4); + _rtw_memcpy(&st_parm->remote_port, remote_port, 2); + } + + cmd_parm->ec_id = SESSION_TRACKER_WK_CID; + cmd_parm->type = 0; + cmd_parm->size = sizeof(struct st_cmd_parm); + cmd_parm->pbuf = (u8 *)st_parm; + init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, CMD_SET_DRV_EXTRA); + cmdobj->no_io = 1; + + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + +exit: + return res; +} + +inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta) +{ + return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL); +} + +inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port) +{ + return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port); +} + +inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port) +{ + return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port); +} + +void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta) +{ + struct st_ctl_t *st_ctl = &sta->st_ctl; + int i; + _list *plist, *phead, *pnext; + _list dlist; + struct session_tracker *st = NULL; + u8 op_wfd_mode = MIRACAST_DISABLED; + + if (DBG_SESSION_TRACKER) + RTW_INFO(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta); + + if (!(sta->state & WIFI_ASOC_STATE)) + goto exit; + + for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) { + if (st_ctl->reg[i].s_proto != 0) + break; + } + if (i >= SESSION_TRACKER_REG_ID_NUM) + goto chk_sta; + + _rtw_init_listhead(&dlist); + + _rtw_spinlock_bh(&st_ctl->tracker_q.lock); + + phead = &st_ctl->tracker_q.queue; + plist = get_next(phead); + pnext = get_next(plist); + while (rtw_end_of_queue_search(phead, plist) == _FALSE) { + st = LIST_CONTAINOR(plist, struct session_tracker, list); + plist = pnext; + pnext = get_next(pnext); + + if (st->status != ST_STATUS_ESTABLISH + && rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS + ) { + rtw_list_delete(&st->list); + rtw_list_insert_tail(&st->list, &dlist); + } + + /* TODO: check OS for status update */ + if (st->status == ST_STATUS_CHECK) + st->status = ST_STATUS_ESTABLISH; + + if (st->status != ST_STATUS_ESTABLISH) + continue; + + #ifdef CONFIG_WFD + if (0) + RTW_INFO(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter) + , ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport + , adapter->wfd_info.peer_rtsp_ctrlport); + if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport) + op_wfd_mode |= MIRACAST_SINK; + if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport) + op_wfd_mode |= MIRACAST_SINK; + if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport) + op_wfd_mode |= MIRACAST_SOURCE; + #endif + } + + _rtw_spinunlock_bh(&st_ctl->tracker_q.lock); + + plist = get_next(&dlist); + while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) { + st = LIST_CONTAINOR(plist, struct session_tracker, list); + plist = get_next(plist); + rtw_mfree((u8 *)st, sizeof(struct session_tracker)); + } + +chk_sta: + if (STA_OP_WFD_MODE(sta) != op_wfd_mode) { + STA_SET_OP_WFD_MODE(sta, op_wfd_mode); + /* TODO: op_wfd_mode inform */ + /* rtw_sta_hal_media_status_rpt_cmd(adapter, sta, 1, 0); */ + } + +exit: + return; +} + +void session_tracker_chk_for_adapter(_adapter *adapter) +{ + struct sta_priv *stapriv = &adapter->stapriv; + struct sta_info *sta; + int i; + _list *plist, *phead; + u8 op_wfd_mode = MIRACAST_DISABLED; + + _rtw_spinlock_bh(&stapriv->sta_hash_lock); + + for (i = 0; i < NUM_STA; i++) { + phead = &(stapriv->sta_hash[i]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + sta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + + session_tracker_chk_for_sta(adapter, sta); + + op_wfd_mode |= STA_OP_WFD_MODE(sta); + } + } + + _rtw_spinunlock_bh(&stapriv->sta_hash_lock); + +#ifdef CONFIG_WFD + adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode); +#endif +} + +void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm) +{ + u8 cmd = parm->cmd; + struct sta_info *sta = parm->sta; + + if (cmd == ST_CMD_CHK) { + if (sta) + session_tracker_chk_for_sta(adapter, sta); + else + session_tracker_chk_for_adapter(adapter); + + goto exit; + + } else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) { + struct st_ctl_t *st_ctl; + u32 local_naddr = parm->local_naddr; + u16 local_port = parm->local_port; + u32 remote_naddr = parm->remote_naddr; + u16 remote_port = parm->remote_port; + struct session_tracker *st = NULL; + _list *plist, *phead; + u8 free_st = 0; + u8 alloc_st = 0; + + if (DBG_SESSION_TRACKER) + RTW_INFO(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n" + , FUNC_ADPT_ARG(adapter), cmd, sta + , IP_ARG(&local_naddr), PORT_ARG(&local_port) + , IP_ARG(&remote_naddr), PORT_ARG(&remote_port) + ); + + if (!(sta->state & WIFI_ASOC_STATE)) + goto exit; + + st_ctl = &sta->st_ctl; + + _rtw_spinlock_bh(&st_ctl->tracker_q.lock); + + phead = &st_ctl->tracker_q.queue; + plist = get_next(phead); + while (rtw_end_of_queue_search(phead, plist) == _FALSE) { + st = LIST_CONTAINOR(plist, struct session_tracker, list); + + if (st->local_naddr == local_naddr + && st->local_port == local_port + && st->remote_naddr == remote_naddr + && st->remote_port == remote_port) + break; + + plist = get_next(plist); + } + + if (rtw_end_of_queue_search(phead, plist) == _TRUE) + st = NULL; + + switch (cmd) { + case ST_CMD_DEL: + if (st) { + rtw_list_delete(plist); + free_st = 1; + } + goto unlock; + case ST_CMD_ADD: + if (!st) + alloc_st = 1; + } + +unlock: + _rtw_spinunlock_bh(&st_ctl->tracker_q.lock); + + if (free_st) { + rtw_mfree((u8 *)st, sizeof(struct session_tracker)); + goto exit; + } + + if (alloc_st) { + st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker)); + if (!st) + goto exit; + + st->local_naddr = local_naddr; + st->local_port = local_port; + st->remote_naddr = remote_naddr; + st->remote_port = remote_port; + st->set_time = rtw_get_current_time(); + st->status = ST_STATUS_CHECK; + + _rtw_spinlock_bh(&st_ctl->tracker_q.lock); + rtw_list_insert_tail(&st->list, phead); + _rtw_spinunlock_bh(&st_ctl->tracker_q.lock); + } + } + +exit: + return; +} + +#if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW) +static s32 rtw_req_per_cmd_hdl(_adapter *adapter) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); + struct macid_bmp req_macid_bmp, *macid_bmp; + u8 i, ret = _FAIL; + + macid_bmp = &macid_ctl->if_g[adapter->iface_id]; + _rtw_memcpy(&req_macid_bmp, macid_bmp, sizeof(struct macid_bmp)); + + /* Clear none mesh's macid */ + for (i = 0; i < macid_ctl->num; i++) { + u8 role; + role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]); + if (role != H2C_MSR_ROLE_MESH) + rtw_macid_map_clr(&req_macid_bmp, i); + } + + /* group_macid: always be 0 in NIC, so only pass macid_bitmap.m0 + * rpt_type: 0 includes all info in 1, use 0 for now + * macid_bitmap: pass m0 only for NIC + */ + ret = rtw_hal_set_req_per_rpt_cmd(adapter, 0, 0, req_macid_bmp.m0); + + return ret; +} + +u8 rtw_req_per_cmd(_adapter *adapter) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + struct submit_ctx sctx; + u8 res = _SUCCESS; + + parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + res = _FAIL; + goto exit; + } + + parm->ec_id = REQ_PER_CMD_WK_CID; + parm->type = 0; + parm->size = 0; + parm->pbuf = NULL; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj)); + if (cmdobj == NULL) { + res = _FAIL; + rtw_mfree((u8 *)parm, sizeof(*parm)); + goto exit; + } + cmdobj->padapter = adapter; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + +exit: + return res; +} +#endif + + +void rtw_ac_parm_cmd_hdl(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, u8 *_ac_parm_buf, int ac_type) +{ + + u32 ac_parm_buf; + + _rtw_memcpy(&ac_parm_buf, _ac_parm_buf, sizeof(ac_parm_buf)); + switch (ac_type) { + case XMIT_VO_QUEUE: + RTW_INFO(FUNC_NDEV_FMT" AC_VO = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf); + rtw_ap_set_edca(padapter, padapter_link, 3, ac_parm_buf); + break; + + case XMIT_VI_QUEUE: + RTW_INFO(FUNC_NDEV_FMT" AC_VI = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf); + rtw_ap_set_edca(padapter, padapter_link, 2, ac_parm_buf); + break; + + case XMIT_BE_QUEUE: + RTW_INFO(FUNC_NDEV_FMT" AC_BE = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf); + rtw_ap_set_edca(padapter, padapter_link, 0, ac_parm_buf); + break; + + case XMIT_BK_QUEUE: + RTW_INFO(FUNC_NDEV_FMT" AC_BK = 0x%08x\n", FUNC_ADPT_ARG(padapter), (unsigned int) ac_parm_buf); + rtw_ap_set_edca(padapter, padapter_link, 1, ac_parm_buf); + break; + + default: + break; + } + +} + +u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf) +{ + int ret = H2C_SUCCESS; + struct drvextra_cmd_parm *pdrvextra_cmd; + + if (!pbuf) + return H2C_PARAMETERS_ERROR; + + pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; + + switch (pdrvextra_cmd->ec_id) { + #if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/ + case DYNAMIC_CHK_WK_CID:/*only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */ + rtw_dynamic_chk_wk_hdl(padapter); + break; + #endif +#ifdef CONFIG_ANTENNA_DIVERSITY + case ANT_SELECT_WK_CID: + antenna_select_wk_hdl(padapter, pdrvextra_cmd->type); + break; +#endif +#ifdef CONFIG_P2P_PS + case P2P_PS_WK_CID: + p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type); + break; +#endif +#ifdef CONFIG_AP_MODE + case CHECK_HIQ_WK_CID: + rtw_chk_hi_queue_hdl(padapter); + break; +#endif + /* add for CONFIG_IEEE80211W, none 11w can use it */ + case RESET_SECURITYPRIV: + reset_securitypriv_hdl(padapter); + break; + case FREE_ASSOC_RESOURCES: + free_assoc_resources_hdl(padapter, (u8)pdrvextra_cmd->type); + break; + case C2H_WK_CID: + switch (pdrvextra_cmd->type) { + case C2H_TYPE_PKT: + rtw_hal_c2h_pkt_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size); + break; + default: + RTW_ERR("unknown C2H type:%d\n", pdrvextra_cmd->type); + rtw_warn_on(1); + break; + } + break; + +#ifdef CONFIG_DFS_MASTER + case DFS_RADAR_DETECT_WK_CID: + rtw_dfs_rd_hdl(adapter_to_dvobj(padapter), (enum phl_band_idx)pdrvextra_cmd->type, 0, CHANNEL_WIDTH_MAX); + break; + case DFS_RADAR_DETECT_EN_DEC_WK_CID: + rtw_dfs_rd_en_dec_update(adapter_to_dvobj(padapter), (enum phl_band_idx)pdrvextra_cmd->type); + break; +#endif + case SESSION_TRACKER_WK_CID: + session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf); + break; + case TEST_H2C_CID: + rtw_hal_fill_h2c_cmd(padapter, pdrvextra_cmd->pbuf[0], pdrvextra_cmd->size - 1, &pdrvextra_cmd->pbuf[1]); + break; + case MP_CMD_WK_CID: +#ifdef CONFIG_MP_INCLUDED + ret = rtw_mp_cmd_hdl(padapter, pdrvextra_cmd->type); +#endif + break; +#ifdef CONFIG_RTW_CUSTOMER_STR + case CUSTOMER_STR_WK_CID: + ret = rtw_customer_str_cmd_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf); + break; +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + case MGNT_TX_WK_CID: + ret = rtw_mgnt_tx_handler(padapter, pdrvextra_cmd->pbuf); + break; +#endif /* CONFIG_IOCTL_CFG80211 */ +#if defined(CONFIG_RTW_MESH) && defined(RTW_PER_CMD_SUPPORT_FW) + case REQ_PER_CMD_WK_CID: + ret = rtw_req_per_cmd_hdl(padapter); + break; +#endif + case SSMPS_WK_CID : + rtw_ssmps_wk_hdl(padapter, (struct ssmps_cmd_parm *)pdrvextra_cmd->pbuf); + break; +#ifdef CONFIG_CTRL_TXSS_BY_TP + case TXSS_WK_CID : + rtw_ctrl_txss_wk_hdl(padapter, (struct txss_cmd_parm *)pdrvextra_cmd->pbuf); + break; +#endif + case AC_PARM_CMD_WK_CID: + rtw_ac_parm_cmd_hdl(padapter, pdrvextra_cmd->adapter_link, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); + break; +#ifdef CONFIG_AP_MODE + case STOP_AP_WK_CID: + stop_ap_hdl(padapter); + break; +#endif +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT + case TBTX_CONTROL_TX_WK_CID: + tx_control_hdl(padapter); + break; +#endif +#ifdef PRIVATE_R + case FIND_REMOTE_WK_CID: + ret = issue_action_find_remote(padapter); + break; +#ifdef CONFIG_P2P + case HIDE_SSID_WK_CID: + issue_beacon(padapter, 0); + break; +#endif +#endif + default: + break; + } + + if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) + rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size); + + return ret; +} + + +void rtw_disassoc_cmd_callback(_adapter *padapter, struct cmd_obj *pcmd) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + + + if (pcmd->res != H2C_SUCCESS) { + _rtw_spinlock_bh(&pmlmepriv->lock); + set_fwstate(pmlmepriv, WIFI_ASOC_STATE); + _rtw_spinunlock_bh(&pmlmepriv->lock); + goto exit; + } +#ifdef CONFIG_BR_EXT + else /* clear bridge database */ + nat25_db_cleanup(padapter); +#endif /* CONFIG_BR_EXT */ + +exit: + return; +} + +void rtw_create_ibss_post_hdl(_adapter *padapter, int status) +{ + struct wlan_network *pwlan = NULL; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network; + struct wlan_network *mlme_cur_network = &(pmlmepriv->dev_cur_network); + + if (status != H2C_SUCCESS) + set_assoc_timer(pmlmepriv, 1); /*_set_timer(&pmlmepriv->assoc_timer, 1);*/ + + /*_cancel_timer_ex(&pmlmepriv->assoc_timer);*/ + cancel_assoc_timer(pmlmepriv); + + _rtw_spinlock_bh(&pmlmepriv->lock); + + { + pwlan = _rtw_alloc_network(pmlmepriv); + _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock)); + if (pwlan == NULL) { + pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); + if (pwlan == NULL) { + _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock)); + goto createbss_cmd_fail; + } + pwlan->last_scanned = rtw_get_current_time(); + } else + rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); + + pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network); + _rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length); + /* pwlan->fixed = _TRUE; */ + + /* copy pdev_network information to pmlmepriv->cur_network */ + _rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network))); + +#if 0 + /* reset DSConfig */ + mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig); +#endif + + _clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING); + _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock)); + /* we will set WIFI_ASOC_STATE when there is one more sat to join us (rtw_stassoc_event_callback) */ + } + +createbss_cmd_fail: + _rtw_spinunlock_bh(&pmlmepriv->lock); + return; +} + + + +void rtw_setstaKey_cmdrsp_callback(_adapter *padapter , struct cmd_obj *pcmd) +{ + + struct sta_priv *pstapriv = &padapter->stapriv; + struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp); + struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr); + + + if (psta == NULL) { + goto exit; + } + + /* psta->phl_sta->aid = psta->phl_sta->macid = psetstakey_rsp->keyid; */ /* CAM_ID(CAM_ENTRY) */ + +exit: + return; +} + +void rtw_getrttbl_cmd_cmdrsp_callback(_adapter *padapter, struct cmd_obj *pcmd) +{ + + rtw_free_cmd_obj(pcmd); +#ifdef CONFIG_MP_INCLUDED + if (padapter->registrypriv.mp_mode == 1) + padapter->mppriv.workparam.bcompleted = _TRUE; +#endif + + +} + +u8 set_txq_params_cmd(_adapter *adapter, struct _ADAPTER_LINK *padapter_link, u32 ac_parm, u8 ac_type) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 *ac_parm_buf = NULL; + u8 sz; + u8 res = _SUCCESS; + + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + cmdobj->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + sz = sizeof(ac_parm); + ac_parm_buf = rtw_zmalloc(sz); + if (ac_parm_buf == NULL) { + rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj)); + rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->adapter_link = padapter_link; + pdrvextra_cmd_parm->ec_id = AC_PARM_CMD_WK_CID; + pdrvextra_cmd_parm->type = ac_type; + pdrvextra_cmd_parm->size = sz; + pdrvextra_cmd_parm->pbuf = ac_parm_buf; + + _rtw_memcpy(ac_parm_buf, &ac_parm, sz); + + init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + +exit: + return res; +} + +char UNKNOWN_CID[16] = "UNKNOWN_EXTRA"; +char *rtw_extra_name(struct drvextra_cmd_parm *pdrvextra_cmd) +{ + switch(pdrvextra_cmd->ec_id) { + case NONE_WK_CID: + return "NONE_WK_CID"; + break; + #if 0 /*#ifdef CONFIG_CORE_DM_CHK_TIMER*/ + case DYNAMIC_CHK_WK_CID: + return "DYNAMIC_CHK_WK_CID"; + break; + #endif + case DM_CTRL_WK_CID: + return "DM_CTRL_WK_CID"; + break; + case PBC_POLLING_WK_CID: + return "PBC_POLLING_WK_CID"; + break; + case LPS_CTRL_WK_CID: + return "LPS_CTRL_WK_CID"; + break; + case ANT_SELECT_WK_CID: + return "ANT_SELECT_WK_CID"; + break; + case P2P_PS_WK_CID: + return "P2P_PS_WK_CID"; + break; + case CHECK_HIQ_WK_CID: + return "CHECK_HIQ_WK_CID"; + break; + case C2H_WK_CID: + return "C2H_WK_CID"; + break; + case RESET_SECURITYPRIV: + return "RESET_SECURITYPRIV"; + break; + case FREE_ASSOC_RESOURCES: + return "FREE_ASSOC_RESOURCES"; + break; + case DM_IN_LPS_WK_CID: + return "DM_IN_LPS_WK_CID"; + break; + case LPS_CHANGE_DTIM_CID: + return "LPS_CHANGE_DTIM_CID"; + break; + case DFS_RADAR_DETECT_WK_CID: + return "DFS_RADAR_DETECT_WK_CID"; + break; + case DFS_RADAR_DETECT_EN_DEC_WK_CID: + return "DFS_RADAR_DETECT_EN_DEC_WK_CID"; + break; + case SESSION_TRACKER_WK_CID: + return "SESSION_TRACKER_WK_CID"; + break; + case TEST_H2C_CID: + return "TEST_H2C_CID"; + break; + case MP_CMD_WK_CID: + return "MP_CMD_WK_CID"; + break; + case CUSTOMER_STR_WK_CID: + return "CUSTOMER_STR_WK_CID"; + break; + case MGNT_TX_WK_CID: + return "MGNT_TX_WK_CID"; + break; + case REQ_PER_CMD_WK_CID: + return "REQ_PER_CMD_WK_CID"; + break; + case SSMPS_WK_CID: + return "SSMPS_WK_CID"; + break; +#ifdef CONFIG_CTRL_TXSS_BY_TP + case TXSS_WK_CID: + return "TXSS_WK_CID"; + break; +#endif + case AC_PARM_CMD_WK_CID: + return "AC_PARM_CMD_WK_CID"; + break; +#ifdef CONFIG_AP_MODE + case STOP_AP_WK_CID: + return "STOP_AP_WK_CID"; + break; +#endif +#ifdef CONFIG_RTW_TOKEN_BASED_XMIT + case TBTX_CONTROL_TX_WK_CID: + return "TBTX_CONTROL_TX_WK_CID"; + break; +#endif +#ifdef PRIVATE_R + case FIND_REMOTE_WK_CID: + return "FIND_REMOTE_WK_CID"; + break; +#ifdef CONFIG_P2P + case HIDE_SSID_WK_CID: + return "HIDE_SSID_WK_CID"; + break; +#endif +#endif + case MAX_WK_CID: + return "MAX_WK_CID"; + break; + default: + return UNKNOWN_CID; + break; + } + return UNKNOWN_CID; +} + +char UNKNOWN_CMD[16] = "UNKNOWN_CMD"; +char *rtw_cmd_name(struct cmd_obj *pcmd) +{ + struct rtw_evt_header *pev; + + if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct rtw_cmd))) + return UNKNOWN_CMD; + + if (pcmd->cmdcode == CMD_SET_MLME_EVT) + return rtw_evt_name((struct rtw_evt_header*)pcmd->parmbuf); + + if (pcmd->cmdcode == CMD_SET_DRV_EXTRA) + return rtw_extra_name((struct drvextra_cmd_parm*)pcmd->parmbuf); + + return wlancmds[pcmd->cmdcode].name; +} + +#ifdef PRIVATE_R +u8 rtw_find_remote_wk_cmd(_adapter *adapter) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 res = _SUCCESS; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + + cmdobj->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = FIND_REMOTE_WK_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + +exit: + return res; +} + +#ifdef CONFIG_P2P +u8 rtw_hide_ssid_wk_cmd(_adapter *adapter) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(adapter)->cmdpriv; + u8 res = _SUCCESS; + + cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) { + res = _FAIL; + goto exit; + } + + cmdobj->padapter = adapter; + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (pdrvextra_cmd_parm == NULL) { + rtw_mfree((unsigned char *)cmdobj, sizeof(struct cmd_obj)); + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = HIDE_SSID_WK_CID; + pdrvextra_cmd_parm->type = 0; + pdrvextra_cmd_parm->size = 0; + pdrvextra_cmd_parm->pbuf = NULL; + init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + res = rtw_enqueue_cmd(pcmdpriv, cmdobj); + +exit: + return res; + +} +#endif +#endif diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csa.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csa.c new file mode 100755 index 00000000..153263d7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csa.c @@ -0,0 +1,1275 @@ +/****************************************************************************** + * + * Copyright(c) 2019 - 2021 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_CSA_C_ +#include + +#if CONFIG_DFS +#ifdef CONFIG_ECSA_PHL +void reset_all_ecsa_param(struct _ADAPTER *a) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + struct _ADAPTER *iface; + u8 i; + + for (i = 0; i < d->iface_nums; i++) { + iface = d->padapters[i]; + if (iface->ecsa_info.core_ecsa_type != ECSA_CORE_TYPE_NONE) + reset_ecsa_param(iface); + } +} + +void reset_ecsa_param(struct _ADAPTER *a) +{ + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + + SET_ECSA_STATE(a, ECSA_ST_NONE); + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_NONE; + ecsa_info->ecsa_allow_case = 0xff; + ecsa_info->ecsa_delay_time = 0; + ecsa_info->channel_width = 255; + ecsa_info->bss_param = NULL; + ecsa_info->trigger_iface = NULL; + ecsa_info->execute_iface = NULL; + _rtw_memset(ecsa_param, 0, sizeof(struct rtw_phl_ecsa_param)); +} + +bool rtw_is_ecsa_enabled(struct _ADAPTER *a) +{ + return a->registrypriv.en_ecsa; +} + +bool rtw_mr_is_ecsa_running(struct _ADAPTER *a) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + struct _ADAPTER *iface; + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + u8 i; + + for (i = 0; i < d->iface_nums; i++) { + iface = d->padapters[i]; + if (!iface) + continue; + if (!CHK_ECSA_STATE(iface, ECSA_ST_NONE)) + return _TRUE; + } + return _FALSE; +} + +bool rtw_hal_is_csa_support(struct _ADAPTER *a) +{ + /* AX series are all supported */ + return true; +} + +static void rtw_ecsa_update_sta_cur_network(struct _ADAPTER_LINK *alink, u8 *pframe, u32 packet_len) +{ + WLAN_BSSID_EX *cur_network = &(alink->mlmepriv.cur_network.network); + + cur_network->IELength = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); + _rtw_memcpy(cur_network->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), cur_network->IELength); +} + +static void rtw_ecsa_parsing_bcn_ie(struct _ADAPTER_LINK *alink) +{ + struct _ADAPTER *a = alink->adapter; + WLAN_BSSID_EX *cur_network = &(alink->mlmepriv.cur_network.network); + u8 *bcn_ie = cur_network->IEs + _BEACON_IE_OFFSET_; + u32 bcn_len = cur_network->IELength - _BEACON_IE_OFFSET_; + + rtw_ie_handler(a, alink, bcn_ie, bcn_len); +} + +/* Reference from rtw_joinbss_update_stainfo() and update_sta_info() */ +static void rtw_ecsa_sta_update_stainfo(struct _ADAPTER_LINK *alink) +{ + struct _ADAPTER *a = alink->adapter; + struct sta_info *psta = NULL; + struct link_mlme_ext_priv *pmlmeext = &(alink->mlmeextpriv); + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct link_mlme_priv *pmlmepriv = &(alink->mlmepriv); + struct wlan_network *cur_network = &(alink->mlmepriv.cur_network); + + psta = rtw_get_stainfo(&a->stapriv, get_link_bssid(&alink->mlmepriv)); + if (!psta) { + RTW_ERR("CSA : %s sta_info is null\n", __func__); + return; + } + + update_wireless_mode(a, alink); + psta->phl_sta->wmode = pmlmeext->cur_wireless_mode; + + /* update supported rate */ + psta->bssratelen = rtw_get_rateset_len(cur_network->network.SupportedRates); + _rtw_memcpy(psta->bssrateset, cur_network->network.SupportedRates, psta->bssratelen); + +#ifdef CONFIG_80211N_HT + if (pmlmeinfo->HT_caps_enable) { + _rtw_memcpy(psta->htpriv.ht_cap.supp_mcs_set, + pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, 16); + + psta->htpriv.ht_option = true; + if (support_short_GI(a, alink, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) + psta->htpriv.sgi_20m = true; + else + psta->htpriv.sgi_20m = false; + + if (support_short_GI(a, alink, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) + psta->htpriv.sgi_40m = true; + else + psta->htpriv.sgi_40m = false; + } else { + _rtw_memset(&(psta->htpriv), 0, sizeof(struct ht_priv)); + } + psta->htpriv.ch_offset = pmlmeext->chandef.offset; +#endif + +#ifdef CONFIG_80211AC_VHT + if (pmlmeinfo->VHT_enable) { + _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv)); + + psta->vhtpriv.vht_option = true; + #ifdef CONFIG_BEAMFORMING + psta->vhtpriv.beamform_cap = pmlmepriv->vhtpriv.beamform_cap; + #endif + } else { + _rtw_memset(&(psta->vhtpriv), 0, sizeof(struct vht_priv)); + } +#endif + +#ifdef CONFIG_80211AX_HE + if (pmlmeinfo->HE_enable) + _rtw_memcpy(&psta->hepriv, &pmlmepriv->hepriv, sizeof(struct he_priv)); + else + _rtw_memset(&(psta->hepriv), 0, sizeof(struct he_priv)); +#endif + +#if CONFIG_IEEE80211_BAND_6GHZ + if (psta->phl_sta->chandef.band == BAND_ON_6G) { + psta->ampdu_priv.ampdu_enable = pmlmepriv->ampdu_priv.ampdu_enable; + /* update mpdu_min_spacing in HE_6g_bandcap_handler */ + psta->ampdu_priv.rx_ampdu_min_spacing = psta->hepriv.mpdu_min_spacing; + } +#endif +} + +void rtw_ecsa_update_sta_mlme(struct _ADAPTER_LINK *alink, u8 *pframe, u32 packet_len) +{ + struct link_mlme_priv *pmlmepriv = &(alink->mlmepriv); + struct link_mlme_ext_info *pmlmeinfo = &(alink->mlmeextpriv.mlmext_info); + struct beacon_keys *cur_beacon = &(pmlmepriv->cur_beacon_keys); + +#ifdef CONFIG_80211N_HT + if (cur_beacon->proto_cap & PROTO_CAP_11N) { + pmlmepriv->htpriv.ht_option = _TRUE; + pmlmeinfo->HT_enable = _TRUE; + } else { + pmlmepriv->htpriv.ht_option = _FALSE; + pmlmeinfo->HT_enable = _FALSE; + } +#endif + +#ifdef CONFIG_80211AC_VHT + if (cur_beacon->proto_cap & PROTO_CAP_11AC) { + pmlmepriv->vhtpriv.vht_option = _TRUE; + pmlmeinfo->VHT_enable = _TRUE; + } else { + pmlmepriv->vhtpriv.vht_option = _FALSE; + pmlmeinfo->VHT_enable = _FALSE; + } +#endif + + rtw_ecsa_update_sta_cur_network(alink, pframe, packet_len); + + /* parse new beacon ie from current network to update protocol information of link_mlme_ext_info */ + rtw_ecsa_parsing_bcn_ie(alink); + + /* update sta_info from protocol information */ + rtw_ecsa_sta_update_stainfo(alink); +} + +void rtw_build_csa_ie(struct _ADAPTER *a, struct rtw_phl_ecsa_param *ecsa_param) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + u8 csa_data[CSA_IE_LEN] = {0}; + + /* + * [0] : Channel Switch Mode + * [1] : New Channel Number + * [2] : Channel Switch Count + */ + csa_data[0] = ecsa_param->mode; + csa_data[1] = ecsa_param->new_chan_def.chan; + csa_data[2] = ecsa_param->count; + rtw_add_bcn_ie(a, pnetwork, WLAN_EID_CHANNEL_SWITCH, csa_data, CSA_IE_LEN); + RTW_INFO("CSA : build channel switch announcement IE by driver\n"); + RTW_INFO("CSA : mode = %u, ch = %u, switch count = %u\n", + csa_data[0], csa_data[1], csa_data[2]); +} + +void rtw_build_ecsa_ie(struct _ADAPTER *a, struct rtw_phl_ecsa_param *ecsa_param) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + u8 ecsa_data[ECSA_IE_LEN] = {0}; + + /* + * [0] : Channel Switch Mode + * [1] : New Operating Class + * [2] : New Channel Number + * [3] : Channel Switch Count + */ + ecsa_data[0] = ecsa_param->mode; + ecsa_data[1] = ecsa_param->op_class; + ecsa_data[2] = ecsa_param->new_chan_def.chan; + ecsa_data[3] = ecsa_param->count; + rtw_add_bcn_ie(a, pnetwork, WLAN_EID_ECSA, ecsa_data, ECSA_IE_LEN); + RTW_INFO("CSA : build extended channel switch announcement IE by driver\n"); + RTW_INFO("CSA : mode = %u, op_class = %u, ch = %u, switch count = %u\n", + ecsa_data[0], ecsa_data[1], ecsa_data[2], ecsa_data[3]); +} + +void rtw_build_sec_offset_ie(struct _ADAPTER *a, u8 seconday_offset) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + + rtw_add_bcn_ie(a, pnetwork, WLAN_EID_SECONDARY_CHANNEL_OFFSET, &seconday_offset, 1); + RTW_INFO("CSA : build secondary channel offset IE by driver, sec_offset = %u\n", seconday_offset); +} + +void rtw_build_wide_bw_cs_ie(struct _ADAPTER *a, struct rtw_chan_def new_chandef) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + u8 csw_data[CS_WR_DATA_LEN] = {0}; + u8 ch_width, seg_0; + + switch (new_chandef.bw) { + case CHANNEL_WIDTH_40: + ch_width = 0; + break; + case CHANNEL_WIDTH_80: + ch_width = 1; + break; + default: + ch_width = 1; + break; + } + + seg_0 = rtw_phl_get_center_ch(&new_chandef); + + /* + * subfields of Wide Bandwidth Channel Switch subelement + * [1] : Length + * [2] : New Channel Width + * [3] : New Channel Center Frequency Segment 0 + * [4] : New Channel Center Frequency Segment 1 + */ + csw_data[0] = WLAN_EID_VHT_WIDE_BW_CHSWITCH; + csw_data[1] = 3; + csw_data[2] = ch_width; + csw_data[3] = seg_0; + csw_data[4] = 0; + rtw_add_bcn_ie(a, pnetwork, WLAN_EID_CHANNEL_SWITCH_WRAPPER, csw_data, CS_WR_DATA_LEN); + RTW_INFO("CSA : build channel switch wrapper IE by driver\n"); + RTW_INFO("CSA : channel width = %u, segment_0 = %u, segment_1 = %u\n", + csw_data[2], csw_data[3], csw_data[4]); +} + +void rtw_core_build_ecsa_beacon(struct _ADAPTER *a, + struct rtw_phl_ecsa_param *ecsa_param, + u8 is_vht) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + struct rtw_chan_def new_chandef = ecsa_param->new_chan_def; + struct ieee80211_info_element *ie; + u8 *ies; + uint ies_len; + bool cs_add = false, ecs_add = false, sco_add = false, csw_add = false; + + ies = pnetwork->IEs + _BEACON_IE_OFFSET_; + ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_; + + /* Check the missing IE of beacon, then build it by driver */ + for_each_ie(ie, ies, ies_len) { + switch (ie->id) { + case WLAN_EID_CHANNEL_SWITCH: + #ifdef DBG_CSA + RTW_INFO("CSA : find CSA IE\n"); + #endif + cs_add = true; + break; + + case WLAN_EID_ECSA: + #ifdef DBG_CSA + RTW_INFO("CSA : find ECSA IE\n"); + #endif + ecs_add = true; + break; + + case WLAN_EID_SECONDARY_CHANNEL_OFFSET: + #ifdef DBG_CSA + RTW_INFO("CSA : find SEC_CH_OFFSET IE\n"); + #endif + sco_add = true; + break; + + case WLAN_EID_CHANNEL_SWITCH_WRAPPER: + #ifdef DBG_CSA + RTW_INFO("CSA : find CH_SW_WRAPPER IE\n"); + #endif + csw_add = true; + break; + + default: + break; + } + } + + /* Build Channel Switch Announcement element */ + if (!cs_add) + rtw_build_csa_ie(a, ecsa_param); + + /* Build Extended Channel Switch Announcement element */ + if (!ecs_add && rtw_is_ecsa_enabled(a)) + rtw_build_ecsa_ie(a, ecsa_param); + + /* Build Secondary Channel Offset element */ + if (!sco_add && new_chandef.offset != CHAN_OFFSET_NO_EXT) + rtw_build_sec_offset_ie(a, new_chandef.offset); + + /* Build Channel Switch Wrapper element which only include Wide Bandwidth Channel Switch subelement */ + if (!csw_add && is_vht && (new_chandef.bw >= CHANNEL_WIDTH_40 && new_chandef.bw <= CHANNEL_WIDTH_80_80)) + rtw_build_wide_bw_cs_ie(a, new_chandef); +} + +void rtw_cfg80211_build_csa_beacon(struct _ADAPTER *a, + struct cfg80211_csa_settings *params, struct rtw_chan_def csa_chdef) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + struct ieee80211_info_element *ie; + u8 *ies; + uint ies_len; + + if (params->beacon_csa.tail) { + ies = (u8 *)params->beacon_csa.tail; + ies_len = params->beacon_csa.tail_len; + RTW_INFO("CSA : Parsing beacon content from cfg80211_csa_settings\n"); + + for_each_ie(ie, ies, ies_len) { + #ifdef DBG_CSA + RTW_INFO("CSA : for each IE, element id = %u, len = %u\n", ie->id, ie->len); + #endif + switch (ie->id) { + case WLAN_EID_CHANNEL_SWITCH: + RTW_INFO("CSA : add channel switch announcement IE to beacon\n"); + RTW_INFO("CSA : mode = %u, ch = %u, switch count = %u\n", + ie->data[0], ie->data[1], ie->data[2]); + rtw_add_bcn_ie(a, pnetwork, ie->id, ie->data, ie->len); + break; + + case WLAN_EID_ECSA: + RTW_INFO("CSA : add extended channel switch announcement IE to beacon\n"); + RTW_INFO("CSA : mode = %u, op_class = %u, ch = %u, switch count = %u\n", + ie->data[0], ie->data[1], ie->data[2], ie->data[3]); + rtw_add_bcn_ie(a, pnetwork, ie->id, ie->data, ie->len); + break; + + /* Secondary channel offset element is not necessary for channel switching to BW_20M */ + case WLAN_EID_SECONDARY_CHANNEL_OFFSET: + RTW_INFO("CSA : add secondary channel offset IE to beacon, sec_offset = %u\n", + ie->data[0]); + rtw_add_bcn_ie(a, pnetwork, ie->id, ie->data, ie->len); + break; + + case WLAN_EID_CHANNEL_SWITCH_WRAPPER: + RTW_INFO("CSA : add channel switch wrapper IE to beacon\n"); + RTW_INFO("CSA : channel width = %u, segment_0 = %u, segment_1 = %u\n", + ie->data[2], ie->data[3], ie->data[4]); + rtw_add_bcn_ie(a, pnetwork, ie->id, ie->data, ie->len); + break; + + default: + break; + } + } + } +} + +static void rtw_ecsa_update_sta_chan_info(struct _ADAPTER *a, + struct _ADAPTER_LINK *alink, + struct rtw_chan_def new_chan_def) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + struct rtw_chset *chset = dvobj_to_chset(d); + u8 new_band = new_chan_def.band; + u8 new_ch = new_chan_def.chan; + u8 new_bw = (u8)new_chan_def.bw; + u8 new_offset = (u8)new_chan_def.offset; + bool is_chctx_add = _FALSE; + struct rtw_mr_chctx_info mr_cc_info = {0}; + struct link_mlme_ext_priv *pmlmeext = &alink->mlmeextpriv; + struct link_mlme_priv *pmlmepriv = &alink->mlmepriv; + u32 csa_wait_bcn_ms; + + pmlmeext->chandef.band= new_band; + pmlmeext->chandef.chan= new_ch; + pmlmeext->chandef.bw = new_bw; + pmlmeext->chandef.offset = new_offset; + pmlmepriv->cur_network.network.Configuration.DSConfig = new_ch; + + /* update wifi role link chandef */ + rtw_hw_update_chan_def(a, alink); + /* update chanctx */ + rtw_phl_chanctx_del(d->phl, a->phl_role, alink->wrlink, NULL); + is_chctx_add = rtw_phl_chanctx_add(d->phl, a->phl_role, + alink->wrlink, + &new_chan_def, &mr_cc_info); + if (is_chctx_add == _FALSE) + RTW_ERR("CSA : "FUNC_ADPT_FMT" chan_ctx add fail!", FUNC_ADPT_ARG(a)); + + set_fwstate(&a->mlmepriv, WIFI_CSA_UPDATE_BEACON); + + #ifdef CONFIG_80211D + rtw_alink_csa_update_regulatory(alink, new_band, new_ch); + #endif + + if (rtw_chset_is_dfs_bchbw(chset, new_band, new_ch, new_bw, new_offset)) + csa_wait_bcn_ms = CAC_TIME_MS + 10000; + else + csa_wait_bcn_ms = WAIT_BCN_TIMES * 2 * 1000; + + RTW_INFO("CSA : set csa_wait_bcn_timer to %u ms\n", csa_wait_bcn_ms); + _set_timer(&a->mlmeextpriv.csa_wait_bcn_timer, csa_wait_bcn_ms); + + #if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ + rtw_dfs_rd_en_dec_on_mlme_act(a, alink, MLME_OPCH_SWITCH, 0); + #endif +} + +void rtw_ap_update_beacon_by_role(void *priv, struct rtw_wifi_role_t *role , struct rtw_wifi_role_link_t *rlink) +{ + /* TODO */ +} +static void rtw_ecsa_update_ap_chan_info(struct _ADAPTER *a, struct rtw_chan_def new_chan_def) +{ + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct createbss_parm *parm; + + ecsa_info->bss_param = (struct createbss_parm *)rtw_zmalloc(sizeof(struct createbss_parm)); + if (ecsa_info->bss_param) { + parm = ecsa_info->bss_param; + parm->adhoc = 0; + parm->ifbmp = BIT(a->iface_id); + parm->excl_ifbmp = 0; + parm->req_band = new_chan_def.band; + parm->req_ch = new_chan_def.chan; + parm->req_bw = new_chan_def.bw; + parm->req_offset = new_chan_def.offset; + parm->ifbmp_ch_changed = 0; + parm->ch_to_set = 0; + parm->bw_to_set = 0; + parm->offset_to_set = 0; + parm->is_change_chbw = _TRUE; + + rtw_core_ap_prepare(a, parm); + } else { + RTW_ERR("CSA : can't allocate memory for bss_param\n"); + } +} + +/** + * rtw_ecsa_update_sta_ap_chan_info - update STA role and AP role chandef + * Flow : + * del AP role chandef -> del STA role chandef -> add STA role chandef -> add AP role chandef + */ +static void rtw_ecsa_update_sta_ap_chan_info(struct _ADAPTER *ap_iface, + struct _ADAPTER_LINK *ap_iface_link, + struct rtw_chan_def ap_new_chan_def) +{ + struct dvobj_priv *d = adapter_to_dvobj(ap_iface); + struct _ADAPTER *sta_iface = ap_iface->ecsa_info.trigger_iface; + struct _ADAPTER_LINK *sta_iface_link = GET_PRIMARY_LINK(sta_iface); + struct rtw_chan_def sta_new_chan_def = sta_iface->ecsa_info.phl_ecsa_param.new_chan_def; + + rtw_phl_chanctx_del(d->phl, ap_iface->phl_role, ap_iface_link->wrlink, NULL); + ap_iface_link->is_ap_chan_ctx_added = false; + + rtw_ecsa_update_sta_chan_info(sta_iface, sta_iface_link, sta_new_chan_def); + + rtw_ecsa_update_ap_chan_info(ap_iface, ap_new_chan_def); +} + +void rtw_ecsa_update_probe_resp(struct xmit_frame *xframe) +{ + struct _ADAPTER *a = xframe->padapter; + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + struct pkt_attrib *pattrib = &xframe->attrib; + u8 hdr_len = sizeof(struct rtw_ieee80211_hdr_3addr); + u8 *ies; + sint ies_len; + u8 *csa_ie, *ecsa_ie; + sint csa_ie_len, ecsa_ie_len; + + ies = xframe->buf_addr + TXDESC_OFFSET + hdr_len + _BEACON_IE_OFFSET_; + ies_len = pattrib->pktlen - hdr_len - _BEACON_IE_OFFSET_; + + csa_ie = rtw_get_ie(ies, WLAN_EID_CHANNEL_SWITCH, &csa_ie_len, ies_len); + + if (csa_ie == NULL) + return; + + csa_ie[2 + CSA_SWITCH_COUNT] = ecsa_param->count; + + #ifdef DBG_CSA + RTW_INFO("CSA : update csa count of probe response = %u\n", + csa_ie[2 + CSA_SWITCH_COUNT]); + #endif + + if (rtw_is_ecsa_enabled(a)) { + ecsa_ie = rtw_get_ie(ies, WLAN_EID_ECSA, &ecsa_ie_len, ies_len); + if (ecsa_ie == NULL) + return; + + /* + * [0] : Channel Switch Mode + * [1] : New Operating Class + * [2] : New Channel Number + * [3] : Channel Switch Count + */ + ecsa_ie[2 + 3] = ecsa_param->count; + + #ifdef DBG_CSA + RTW_INFO("CSA : update ecsa count of probe response = %u\n", + ecsa_ie[2 + 3]); + #endif + } +} + +static void rtw_check_phl_ecsa_request(struct _ADAPTER *a) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + u8 is_vht = alink->mlmepriv.vhtpriv.vht_option; + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + struct rtw_phl_ecsa_param *phl_ecsa_param; + + /* ECSA request comes from PHL MR module, so we need to fill ecsa_param */ + if (CHK_ECSA_STATE(a, ECSA_ST_SW_START) && + ecsa_info->core_ecsa_type == ECSA_CORE_TYPE_NONE) { + /* Get pointer of ecsa_parameter from PHL, then copy value to ecsa_parameter of core */ + rtw_phl_ecsa_get_param(d->phl, &phl_ecsa_param); + _rtw_memcpy(ecsa_param, phl_ecsa_param, sizeof(struct rtw_phl_ecsa_param)); + rtw_core_build_ecsa_beacon(a, ecsa_param, is_vht); + } +} + +static bool _chk_csa_groupd(struct rtw_chan_def *chandef_a, + struct rtw_chan_def *chandef_b) +{ + if (chandef_a->band != chandef_b->band) + return _FALSE; + + if ((chandef_a->bw == CHANNEL_WIDTH_40 || chandef_a->bw == CHANNEL_WIDTH_80) && + (chandef_b->bw == CHANNEL_WIDTH_40 || chandef_b->bw == CHANNEL_WIDTH_80)) { + if (chandef_a->offset != chandef_b->offset) + return _FALSE; + } + return _TRUE; +} + +void rtw_ecsa_update_beacon(void *priv, struct rtw_wifi_role_t *role , struct rtw_wifi_role_link_t *rlink) +{ +#ifdef CONFIG_AP_MODE + struct dvobj_priv *d = (struct dvobj_priv *)priv; + struct _ADAPTER *a = d->padapters[role->id]; + struct _ADAPTER_LINK *alink = GET_LINK(a, rlink->id); + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + WLAN_BSSID_EX *pnetwork = &(alink->mlmeextpriv.mlmext_info.network); + + rtw_check_phl_ecsa_request(a); + + /* update CSA and ECSA IE at the same time */ + _update_beacon(a, alink, WLAN_EID_CHANNEL_SWITCH, NULL, _TRUE, 0, "update CSA count"); + + if (ecsa_param->count == 0) { + rtw_remove_bcn_ie(a, pnetwork, WLAN_EID_SECONDARY_CHANNEL_OFFSET); + rtw_remove_bcn_ie(a, pnetwork, WLAN_EID_CHANNEL_SWITCH_WRAPPER); + } +#endif +} + +/* PHL MR module check core layer whether AP mode can switch channel now */ +bool rtw_ap_check_ecsa_allow( + void *priv, + struct rtw_wifi_role_t *role, + struct rtw_chan_def sta_chdef, + enum phl_ecsa_start_reason reason, +#ifdef CONFIG_ECSA_EXTEND_OPTION + u32 *extend_option, +#endif + u32 *delay_start_ms +) +{ + struct dvobj_priv *d = (struct dvobj_priv *)priv; + struct _ADAPTER *a = d->padapters[role->id]; + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + struct rtw_chan_def ap_chdef = alink->wrlink->chandef; + struct rf_ctl_t *rfctl = dvobj_to_rfctl(d); + RT_CHANNEL_INFO *chinfo = rtw_chset_get_chinfo_by_bch(&rfctl->chset, sta_chdef.band, sta_chdef.chan, 0); + bool ecsa_allow = _TRUE; + u8 i; + +#ifdef CONFIG_MCC_MODE + if (rtw_hw_mcc_chk_inprogress(a, alink)) { + RTW_INFO("CSA : "FUNC_ADPT_FMT" : Don't switch channel if MCC enabled\n", + FUNC_ADPT_ARG(a)); + ecsa_allow = _FALSE; + goto exit; + } +#endif + + if (!(ecsa_info->ecsa_allow_case & BIT(reason))) { + RTW_INFO("CSA : "FUNC_ADPT_FMT" : Case %u not support!\n", FUNC_ADPT_ARG(a), reason); + ecsa_allow = _FALSE; + goto exit; + } + + /* Check DFS channel */ + if (!chinfo || (chinfo->flags & (RTW_CHF_NO_IR | RTW_CHF_DFS))) { + RTW_ERR("CSA : "FUNC_ADPT_FMT" : DFS channel (%u) not support!\n", + FUNC_ADPT_ARG(a), sta_chdef.chan); + ecsa_allow = _FALSE; + goto exit; + } + + if (ecsa_info->ecsa_delay_time != 0) + *delay_start_ms = ecsa_info->ecsa_delay_time; + else if (reason <= ECSA_START_MCC_5G_TO_24G) + *delay_start_ms = MCC_ECSA_DELAY_START_TIME; + RTW_INFO("CSA : "FUNC_ADPT_FMT" ECSA will delay %u ms to start\n", FUNC_ADPT_ARG(a), *delay_start_ms); + + SET_ECSA_STATE(a, ECSA_ST_SW_START); + + /* + * AP mode use the its bandwidth/offset to switch channel if its bandwidth/offset can group with STA mode. + * Otherwise, AP mode use chandef of STA mode. + */ + if (_chk_csa_groupd(&ap_chdef, &sta_chdef)) { + #ifdef CONFIG_ECSA_EXTEND_OPTION + *extend_option = ECSA_EX_OPTION_USE_AP_CHANDEF; + #endif + RTW_INFO("CSA : AP mode use its bandwidth/offset to switch channel\n"); + } else { + RTW_INFO("CSA : bandwidth/offset of AP mode can't group with STA mode, so use bandwidth/offset of STA mode\n"); + } + + RTW_INFO("CSA : Switch AP to STA's channel. AP:%u,%u,%u STA:%u,%u,%u\n", + ap_chdef.chan, ap_chdef.bw, ap_chdef.offset, + sta_chdef.chan, sta_chdef.bw, sta_chdef.offset); +exit: + return ecsa_allow; +} + +void rtw_ecsa_mr_update_chan_info_by_role( + void *priv, + struct rtw_wifi_role_t *role, + struct rtw_wifi_role_link_t *rlink, + struct rtw_chan_def new_chan_def) +{ + struct dvobj_priv *d = (struct dvobj_priv *)priv; + struct _ADAPTER *a = d->padapters[role->id]; + struct _ADAPTER_LINK *alink = GET_LINK(a, rlink->id); + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + + RTW_INFO("CSA : "FUNC_ADPT_FMT", new ch/bw/offset = %u,%u,%u\n", + FUNC_ADPT_ARG(a), new_chan_def.chan, new_chan_def.bw, + new_chan_def.offset); + + if (ecsa_info->core_ecsa_type == ECSA_CORE_TYPE_SCC_STA_AP && + (role->type == PHL_RTYPE_AP || role->type == PHL_RTYPE_P2P_GO)) { + /* multi-role STA + AP in SCC */ + rtw_ecsa_update_sta_ap_chan_info(a, alink, new_chan_def); + } else { + /* single-role or multi-role in MCC or DBCC */ + if (role->type == PHL_RTYPE_STATION || role->type == PHL_RTYPE_P2P_GC) + rtw_ecsa_update_sta_chan_info(a, alink, new_chan_def); + else if (role->type == PHL_RTYPE_AP ||role->type == PHL_RTYPE_P2P_GO) + rtw_ecsa_update_ap_chan_info(a, new_chan_def); + } +} + +bool rtw_ecsa_check_tx_resume_allow(void *priv, struct rtw_wifi_role_t *role) +{ + /* TODO */ + /* Is DFS slave still monitoring channel ? + If Yes, return False to PHL; If no, return True to PHL */ + struct dvobj_priv *d = (struct dvobj_priv *)priv; + struct _ADAPTER *a = d->padapters[role->id]; + + RTW_INFO("CSA : "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(a)); + return 1; +} + +void rtw_ecsa_complete(void *priv, struct rtw_wifi_role_t *role) +{ + struct dvobj_priv *d = (struct dvobj_priv *)priv; + struct _ADAPTER *a = d->padapters[role->id]; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(a); + struct rf_ctl_t *rfctl = dvobj_to_rfctl(d); + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct createbss_parm *parm; + u8 ht_option = 0; + + RTW_INFO("CSA : "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(a)); + rtw_phl_mr_dump_cur_chandef(d->phl, role); + + /* single-rol or multi-role in MCC or DBCC */ + if (role->type == PHL_RTYPE_STATION || role->type == PHL_RTYPE_P2P_GC) { + /* + * TODO + * STA mode need to update RA if it receive CHANNEL_SWITCH_WRAPPER IE + * STA mode update its RA at rtw_check_bcn_info() now + */ + rtw_rfctl_update_op_mode(rfctl, 0, 0, 0); + + clr_fwstate(&(a->mlmepriv), WIFI_CSA_SKIP_CHECK_BEACON); + } else if (role->type == PHL_RTYPE_AP ||role->type == PHL_RTYPE_P2P_GO) { + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) + #ifdef CONFIG_80211N_HT + ht_option = alink->mlmepriv.htpriv.ht_option; + #endif + rtw_cfg80211_ch_switch_notify(a, + GET_PRIMARY_LINK(a), + &alink->mlmeextpriv.chandef, + ht_option, 0); + #endif + + parm = ecsa_info->bss_param; + rtw_rfctl_update_op_mode(adapter_to_rfctl(a), + parm->ifbmp, 1, parm->excl_ifbmp); + rtw_core_ap_start(a, parm); + rtw_ap_update_clients_rainfo(a, 0); + rtw_mfree((u8 *)parm, sizeof(struct createbss_parm)); + } + + rtw_mi_os_xmit_schedule(a); + reset_all_ecsa_param(a); +} + +static void rtw_ap_send_csa_action_frame(struct _ADAPTER *a, struct _ADAPTER_LINK *alink) +{ + _list *phead, *plist; + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &(a->stapriv); + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + rtw_stapriv_asoc_list_lock(pstapriv); + phead = &pstapriv->asoc_list; + plist = get_next(phead); + + /* for each sta in asoc_queue */ + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + + issue_action_spct_ch_switch(a, alink, psta->phl_sta->mac_addr); + } + rtw_stapriv_asoc_list_unlock(pstapriv); + + issue_action_spct_ch_switch(a, alink, bc_addr); +} + +/* Get ch/bw/offset of CSA from adapter, and check these parameters is valid or not */ +static bool rtw_sta_get_ecsa_setting(struct _ADAPTER *a) +{ + struct rtw_chset *chset = adapter_to_chset(a); + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + struct rtw_chan_def chan_def; + u8 csa_band = ecsa_param->new_chan_def.band; + u8 csa_chan = ecsa_param->new_chan_def.chan; + u8 csa_offset = ecsa_param->new_chan_def.offset; + u8 csa_op_class = ecsa_param->op_class; + bool get_bw_offset_from_opclass; + u8 req_band, req_ch, req_bw, req_offset; + u8 i, r_offset[2], r_offset_num; + bool valid_offset = false; + + req_band = csa_band; + req_ch = csa_chan; + req_bw = CHANNEL_WIDTH_20; + req_offset = CHAN_OFFSET_NO_EXT; + + if (rtw_chset_search_bch(chset, csa_band, csa_chan) < 0 + || rtw_chset_is_bch_non_ocp(chset, csa_band, csa_chan)) { + RTW_INFO("CSA : channel %u is not supported, so do not switching channel\n", csa_chan); + return false; + } + + get_bw_offset_from_opclass = rtw_phl_get_chandef_from_operating_class(req_ch, + csa_op_class, &chan_def); + + if (get_bw_offset_from_opclass) { + req_band = chan_def.band; + req_bw = chan_def.bw; + req_offset = chan_def.offset; + } else { + /* Transform channel_width to bandwidth 20/40/80M */ + switch (ecsa_info->channel_width) { + case CH_WIDTH_80_160M: + req_bw = CHANNEL_WIDTH_80; + req_offset = csa_offset; + break; + case CH_WIDTH_20_40M: + /* + * We don't know the actual offset of channel 5 to 9 + * if offset is CHAN_OFFSET_NO_EXT and bandwidth is 40MHz, + * so force its bandwidth to 20MHz + */ + if ((csa_band == BAND_ON_24G && req_ch >= 5 && req_ch <=9) && + csa_offset == CHAN_OFFSET_NO_EXT) + req_bw = CHANNEL_WIDTH_20; + else + req_bw = CHANNEL_WIDTH_40; + req_offset = csa_offset; + break; + default: + req_bw = CHANNEL_WIDTH_20; + req_offset = CHAN_OFFSET_NO_EXT; + break; + } + } + + /* Get correct offset and check ch/bw/offset is valid or not */ + if (req_bw > CHANNEL_WIDTH_20 && + (req_offset == CHAN_OFFSET_NO_EXT || req_offset == CHAN_OFFSET_NO_DEF)) { + if (rtw_get_offsets_by_bchbw(req_band, req_ch, req_bw, r_offset, &r_offset_num)) { + for (i = 0; i < r_offset_num; i++) { + req_offset = r_offset[i]; + /* choose first valid offset */ + if (rtw_chset_is_bchbw_valid(chset, req_band, req_ch, req_bw, req_offset, 0, 0)) { + valid_offset = true; + break; + } + } + } + + if (!valid_offset) { + req_bw = CHANNEL_WIDTH_20; + req_offset = CHAN_OFFSET_NO_EXT; + } + } + + ecsa_param->new_chan_def.band = req_band; + ecsa_param->new_chan_def.chan = req_ch; + ecsa_param->new_chan_def.bw = req_bw; + ecsa_param->new_chan_def.offset = req_offset; + + /* bw/offset is limited by SW capability */ + if (rtw_adjust_bchbw(a, ecsa_param->new_chan_def.band, + ecsa_param->new_chan_def.chan, + (u8 *)&ecsa_param->new_chan_def.bw, + (u8 *)&ecsa_param->new_chan_def.offset)) { + RTW_INFO("CSA : "FUNC_ADPT_FMT" limit by cap bw (%u) to (%u)\n", + FUNC_ADPT_ARG(a), req_bw, ecsa_param->new_chan_def.bw); + } + + return true; +} + +static void rtw_sta_ecsa_invalid_hdl(struct _ADAPTER *a) +{ + struct dvobj_priv *d = adapter_to_dvobj(a); + struct rf_ctl_t *rfctl = dvobj_to_rfctl(d); + struct mlme_ext_priv *pmlmeext = &a->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(a); + struct rtw_chan_def mr_chdef = {0}; + + if (!ifbmp_s) + return; + + set_fwstate(&a->mlmepriv, WIFI_OP_CH_SWITCHING); + issue_deauth(a, get_bssid(&a->mlmepriv), WLAN_REASON_DEAUTH_LEAVING); + + /* TODO : DFS slave may need to switch channel as soon as possible before disconnect */ + + /* This context can't I/O, so use RTW_CMDF_DIRECTLY */ + rtw_disassoc_cmd(a, 0, RTW_CMDF_DIRECTLY); + rtw_indicate_disconnect(a, 0, _FALSE); + #ifndef CONFIG_STA_CMD_DISPR + rtw_free_assoc_resources(a, _TRUE); + #endif + rtw_free_network_queue(a, _TRUE); + rtw_free_mld_network_queue(a, _TRUE); + RTW_INFO("CSA : "FUNC_ADPT_FMT" disconnect with AP\n", FUNC_ADPT_ARG(a)); + + pmlmeinfo->disconnect_occurred_time = rtw_systime_to_ms(rtw_get_current_time()); + pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_INVALID_CSA; + pmlmeinfo->wifi_reason_code = WLAN_REASON_DEAUTH_LEAVING; + + rtw_mi_os_xmit_schedule(a); + + reset_ecsa_param(a); +} + +static enum ecsa_mr_case rtw_ecsa_mr_check(struct _ADAPTER *execute_iface) +{ + struct dvobj_priv *d = adapter_to_dvobj(execute_iface); + struct rtw_wifi_role_t *role = execute_iface->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(execute_iface); + struct rtw_wifi_role_link_t *rlink = alink->wrlink; + struct core_ecsa_info *ecsa_info = &(execute_iface->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + struct rtw_chan_def n_chdef; + struct mi_state mstate = {0}; + struct rtw_mr_chctx_info mr_cc_info = {0}; + + n_chdef = ecsa_param->new_chan_def; + rtw_mi_status(execute_iface, &mstate); + + /* Check whether channel, bandwidth, offset can group under multi-role */ + if ((MSTATE_STA_LD_NUM(&mstate) + + MSTATE_AP_NUM(&mstate) + + MSTATE_MESH_NUM(&mstate) >= 2) && + !rtw_phl_chanctx_chk(GET_PHL_INFO(d), role, rlink, &n_chdef, &mr_cc_info)) { + #ifdef CONFIG_DBCC_SUPPORT + if (mr_cc_info.sugg_opmode == MR_OP_DBCC) { + rtw_phl_mr_trig_dbcc_enable(GET_PHL_INFO(d)); + } else + #endif + { + /* chandef of multi-role can't group */ + RTW_INFO("CSA : "FUNC_ADPT_FMT ": " + "chandef can't group, use SCC mode to switch channel! " + "ld_sta_num:%u, ap_num:%u, mesh_num:%u\n", + FUNC_ADPT_ARG(execute_iface), MSTATE_STA_LD_NUM(&mstate), + MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)); + + /* Support ECSA of one STA + one AP/GO */ + if (MSTATE_STA_LD_NUM(&mstate) == 1 && + (MSTATE_AP_NUM(&mstate) + MSTATE_MESH_NUM(&mstate) == 1)) + return ECSA_MR_SCC_STA_AP; + else + return ECSA_MR_UNSUPPORTED; + } + } + + return ECSA_SINGLE_ROLE; +} + +static struct _ADAPTER *rtw_scc_sta_ap_init_ap_role(struct _ADAPTER *sta_iface) +{ + struct dvobj_priv *d = adapter_to_dvobj(sta_iface); + struct core_ecsa_info *sta_ecsa_info = &(sta_iface->ecsa_info); + struct rtw_phl_ecsa_param *sta_ecsa_param = &(sta_ecsa_info->phl_ecsa_param); + struct core_ecsa_info *ap_ecsa_info; + struct rtw_phl_ecsa_param *ap_ecsa_param; + struct _ADAPTER *ap_iface = NULL; + struct _ADAPTER_LINK *alink; + struct link_mlme_ext_priv *lmlmeext; + struct rtw_chan_def *ap_new_chan_def; + u8 is_vht; + u8 i; + + sta_ecsa_info->trigger_iface = sta_iface; + for (i = 0; i < d->iface_nums; i++) { + ap_iface = d->padapters[i]; + + if (!ap_iface || ap_iface == sta_iface || !rtw_is_adapter_up(ap_iface)) + continue; + + if ((MLME_IS_AP(ap_iface) || MLME_IS_MESH(ap_iface)) + && check_fwstate(&ap_iface->mlmepriv, WIFI_ASOC_STATE)) { + + sta_ecsa_info->execute_iface = ap_iface; + alink = GET_PRIMARY_LINK(ap_iface); + lmlmeext = &(alink->mlmeextpriv); + ap_ecsa_info = &(ap_iface->ecsa_info); + ap_ecsa_param = &(ap_ecsa_info->phl_ecsa_param); + + SET_ECSA_STATE(ap_iface, ECSA_ST_SW_START); + ap_ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_SCC_STA_AP; + ap_ecsa_info->trigger_iface = sta_iface; + ap_ecsa_info->execute_iface = ap_iface; + _rtw_memcpy(ap_ecsa_param, sta_ecsa_param, sizeof(struct rtw_phl_ecsa_param)); + + ap_new_chan_def = &(ap_ecsa_param->new_chan_def); + ap_new_chan_def->bw = lmlmeext->chandef.bw; + ap_new_chan_def->offset = lmlmeext->chandef.offset; + + /* adjust bw according registery and hw cap*/ + rtw_adjust_bchbw(ap_iface, ap_new_chan_def->band, + ap_new_chan_def->chan, + (u8 *)&ap_new_chan_def->bw, + (u8 *)&ap_new_chan_def->offset); + + /* adjust bw and offset according chanctx to avoid wrong offset */ + rtw_phl_adjust_chandef(d->phl, alink->wrlink, ap_new_chan_def); + + is_vht = alink->mlmepriv.vhtpriv.vht_option; + rtw_core_build_ecsa_beacon(ap_iface, ap_ecsa_param, is_vht); + break; + } + } + + return ap_iface; +} + +void rtw_fill_phl_ecsa_type(struct core_ecsa_info *ecsa_info) +{ + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + + switch (ecsa_info->core_ecsa_type) { + case ECSA_CORE_TYPE_NONE: + ecsa_param->ecsa_type = ECSA_TYPE_NONE; + break; + case ECSA_CORE_TYPE_AP: + ecsa_param->ecsa_type = ECSA_TYPE_AP; + break; + case ECSA_CORE_TYPE_STA: + ecsa_param->ecsa_type = ECSA_TYPE_STA; + break; + case ECSA_CORE_TYPE_SCC_STA_AP: + ecsa_param->ecsa_type = ECSA_TYPE_AP; + break; + } +} + +/** + * @trigger_iface : interface which trigger core layer ECSA flow + * @execute_iface : interface which actually execute PHL ECSA FG + */ +bool rtw_trigger_phl_ecsa_start(struct _ADAPTER *trigger_iface, + enum csa_trigger_type trigger_type) +{ + struct dvobj_priv *d = adapter_to_dvobj(trigger_iface); + struct _ADAPTER *execute_iface = trigger_iface; + struct rtw_wifi_role_t *role = execute_iface->phl_role; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(execute_iface); + struct rtw_wifi_role_link_t *rlink = alink->wrlink; + struct rtw_chan_def c_chdef = alink->mlmeextpriv.chandef; + struct core_ecsa_info *ecsa_info = &(execute_iface->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + struct rtw_chan_def n_chdef; + enum ecsa_mr_case mr_case; + u8 is_vht = alink->mlmepriv.vhtpriv.vht_option; + + switch (trigger_type) { + case CSA_AP_CORE_SWITCH_CH: + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_AP; + + /* Build CSA beacon by self */ + rtw_core_build_ecsa_beacon(trigger_iface, ecsa_param, is_vht); + break; + + case CSA_AP_CFG80211_SWITCH_CH: + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_AP; + + /* Build CSA beacon by self */ + rtw_core_build_ecsa_beacon(trigger_iface, ecsa_param, is_vht); + break; + + case CSA_STA_RX_CSA_IE: + if (!rtw_sta_get_ecsa_setting(execute_iface)) { + /* we should handle error case by core layer self */ + rtw_sta_ecsa_invalid_hdl(execute_iface); + return false; + } + + mr_case = rtw_ecsa_mr_check(execute_iface); + switch (mr_case) { + case ECSA_SINGLE_ROLE: + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_STA; + break; + + case ECSA_MR_SCC_STA_AP: + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_SCC_STA_AP; + + /* Use AP interface to execute ECSA FG */ + execute_iface = rtw_scc_sta_ap_init_ap_role(trigger_iface); + if (execute_iface == NULL) + goto err_hdl; + break; + + case ECSA_MR_UNSUPPORTED: + RTW_ERR("CSA : only support ECSA of one STA + one AP/GO for now\n"); + goto err_hdl; + break; + } + + set_fwstate(&execute_iface->mlmepriv, WIFI_CSA_SKIP_CHECK_BEACON); + break; + + case CSA_STA_DISCONNECT_ON_DFS: + ecsa_info->core_ecsa_type = ECSA_CORE_TYPE_AP; + + /* Build CSA beacon by self */ + rtw_core_build_ecsa_beacon(trigger_iface, ecsa_param, is_vht); + + /* Send CSA action frame to clients */ + rtw_ap_send_csa_action_frame(trigger_iface, alink); + break; + + default: + goto err_hdl; + } + + n_chdef = ecsa_param->new_chan_def; + RTW_INFO("CSA : "FUNC_ADPT_FMT" core_ecsa_type = %u\n", + FUNC_ADPT_ARG(trigger_iface), ecsa_info->core_ecsa_type); + RTW_INFO("CSA : Trigger interface("ADPT_FMT")" + "current:%u,%u,%u,%u ==> new:%u,%u,%u,%u\n", + ADPT_ARG(trigger_iface), + c_chdef.band, c_chdef.chan, c_chdef.bw, c_chdef.offset, + n_chdef.band, n_chdef.chan, n_chdef.bw, n_chdef.offset); + + /** + * Update all parameters to parameters of interface which execute ECSA FG + * if execute_iface doesn't equal to trigger_iface. + */ + if (execute_iface != trigger_iface) { + role = execute_iface->phl_role; + alink = GET_PRIMARY_LINK(execute_iface); + rlink = alink->wrlink; + ecsa_info = &(execute_iface->ecsa_info); + ecsa_param = &(ecsa_info->phl_ecsa_param); + + c_chdef = alink->mlmeextpriv.chandef; + n_chdef = ecsa_param->new_chan_def; + RTW_INFO("CSA : Execute interface("ADPT_FMT")" + "current:%u,%u,%u,%u ==> new:%u,%u,%u,%u\n", + ADPT_ARG(execute_iface), + c_chdef.band, c_chdef.chan, c_chdef.bw, c_chdef.offset, + n_chdef.band, n_chdef.chan, n_chdef.bw, n_chdef.offset); + } + + /* Only execute interface needs to fill PHL ECSA type */ + rtw_fill_phl_ecsa_type(ecsa_info); + if (rtw_phl_ecsa_start(GET_PHL_INFO(d), role, rlink, ecsa_param) != RTW_PHL_STATUS_SUCCESS) { + RTW_ERR("CSA : "FUNC_ADPT_FMT" Start PHL ECSA fail\n", FUNC_ADPT_ARG(execute_iface)); + goto err_hdl; + } + + return true; + +err_hdl: + reset_all_ecsa_param(execute_iface); + return false; +} + +/* + * @csa_ch_width gets from Channel Switch Wrapper IE + * 0 for 40 MHz + * 1 for 80 MHz, 160 MHz or 80+80 MHz + * 255 for initial value, defined by driver + * + * @ecsa_op_class gets from ECSA IE + */ +bool rtw_hal_trigger_csa_start(struct _ADAPTER *a, enum csa_trigger_type trigger_type, + u8 csa_mode, u8 ecsa_op_class, u8 csa_switch_cnt, + u8 csa_band, u8 csa_ch, u8 csa_bw, u8 csa_offset, + u8 csa_ch_width, u8 csa_ch_freq_seg0, u8 csa_ch_freq_seg1) +{ + struct core_ecsa_info *ecsa_info = &(a->ecsa_info); + struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param); + + RTW_INFO("CSA : "FUNC_ADPT_FMT" csa trigger type = %u\n", FUNC_ADPT_ARG(a), trigger_type); + SET_ECSA_STATE(a, ECSA_ST_SW_START); + ecsa_param->mode = csa_mode; + ecsa_param->op_class = ecsa_op_class; + ecsa_param->count = csa_switch_cnt; + ecsa_param->new_chan_def.band = csa_band; + ecsa_param->new_chan_def.chan = csa_ch; + ecsa_param->new_chan_def.bw = csa_bw; + ecsa_param->new_chan_def.offset = csa_offset; + /* The channel width defined in 802.11 spec */ + ecsa_info->channel_width = csa_ch_width; + ecsa_param->new_chan_def.center_freq1 = csa_ch_freq_seg0; + ecsa_param->new_chan_def.center_freq2 = csa_ch_freq_seg1; + ecsa_param->flag = 0; + ecsa_param->delay_start_ms = 0; + + return rtw_trigger_phl_ecsa_start(a, trigger_type); +} + +bool rtw_hal_dfs_trigger_csa(struct _ADAPTER *a, + enum csa_trigger_type trigger_type, + u8 band_idx, u8 u_ch, u8 u_bw, u8 u_offset) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(a); + enum band_type band; + u8 ch, bw, offset; + bool ch_avail, ret; + struct rtw_chan_def new_chandef = {0}; + u8 csa_mode, ecsa_op_class, csa_switch_cnt; + u8 csa_ch_width = 0, csa_ch_freq_seg0 = 0, csa_ch_freq_seg1 = 0; + + #ifndef PRIVATE_R + /* select new chan_def */ + ch_avail = rtw_rfctl_choose_bchbw(rfctl, BAND_MAX, 0, u_bw, 0, + BAND_ON_5G, u_ch, u_offset, + &band, &ch, &bw, &offset, + false, false, __func__); + if (!ch_avail) + return false; + #else + /* only select CH36 or CH149 */ + band = BAND_ON_5G; + ch = rfctl->p2p_park_ch; + bw = CHANNEL_WIDTH_20; + offset = CHAN_OFFSET_NO_EXT; + #endif + + RTW_INFO(FUNC_HWBAND_FMT" CSA to %s-%u,%u,%u\n", + FUNC_HWBAND_ARG(band_idx), band_str(band), ch, bw, offset); + + csa_mode = 1; + new_chandef.band = band; + new_chandef.chan = ch; + new_chandef.bw = bw; + new_chandef.offset = offset; + ecsa_op_class = rtw_phl_get_operating_class(new_chandef); + csa_switch_cnt = 2; + + ret = rtw_hal_trigger_csa_start(a, CSA_STA_DISCONNECT_ON_DFS, + csa_mode, ecsa_op_class, csa_switch_cnt, + band, ch, bw, offset, + csa_ch_width, csa_ch_freq_seg0, csa_ch_freq_seg1); + + return ret; +} +#endif /* CONFIG_ECSA_PHL */ +#endif /* CONFIG_DFS */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.c new file mode 100644 index 00000000..0ef6f5d7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.c @@ -0,0 +1,320 @@ + +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ + +#define _RTW_CSI_C_ + +#include + +#ifdef CONFIG_RTW_CSI_CHANNEL_INFO + +#ifdef CONFIG_RTW_CSI_NETLINK +#include +#include +#include +#include + +#define NETLINK_CSI_FAMILY 19 + +static void csi_nl_recv_msg(struct sk_buff *skb) +{ + struct nlmsghdr *nlh; + int pid; + struct sk_buff *skb_out; + int msg_size; + char *msg = "Hello from kernel"; + int res; + + RTW_INFO("Entering: %s\n", __FUNCTION__); + + msg_size = strlen(msg); + + nlh = (struct nlmsghdr *)skb->data; + RTW_INFO("Kernel: Netlink received msg payload:%s\n", (char *)nlmsg_data(nlh)); +#if 1 + pid = nlh->nlmsg_pid; /*pid of sending process */ +#else + usr_pid = nlh->nlmsg_pid; /*pid of sending process */ +#endif + +#if 0//no send back + skb_out = nlmsg_new(msg_size, 0); + if (!skb_out) { + RTW_ERR("Failed to allocate new skb\n"); + return; + } + + nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0); + NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */ + strncpy(nlmsg_data(nlh), msg, msg_size); + + res = nlmsg_unicast(nl_sk, skb_out, pid); + if (res < 0) + RTW_ERR("Error while sending bak to user\n"); +#endif +} + +int rtw_csi_nl_init(struct dvobj_priv *dvobj) +{ + struct sock *nl_sk; + struct netlink_kernel_cfg cfg; + + RTW_INFO("Entering: %s\n", __func__); + + nl_sk = NULL; + dvobj->csi_nl_sk = NULL; + cfg.input = csi_nl_recv_msg; + + nl_sk = netlink_kernel_create(&init_net, NETLINK_CSI_FAMILY, &cfg); + if (!nl_sk) { + RTW_ERR("%s: Error creating socket.\n", __func__); + return -10; + } + dvobj->csi_nl_sk = nl_sk; + + return 0; +} + +void rtw_csi_nl_exit(struct dvobj_priv *dvobj) +{ + RTW_INFO("Exiting: %s\n", __func__); + netlink_kernel_release(dvobj->csi_nl_sk); + dvobj->csi_nl_sk = NULL; +} + +#endif /*CONFIG_RTW_CSI_NETLINK*/ + +#ifdef CONFIG_CSI_TIMER_POLLING + +/******CSI header for OWI******/ + +static int ow_pid = 123; + +#define IEEE80211_ADDR_LEN 6 + +struct ow_csi_netlink_header { + u8 phynetdevidx; + u32 sequence_number; + u16 fragment_index; +} __attribute__ ((__packed__)); + +/* + src_macaddr received frame source MAC address + csi_capture_status 1 - CSI capture successful; 0 - CSI capture not successful + csi_timestamp received frame TSF timestamp + csi_nc Nrx + csi_nr Nsts + csi_bw received frame bandwidth + csi_rx_rate received frame date rate + csi_dump_length Length of the CSI dump, it excludes the header size +*/ +struct ow_csi_frame_header { + u32 rsvd1[4]; + u8 src_macaddr[IEEE80211_ADDR_LEN]; + u8 csi_capture_status; + u8 rsvd2[13]; + u32 csi_timestamp; + u8 csi_nc; + u8 csi_nr; + u8 csi_bw; + u16 csi_rx_rate; + u8 csi_rssi[2]; + u8 csi_subc_num; + u8 csi_tone_bit; + u32 csi_data_length; +}; +/******************************/ + + +#define CSI_MSG_LEN 1000 +#define CSI_POLL_TIME 30 /*msec*/ +static u8 msg_buf[CSI_MSG_LEN] = {0}; +static u8 buff[CSI_MSG_LEN] = {0}; + +void rtw_csi_poll_timer_set(struct dvobj_priv *dvobj, u32 delay) +{ + _timer *timer = NULL; + + timer = &dvobj->csi_poll_timer; + _set_timer(timer, delay); +} + +void rtw_csi_poll_timer_cancel(struct dvobj_priv *dvobj) +{ + _timer *timer = NULL; + + timer = &dvobj->csi_poll_timer; + _cancel_timer_ex(timer); + timer->function = NULL; +} + +void rtw_nl_send_csi(struct dvobj_priv* dvobj, u8* buffer, u32 buf_len, struct csi_header_t *csi_header) +{ + struct nlmsghdr *nlh; + struct sk_buff *skb_out; + int msg_size = 0; + //char *msg = "NL msg send from kernel"; + //char *msg_send; + int res; + struct ow_csi_netlink_header ow_csi_nlh; + struct ow_csi_frame_header ow_csi_h; + + if ((buf_len + sizeof(struct csi_header_t)) > CSI_MSG_LEN) { + RTW_ERR("%s: CSI Buffer len is not enought.\n", __func__); + return; + } + else { + //RTW_INFO("%s: CSI total len = %d\n", __func__, buf_len + sizeof(struct csi_header_t)); + } + + /* Fill ow_csi_netlink_header */ + RTW_DBG("%s: len=%ld\n", __func__, sizeof(struct ow_csi_netlink_header)); + _rtw_memset(&ow_csi_nlh, 0, sizeof(struct ow_csi_netlink_header)); + ow_csi_nlh.phynetdevidx = 0; // ToDo + ow_csi_nlh.sequence_number = 0; //ToDo + ow_csi_nlh.fragment_index = 0; + + /* Fill ow_csi_frame_header */ + RTW_DBG("%s: len=%ld\n", __func__, sizeof(struct ow_csi_frame_header)); + _rtw_memset(&ow_csi_h, 0, sizeof(struct ow_csi_frame_header)); + _rtw_memcpy(ow_csi_h.src_macaddr, csi_header->mac_addr, 6); + ow_csi_h.csi_capture_status = csi_header->csi_valid; + ow_csi_h.csi_timestamp = csi_header->hw_assigned_timestamp; + ow_csi_h.csi_data_length = csi_header->csi_data_length; + ow_csi_h.csi_nc = csi_header->nc; + ow_csi_h.csi_nr = csi_header->nr; + ow_csi_h.csi_bw = csi_header->bandwidth; + ow_csi_h.csi_rx_rate = csi_header->rx_data_rate; + ow_csi_h.csi_subc_num = csi_header->num_sub_carrier; + ow_csi_h.csi_tone_bit = csi_header->num_bit_per_tone; + ow_csi_h.csi_rssi[0] = csi_header->rssi[0]; + ow_csi_h.csi_rssi[1] = csi_header->rssi[1]; + + /* Prepare NL msg */ + _rtw_memcpy(msg_buf, &ow_csi_nlh, sizeof(struct ow_csi_netlink_header)); + msg_size += sizeof(struct ow_csi_netlink_header); + + _rtw_memcpy(msg_buf + msg_size, &ow_csi_h, sizeof(struct ow_csi_frame_header)); + msg_size += sizeof(struct ow_csi_frame_header); + + /* Fill csi_raw */ +#if 1 + RTW_DBG(":%s: len=%d\n", __func__, csi_header->csi_data_length); + _rtw_memcpy(msg_buf + msg_size, buffer, csi_header->csi_data_length); + msg_size += csi_header->csi_data_length; +#else + RTW_DBG(":%s: len=%d\n", __func__, buf_len); + _rtw_memcpy(msg_buf + msg_size, buffer, buf_len); + msg_size += buf_len; +#endif + RTW_DBG("%s: msg_size = %d\n", __func__, msg_size); + + skb_out = nlmsg_new(msg_size, 0); + + if (!skb_out) { + RTW_ERR("%s: Failed to allocate new skb\n", __func__); + return; + } + + nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0); + NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */ + + _rtw_memcpy(nlmsg_data(nlh), msg_buf, msg_size); + + if (!dvobj->csi_nl_sk) { + RTW_ERR("%s fail: csi_nl_sk is NULL\n", __func__); + return; + } + + res = nlmsg_unicast(dvobj->csi_nl_sk, skb_out, ow_pid); + if (res < 0) { + if (printk_ratelimit()) + RTW_ERR("%s: Error while sending bak to user\n", __func__); + } +} + +void rtw_csi_poll_timeout_handler(void *FunctionContext) +{ + struct dvobj_priv *d; + struct csi_header_t csi_header; + void *phl; + u32 buf_len; + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + int i; + + d = (struct dvobj_priv *)FunctionContext; + phl = GET_PHL_INFO(d); + + rtw_csi_poll_timer_set(d, CSI_POLL_TIME); + + _rtw_memset(&csi_header, 0, sizeof(csi_header)); + status = rtw_phl_query_chan_info(phl, CSI_MSG_LEN, buff, &buf_len, &csi_header); + if (status == RTW_PHL_STATUS_SUCCESS) { + + /* send to user app by NL */ + rtw_nl_send_csi(d, buff, buf_len, &csi_header); + +#if 0 //debug dump + //RTW_DUMP_SEL(m, buff, buf_len); + RTW_INFO("csi_valid=%d\n", csi_header.csi_valid); + RTW_INFO("csi_data_length=%d\n", csi_header.csi_data_length); + RTW_INFO("rxsc=%d\n", csi_header.rxsc); + RTW_INFO("nc=%d\n", csi_header.nc); + RTW_INFO("nr=%d\n", csi_header.nr); + RTW_INFO("avg_idle_noise_pwr=%d\n", csi_header.avg_idle_noise_pwr); + RTW_INFO("evm[0]=%d\n", csi_header.evm[0]); + RTW_INFO("evm[1]=%d\n", csi_header.evm[1]); + RTW_INFO("rssi[0]=%d%%\n", csi_header.rssi[0] >> 1); + RTW_INFO("rssi[1]=%d%%\n", csi_header.rssi[1] >> 1); + RTW_INFO("timestamp=%u\n", csi_header.hw_assigned_timestamp); + RTW_INFO("rx_data_rate=%d\n", csi_header.rx_data_rate); + RTW_INFO("channel=%d\n", csi_header.channel); + RTW_INFO("bandwidth=%d\n", csi_header.bandwidth); + RTW_INFO("num_sub_carrier=%d\n", csi_header.num_sub_carrier); + RTW_INFO("num_bit_per_tone=%d\n", csi_header.num_bit_per_tone); + printk(KERN_CONT "srcmac= "); + for (i = 0; i < 6; i++) + printk(KERN_CONT "%x ", csi_header.mac_addr[i]); + RTW_INFO("\n"); + +#if 0 + RTW_INFO("CSI RAW(len=%d):\n", buf_len); + for (i = 0; i < buf_len; i++) { + printk(KERN_CONT "%x ", buff[i]); + if ((i%8)==7) + printk(KERN_CONT "\n"); + } + printk("\n"); +#endif +#endif + } +} + +void rtw_csi_poll_init(struct dvobj_priv *dvobj) +{ + _timer *timer = &dvobj->csi_poll_timer; + + if (timer->function != NULL) { + RTW_INFO("CSI polling timer has been init.\n"); + return; + } + + rtw_init_timer(timer, rtw_csi_poll_timeout_handler, dvobj); + rtw_csi_poll_timer_set(dvobj, CSI_POLL_TIME); + RTW_INFO("CSI polling timer init!\n"); +} +#endif /*CONFIG_CSI_TIMER_POLLING*/ +#endif /*CONFIG_RTW_CSI_CHANNEL_INFO*/ + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.h b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.h new file mode 100644 index 00000000..8a18c34e --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_csi.h @@ -0,0 +1,29 @@ + +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_CSI_H_ +#define __RTW_CSI_H_ + +#ifdef CONFIG_RTW_CSI_NETLINK +int rtw_csi_nl_init(struct dvobj_priv *dvobj); +void rtw_csi_nl_exit(struct dvobj_priv *dvobj); +#endif + +#ifdef CONFIG_CSI_TIMER_POLLING +void rtw_csi_poll_init(struct dvobj_priv *dvobj); +void rtw_csi_poll_timer_cancel(struct dvobj_priv *dvobj); +#endif + +#endif /*__RTW_CSI_H_*/ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_debug.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_debug.c new file mode 100755 index 00000000..12e82243 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_debug.c @@ -0,0 +1,7449 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_DEBUG_C_ + +#include +#include "_hal_rate.h" + +#ifdef CONFIG_MP_INCLUDED +#include +#endif + + +#ifdef CONFIG_RTW_DEBUG +const char *rtw_log_level_str[] = { + "_DRV_NONE_ = 0", + "_DRV_ALWAYS_ = 1", + "_DRV_ERR_ = 2", + "_DRV_WARNING_ = 3", + "_DRV_INFO_ = 4", + "_DRV_DEBUG_ = 5", + "_DRV_MAX_ = 6", +}; +#endif + +#ifdef CONFIG_DEBUG_RTL871X + u64 GlobalDebugComponents = 0; +#endif /* CONFIG_DEBUG_RTL871X */ + +#include + +#ifdef CONFIG_TDLS + #define TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE 41 +#endif + +void dump_drv_version(void *sel) +{ + RTW_PRINT_SEL(sel, "%s %s\n", DRV_NAME, DRIVERVERSION); + RTW_PRINT_SEL(sel, "build time: %s %s\n", __DATE__, __TIME__); +} + +void dump_drv_cfg(void *sel) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) + char *kernel_version = utsname()->release; + + RTW_PRINT_SEL(sel, "\nKernel Version: %s\n", kernel_version); +#endif + +#ifdef CONFIG_RTW_ANDROID + RTW_PRINT_SEL(sel, "Android Driver: %d\n", CONFIG_RTW_ANDROID); +#else + RTW_PRINT_SEL(sel, "Linux Driver: \n"); +#endif /* CONFIG_RTW_ANDROID */ + + RTW_PRINT_SEL(sel, "Driver Version: %s\n", DRIVERVERSION); + RTW_PRINT_SEL(sel, "------------------------------------------------\n"); + +#ifdef CONFIG_IOCTL_CFG80211 + RTW_PRINT_SEL(sel, "CFG80211\n"); +#ifdef RTW_USE_CFG80211_STA_EVENT + RTW_PRINT_SEL(sel, "RTW_USE_CFG80211_STA_EVENT\n"); +#endif + #ifdef CONFIG_RADIO_WORK + RTW_PRINT_SEL(sel, "CONFIG_RADIO_WORK\n"); + #endif +#else + RTW_PRINT_SEL(sel, "WEXT\n"); +#endif + + RTW_PRINT_SEL(sel, "DBG:%d\n", DBG); +#ifdef CONFIG_RTW_DEBUG + RTW_PRINT_SEL(sel, "CONFIG_RTW_DEBUG\n"); +#endif + +#ifdef CONFIG_CONCURRENT_MODE + RTW_PRINT_SEL(sel, "CONFIG_CONCURRENT_MODE\n"); + + #ifdef CONFIG_RTW_STATIC_NDEV_NUM + RTW_PRINT_SEL(sel, "CONFIG_RTW_STATIC_NDEV_NUM = %d\n", CONFIG_RTW_STATIC_NDEV_NUM); + #endif + #if (RTW_P2P_GROUP_INTERFACE == 1) + RTW_PRINT_SEL(sel, "RTW_P2P_GROUP_INTERFACE\n"); + #endif + #ifdef RTW_DEDICATED_P2P_DEVICE + RTW_PRINT_SEL(sel, "RTW_DEDICATED_P2P_DEVICE\n"); + #endif + #if defined(CONFIG_P2P) && defined(CONFIG_SEL_P2P_IFACE) + RTW_PRINT_SEL(sel, "CONFIG_SEL_P2P_IFACE = %d\n", CONFIG_SEL_P2P_IFACE); + #endif +#endif + +#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE + RTW_PRINT_SEL(sel, "LOAD_PHY_PARA_FROM_FILE - REALTEK_CONFIG_PATH=%s\n", REALTEK_CONFIG_PATH); + #if defined(CONFIG_MULTIDRV) || defined(REALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER) + RTW_PRINT_SEL(sel, "LOAD_PHY_PARA_FROM_FILE - REALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER\n"); + #endif + +/* configurations about TX power */ +#ifdef CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY + RTW_PRINT_SEL(sel, "CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY\n"); +#endif +#ifdef CONFIG_CALIBRATE_TX_POWER_TO_MAX + RTW_PRINT_SEL(sel, "CONFIG_CALIBRATE_TX_POWER_TO_MAX\n"); +#endif +#endif + RTW_PRINT_SEL(sel, "RTW_DEF_MODULE_REGULATORY_CERT=0x%02x\n", RTW_DEF_MODULE_REGULATORY_CERT); + + RTW_PRINT_SEL(sel, "CONFIG_TXPWR_BY_RATE=%d\n", CONFIG_TXPWR_BY_RATE); + RTW_PRINT_SEL(sel, "CONFIG_TXPWR_BY_RATE_EN=%d\n", CONFIG_TXPWR_BY_RATE_EN); + RTW_PRINT_SEL(sel, "CONFIG_TXPWR_LIMIT=%d\n", CONFIG_TXPWR_LIMIT); + RTW_PRINT_SEL(sel, "CONFIG_TXPWR_LIMIT_EN=%d\n", CONFIG_TXPWR_LIMIT_EN); + + +#ifdef CONFIG_DISABLE_ODM + RTW_PRINT_SEL(sel, "CONFIG_DISABLE_ODM\n"); +#endif + +#ifdef CONFIG_MINIMAL_MEMORY_USAGE + RTW_PRINT_SEL(sel, "CONFIG_MINIMAL_MEMORY_USAGE\n"); +#endif + + RTW_PRINT_SEL(sel, "CONFIG_RTW_EDCCA_MODE_SEL = %d\n", CONFIG_RTW_EDCCA_MODE_SEL); + RTW_PRINT_SEL(sel, "CONFIG_RTW_ADAPTIVITY_EN = %d\n", CONFIG_RTW_ADAPTIVITY_EN); + RTW_PRINT_SEL(sel, "CONFIG_RTW_ADAPTIVITY_MODE = %d\n", CONFIG_RTW_ADAPTIVITY_MODE); + +#ifdef CONFIG_POWER_SAVE + RTW_PRINT_SEL(sel, "\n===CONFIG_POWER_SAVING===\n"); + #ifdef RTW_IPS_MODE + RTW_PRINT_SEL(sel, "CONFIG_IPS_MODE=%d\n", RTW_IPS_MODE); + #endif /* RTW_IPS_MODE */ + #ifdef RTW_LPS_MODE + RTW_PRINT_SEL(sel, "CONFIG_LPS_MODE=%d\n", RTW_LPS_MODE); + #endif /* RTW_LPS_MODE */ + #ifdef RTW_WOW_IPS_MODE + RTW_PRINT_SEL(sel, "CONFIG_WOW_IPS_MODE=%d\n", RTW_WOW_IPS_MODE);; + #endif /* RTW_WOW_IPS_MODE */ + #ifdef RTW_WOW_LPS_MODE + RTW_PRINT_SEL(sel, "CONFIG_WOW_LPS_MODE=%d\n\n", RTW_WOW_LPS_MODE); + #endif /* RTW_WOW_LPS_MODE */ +#endif /* CONFIG_POWER_SAVE */ + +#ifdef CONFIG_WOWLAN + RTW_PRINT_SEL(sel, "CONFIG_WOWLAN - "); + +#ifdef CONFIG_GPIO_WAKEUP + RTW_PRINT_SEL(sel, "CONFIG_GPIO_WAKEUP - WAKEUP_GPIO_IDX:%d\n", WAKEUP_GPIO_IDX); +#endif +#endif + +#ifdef CONFIG_TDLS + RTW_PRINT_SEL(sel, "CONFIG_TDLS\n"); +#endif + +#ifdef CONFIG_RTW_80211R + RTW_PRINT_SEL(sel, "CONFIG_RTW_80211R\n"); +#endif + +#ifdef CONFIG_RTW_NETIF_SG + RTW_PRINT_SEL(sel, "CONFIG_RTW_NETIF_SG\n"); +#endif + +#ifdef CONFIG_RTW_WIFI_HAL + RTW_PRINT_SEL(sel, "CONFIG_RTW_WIFI_HAL\n"); +#endif + +#ifdef RTW_BUSY_DENY_SCAN + RTW_PRINT_SEL(sel, "RTW_BUSY_DENY_SCAN\n"); + RTW_PRINT_SEL(sel, "BUSY_TRAFFIC_SCAN_DENY_PERIOD = %u ms\n", \ + BUSY_TRAFFIC_SCAN_DENY_PERIOD); +#endif + +#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX + RTW_PRINT_SEL(sel, "CONFIG_TCP_CSUM_OFFLOAD_TX\n"); +#endif + +#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX + RTW_PRINT_SEL(sel, "CONFIG_TCP_CSUM_OFFLOAD_RX\n"); +#endif + +#ifdef CONFIG_CORE_TXSC + RTW_PRINT_SEL(sel, "CONFIG_CORE_TXSC\n"); +#endif + +#ifdef CONFIG_USB_HCI +#ifdef CONFIG_SUPPORT_USB_INT + RTW_PRINT_SEL(sel, "CONFIG_SUPPORT_USB_INT\n"); +#endif +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + RTW_PRINT_SEL(sel, "CONFIG_USB_INTERRUPT_IN_PIPE\n"); +#endif +#ifdef CONFIG_USB_TX_AGGREGATION + RTW_PRINT_SEL(sel, "CONFIG_USB_TX_AGGREGATION\n"); +#endif +#ifdef CONFIG_USB_RX_AGGREGATION + RTW_PRINT_SEL(sel, "CONFIG_USB_RX_AGGREGATION\n"); +#endif +#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX + RTW_PRINT_SEL(sel, "CONFIG_USE_USB_BUFFER_ALLOC_TX\n"); +#endif +#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX + RTW_PRINT_SEL(sel, "CONFIG_USE_USB_BUFFER_ALLOC_RX\n"); +#endif + +#ifdef CONFIG_FIX_NR_BULKIN_BUFFER + RTW_PRINT_SEL(sel, "CONFIG_FIX_NR_BULKIN_BUFFER\n"); +#endif +#endif /*CONFIG_USB_HCI*/ + +#ifdef CONFIG_SDIO_HCI +#ifdef DBG_SDIO + RTW_PRINT_SEL(sel, "DBG_SDIO = %d\n", DBG_SDIO); +#endif + +#ifdef RTW_WKARD_SDIO_TX_USE_YIELD + RTW_PRINT_SEL(sel, "RTW_WKARD_SDIO_TX_USE_YIELD\n"); +#endif + +#ifdef RTW_XMIT_THREAD_HIGH_PRIORITY + RTW_PRINT_SEL(sel, "RTW_XMIT_THREAD_HIGH_PRIORITY\n"); +#endif +#ifdef RTW_XMIT_THREAD_CB_HIGH_PRIORITY + RTW_PRINT_SEL(sel, "RTW_XMIT_THREAD_CB_HIGH_PRIORITY\n"); +#endif +#ifdef RTW_RECV_THREAD_HIGH_PRIORITY + RTW_PRINT_SEL(sel, "RTW_RECV_THREAD_HIGH_PRIORITY\n"); +#endif + +#endif /*CONFIG_SDIO_HCI*/ + + + RTW_PRINT_SEL(sel, "CONFIG_IFACE_NUMBER = %d\n", CONFIG_IFACE_NUMBER); + + +#ifdef CONFIG_PCI_TX_POLLING + RTW_PRINT_SEL(sel, "CONFIG_PCI_TX_POLLING\n"); +#endif + RTW_PRINT_SEL(sel, "CONFIG_RTW_UP_MAPPING_RULE = %s\n", (CONFIG_RTW_UP_MAPPING_RULE == 1) ? "dscp" : "tos"); + + /*GEORGIA_TODO_TRX - need get trx buff accroding to IC spec*/ + RTW_PRINT_SEL(sel, "\n=== XMIT-INFO ===\n"); + RTW_PRINT_SEL(sel, "NR_XMITFRAME = %d\n", NR_XMITFRAME); + RTW_PRINT_SEL(sel, "MAX_TX_PHL_RING_ENTRY_NUM = %d\n", MAX_PHL_TX_RING_ENTRY_NUM); +#ifdef CONFIG_QUOTA_TURBO_ENABLE + RTW_PRINT_SEL(sel, "CONFIG_QUOTA_TURBO_ENABLE\n"); +#endif +#ifdef CONFIG_USB_HCI + RTW_PRINT_SEL(sel, "MAX_XMITBUF_SZ = %d\n", MAX_XMITBUF_SZ); + RTW_PRINT_SEL(sel, "NR_XMITBUFF = %d\n", NR_XMITBUFF); + RTW_PRINT_SEL(sel, "MAX_MGNT_XMITBUF_SZ = %d\n", MAX_MGNT_XMITBUF_SZ); + RTW_PRINT_SEL(sel, "NR_MGNT_XMITBUFF = %d\n", NR_MGNT_XMITBUFF); +#endif + + RTW_PRINT_SEL(sel, "\n=== RECV-INFO ===\n"); + RTW_PRINT_SEL(sel, "NR_RECVFRAME = %d\n", NR_RECVFRAME); + RTW_PRINT_SEL(sel, "MAX_RX_PHL_RING_ENTRY_NUM = %d\n", MAX_PHL_RX_RING_ENTRY_NUM); +#ifdef CONFIG_USB_HCI + RTW_PRINT_SEL(sel, "MAX_RECVBUF_SZ = %d\n", MAX_RECVBUF_SZ); + RTW_PRINT_SEL(sel, "NR_RECVBUFF = %d\n", NR_RECVBUFF); + RTW_PRINT_SEL(sel, "NR_RECV_URB = %d\n", NR_RECV_URB); +#endif + +#ifdef CONFIG_MSG_NUM + RTW_PRINT_SEL(sel, "CONFIG_MSG_NUM = %d\n", CONFIG_MSG_NUM); +#endif +#ifdef CONFIG_DIS_DYN_RXBUF + RTW_PRINT_SEL(sel, "CONFIG_DIS_DYN_RXBUF\n"); +#endif +#ifdef CONFIG_DYNAMIC_RX_BUF + RTW_PRINT_SEL(sel, "CONFIG_DYNAMIC_RX_BUF\n"); +#endif +#ifdef CONFIG_TX_SKB_ORPHAN + RTW_PRINT_SEL(sel, "CONFIG_TX_SKB_ORPHAN\n"); +#endif +#ifdef RTW_WKARD_98D_RXTAG + RTW_PRINT_SEL(sel, "RTW_WKARD_98D_RXTAG\n"); +#endif +#ifdef CONFIG_CPU_BALANCE + RTW_PRINT_SEL(sel, "CONFIG_CPU_BALANCE\n"); +#if defined(CONFIG_RTW_TX_HDL_USE_WQ) && defined(CONFIG_CPU_SPECIFIC) + RTW_PRINT_SEL(sel, "CONFIG_CPU_SPECIFIC_TX_HDL, CPU-ID: %d\n", CPU_ID_TX_HDL); +#endif +#if defined(CONFIG_RTW_RX_HDL_USE_WQ) && defined(CONFIG_CPU_SPECIFIC) + RTW_PRINT_SEL(sel, "CONFIG_CPU_SPECIFIC_RX_HDL, CPU-ID: %d\n", CPU_ID_RX_HDL); +#endif +#if defined(CONFIG_RTW_EVENT_HDL_USE_WQ) && defined(CONFIG_CPU_SPECIFIC) + RTW_PRINT_SEL(sel, "CONFIG_CPU_SPECIFIC_EVENT_HDL, CPU-ID: %d\n", CPU_ID_EVENT_HDL); +#endif +#endif + +#ifdef CONFIG_RTW_TX_AMSDU_USE_WQ + RTW_PRINT_SEL(sel, "CONFIG_RTW_TX_AMSDU_USE_WQ\n"); + RTW_PRINT_SEL(sel, "CPU_ID_TX_AMSDU = %d\n", CPU_ID_TX_AMSDU); +#endif + +#ifdef CONFIG_RTW_TX_HDL_USE_THREAD + RTW_PRINT_SEL(sel, "CONFIG_RTW_TX_HDL_USE_THREAD\n"); +#endif +#ifdef CONFIG_RTW_RX_HDL_USE_THREAD + RTW_PRINT_SEL(sel, "CONFIG_RTW_RX_HDL_USE_THREAD\n"); +#endif +#ifdef CONFIG_RTW_RX_EVENT_USE_THREAD + RTW_PRINT_SEL(sel, "CONFIG_RTW_RX_EVENT_USE_THREAD\n"); +#endif + +#ifdef USE_AML_PCIE_TEE_MEM + RTW_PRINT_SEL(sel, "USE_AML_PCIE_TEE_MEM\n"); +#endif + + + RTW_PRINT_SEL(sel, "CORE_TXBD_NUM = %d\n", CORE_TXBD_NUM); + RTW_PRINT_SEL(sel, "CORE_RXBD_NUM = %d\n", CORE_RXBD_NUM); + RTW_PRINT_SEL(sel, "CONFIG_RPQ_AGG_NUM = %d\n", CONFIG_RPQ_AGG_NUM); + RTW_PRINT_SEL(sel, "MAX_PHL_TX_RING_ENTRY_NUM = %d\n", MAX_PHL_TX_RING_ENTRY_NUM); + RTW_PRINT_SEL(sel, "MAX_PHL_RX_RING_ENTRY_NUM = %d\n", MAX_PHL_RX_RING_ENTRY_NUM); +#ifdef CORE_TX_AMSDU_AGG_NUM + RTW_PRINT_SEL(sel, "CORE_TX_AMSDU_AGG_NUM = %d\n", CORE_TX_AMSDU_AGG_NUM); +#endif + +#ifdef CONFIG_RTW_REDUCE_MEM + RTW_PRINT_SEL(sel, "\n=== REDUCE MEM INFO ===\n"); + RTW_PRINT_SEL(sel, "CORE_RXBUF_SIZE = %d\n", CORE_RXBUF_SIZE); + RTW_PRINT_SEL(sel, "CORE_RXBUF_NUM = %d\n", CORE_RXBUF_NUM); + RTW_PRINT_SEL(sel, "CORE_RPBUF_SIZE = %d\n", CORE_RPBUF_SIZE); + RTW_PRINT_SEL(sel, "CORE_RPBUF_NUM = %d\n", CORE_RPBUF_NUM); + RTW_PRINT_SEL(sel, "MAX_ASMDU_LEN = %d\n", MAX_ASMDU_LEN); + RTW_PRINT_SEL(sel, "NR_XMITFRAME = %d\n", NR_XMITFRAME); + RTW_PRINT_SEL(sel, "MAX_TX_RING_NUM = %d\n", MAX_TX_RING_NUM); + RTW_PRINT_SEL(sel, "RTW_MAX_FRAG_NUM = %d\n", RTW_MAX_FRAG_NUM); + +#ifdef RTW_WD_PAGE_USE_SHMEM_POOL + RTW_PRINT_SEL(sel, "RTW_WD_PAGE_USE_SHMEM_POOL=y\n"); +#endif + +#ifdef CONFIG_PCI_HCI + RTW_PRINT_SEL(sel, "PCIe DMA mode: "); +#ifdef CONFIG_RTW_NORMAL_DMA + RTW_PRINT_SEL(sel, "CONFIG_RTW_NORMAL_DMA\n"); +#elif defined(CONFIG_RTW_SECURE_DMA) + RTW_PRINT_SEL(sel, "CONFIG_RTW_SECURE_DMA\n"); +#elif defined(CONFIG_RTW_SWIOTLB_DMA) + RTW_PRINT_SEL(sel, "CONFIG_RTW_SWIOTLB_DMA\n"); +#endif +#endif + +#endif +} + +void dump_log_level(void *sel) +{ +#ifdef CONFIG_RTW_DEBUG + int i; + + RTW_PRINT_SEL(sel, "drv_log_level:%d\n", rtw_drv_log_level); + for (i = 0; i <= _DRV_MAX_; i++) { + if (rtw_log_level_str[i]) + RTW_PRINT_SEL(sel, "%c %s = %d\n", + (rtw_drv_log_level == i) ? '+' : ' ', rtw_log_level_str[i], i); + } +#else + RTW_PRINT_SEL(sel, "CONFIG_RTW_DEBUG is disabled\n"); +#endif +} + + +void rtw_sink_rtp_seq_dbg(_adapter *adapter, u8 *ehdr_pos) +{ + struct recv_info *precvinfo = &(adapter->recvinfo); + if (precvinfo->sink_udpport > 0) { + if (*((u16 *)(ehdr_pos + 0x24)) == cpu_to_be16(precvinfo->sink_udpport)) { + precvinfo->pre_rtp_rxseq = precvinfo->cur_rtp_rxseq; + precvinfo->cur_rtp_rxseq = be16_to_cpu(*((u16 *)(ehdr_pos + 0x2C))); + if (precvinfo->pre_rtp_rxseq + 1 != precvinfo->cur_rtp_rxseq) { + if(precvinfo->pre_rtp_rxseq == 65535 ) { + if( precvinfo->cur_rtp_rxseq != 0) { + RTW_INFO("%s : RTP Seq num from %d to %d\n", __FUNCTION__, precvinfo->pre_rtp_rxseq, precvinfo->cur_rtp_rxseq); + } + } else { + RTW_INFO("%s : RTP Seq num from %d to %d\n", __FUNCTION__, precvinfo->pre_rtp_rxseq, precvinfo->cur_rtp_rxseq); + } + } + } + } +} + +void sta_rx_reorder_ctl_dump(void *sel, struct sta_info *sta) +{ + struct recv_reorder_ctrl *reorder_ctl; + int i; + + for (i = 0; i < 16; i++) { + reorder_ctl = &sta->recvreorder_ctrl[i]; + if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID || reorder_ctl->indicate_seq != 0xFFFF) { + RTW_PRINT_SEL(sel, "tid=%d, enable=%d, ampdu_size=%u, indicate_seq=%u\n" + , i, reorder_ctl->enable, reorder_ctl->ampdu_size, reorder_ctl->indicate_seq + ); + } + } +} + +void dump_tx_rate_bmp(void *sel, struct dvobj_priv *dvobj) +{ + _adapter *adapter = dvobj_get_primary_adapter(dvobj); + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + u8 bw; + + RTW_PRINT_SEL(sel, "%-6s", "bw"); + if (rtw_hw_chk_proto_cap(dvobj, PROTO_CAP_11AC)) + _RTW_PRINT_SEL(sel, " %-15s", "vht"); + + _RTW_PRINT_SEL(sel, " %-11s %-4s %-3s\n", "ht", "ofdm", "cck"); + + for (bw = CHANNEL_WIDTH_20; bw <= CHANNEL_WIDTH_160; bw++) { + if (!rtw_hw_is_bw_support(adapter_to_dvobj(adapter), bw)) + continue; + + RTW_PRINT_SEL(sel, "%6s", ch_width_str(bw)); + if (rtw_hw_chk_proto_cap(dvobj, PROTO_CAP_11AC)) { + _RTW_PRINT_SEL(sel, " %03x %03x %03x %03x" + , RATE_BMP_GET_VHT_4SS(rfctl->rate_bmp_vht_by_bw[bw]) + , RATE_BMP_GET_VHT_3SS(rfctl->rate_bmp_vht_by_bw[bw]) + , RATE_BMP_GET_VHT_2SS(rfctl->rate_bmp_vht_by_bw[bw]) + , RATE_BMP_GET_VHT_1SS(rfctl->rate_bmp_vht_by_bw[bw]) + ); + } + + _RTW_PRINT_SEL(sel, " %02x %02x %02x %02x" + , bw <= CHANNEL_WIDTH_40 ? RATE_BMP_GET_HT_4SS(rfctl->rate_bmp_ht_by_bw[bw]) : 0 + , bw <= CHANNEL_WIDTH_40 ? RATE_BMP_GET_HT_3SS(rfctl->rate_bmp_ht_by_bw[bw]) : 0 + , bw <= CHANNEL_WIDTH_40 ? RATE_BMP_GET_HT_2SS(rfctl->rate_bmp_ht_by_bw[bw]) : 0 + , bw <= CHANNEL_WIDTH_40 ? RATE_BMP_GET_HT_1SS(rfctl->rate_bmp_ht_by_bw[bw]) : 0 + ); + + _RTW_PRINT_SEL(sel, " %03x %01x\n" + , bw <= CHANNEL_WIDTH_20 ? RATE_BMP_GET_OFDM(rfctl->rate_bmp_cck_ofdm) : 0 + , bw <= CHANNEL_WIDTH_20 ? RATE_BMP_GET_CCK(rfctl->rate_bmp_cck_ofdm) : 0 + ); + } +} + +void dump_adapters_status(void *sel, struct dvobj_priv *dvobj) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + int i; + _adapter *iface; + u8 u_ch, u_bw, u_offset; + struct _ADAPTER_LINK *iface_link; + + dump_mi_status(sel, dvobj); + + RTW_PRINT_SEL(sel, "dev status:%s%s\n\n" + , dev_is_surprise_removed(dvobj) ? " SR" : "" + , dev_is_drv_stopped(dvobj) ? " DS" : "" + ); + +#ifdef CONFIG_P2P +#define P2P_INFO_TITLE_FMT " %-3s %-4s" +#define P2P_INFO_TITLE_ARG , "lch", "p2ps" +#ifdef CONFIG_IOCTL_CFG80211 +#define P2P_INFO_VALUE_FMT " %3u %4c" +#define P2P_INFO_VALUE_ARG , iface->wdinfo.listen_channel, iface->wdev_data.p2p_enabled ? 'e' : ' ' +#else +#define P2P_INFO_VALUE_FMT " %3u" +#define P2P_INFO_VALUE_ARG , iface->wdinfo.listen_channel +#endif +#define P2P_INFO_DASH "---------" +#else +#define P2P_INFO_TITLE_FMT "" +#define P2P_INFO_TITLE_ARG +#define P2P_INFO_VALUE_FMT "" +#define P2P_INFO_VALUE_ARG +#define P2P_INFO_DASH +#endif + +#define INFO_FMT "" +#define INFO_ARG +#define INFO_CNT_FMT "" +#define INFO_CNT_ARG + + + RTW_PRINT_SEL(sel, "%-2s %-15s %c %-8s %-17s %-6s %-4s %-4s %-7s %-5s" + P2P_INFO_TITLE_FMT + " %s"INFO_FMT"\n" + , "id", "ifname", ' ', "netif_up", "macaddr", "hwband", "port", "band", "ch", "class" + P2P_INFO_TITLE_ARG + , "status"INFO_ARG); + + RTW_PRINT_SEL(sel, "------------------------------------------------------------------------------" + P2P_INFO_DASH + "-------\n"); + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface) { + iface_link = GET_PRIMARY_LINK(iface); + RTW_PRINT_SEL(sel, "%2d %-15s %c %8u "MAC_FMT" %6hhu %4hhu %-4s %3u,%u,%u %5u" + P2P_INFO_VALUE_FMT + " "MLME_STATE_FMT" " INFO_CNT_FMT"\n" + , i, iface->registered ? ADPT_ARG(iface) : NULL + , iface->registered ? 'R' : ' ' + , iface->netif_up + , MAC_ARG(adapter_mac_addr(iface)) + , (iface_link->wrlink) ? iface_link->wrlink->hw_band : HW_BAND_MAX + , (iface_link->wrlink) ? iface_link->wrlink->hw_port : HW_PORT_MAX + , band_str(iface_link->mlmeextpriv.chandef.band) + , iface_link->mlmeextpriv.chandef.chan + , iface_link->mlmeextpriv.chandef.bw + , iface_link->mlmeextpriv.chandef.offset + , rtw_get_op_class_by_bchbw(iface_link->mlmeextpriv.chandef.band + , iface_link->mlmeextpriv.chandef.chan + , iface_link->mlmeextpriv.chandef.bw + , iface_link->mlmeextpriv.chandef.offset) + P2P_INFO_VALUE_ARG + , MLME_STATE_ARG(iface) + INFO_CNT_ARG + ); + } + } + + RTW_PRINT_SEL(sel, "------------------------------------------------------------------------------" + P2P_INFO_DASH + "-------\n"); +#if 0 + if (rtw_mi_get_ch_setting_union(dvobj_get_primary_adapter(dvobj), &u_ch, &u_bw, &u_offset)) + RTW_PRINT_SEL(sel, "%55s %3u,%u,%u %5u\n" + , "union:" + , u_ch, u_bw, u_offset, rtw_get_op_class_by_chbw(u_ch, u_bw, u_offset)); + + RTW_PRINT_SEL(sel, "%55s %3u,%u,%u offch_state:%d\n" + , "oper:" + , dvobj->chandef.chan + , dvobj->chandef.bw + , dvobj->chandef.offset + , rfctl->offch_state + ); +#endif + + #if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ + dump_radar_detect_status(sel, rfctl, " radar_detect:"); + #endif +} + +static u8 del_rx_ampdu_test_no_tx_fail = 0; + +bool rtw_del_rx_ampdu_test_trigger_no_tx_fail(void) +{ + if (del_rx_ampdu_test_no_tx_fail) { + RTW_PRINT("del_rx_ampdu test case: trigger no_tx_fail\n"); + del_rx_ampdu_test_no_tx_fail--; + return _TRUE; + } + return _FALSE; +} + +static u32 g_wait_hiq_empty_ms = 0; + +u32 rtw_get_wait_hiq_empty_ms(void) +{ + return g_wait_hiq_empty_ms; +} + +static systime sta_linking_test_start_time = 0; +static u32 sta_linking_test_wait_ms = 0; +static u8 sta_linking_test_force_fail = 0; + +void rtw_sta_linking_test_set_start(void) +{ + sta_linking_test_start_time = rtw_get_current_time(); +} + +bool rtw_sta_linking_test_wait_done(void) +{ + return rtw_get_passing_time_ms(sta_linking_test_start_time) >= sta_linking_test_wait_ms; +} + +bool rtw_sta_linking_test_force_fail(void) +{ + return sta_linking_test_force_fail; +} + +#ifdef CONFIG_AP_MODE +static u16 ap_linking_test_force_auth_fail = 0; +static u16 ap_linking_test_force_asoc_fail = 0; + +u16 rtw_ap_linking_test_force_auth_fail(void) +{ + return ap_linking_test_force_auth_fail; +} + +u16 rtw_ap_linking_test_force_asoc_fail(void) +{ + return ap_linking_test_force_asoc_fail; +} +#endif + +int proc_get_defs_param(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *mlme = &adapter->mlmepriv; + + RTW_PRINT_SEL(m, "%s %15s\n", "lmt_sta", "lmt_time"); + RTW_PRINT_SEL(m, "%-15u %-15u\n" + , mlme->defs_lmt_sta + , mlme->defs_lmt_time + ); + + return 0; +} + +ssize_t proc_set_defs_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *mlme = &adapter->mlmepriv; + + char tmp[32]; + u32 defs_lmt_sta; + u32 defs_lmt_time; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%u %u", &defs_lmt_sta, &defs_lmt_time); + + if (num >= 1) + mlme->defs_lmt_sta = defs_lmt_sta; + if (num >= 2) + mlme->defs_lmt_time = defs_lmt_time; + } + + return count; + +} + +ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + char tmp[32]; + u32 addr, val, len; + + if (count < 3) { + RTW_INFO("argument size is less than 3\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x %x %x", &addr, &val, &len); + + if (num != 3) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } + + switch (len) { + case 1: + rtw_phl_write8(dvobj->phl, addr, (u8)val); + break; + case 2: + rtw_phl_write16(dvobj->phl, addr, (u16)val); + break; + case 4: + rtw_phl_write32(dvobj->phl, addr, val); + break; + default: + RTW_INFO("error write length=%d", len); + break; + } + + } + return count; + +} + +static u32 proc_get_read_addr = 0xeeeeeeee; +static u32 proc_get_read_len = 0x4; + +int proc_get_read_reg(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + + if (proc_get_read_addr == 0xeeeeeeee) { + RTW_PRINT_SEL(m, "address not initialized\n"); + return 0; + } + + switch (proc_get_read_len) { + case 1: + RTW_PRINT_SEL(m, "reg_read8(0x%x)=0x%x\n", proc_get_read_addr, + rtw_phl_read8(dvobj->phl, proc_get_read_addr)); + break; + case 2: + RTW_PRINT_SEL(m, "reg_read16(0x%x)=0x%x\n", proc_get_read_addr, + rtw_phl_read16(dvobj->phl, proc_get_read_addr)); + break; + case 4: + RTW_PRINT_SEL(m, "reg_read32(0x%x)=0x%x\n", proc_get_read_addr, + rtw_phl_read32(dvobj->phl, proc_get_read_addr)); + break; + default: + RTW_PRINT_SEL(m, "error read length=%d\n", proc_get_read_len); + break; + } + + return 0; +} + +ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[16]; + u32 addr, len; + + if (count < 2) { + RTW_INFO("argument size is less than 2\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x %x", &addr, &len); + + if (num != 2) { + RTW_INFO("invalid read_reg parameter!\n"); + return count; + } + + proc_get_read_addr = addr; + + proc_get_read_len = len; + } + + return count; + +} + +ssize_t proc_set_mac_dbg_status_dump(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + char tmp[32] = {0}; + u32 val[2] = {0}; + u32 en; + u8 en_u8; + + if (count < 1) { + RTW_INFO("argument size is less than 1\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x", &en); + + if (num != 1) { + RTW_INFO("invalid mac_dbg_status_dump parameter!\n"); + return count; + } + en_u8 = (u8)en; + rtw_phl_mac_dbg_status_dump(dvobj->phl, val, &en_u8); + if (en & BIT0) + RTW_INFO_DUMP("ss_dbgpkg: ", (const u8 *)val, 8); + } + return count; + +} + +#ifdef CONFIG_IGNORE_GO_AND_LOW_RSSI_IN_SCAN_LIST +int proc_get_ignore_go_and_low_rssi_in_scan(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + RTW_PRINT_SEL(m, "ignore_go_in_scan=%d, ignore_low_rssi_in_scan=%d\n", + pregpriv->ignore_go_in_scan, pregpriv->ignore_low_rssi_in_scan); + return 0; +} + +ssize_t proc_set_ignore_go_and_low_rssi_in_scan(struct file *file, + const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + char tmp[32] = {0}; + int enable = 0; + int num = 0, low_rssi=0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + num = sscanf(tmp, "%d %d", &enable, &low_rssi); + RTW_INFO("num=%d enable=%d low_rssi=%d\n", num, enable, low_rssi); + + if (num != 2) { + RTW_INFO("argument number is wrong\n"); + return -EFAULT; + } + + pregpriv->ignore_go_in_scan = enable; + pregpriv->ignore_low_rssi_in_scan = low_rssi; + } + return count; +} +#endif /*CONFIG_IGNORE_GO_AND_LOW_RSSI_IN_SCAN_LIST*/ + +#ifdef CONFIG_PROC_DEBUG +int proc_get_rx_stat(struct seq_file *m, void *v) +{ + _list *plist, *phead; + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_info *psta = NULL; + struct stainfo_stats *pstats = NULL; + struct sta_priv *pstapriv = &(adapter->stapriv); + u32 i, j; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 null_addr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + pstats = &psta->sta_stats; + + if (pstats == NULL) + continue; + if ((_rtw_memcmp(psta->phl_sta->mac_addr, bc_addr, ETH_ALEN) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, null_addr, ETH_ALEN) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, psta->padapter_link->mac_addr, ETH_ALEN) != _TRUE)) { + RTW_PRINT_SEL(m, "MAC :\t\t"MAC_FMT "\n", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "data_rx_cnt :\t%llu\n", sta_rx_data_uc_pkts(psta) - pstats->last_rx_data_uc_pkts); + pstats->last_rx_data_uc_pkts = sta_rx_data_uc_pkts(psta); + RTW_PRINT_SEL(m, "duplicate_cnt :\t%u\n", pstats->duplicate_cnt); + pstats->duplicate_cnt = 0; + RTW_PRINT_SEL(m, "rx_per_rate_cnt :\n"); + + for (j = 0; j < 0x60; j++) { + RTW_PRINT_SEL(m, "%08u ", pstats->rxratecnt[j]); + pstats->rxratecnt[j] = 0; + if ((j%8) == 7) + RTW_PRINT_SEL(m, "\n"); + } + RTW_PRINT_SEL(m, "\n"); + } + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + return 0; +} + +int proc_get_sta_tx_stat(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_priv *stapriv = &(adapter->stapriv); + struct sta_priv *stapriv_primary = &(GET_PRIMARY_ADAPTER(adapter))->stapriv; + struct sta_info *sta; + struct stainfo_stats *stats; + u8 mac[ETH_ALEN] = {0}; + int ret = 0; + + _rtw_memcpy(mac, stapriv_primary->c2h_sta_mac, ETH_ALEN); + sta = rtw_get_stainfo(stapriv, mac); + if (sta) { + ret = rtw_get_sta_tx_stat(adapter, sta); + stats = &sta->sta_stats; + RTW_PRINT_SEL(m, "MAC: " MAC_FMT " fail: %u retry: %u\n", + MAC_ARG(mac), stats->tx_fail_cnt_sum, stats->tx_retry_cnt_sum); + if (ret == _SUCCESS) + ret = 0; + else + ret = -ENODATA; + } else + ret = -ENODATA; + return ret; +} + +ssize_t proc_set_sta_tx_stat(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_priv *stapriv_primary = &(GET_PRIMARY_ADAPTER(adapter))->stapriv; + char tmp[18] = {0}; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + if (sscanf(tmp, MAC_SFMT, MAC_SARG(stapriv_primary->c2h_sta_mac)) != 6) { + _rtw_memset(stapriv_primary->c2h_sta_mac, 0, 6); + RTW_PRINT(FUNC_ADPT_FMT" Invalid format\n", + FUNC_ADPT_ARG(adapter)); + } + + } + + return count; +} + +int proc_get_tx_stat(struct seq_file *m, void *v) +{ + _list *plist, *phead; + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_info *psta = NULL; + u8 sta_mac[NUM_STA][ETH_ALEN] = {{0}}; + uint mac_id[NUM_STA]; + struct stainfo_stats *pstats = NULL; + struct sta_priv *pstapriv = &(adapter->stapriv); + struct sta_priv *pstapriv_primary = &(GET_PRIMARY_ADAPTER(adapter))->stapriv; + u32 i, macid_rec_idx = 0; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 null_addr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + if ((_rtw_memcmp(psta->phl_sta->mac_addr, bc_addr, ETH_ALEN) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, null_addr, ETH_ALEN) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, psta->padapter_link->mac_addr, ETH_ALEN) != _TRUE)) { + _rtw_memcpy(&sta_mac[macid_rec_idx][0], psta->phl_sta->mac_addr, ETH_ALEN); + mac_id[macid_rec_idx] = psta->phl_sta->macid; + macid_rec_idx++; + } + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < macid_rec_idx; i++) { + psta = rtw_get_stainfo(pstapriv, &sta_mac[i][0]); + if(psta) { + rtw_get_sta_tx_stat(adapter, psta); + pstats = &psta->sta_stats; +#if defined(PRIVATE_R) || defined(CONFIG_RTW_MULTI_AP) + RTW_PRINT_SEL(m, "MAC: " MAC_FMT " sent: %u fail: %u retry: %u\n", + MAC_ARG(&sta_mac[i][0]), pstats->tx_ok_cnt, pstats->tx_fail_cnt, pstats->tx_retry_cnt); +#else + RTW_PRINT_SEL(m, "data_sent_cnt :\t%u\n", pstats->tx_ok_cnt + pstats->tx_fail_cnt); + RTW_PRINT_SEL(m, "success_cnt :\t%u\n", pstats->tx_ok_cnt); + RTW_PRINT_SEL(m, "failure_cnt :\t%u\n", pstats->tx_fail_cnt); + RTW_PRINT_SEL(m, "retry_cnt :\t%u\n\n", pstats->tx_retry_cnt); +#endif + + } else + RTW_PRINT_SEL(m, "STA is gone\n"); + } + return 0; +} + +int proc_get_fwstate(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + + RTW_PRINT_SEL(m, "fwstate=0x%x\n", get_fwstate(pmlmepriv)); + + return 0; +} + +int proc_get_sec_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct security_priv *sec = &padapter->securitypriv; + + RTW_PRINT_SEL(m, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", + sec->dot11AuthAlgrthm, sec->dot11PrivacyAlgrthm, + sec->ndisauthtype, sec->ndisencryptstatus); + + RTW_PRINT_SEL(m, "hw_decrypted=%d\n", sec->hw_decrypted); + RTW_PRINT_SEL(m, "wpa_psk="); + if(sec->wpa_psk & BIT(0)) + RTW_PRINT_SEL(m, "WPA "); + if(sec->wpa_psk & BIT(1)) + RTW_PRINT_SEL(m, "WPA2 "); + RTW_PRINT_SEL(m, "\n"); + RTW_PRINT_SEL(m, "wpa2_group_cipher=%d\n", sec->wpa2_group_cipher); + RTW_PRINT_SEL(m, "wpa2_pairwise_cipher=%d\n", sec->wpa2_pairwise_cipher); + RTW_PRINT_SEL(m, "wpa_group_cipher=%d\n", sec->wpa_group_cipher); + RTW_PRINT_SEL(m, "wpa_pairwise_cipher=%d\n", sec->wpa_pairwise_cipher); + RTW_PRINT_SEL(m, "80211W_enable=%d\n", sec->mfp_opt); + RTW_PRINT_SEL(m, "akm_suite_bitmap=0x%x\n", sec->akmp); + +#ifdef DBG_SW_SEC_CNT + RTW_PRINT_SEL(m, "==sw counters(bc, mc, uc)==\n"); + RTW_PRINT_SEL(m, "wep_sw_enc_cnt=%llu, %llu, %llu\n" + , sec->wep_sw_enc_cnt_bc , sec->wep_sw_enc_cnt_mc, sec->wep_sw_enc_cnt_uc); + RTW_PRINT_SEL(m, "wep_sw_dec_cnt=%llu, %llu, %llu\n" + , sec->wep_sw_dec_cnt_bc , sec->wep_sw_dec_cnt_mc, sec->wep_sw_dec_cnt_uc); + + RTW_PRINT_SEL(m, "tkip_sw_enc_cnt=%llu, %llu, %llu\n" + , sec->tkip_sw_enc_cnt_bc , sec->tkip_sw_enc_cnt_mc, sec->tkip_sw_enc_cnt_uc); + RTW_PRINT_SEL(m, "tkip_sw_dec_cnt=%llu, %llu, %llu\n" + , sec->tkip_sw_dec_cnt_bc , sec->tkip_sw_dec_cnt_mc, sec->tkip_sw_dec_cnt_uc); + + RTW_PRINT_SEL(m, "aes_sw_enc_cnt=%llu, %llu, %llu\n" + , sec->aes_sw_enc_cnt_bc , sec->aes_sw_enc_cnt_mc, sec->aes_sw_enc_cnt_uc); + RTW_PRINT_SEL(m, "aes_sw_dec_cnt=%llu, %llu, %llu\n" + , sec->aes_sw_dec_cnt_bc , sec->aes_sw_dec_cnt_mc, sec->aes_sw_dec_cnt_uc); + + RTW_PRINT_SEL(m, "gcmp_sw_enc_cnt=%llu, %llu, %llu\n" + , sec->gcmp_sw_enc_cnt_bc , sec->gcmp_sw_enc_cnt_mc, sec->gcmp_sw_enc_cnt_uc); + RTW_PRINT_SEL(m, "gcmp_sw_dec_cnt=%llu, %llu, %llu\n" + , sec->gcmp_sw_dec_cnt_bc , sec->gcmp_sw_dec_cnt_mc, sec->gcmp_sw_dec_cnt_uc); +#endif /* DBG_SW_SEC_CNT */ + + return 0; +} + +int proc_get_mlmext_state(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + RTW_PRINT_SEL(m, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state); + + return 0; +} + +#ifdef CONFIG_LAYER2_ROAMING +int proc_get_roam_flags(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "0x%02x\n", rtw_roam_flags(adapter)); + + return 0; +} + +ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + char tmp[32]; + u8 flags; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx", &flags); + + if (num == 1) + rtw_assign_roam_flags(adapter, flags); + } + + return count; + +} + +int proc_get_roam_param(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *mlme = &adapter->mlmepriv; + + RTW_PRINT_SEL(m, "%12s %15s %26s %16s\n", "rssi_diff_th", "scanr_exp_ms", "scan_interval(unit:2 sec)", "rssi_threshold"); + RTW_PRINT_SEL(m, "%-15u %-13u %-27u %-11u\n" + , mlme->roam_rssi_diff_th + , mlme->roam_scanr_exp_ms + , mlme->roam_scan_int + , mlme->roam_rssi_threshold + ); + + return 0; +} + +ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *mlme = &adapter->mlmepriv; + + char tmp[32]; + u8 rssi_diff_th; + u32 scanr_exp_ms; + u32 scan_int; + u8 rssi_threshold; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu %u %u %hhu", &rssi_diff_th, &scanr_exp_ms, &scan_int, &rssi_threshold); + + if (num >= 1) + mlme->roam_rssi_diff_th = rssi_diff_th; + if (num >= 2) + mlme->roam_scanr_exp_ms = scanr_exp_ms; + if (num >= 3) + mlme->roam_scan_int = scan_int; + if (num >= 4) + mlme->roam_rssi_threshold = rssi_threshold; + } + + return count; + +} + +ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + char tmp[32]; + u8 addr[ETH_ALEN]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5); + if (num == 6) + _rtw_memcpy(adapter->mlmepriv.roam_tgt_addr, addr, ETH_ALEN); + + RTW_INFO("set roam_tgt_addr to "MAC_FMT"\n", MAC_ARG(adapter->mlmepriv.roam_tgt_addr)); + } + + return count; +} +#endif /* CONFIG_LAYER2_ROAMING */ + + +int proc_get_qos_option(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + + RTW_PRINT_SEL(m, "qos_option=%d\n", pmlmepriv->qospriv.qos_option); + + return 0; +} + +int proc_get_ht_option(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + +#ifdef CONFIG_80211N_HT + RTW_PRINT_SEL(m, "ht_option=%d\n", pmlmepriv->htpriv.ht_option); +#endif /* CONFIG_80211N_HT */ + + return 0; +} + +int proc_get_rf_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + + RTW_PRINT_SEL(m, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n", + pmlmeext->chandef.chan, pmlmeext->chandef.bw, pmlmeext->chandef.offset); + + RTW_PRINT_SEL(m, "oper_ch=%d, oper_bw=%d, oper_ch_offet=%d\n", + rtw_get_oper_ch(padapter, padapter_link), rtw_get_oper_bw(padapter, padapter_link), + rtw_get_oper_choffset(padapter, padapter_link)); + + return 0; +} + +int proc_get_scan_param(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + struct ss_res *ss = &mlmeext->sitesurvey_res; + +#define SCAN_PARAM_TITLE_FMT "%10s" +#define SCAN_PARAM_VALUE_FMT "%-10u" +#define SCAN_PARAM_TITLE_ARG , "scan_ch_ms" +#define SCAN_PARAM_VALUE_ARG , ss->scan_ch_ms +#ifdef CONFIG_80211N_HT +#define SCAN_PARAM_TITLE_FMT_HT " %15s %13s" +#define SCAN_PARAM_VALUE_FMT_HT " %-15u %-13u" +#define SCAN_PARAM_TITLE_ARG_HT , "rx_ampdu_accept", "rx_ampdu_size" +#define SCAN_PARAM_VALUE_ARG_HT , ss->rx_ampdu_accept, ss->rx_ampdu_size +#else +#define SCAN_PARAM_TITLE_FMT_HT "" +#define SCAN_PARAM_VALUE_FMT_HT "" +#define SCAN_PARAM_TITLE_ARG_HT +#define SCAN_PARAM_VALUE_ARG_HT +#endif +#ifdef CONFIG_SCAN_BACKOP +#define SCAN_PARAM_TITLE_FMT_BACKOP " %9s %12s" +#define SCAN_PARAM_VALUE_FMT_BACKOP " %-9u %-12u" +#define SCAN_PARAM_TITLE_ARG_BACKOP , "backop_ms", "scan_cnt_max" +#define SCAN_PARAM_VALUE_ARG_BACKOP , ss->backop_ms, ss->scan_cnt_max +#else +#define SCAN_PARAM_TITLE_FMT_BACKOP "" +#define SCAN_PARAM_VALUE_FMT_BACKOP "" +#define SCAN_PARAM_TITLE_ARG_BACKOP +#define SCAN_PARAM_VALUE_ARG_BACKOP +#endif + + RTW_PRINT_SEL(m, + SCAN_PARAM_TITLE_FMT + SCAN_PARAM_TITLE_FMT_HT + SCAN_PARAM_TITLE_FMT_BACKOP + "\n" + SCAN_PARAM_TITLE_ARG + SCAN_PARAM_TITLE_ARG_HT + SCAN_PARAM_TITLE_ARG_BACKOP + ); + + RTW_PRINT_SEL(m, + SCAN_PARAM_VALUE_FMT + SCAN_PARAM_VALUE_FMT_HT + SCAN_PARAM_VALUE_FMT_BACKOP + "\n" + SCAN_PARAM_VALUE_ARG + SCAN_PARAM_VALUE_ARG_HT + SCAN_PARAM_VALUE_ARG_BACKOP + ); + + return 0; +} + +ssize_t proc_set_scan_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; + struct ss_res *ss = &mlmeext->sitesurvey_res; + + char tmp[32] = {0}; + + u16 scan_ch_ms; +#define SCAN_PARAM_INPUT_FMT "%hu" +#define SCAN_PARAM_INPUT_ARG , &scan_ch_ms +#ifdef CONFIG_80211N_HT + u8 rx_ampdu_accept; + u16 rx_ampdu_size; +#define SCAN_PARAM_INPUT_FMT_HT " %hhu %hu" +#define SCAN_PARAM_INPUT_ARG_HT , &rx_ampdu_accept, &rx_ampdu_size +#else +#define SCAN_PARAM_INPUT_FMT_HT "" +#define SCAN_PARAM_INPUT_ARG_HT +#endif +#ifdef CONFIG_SCAN_BACKOP + u16 backop_ms; + u8 scan_cnt_max; +#define SCAN_PARAM_INPUT_FMT_BACKOP " %hu %hhu" +#define SCAN_PARAM_INPUT_ARG_BACKOP , &backop_ms, &scan_cnt_max +#else +#define SCAN_PARAM_INPUT_FMT_BACKOP "" +#define SCAN_PARAM_INPUT_ARG_BACKOP +#endif + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, + SCAN_PARAM_INPUT_FMT + SCAN_PARAM_INPUT_FMT_HT + SCAN_PARAM_INPUT_FMT_BACKOP + SCAN_PARAM_INPUT_ARG + SCAN_PARAM_INPUT_ARG_HT + SCAN_PARAM_INPUT_ARG_BACKOP + ); + + if (num-- > 0) + ss->scan_ch_ms = scan_ch_ms; +#ifdef CONFIG_80211N_HT + if (num-- > 0) + ss->rx_ampdu_accept = rx_ampdu_accept; + if (num-- > 0) + ss->rx_ampdu_size = rx_ampdu_size; +#endif +#ifdef CONFIG_SCAN_BACKOP + if (num-- > 0) + ss->backop_ms = backop_ms; + if (num-- > 0) + ss->scan_cnt_max = scan_cnt_max; +#endif + } + + return count; +} +ssize_t proc_set_scan_abort(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + u32 timeout = 0; + + if (count < 1) { + RTW_INFO("argument size is less than 1\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = 0; + + num = sscanf(tmp, "%d", &timeout); + if (num != 1) { + RTW_INFO("invalid parameter!\n"); + return count; + } + + rtw_scan_abort(padapter, timeout); + } + + return count; +} + +int proc_get_scan_abort(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + + return 0; +} + +int proc_get_survey_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = rtw_netdev_priv(dev); + + dump_scanned_queue(m, adapter); + + return 0; +} + +ssize_t proc_set_survey_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + u8 _status = _FALSE; + u8 ssc_chk; + char tmp[32] = {0}; + char cmd[8] = {0}; + bool acs = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%s", cmd); + + if (num < 1) + return count; + + if (strcmp("acs", cmd) == 0) + acs = 1; + } + +#if 1 + ssc_chk = rtw_sitesurvey_condition_check(padapter, _FALSE); + if (ssc_chk != SS_ALLOW) + goto exit; + + if (!rtw_is_adapter_up(padapter)) { + RTW_INFO("scan abort!! adapter cannot use\n"); + goto exit; + } +#else +#ifdef CONFIG_MP_INCLUDED + if (rtw_mp_mode_check(padapter)) { + RTW_INFO("MP mode block Scan request\n"); + goto exit; + } +#endif + if (rtw_is_scan_deny(padapter)) { + RTW_INFO(FUNC_ADPT_FMT ": scan deny\n", FUNC_ADPT_ARG(padapter)); + goto exit; + } + + if (!rtw_is_adapter_up(padapter)) { + RTW_INFO("scan abort!! adapter cannot use\n"); + goto exit; + } + + if (rtw_mi_busy_traffic_check(padapter)) { + RTW_INFO("scan abort!! BusyTraffic == _TRUE\n"); + goto exit; + } + + if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { + RTW_INFO("scan abort!! AP mode process WPS\n"); + goto exit; + } + if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING) == _TRUE) { + RTW_INFO("scan abort!! fwstate=0x%x\n", pmlmepriv->fw_state); + goto exit; + } + +#ifdef CONFIG_CONCURRENT_MODE + if (rtw_mi_buddy_check_fwstate(padapter, + WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING | WIFI_UNDER_WPS)) { + RTW_INFO("scan abort!! buddy_fwstate check failed\n"); + goto exit; + } +#endif +#endif + + if (acs) { + #ifdef CONFIG_RTW_ACS + _status = rtw_set_acs_sitesurvey(padapter); + #endif + } else + _status = rtw_sitesurvey_cmd(padapter, NULL); + +exit: + return count; +} +#ifdef PRIVATE_R +int proc_get_infra_ap(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct sta_info *psta; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct ht_priv_infra_ap *phtpriv = &pmlmepriv->htpriv_infra_ap; +#ifdef CONFIG_80211AC_VHT + struct vht_priv_infra_ap *pvhtpriv = &pmlmepriv->vhtpriv_infra_ap; +#endif + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct sta_priv *pstapriv = &padapter->stapriv; + + if (MLME_IS_STA(padapter)) { + psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); + if (psta) { + unsigned int i, j; + unsigned int Rx_ss = 0, Tx_ss = 0; + + RTW_PRINT_SEL(m, "SSID=%s\n", pmlmeinfo->network.Ssid.Ssid); + RTW_PRINT_SEL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "Supported rate="); + for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { + if (pmlmeinfo->SupportedRates_infra_ap[i] == 0) + break; + RTW_PRINT_SEL(m, " 0x%x", pmlmeinfo->SupportedRates_infra_ap[i]); + } + RTW_PRINT_SEL(m, "\n"); +#ifdef CONFIG_80211N_HT + if (pmlmeinfo->ht_vht_received & BIT(0)) { + RTW_PRINT_SEL(m, "Supported MCS set="); + for (i = 0; i < 16 ; i++) + RTW_PRINT_SEL(m, " 0x%02x", phtpriv->MCS_set_infra_ap[i]); + RTW_PRINT_SEL(m, "\n"); + RTW_PRINT_SEL(m, "highest supported data rate=0x%x\n", phtpriv->rx_highest_data_rate_infra_ap); + RTW_PRINT_SEL(m, "HT_supported_channel_width_set=0x%x\n", phtpriv->channel_width_infra_ap); + RTW_PRINT_SEL(m, "sgi_20m=%d, sgi_40m=%d\n", phtpriv->sgi_20m_infra_ap, phtpriv->sgi_40m_infra_ap); + RTW_PRINT_SEL(m, "ldpc_cap=0x%x, stbc_cap=0x%x\n", phtpriv->ldpc_cap_infra_ap, phtpriv->stbc_cap_infra_ap); + RTW_PRINT_SEL(m, "HT_number_of_stream=%d\n", phtpriv->Rx_ss_infra_ap); + } +#endif + +#ifdef CONFIG_80211AC_VHT + if (pmlmeinfo->ht_vht_received & BIT(1)) { + RTW_PRINT_SEL(m, "VHT_supported_channel_width_set=0x%x\n", pvhtpriv->channel_width_infra_ap); + RTW_PRINT_SEL(m, "vht_ldpc_cap=0x%x, vht_stbc_cap=0x%x, vht_beamform_cap=0x%x\n", pvhtpriv->ldpc_cap_infra_ap, pvhtpriv->stbc_cap_infra_ap, pvhtpriv->beamform_cap_infra_ap); + RTW_PRINT_SEL(m, "Rx_vht_mcs_map=0x%x, Tx_vht_mcs_map=0x%x\n", *(u16 *)pvhtpriv->vht_mcs_map_infra_ap, *(u16 *)pvhtpriv->vht_mcs_map_tx_infra_ap); + RTW_PRINT_SEL(m, "VHT_number_of_stream=%d\n", pvhtpriv->number_of_streams_infra_ap); + } +#endif + } else + RTW_PRINT_SEL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); + } else + RTW_PRINT_SEL(m, "this only applies to STA mode\n"); + return 0; +} + +#endif /* PRIVATE_R */ + +static int wireless_mode_to_str(u32 mode, char *str) +{ + str[0]='\0'; + if (mode & WLAN_MD_11A) + sprintf(str+strlen(str),"%s","A/"); + if (mode & WLAN_MD_11B) + sprintf(str+strlen(str),"%s","B/"); + if (mode & WLAN_MD_11G) + sprintf(str+strlen(str),"%s","G/"); + #ifdef CONFIG_80211N_HT + if (mode & WLAN_MD_11N) + sprintf(str+strlen(str),"%s","N/"); + #endif + #ifdef CONFIG_80211AC_VHT + if (mode & WLAN_MD_11AC) + sprintf(str+strlen(str),"%s","AC/"); + #endif + #ifdef CONFIG_80211AX_HE + if (mode & WLAN_MD_11AX) + sprintf(str+strlen(str),"%s","AX/"); + #endif + if (strlen(str)>1) + str[strlen(str)-1]='\0'; + + return strlen(str); +} + +static void dump_ap_channel_rpt_ie(void *sel, struct link_mlme_ext_priv *pmlmeext) +{ + int i = 0; + if (pmlmeext->op_class != 0) { + RTW_PRINT_SEL(sel, "Operating Class=%d\n", pmlmeext->op_class); + while (i < MAX_CHANNEL_NUM && pmlmeext->channel_list[i] != 0) { + RTW_PRINT_SEL(sel, "Channel List = %d\n", pmlmeext->channel_list[i]); + i++; + } + } +} + +static bool country_env_is_op_class(char env) +{ + switch (env) { + case ' ': + case 'O': + case 'I': + case 'X': + return false; + } + + return true;; +} + +static const char *country_env_str(char env) +{ + switch (env) { + case ' ': + return "ANY"; + case 'O': + return "INDOOR"; + case 'I': + return "OUTDOOR"; + case 'X': + return "NONCOUNTRY"; + default: + return "OPERATING_ClASS"; + } +} + +static void dump_country_element_ie(void *sel, struct link_mlme_ext_priv *pmlmeext) +{ + int i = 0; + /* check the country code valid or not.*/ + if (is_alpha(pmlmeext->country[0]) == _FALSE + || is_alpha(pmlmeext->country[1]) == _FALSE) + return; + + RTW_PRINT_SEL(sel, "country=%c%c\n", pmlmeext->country[0], pmlmeext->country[1]); + if (country_env_is_op_class(pmlmeext->country[2])) + RTW_PRINT_SEL(sel, "Operating class=0x%02x\n", pmlmeext->country[2]); + else + RTW_PRINT_SEL(sel, "Environment=%s\n", country_env_str(pmlmeext->country[2])); + + while (i < MAX_CHANNEL_NUM && pmlmeext->ch_info[i].first_ch != 0) { + RTW_PRINT_SEL(sel, "First channel number = %d ", pmlmeext->ch_info[i].first_ch); + RTW_PRINT_SEL(sel, "Number of channel = %d ", pmlmeext->ch_info[i].num_of_ch); + RTW_PRINT_SEL(sel, "Maximum Transmit power level = %d dBm\n", pmlmeext->ch_info[i].power_level); + i++; + } +} + +int proc_get_ap_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct sta_info *psta; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct mlme_ext_info *pmlmeinfo = &(padapter->mlmeextpriv.mlmext_info); + struct sta_priv *pstapriv = &padapter->stapriv; + char wl_mode[16]; + u32 mbps = 0; + + /* ap vendor */ + char vendor[VENDOR_NAME_LEN] = {0}; + get_assoc_AP_Vendor(vendor, pmlmeinfo->assoc_AP_vendor); + RTW_PRINT_SEL(m,"AP Vendor %s\n", vendor); + + psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); + if (psta) { + mbps = ((u32)rtw_get_cur_max_rate(padapter) / 10); + wireless_mode_to_str(psta->phl_sta->wmode, wl_mode); + RTW_PRINT_SEL(m, "SSID=%s\n", cur_network->network.Ssid.Ssid); + RTW_PRINT_SEL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "Max Bit Rate=%u (Mbps)\n", mbps); + RTW_PRINT_SEL(m, "cur_channel=%d, cur_bwmode=%d(%s), cur_ch_offset=%d\n", pmlmeext->chandef.chan, pmlmeext->chandef.bw, ch_width_str(pmlmeext->chandef.bw), pmlmeext->chandef.offset); + RTW_PRINT_SEL(m, "wireless_mode=0x%x(%s), rtsen=%d, cts2slef=%d hw_rts_en=%d\n", + psta->phl_sta->wmode, wl_mode, psta->rtsen, psta->cts2self, psta->hw_rts_en); + /* ToDo: need API to query hal_sta->ra_info.rate_id */ + /* RTW_PRINT_SEL(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", + psta->state, psta->phl_sta->aid, psta->phl_sta->macid, psta->phl_sta->ra_info.rate_id); */ + RTW_PRINT_SEL(m, "state=0x%x, aid=%d, macid=%d\n", + psta->state, psta->phl_sta->aid, psta->phl_sta->macid); + if (MLME_IS_STA(padapter)) { + dump_country_element_ie(m, pmlmeext); + dump_ap_channel_rpt_ie(m, pmlmeext); + } +#ifdef CONFIG_80211N_HT + RTW_PRINT_SEL(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); + RTW_PRINT_SEL(m, "bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n" + , psta->phl_sta->chandef.bw, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); + RTW_PRINT_SEL(m, "ampdu_enable = %d\n", psta->ampdu_priv.ampdu_enable); + RTW_PRINT_SEL(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->ampdu_priv.agg_enable_bitmap, psta->ampdu_priv.candidate_tid_bitmap); + RTW_PRINT_SEL(m, "ldpc_cap=0x%x, stbc_cap=0x%x, beamform_cap=0x%x\n", psta->htpriv.ldpc_cap, psta->htpriv.stbc_cap, psta->htpriv.beamform_cap); +#endif /* CONFIG_80211N_HT */ + if (MLME_IS_AP(padapter)) + RTW_PRINT_SEL(m, " VHT or HE IE is configured by upper layer : %s\n", pmlmepriv->upper_layer_setting ? "True" : "False"); +#ifdef CONFIG_80211AC_VHT + RTW_PRINT_SEL(m, "vht_en=%u, vht_sgi_80m=%u\n", psta->vhtpriv.vht_option, psta->vhtpriv.sgi_80m); + RTW_PRINT_SEL(m, "vht_ldpc_cap=0x%x, vht_stbc_cap=0x%x, vht_beamform_cap=0x%x\n", psta->vhtpriv.ldpc_cap, psta->vhtpriv.stbc_cap, psta->vhtpriv.beamform_cap); + RTW_PRINT_SEL(m, "vht_mcs_map=0x%x, vht_highest_rate=0x%x, vht_ampdu_len=%d\n", *(u16 *)psta->vhtpriv.vht_mcs_map, psta->vhtpriv.vht_highest_rate, psta->vhtpriv.ampdu_len); + if (psta->vhtpriv.vht_option) { + RTW_MAP_DUMP_SEL_ALWAYS(m, "vht_cap=", psta->vhtpriv.vht_cap, 32); + } else { + RTW_PRINT_SEL(m, "vht_cap=N/A\n"); + } +#endif +#ifdef CONFIG_80211AX_HE + RTW_PRINT_SEL(m, "he_en=%d\n", psta->hepriv.he_option); + if (psta->hepriv.he_option) { + RTW_MAP_DUMP_SEL_ALWAYS(m, "he_cap=", psta->hepriv.he_cap, HE_CAP_ELE_MAX_LEN); + } else { + RTW_PRINT_SEL(m, "he_cap=N/A\n"); + } +#endif +#ifdef CONFIG_RECV_REORDERING_CTRL + sta_rx_reorder_ctl_dump(m, psta); +#endif + } else + RTW_PRINT_SEL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); + + return 0; +} + +ssize_t proc_reset_trx_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct recv_info *precvinfo = &padapter->recvinfo; + char cmd[32] = {0}; + u8 cnt = 0; + + if (count > sizeof(cmd)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(cmd, buffer, count)) { + int num = sscanf(cmd, "%hhx", &cnt); + + if (num == 1 && cnt == 0) { + precvinfo->dbg_rx_ampdu_drop_count = 0; + precvinfo->dbg_rx_ampdu_forced_indicate_count = 0; + precvinfo->dbg_rx_ampdu_loss_count = 0; + precvinfo->dbg_rx_dup_mgt_frame_drop_count = 0; + precvinfo->dbg_rx_ampdu_window_shift_cnt = 0; + precvinfo->dbg_rx_conflic_mac_addr_cnt = 0; + precvinfo->dbg_rx_drop_count = 0; + } + } + + return count; +} + +int proc_get_trx_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct recv_info *precvinfo = &padapter->recvinfo; + struct recv_priv *precvpriv = &adapter_to_dvobj(padapter)->recvpriv; + struct hw_xmit *phwxmit; + struct trx_data_buf_q *litexmitbuf_q = &dvobj->litexmitbuf_q; + struct trx_data_buf_q *literecvbuf_q = &dvobj->literecvbuf_q; +#ifdef CONFIG_USB_HCI + struct trx_urb_buf_q *xmit_urb_q = &dvobj->xmit_urb_q; + struct trx_urb_buf_q *recv_urb_q = &dvobj->recv_urb_q; +#endif + u16 vo_params[4]={0}, vi_params[4]={0}, be_params[4]={0}, bk_params[4]={0}; + + rtw_hal_read_edca(padapter, vo_params, vi_params, be_params, bk_params); + + RTW_PRINT_SEL(m, "wmm_edca_vo, aifs = %u us, cw_min = %u, cw_max = %u, txop_limit = %u us\n", vo_params[0], vo_params[1], vo_params[2], vo_params[3]); + RTW_PRINT_SEL(m, "wmm_edca_vi, aifs = %u us, cw_min = %u, cw_max = %u, txop_limit = %u us\n", vi_params[0], vi_params[1], vi_params[2], vi_params[3]); + RTW_PRINT_SEL(m, "wmm_edca_be, aifs = %u us, cw_min = %u, cw_max = %u, txop_limit = %u us\n", be_params[0], be_params[1], be_params[2], be_params[3]); + RTW_PRINT_SEL(m, "wmm_edca_bk, aifs = %u us, cw_min = %u, cw_max = %u, txop_limit = %u us\n", bk_params[0], bk_params[1], bk_params[2], bk_params[3]); + + dump_os_queue(m, padapter); + + #if 0 /*CONFIG_CORE_XMITBUF*/ + RTW_PRINT_SEL(m, "free_xmitbuf_cnt=%d\n" + , pxmitpriv->free_xmitbuf_cnt); + RTW_PRINT_SEL(m, "free_ext_xmitbuf_cnt=%d\n" + , pxmitpriv->free_xmit_extbuf_cnt); + #endif + + RTW_PRINT_SEL(m, "free_xmitframe_cnt=%d\n" + , pxmitpriv->free_xmitframe_cnt); + RTW_PRINT_SEL(m, "free_xframe_ext_cnt=%d\n" + , pxmitpriv->free_xframe_ext_cnt); + RTW_PRINT_SEL(m, "free_recvframe_cnt=%d\n" + , precvpriv->free_recvframe_cnt); + + RTW_PRINT_SEL(m, "free_litexmitbuf_cnt=%d\n" + , litexmitbuf_q->free_data_buf_cnt); + RTW_PRINT_SEL(m, "free_recvbuf_cnt=%d\n" + , literecvbuf_q->free_data_buf_cnt); + + for (i = 0; i < 4; i++) { + phwxmit = pxmitpriv->hwxmits + i; + RTW_PRINT_SEL(m, "%d, hwq.accnt=%d\n", i, phwxmit->accnt); + } + + rtw_hal_get_hwreg(padapter, HW_VAR_DUMP_MAC_TXFIFO, (u8 *)m); + +#ifdef CONFIG_USB_HCI + RTW_PRINT_SEL(m, "tx_urb_cnt=%d\n", xmit_urb_q->free_urb_buf_cnt); + RTW_PRINT_SEL(m, "rx_urb_cnt=%d\n", recv_urb_q->free_urb_buf_cnt); + RTW_PRINT_SEL(m, "rx_urb_pending_cn=%d\n", ATOMIC_READ(&(dvobj->rx_pending_cnt))); +#endif + + /* Folowing are RX info */ + RTW_PRINT_SEL(m, "RX: Count of Packets dropped by Driver: %llu\n", (unsigned long long)precvinfo->dbg_rx_drop_count); + /* Counts of packets whose seq_num is less than preorder_ctrl->indicate_seq, Ex delay, retransmission, redundant packets and so on */ + RTW_PRINT_SEL(m, "Rx: Counts of Packets Whose Seq_Num Less Than Reorder Control Seq_Num: %llu\n", (unsigned long long)precvinfo->dbg_rx_ampdu_drop_count); + /* How many times the Rx Reorder Timer is triggered. */ + RTW_PRINT_SEL(m, "Rx: Reorder Time-out Trigger Counts: %llu\n", (unsigned long long)precvinfo->dbg_rx_ampdu_forced_indicate_count); + /* Total counts of packets loss */ + RTW_PRINT_SEL(m, "Rx: Packet Loss Counts: %llu\n", (unsigned long long)precvinfo->dbg_rx_ampdu_loss_count); + RTW_PRINT_SEL(m, "Rx: Duplicate Management Frame Drop Count: %llu\n", (unsigned long long)precvinfo->dbg_rx_dup_mgt_frame_drop_count); + RTW_PRINT_SEL(m, "Rx: AMPDU BA window shift Count: %llu\n", (unsigned long long)precvinfo->dbg_rx_ampdu_window_shift_cnt); + /*The same mac addr counts*/ + RTW_PRINT_SEL(m, "Rx: Conflict MAC Address Frames Count: %llu\n", (unsigned long long)precvinfo->dbg_rx_conflic_mac_addr_cnt); + return 0; +} + +static const char *rtw_data_rate_str(enum rtw_data_rate rate) +{ + if (rate >= RTW_DATA_RATE_CCK1 && rate <= RTW_DATA_RATE_CCK11) { + switch (rate) { +#define CASE_CCK_RATE(cck) case RTW_DATA_RATE_CCK ## cck: return "CCK_" # cck "M" + CASE_CCK_RATE(1); + CASE_CCK_RATE(2); + CASE_CCK_RATE(5_5); + CASE_CCK_RATE(11); +#undef CASE_CCK_RATE + default: + return "CCK_UNKNOWN"; + } + } else if (rate >= RTW_DATA_RATE_OFDM6 && rate <= RTW_DATA_RATE_OFDM54) { + switch (rate) { +#define CASE_OFDM_RATE(ofdm) case RTW_DATA_RATE_OFDM ## ofdm: return "OFDM_" # ofdm "M" + CASE_OFDM_RATE(6); + CASE_OFDM_RATE(9); + CASE_OFDM_RATE(12); + CASE_OFDM_RATE(18); + CASE_OFDM_RATE(24); + CASE_OFDM_RATE(36); + CASE_OFDM_RATE(48); + CASE_OFDM_RATE(54); +#undef CASE_OFDM_RATE + default: + return "OFDM_UNKNOWN"; + } + } else if (rate >= RTW_DATA_RATE_MCS0 && rate <= RTW_DATA_RATE_MCS31) { + switch (rate) { +#define CASE_HT_RATE(mcs) case RTW_DATA_RATE_MCS ## mcs: return "MCS_" # mcs + CASE_HT_RATE(0); + CASE_HT_RATE(1); + CASE_HT_RATE(2); + CASE_HT_RATE(3); + CASE_HT_RATE(4); + CASE_HT_RATE(5); + CASE_HT_RATE(6); + CASE_HT_RATE(7); + CASE_HT_RATE(8); + CASE_HT_RATE(9); + CASE_HT_RATE(10); + CASE_HT_RATE(11); + CASE_HT_RATE(12); + CASE_HT_RATE(13); + CASE_HT_RATE(14); + CASE_HT_RATE(15); + CASE_HT_RATE(16); + CASE_HT_RATE(17); + CASE_HT_RATE(18); + CASE_HT_RATE(19); + CASE_HT_RATE(20); + CASE_HT_RATE(21); + CASE_HT_RATE(22); + CASE_HT_RATE(23); + CASE_HT_RATE(24); + CASE_HT_RATE(25); + CASE_HT_RATE(26); + CASE_HT_RATE(27); + CASE_HT_RATE(28); + CASE_HT_RATE(29); + CASE_HT_RATE(30); + CASE_HT_RATE(31); +#undef CASE_HT_RATE + default: + return "HT_UNKNOWN"; + } + } else if (rate >= RTW_DATA_RATE_VHT_NSS1_MCS0 && rate <= RTW_DATA_RATE_VHT_NSS4_MCS9) { + switch (rate) { +#define CASE_VHT_RATE(ss, mcs) case RTW_DATA_RATE_VHT_NSS ## ss ##_MCS ##mcs: return "VHT_SS" #ss "MCS" #mcs + CASE_VHT_RATE(1, 0); + CASE_VHT_RATE(1, 1); + CASE_VHT_RATE(1, 2); + CASE_VHT_RATE(1, 3); + CASE_VHT_RATE(1, 4); + CASE_VHT_RATE(1, 5); + CASE_VHT_RATE(1, 6); + CASE_VHT_RATE(1, 7); + CASE_VHT_RATE(1, 8); + CASE_VHT_RATE(1, 9); + CASE_VHT_RATE(2, 0); + CASE_VHT_RATE(2, 1); + CASE_VHT_RATE(2, 2); + CASE_VHT_RATE(2, 3); + CASE_VHT_RATE(2, 4); + CASE_VHT_RATE(2, 5); + CASE_VHT_RATE(2, 6); + CASE_VHT_RATE(2, 7); + CASE_VHT_RATE(2, 8); + CASE_VHT_RATE(2, 9); + CASE_VHT_RATE(3, 0); + CASE_VHT_RATE(3, 1); + CASE_VHT_RATE(3, 2); + CASE_VHT_RATE(3, 3); + CASE_VHT_RATE(3, 4); + CASE_VHT_RATE(3, 5); + CASE_VHT_RATE(3, 6); + CASE_VHT_RATE(3, 7); + CASE_VHT_RATE(3, 8); + CASE_VHT_RATE(3, 9); + CASE_VHT_RATE(4, 0); + CASE_VHT_RATE(4, 1); + CASE_VHT_RATE(4, 2); + CASE_VHT_RATE(4, 3); + CASE_VHT_RATE(4, 4); + CASE_VHT_RATE(4, 5); + CASE_VHT_RATE(4, 6); + CASE_VHT_RATE(4, 7); + CASE_VHT_RATE(4, 8); + CASE_VHT_RATE(4, 9); +#undef CASE_VHT_RATE + default: + return "VHT_UNKNOWN"; + } + } else if (rate >= RTW_DATA_RATE_HE_NSS1_MCS0 && rate <= RTW_DATA_RATE_HE_NSS4_MCS11) { + switch (rate) { +#define CASE_HE_RATE(ss, mcs) case RTW_DATA_RATE_HE_NSS ## ss ##_MCS ##mcs: return "HE_SS" #ss "MCS" #mcs + CASE_HE_RATE(1, 0); + CASE_HE_RATE(1, 1); + CASE_HE_RATE(1, 2); + CASE_HE_RATE(1, 3); + CASE_HE_RATE(1, 4); + CASE_HE_RATE(1, 5); + CASE_HE_RATE(1, 6); + CASE_HE_RATE(1, 7); + CASE_HE_RATE(1, 8); + CASE_HE_RATE(1, 9); + CASE_HE_RATE(1, 10); + CASE_HE_RATE(1, 11); + CASE_HE_RATE(2, 0); + CASE_HE_RATE(2, 1); + CASE_HE_RATE(2, 2); + CASE_HE_RATE(2, 3); + CASE_HE_RATE(2, 4); + CASE_HE_RATE(2, 5); + CASE_HE_RATE(2, 6); + CASE_HE_RATE(2, 7); + CASE_HE_RATE(2, 8); + CASE_HE_RATE(2, 9); + CASE_HE_RATE(2, 10); + CASE_HE_RATE(2, 11); + CASE_HE_RATE(3, 0); + CASE_HE_RATE(3, 1); + CASE_HE_RATE(3, 2); + CASE_HE_RATE(3, 3); + CASE_HE_RATE(3, 4); + CASE_HE_RATE(3, 5); + CASE_HE_RATE(3, 6); + CASE_HE_RATE(3, 7); + CASE_HE_RATE(3, 8); + CASE_HE_RATE(3, 9); + CASE_HE_RATE(3, 10); + CASE_HE_RATE(3, 11); + CASE_HE_RATE(4, 0); + CASE_HE_RATE(4, 1); + CASE_HE_RATE(4, 2); + CASE_HE_RATE(4, 3); + CASE_HE_RATE(4, 4); + CASE_HE_RATE(4, 5); + CASE_HE_RATE(4, 6); + CASE_HE_RATE(4, 7); + CASE_HE_RATE(4, 8); + CASE_HE_RATE(4, 9); + CASE_HE_RATE(4, 10); + CASE_HE_RATE(4, 11); +#undef CASE_HE_RATE + default: + return "HE_UNKNOWN"; + } + } + + return "ALL_UNKNOWN"; +} + +int proc_get_rate_ctl(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + u16 data_rate = 0; + u8 sgi = 0, data_fb = 0; + + if (adapter->fix_rate != NO_FIX_RATE) { + data_rate = GET_FIX_RATE(adapter->fix_rate); + sgi = GET_FIX_RATE_SGI(adapter->fix_rate); + data_fb = adapter->data_fb ? 1 : 0; + RTW_PRINT_SEL(m, "FIXED %s%s%s\n" + , rtw_data_rate_str(data_rate) + , data_rate >= RTW_DATA_RATE_MCS0 ? (sgi ? " SGI" : " LGI") : "" + , data_fb ? " FB" : "" + ); + RTW_PRINT_SEL(m, "0x%02x %u\n", adapter->fix_rate, adapter->data_fb); + } else + RTW_PRINT_SEL(m, "RA\n"); + + return 0; +} + +ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u16 fix_rate = NO_FIX_RATE; + u8 data_fb = 0; + + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%hx %hhu", &fix_rate, &data_fb); + + if (num >= 1) { + u16 fix_rate_ori = adapter->fix_rate; + + adapter->fix_rate = fix_rate; + #if 0 /*GEORGIA_TODO_FIXIT*/ + if (fix_rate == 0xFF) + hal_data->ForcedDataRate = 0; + else + hal_data->ForcedDataRate = hwrate_to_mrate(fix_rate & 0x7F); + #endif + if (adapter->fix_bw != NO_FIX_BW && fix_rate_ori != fix_rate) + rtw_run_in_thread_cmd(adapter, ((void *)(rtw_update_tx_rate_bmp)), adapter_to_dvobj(adapter)); + } + if (num >= 2) + adapter->data_fb = data_fb ? 1 : 0; + } + + return count; +} + +#ifdef CONFIG_AP_MODE +int proc_get_bmc_tx_rate(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter)) { + RTW_PRINT_SEL(m, "[ERROR] Not in SoftAP/Mesh mode !!\n"); + return 0; + } + + RTW_PRINT_SEL(m, " BMC Tx rate - %s\n", MGN_RATE_STR(adapter->bmc_tx_rate)); + return 0; +} + +ssize_t proc_set_bmc_tx_rate(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 bmc_tx_rate; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx", &bmc_tx_rate); + + if (num >= 1) + /*adapter->bmc_tx_rate = hwrate_to_mrate(bmc_tx_rate);*/ + adapter->bmc_tx_rate = bmc_tx_rate; + } + + return count; +} +#endif /*CONFIG_AP_MODE*/ + + +int proc_get_tx_power_offset(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "Tx power offset - %u\n", adapter->power_offset); + return 0; +} + +ssize_t proc_set_tx_power_offset(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 power_offset = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu", &power_offset); + + if (num >= 1) { + if (power_offset > 5) + power_offset = 0; + + adapter->power_offset = power_offset; + } + } + + return count; +} + +int proc_get_bw_ctl(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + u8 data_bw = 0; + + if (adapter->fix_bw != NO_FIX_BW) { + data_bw = adapter->fix_bw; + RTW_PRINT_SEL(m, "FIXED %s\n", ch_width_str(data_bw)); + } else + RTW_PRINT_SEL(m, "Auto\n"); + + return 0; +} + +ssize_t proc_set_bw_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 fix_bw; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%hhu", &fix_bw); + + if (num >= 1) { + u8 fix_bw_ori = adapter->fix_bw; + + adapter->fix_bw = fix_bw; + + if (adapter->fix_rate != NO_FIX_RATE && fix_bw_ori != fix_bw) + rtw_run_in_thread_cmd(adapter, ((void *)(rtw_update_tx_rate_bmp)), adapter_to_dvobj(adapter)); + } + } + + return count; +} + +#ifdef DBG_RX_COUNTER_DUMP +int proc_get_rx_cnt_dump(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + int i; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "BIT0- Dump RX counters of DRV\n"); + RTW_PRINT_SEL(m, "BIT1- Dump RX counters of MAC\n"); + RTW_PRINT_SEL(m, "BIT2- Dump RX counters of PHY\n"); + RTW_PRINT_SEL(m, "BIT3- Dump TRX data frame of DRV\n"); + RTW_PRINT_SEL(m, "dump_rx_cnt_mode = 0x%02x\n", adapter->dump_rx_cnt_mode); + + return 0; +} +ssize_t proc_set_rx_cnt_dump(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 dump_rx_cnt_mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx", &dump_rx_cnt_mode); + + if (num == 1) { + rtw_dump_phy_rxcnts_preprocess(adapter, dump_rx_cnt_mode); + adapter->dump_rx_cnt_mode = dump_rx_cnt_mode; + } + } + + return count; +} +#endif + + +ssize_t proc_set_del_rx_ampdu_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) + sscanf(tmp, "%hhu", &del_rx_ampdu_test_no_tx_fail); + + return count; +} + +ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) + sscanf(tmp, "%u", &g_wait_hiq_empty_ms); + + return count; +} + +ssize_t proc_set_sta_linking_test(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + u32 wait_ms = 0; + u8 force_fail = 0; + int num = sscanf(tmp, "%u %hhu", &wait_ms, &force_fail); + + if (num >= 1) + sta_linking_test_wait_ms = wait_ms; + if (num >= 2) + sta_linking_test_force_fail = force_fail; + } + + return count; +} + +#ifdef CONFIG_AP_MODE +ssize_t proc_set_ap_linking_test(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + u16 force_auth_fail = 0; + u16 force_asoc_fail = 0; + int num = sscanf(tmp, "%hu %hu", &force_auth_fail, &force_asoc_fail); + + if (num >= 1) + ap_linking_test_force_auth_fail = force_auth_fail; + if (num >= 2) + ap_linking_test_force_asoc_fail = force_asoc_fail; + } + + return count; +} +#endif /* CONFIG_AP_MODE */ + +int proc_get_ps_dbg_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = padapter->dvobj; + struct debug_priv *pdbgpriv = &dvobj->drv_dbg; + + RTW_PRINT_SEL(m, "dbg_sdio_alloc_irq_cnt=%d\n", pdbgpriv->dbg_sdio_alloc_irq_cnt); + RTW_PRINT_SEL(m, "dbg_sdio_free_irq_cnt=%d\n", pdbgpriv->dbg_sdio_free_irq_cnt); + RTW_PRINT_SEL(m, "dbg_sdio_alloc_irq_error_cnt=%d\n", pdbgpriv->dbg_sdio_alloc_irq_error_cnt); + RTW_PRINT_SEL(m, "dbg_sdio_free_irq_error_cnt=%d\n", pdbgpriv->dbg_sdio_free_irq_error_cnt); + RTW_PRINT_SEL(m, "dbg_sdio_init_error_cnt=%d\n", pdbgpriv->dbg_sdio_init_error_cnt); + RTW_PRINT_SEL(m, "dbg_sdio_deinit_error_cnt=%d\n", pdbgpriv->dbg_sdio_deinit_error_cnt); + RTW_PRINT_SEL(m, "dbg_suspend_error_cnt=%d\n", pdbgpriv->dbg_suspend_error_cnt); + RTW_PRINT_SEL(m, "dbg_suspend_cnt=%d\n", pdbgpriv->dbg_suspend_cnt); + RTW_PRINT_SEL(m, "dbg_resume_cnt=%d\n", pdbgpriv->dbg_resume_cnt); + RTW_PRINT_SEL(m, "dbg_resume_error_cnt=%d\n", pdbgpriv->dbg_resume_error_cnt); + RTW_PRINT_SEL(m, "dbg_deinit_fail_cnt=%d\n", pdbgpriv->dbg_deinit_fail_cnt); + RTW_PRINT_SEL(m, "dbg_carddisable_cnt=%d\n", pdbgpriv->dbg_carddisable_cnt); + RTW_PRINT_SEL(m, "dbg_ps_insuspend_cnt=%d\n", pdbgpriv->dbg_ps_insuspend_cnt); + RTW_PRINT_SEL(m, "dbg_dev_unload_inIPS_cnt=%d\n", pdbgpriv->dbg_dev_unload_inIPS_cnt); + RTW_PRINT_SEL(m, "dbg_scan_pwr_state_cnt=%d\n", pdbgpriv->dbg_scan_pwr_state_cnt); + RTW_PRINT_SEL(m, "dbg_downloadfw_pwr_state_cnt=%d\n", pdbgpriv->dbg_downloadfw_pwr_state_cnt); + RTW_PRINT_SEL(m, "dbg_carddisable_error_cnt=%d\n", pdbgpriv->dbg_carddisable_error_cnt); + RTW_PRINT_SEL(m, "dbg_fw_read_ps_state_fail_cnt=%d\n", pdbgpriv->dbg_fw_read_ps_state_fail_cnt); + RTW_PRINT_SEL(m, "dbg_leave_ips_fail_cnt=%d\n", pdbgpriv->dbg_leave_ips_fail_cnt); + RTW_PRINT_SEL(m, "dbg_leave_lps_fail_cnt=%d\n", pdbgpriv->dbg_leave_lps_fail_cnt); + RTW_PRINT_SEL(m, "dbg_h2c_leave32k_fail_cnt=%d\n", pdbgpriv->dbg_h2c_leave32k_fail_cnt); + RTW_PRINT_SEL(m, "dbg_diswow_dload_fw_fail_cnt=%d\n", pdbgpriv->dbg_diswow_dload_fw_fail_cnt); + RTW_PRINT_SEL(m, "dbg_enwow_dload_fw_fail_cnt=%d\n", pdbgpriv->dbg_enwow_dload_fw_fail_cnt); + RTW_PRINT_SEL(m, "dbg_ips_drvopen_fail_cnt=%d\n", pdbgpriv->dbg_ips_drvopen_fail_cnt); + RTW_PRINT_SEL(m, "dbg_poll_fail_cnt=%d\n", pdbgpriv->dbg_poll_fail_cnt); + RTW_PRINT_SEL(m, "dbg_rpwm_toogle_cnt=%d\n", pdbgpriv->dbg_rpwm_toogle_cnt); + RTW_PRINT_SEL(m, "dbg_rpwm_timeout_fail_cnt=%d\n", pdbgpriv->dbg_rpwm_timeout_fail_cnt); + RTW_PRINT_SEL(m, "dbg_fw_mem_dl_error_cnt=%d\n", pdbgpriv->dbg_fw_mem_dl_error_cnt); + + return 0; +} +ssize_t proc_set_ps_dbg_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter->dvobj; + struct debug_priv *pdbgpriv = &dvobj->drv_dbg; + char tmp[32]; + u8 ps_dbg_cmd_id; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx", &ps_dbg_cmd_id); + + if (num == 1 && ps_dbg_cmd_id == 1) /*Clean all*/ + _rtw_memset(pdbgpriv, 0, sizeof(struct debug_priv)); + + } + + return count; +} + + +#ifdef CONFIG_DBG_COUNTER + +int proc_get_rx_logs(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rx_logs *rx_logs = &padapter->rx_logs; + + RTW_PRINT_SEL(m, + "intf_rx=%d\n" + "intf_rx_err_recvframe=%d\n" + "intf_rx_err_skb=%d\n" + "intf_rx_report=%d\n" + "core_rx=%d\n" + "core_rx_pre=%d\n" + "core_rx_pre_ver_err=%d\n" + "core_rx_pre_mgmt=%d\n" + "core_rx_pre_mgmt_err_80211w=%d\n" + "core_rx_pre_mgmt_err=%d\n" + "core_rx_pre_ctrl=%d\n" + "core_rx_pre_ctrl_err=%d\n" + "core_rx_pre_data=%d\n" + "core_rx_pre_data_wapi_seq_err=%d\n" + "core_rx_pre_data_wapi_key_err=%d\n" + "core_rx_pre_data_handled=%d\n" + "core_rx_pre_data_err=%d\n" + "core_rx_pre_data_unknown=%d\n" + "core_rx_pre_unknown=%d\n" + "core_rx_enqueue=%d\n" + "core_rx_dequeue=%d\n" + "core_rx_post=%d\n" + "core_rx_post_decrypt=%d\n" + "core_rx_post_decrypt_wep=%d\n" + "core_rx_post_decrypt_tkip=%d\n" + "core_rx_post_decrypt_aes=%d\n" + "core_rx_post_decrypt_wapi=%d\n" + "core_rx_post_decrypt_hw=%d\n" + "core_rx_post_decrypt_unknown=%d\n" + "core_rx_post_decrypt_err=%d\n" + "core_rx_post_defrag_err=%d\n" + "core_rx_post_portctrl_err=%d\n" + "core_rx_post_indicate=%d\n" + "core_rx_post_indicate_in_oder=%d\n" + "core_rx_post_indicate_reoder=%d\n" + "core_rx_post_indicate_err=%d\n" + "os_indicate=%d\n" + "os_indicate_ap_mcast=%d\n" + "os_indicate_ap_forward=%d\n" + "os_indicate_ap_self=%d\n" + "os_indicate_err=%d\n" + "os_netif_ok=%d\n" + "os_netif_err=%d\n", + rx_logs->intf_rx, + rx_logs->intf_rx_err_recvframe, + rx_logs->intf_rx_err_skb, + rx_logs->intf_rx_report, + rx_logs->core_rx, + rx_logs->core_rx_pre, + rx_logs->core_rx_pre_ver_err, + rx_logs->core_rx_pre_mgmt, + rx_logs->core_rx_pre_mgmt_err_80211w, + rx_logs->core_rx_pre_mgmt_err, + rx_logs->core_rx_pre_ctrl, + rx_logs->core_rx_pre_ctrl_err, + rx_logs->core_rx_pre_data, + rx_logs->core_rx_pre_data_wapi_seq_err, + rx_logs->core_rx_pre_data_wapi_key_err, + rx_logs->core_rx_pre_data_handled, + rx_logs->core_rx_pre_data_err, + rx_logs->core_rx_pre_data_unknown, + rx_logs->core_rx_pre_unknown, + rx_logs->core_rx_enqueue, + rx_logs->core_rx_dequeue, + rx_logs->core_rx_post, + rx_logs->core_rx_post_decrypt, + rx_logs->core_rx_post_decrypt_wep, + rx_logs->core_rx_post_decrypt_tkip, + rx_logs->core_rx_post_decrypt_aes, + rx_logs->core_rx_post_decrypt_wapi, + rx_logs->core_rx_post_decrypt_hw, + rx_logs->core_rx_post_decrypt_unknown, + rx_logs->core_rx_post_decrypt_err, + rx_logs->core_rx_post_defrag_err, + rx_logs->core_rx_post_portctrl_err, + rx_logs->core_rx_post_indicate, + rx_logs->core_rx_post_indicate_in_oder, + rx_logs->core_rx_post_indicate_reoder, + rx_logs->core_rx_post_indicate_err, + rx_logs->os_indicate, + rx_logs->os_indicate_ap_mcast, + rx_logs->os_indicate_ap_forward, + rx_logs->os_indicate_ap_self, + rx_logs->os_indicate_err, + rx_logs->os_netif_ok, + rx_logs->os_netif_err + ); + + return 0; +} + +int proc_get_tx_logs(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct tx_logs *tx_logs = &padapter->tx_logs; + + RTW_PRINT_SEL(m, + "os_tx=%d\n" + "os_tx_err_up=%d\n" + "os_tx_err_xmit=%d\n" + "os_tx_m2u=%d\n" + "os_tx_m2u_ignore_fw_linked=%d\n" + "os_tx_m2u_ignore_self=%d\n" + "os_tx_m2u_entry=%d\n" + "os_tx_m2u_entry_err_xmit=%d\n" + "os_tx_m2u_entry_err_skb=%d\n" + "os_tx_m2u_stop=%d\n" + "core_tx=%d\n" + "core_tx_err_pxmitframe=%d\n" + "core_tx_err_brtx=%d\n" + "core_tx_upd_attrib=%d\n" + "core_tx_upd_attrib_adhoc=%d\n" + "core_tx_upd_attrib_sta=%d\n" + "core_tx_upd_attrib_ap=%d\n" + "core_tx_upd_attrib_unknown=%d\n" + "core_tx_upd_attrib_dhcp=%d\n" + "core_tx_upd_attrib_icmp=%d\n" + "core_tx_upd_attrib_active=%d\n" + "core_tx_upd_attrib_err_ucast_sta=%d\n" + "core_tx_upd_attrib_err_ucast_ap_link=%d\n" + "core_tx_upd_attrib_err_sta=%d\n" + "core_tx_upd_attrib_err_link=%d\n" + "core_tx_upd_attrib_err_sec=%d\n" + "core_tx_ap_enqueue_warn_fwstate=%d\n" + "core_tx_ap_enqueue_warn_sta=%d\n" + "core_tx_ap_enqueue_warn_nosta=%d\n" + "core_tx_ap_enqueue_warn_link=%d\n" + "core_tx_ap_enqueue_warn_trigger=%d\n" + "core_tx_ap_enqueue_mcast=%d\n" + "core_tx_ap_enqueue_ucast=%d\n" + "core_tx_ap_enqueue=%d\n" + "intf_tx=%d\n" + "intf_tx_pending_ac=%d\n" + "intf_tx_pending_fw_under_survey=%d\n" + "intf_tx_pending_fw_under_linking=%d\n" + "intf_tx_pending_xmitbuf=%d\n" + "intf_tx_enqueue=%d\n" + "core_tx_enqueue=%d\n" + "core_tx_enqueue_class=%d\n" + "core_tx_enqueue_class_err_sta=%d\n" + "core_tx_enqueue_class_err_nosta=%d\n" + "core_tx_enqueue_class_err_fwlink=%d\n" + "intf_tx_direct=%d\n" + "intf_tx_direct_err_coalesce=%d\n" + "intf_tx_dequeue=%d\n" + "intf_tx_dequeue_err_coalesce=%d\n" + "intf_tx_dump_xframe=%d\n" + "intf_tx_dump_xframe_err_txdesc=%d\n" + "intf_tx_dump_xframe_err_port=%d\n", + tx_logs->os_tx, + tx_logs->os_tx_err_up, + tx_logs->os_tx_err_xmit, + tx_logs->os_tx_m2u, + tx_logs->os_tx_m2u_ignore_fw_linked, + tx_logs->os_tx_m2u_ignore_self, + tx_logs->os_tx_m2u_entry, + tx_logs->os_tx_m2u_entry_err_xmit, + tx_logs->os_tx_m2u_entry_err_skb, + tx_logs->os_tx_m2u_stop, + tx_logs->core_tx, + tx_logs->core_tx_err_pxmitframe, + tx_logs->core_tx_err_brtx, + tx_logs->core_tx_upd_attrib, + tx_logs->core_tx_upd_attrib_adhoc, + tx_logs->core_tx_upd_attrib_sta, + tx_logs->core_tx_upd_attrib_ap, + tx_logs->core_tx_upd_attrib_unknown, + tx_logs->core_tx_upd_attrib_dhcp, + tx_logs->core_tx_upd_attrib_icmp, + tx_logs->core_tx_upd_attrib_active, + tx_logs->core_tx_upd_attrib_err_ucast_sta, + tx_logs->core_tx_upd_attrib_err_ucast_ap_link, + tx_logs->core_tx_upd_attrib_err_sta, + tx_logs->core_tx_upd_attrib_err_link, + tx_logs->core_tx_upd_attrib_err_sec, + tx_logs->core_tx_ap_enqueue_warn_fwstate, + tx_logs->core_tx_ap_enqueue_warn_sta, + tx_logs->core_tx_ap_enqueue_warn_nosta, + tx_logs->core_tx_ap_enqueue_warn_link, + tx_logs->core_tx_ap_enqueue_warn_trigger, + tx_logs->core_tx_ap_enqueue_mcast, + tx_logs->core_tx_ap_enqueue_ucast, + tx_logs->core_tx_ap_enqueue, + tx_logs->intf_tx, + tx_logs->intf_tx_pending_ac, + tx_logs->intf_tx_pending_fw_under_survey, + tx_logs->intf_tx_pending_fw_under_linking, + tx_logs->intf_tx_pending_xmitbuf, + tx_logs->intf_tx_enqueue, + tx_logs->core_tx_enqueue, + tx_logs->core_tx_enqueue_class, + tx_logs->core_tx_enqueue_class_err_sta, + tx_logs->core_tx_enqueue_class_err_nosta, + tx_logs->core_tx_enqueue_class_err_fwlink, + tx_logs->intf_tx_direct, + tx_logs->intf_tx_direct_err_coalesce, + tx_logs->intf_tx_dequeue, + tx_logs->intf_tx_dequeue_err_coalesce, + tx_logs->intf_tx_dump_xframe, + tx_logs->intf_tx_dump_xframe_err_txdesc, + tx_logs->intf_tx_dump_xframe_err_port + ); + + return 0; +} + +int proc_get_int_logs(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, + "all=%d\n" + "known=%d\n" + "err=%d\n", + padapter->int_logs.all, + padapter->int_logs.known, + padapter->int_logs.err + ); + + return 0; +} + +#endif /* CONFIG_DBG_COUNTER */ + +int proc_get_hw_status(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = padapter->dvobj; + struct debug_priv *pdbgpriv = &dvobj->drv_dbg; + struct registry_priv *regsty = dvobj_to_regsty(dvobj); + + if (regsty->check_hw_status == 0) + RTW_PRINT_SEL(m, "RX FIFO full count: not check in watch dog\n"); + else if (pdbgpriv->dbg_rx_fifo_last_overflow == 1 + && pdbgpriv->dbg_rx_fifo_curr_overflow == 1 + && pdbgpriv->dbg_rx_fifo_diff_overflow == 1 + ) + RTW_PRINT_SEL(m, "RX FIFO full count: no implementation\n"); + else { + RTW_PRINT_SEL(m, "RX FIFO full count: last_time=%llu, current_time=%llu, differential=%llu\n" + , pdbgpriv->dbg_rx_fifo_last_overflow, pdbgpriv->dbg_rx_fifo_curr_overflow, pdbgpriv->dbg_rx_fifo_diff_overflow); + } + + return 0; +} + +ssize_t proc_set_hw_status(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = padapter->dvobj; + struct registry_priv *regsty = dvobj_to_regsty(dvobj); + char tmp[32]; + u32 enable; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &enable); + + if (num == 1 && regsty && enable <= 1) { + regsty->check_hw_status = enable; + RTW_INFO("check_hw_status=%d\n", regsty->check_hw_status); + } + } + + return count; +} + +int proc_get_trx_info_debug(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + /*============ tx info ============ */ + rtw_hal_get_def_var(padapter, padapter_link, HW_DEF_RA_INFO_DUMP, m); + + /*============ rx info ============ */ + /*rtw_hal_set_phydm_var(padapter, HAL_PHYDM_RX_INFO_DUMP, m, _FALSE);*/ + + return 0; +} + +int proc_get_rx_signal(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); +#ifdef CONFIG_SNR_RPT + _list *plist, *phead; + struct sta_info *psta = NULL; + u8 sta_mac[NUM_STA][ETH_ALEN] = {{0}}; + uint mac_id[NUM_STA]; + struct stainfo_stats *pstats = NULL; + struct sta_priv *pstapriv = &(padapter->stapriv); + u32 i, j, macid_rec_idx = 0; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 null_addr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + if ((_rtw_memcmp(psta->phl_sta->mac_addr, bc_addr, 6) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, null_addr, 6) != _TRUE) + && (_rtw_memcmp(psta->phl_sta->mac_addr, psta->padapter_link->mac_addr, 6) != _TRUE)) { + _rtw_memcpy(&sta_mac[macid_rec_idx][0], psta->phl_sta->mac_addr, ETH_ALEN); + mac_id[macid_rec_idx] = psta->phl_sta->macid; + macid_rec_idx++; + } + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + + for (i = 0; i < macid_rec_idx; i++) { + psta = rtw_get_stainfo(pstapriv, &sta_mac[i][0]); + if(psta) { + /*ToDo, base on the real number of rf path to show the information*/ + RTW_PRINT_SEL(m, "STA:"MAC_FMT" SNR:{%d, %d, %d, %d}\n", MAC_ARG(psta->phl_sta->mac_addr), + psta->snr_fd_avg[0], psta->snr_fd_avg[1], psta->snr_fd_avg[2], psta->snr_fd_avg[3]); + } else { + RTW_INFO("STA is gone\n"); + } + } +#endif /* CONFIG_SNR_RPT */ + + RTW_PRINT_SEL(m, "rssi:%d\n", padapter->recvinfo.rssi); +#ifdef CONFIG_MP_INCLUDED + if (padapter->registrypriv.mp_mode == 1) { + if (padapter->mppriv.antenna_trx == MP_ANTENNA_A) + RTW_PRINT_SEL(m, "Antenna: A\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_B) + RTW_PRINT_SEL(m, "Antenna: B\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_C) + RTW_PRINT_SEL(m, "Antenna: C\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_D) + RTW_PRINT_SEL(m, "Antenna: D\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_AB) + RTW_PRINT_SEL(m, "Antenna: AB\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_BC) + RTW_PRINT_SEL(m, "Antenna: BC\n"); + else if (padapter->mppriv.antenna_trx == MP_ANTENNA_CD) + RTW_PRINT_SEL(m, "Antenna: CD\n"); + else + RTW_PRINT_SEL(m, "Antenna: __\n"); + RTW_PRINT_SEL(m, "rx_rate = %s\n", MGN_RATE_STR(hwrate_to_mrate(padapter->mppriv.rx_rate))); + return 0; + } else +#endif + { + /* RTW_PRINT_SEL(m, "rxpwdb:%d\n", padapter->recvinfo.rxpwdb); */ + RTW_PRINT_SEL(m, "signal_strength:%u\n", padapter->recvinfo.signal_strength); + RTW_PRINT_SEL(m, "signal_qual:%u\n", padapter->recvinfo.signal_qual); + } + + return 0; +} + +ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 is_signal_dbg, signal_strength; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); + + if (num < 1) + return count; + + is_signal_dbg = is_signal_dbg == 0 ? 0 : 1; + + if (is_signal_dbg && num < 2) + return count; + + signal_strength = signal_strength > PHL_MAX_RSSI ? PHL_MAX_RSSI : signal_strength; + + padapter->recvinfo.is_signal_dbg = is_signal_dbg; + padapter->recvinfo.signal_strength_dbg = signal_strength; + + if (is_signal_dbg) + RTW_INFO("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); + else + RTW_INFO("set %s\n", "HW_SIGNAL_STRENGTH"); + + } + + return count; + +} + +int proc_get_mac_rptbuf(struct seq_file *m, void *v) +{ + return 0; +} + +#ifdef CONFIG_80211N_HT + +int proc_get_ht_enable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "%d\n", pregpriv->ht_enable); + + return 0; +} + +ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if ( num == 1 && pregpriv && mode < 2) { + pregpriv->ht_enable = mode; + RTW_INFO("ht_enable=%d\n", pregpriv->ht_enable); + } + } + + return count; + +} + +int proc_get_bw_mode(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "0x%02x\n", pregpriv->bw_mode); + + return 0; +} + +ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + u8 bw_2g; + u8 bw_5g; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x ", &mode); + bw_5g = mode >> 4; + bw_2g = mode & 0x0f; + + if (num == 1 && pregpriv && bw_2g <= 4 && bw_5g <= 4) { + pregpriv->bw_mode = mode; + printk("bw_mode=0x%x\n", mode); + } + } + + return count; + +} + +int proc_get_ampdu_enable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "%d\n", pregpriv->ampdu_enable); + + return 0; +} + +ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if (num == 1 && pregpriv && mode < 2) { + pregpriv->ampdu_enable = mode; + printk("ampdu_enable=%d\n", mode); + } + + } + + return count; + +} + + +void dump_regsty_rx_ampdu_size_limit(void *sel, _adapter *adapter) +{ + struct registry_priv *regsty = adapter_to_regsty(adapter); + int i; + + RTW_PRINT_SEL(sel, "%-3s %-5s %-5s %-5s %-5s\n" + , "", "20M", "40M", "80M", "160M"); + for (i = 0; i < 4; i++) + RTW_PRINT_SEL(sel, "%dSS %5u %5u %5u %5u\n", i + 1 + , regsty->rx_ampdu_sz_limit_by_nss_bw[i][0] + , regsty->rx_ampdu_sz_limit_by_nss_bw[i][1] + , regsty->rx_ampdu_sz_limit_by_nss_bw[i][2] + , regsty->rx_ampdu_sz_limit_by_nss_bw[i][3]); +} + +int proc_get_rx_ampdu(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + _RTW_PRINT_SEL(m, "accept: "); + if (padapter->fix_rx_ampdu_accept == RX_AMPDU_ACCEPT_INVALID) + RTW_PRINT_SEL(m, "%u%s\n", rtw_rx_ampdu_is_accept(padapter), "(auto)"); + else + RTW_PRINT_SEL(m, "%u%s\n", padapter->fix_rx_ampdu_accept, "(fixed)"); + + _RTW_PRINT_SEL(m, "size: "); + if (padapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID) { + RTW_PRINT_SEL(m, "%u%s\n", rtw_rx_ampdu_size(padapter), "(auto) with conditional limit:"); + dump_regsty_rx_ampdu_size_limit(m, padapter); + } else + RTW_PRINT_SEL(m, "%u%s\n", padapter->fix_rx_ampdu_size, "(fixed)"); + RTW_PRINT_SEL(m, "\n"); + + RTW_PRINT_SEL(m, "%19s %17s\n", "fix_rx_ampdu_accept", "fix_rx_ampdu_size"); + + _RTW_PRINT_SEL(m, "%-19d %-17u\n" + , padapter->fix_rx_ampdu_accept + , padapter->fix_rx_ampdu_size); + + return 0; +} + +ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 accept; + u16 size; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu %hu", &accept, &size); + + if (num >= 1) + rtw_rx_ampdu_set_accept(padapter, accept, RX_AMPDU_DRV_FIXED); + if (num >= 2) + rtw_rx_ampdu_set_size(padapter, size, RX_AMPDU_DRV_FIXED); + + rtw_rx_ampdu_apply(padapter); + } + + return count; +} + +int proc_get_rx_ampdu_factor(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + + if (padapter) + RTW_PRINT_SEL(m, "rx ampdu factor = %x\n", padapter->driver_rx_ampdu_factor); + + return 0; +} + +ssize_t proc_set_rx_ampdu_factor(struct file *file, const char __user *buffer + , size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 factor; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &factor); + + if (padapter && (num == 1)) { + RTW_INFO("padapter->driver_rx_ampdu_factor = %x\n", factor); + + if (factor > 0x03) + padapter->driver_rx_ampdu_factor = 0xFF; + else + padapter->driver_rx_ampdu_factor = factor; + } + } + + return count; +} + +int proc_get_tx_ampdu_num(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj; + struct rtw_phl_com_t *phl_com; + u8 hw_band_num = 1; + int i; + + if (padapter) { + dvobj = adapter_to_dvobj(padapter); + phl_com = GET_PHL_COM(dvobj); + +#ifdef CONFIG_DBCC_SUPPORT + if (is_dbcc_sup(phl_com)) + hw_band_num = HW_BAND_MAX; +#endif + + for (i = HW_BAND_0 ; i < hw_band_num ; i++) { + RTW_PRINT_SEL(m, "===== HW band index %d =====\n", i); + RTW_PRINT_SEL(m, "[phy_cap] tx ampdu num = %s", + phl_com->phy_cap[i].txagg_num ? "":"not yet set"); + if (phl_com->phy_cap[i].txagg_num) + RTW_PRINT_SEL(m, "%d\n", phl_com->phy_cap[i].txagg_num); + else + RTW_PRINT_SEL(m, "\n"); + + RTW_PRINT_SEL(m, "[phy_sw_cap] tx ampdu num = %s", + phl_com->phy_sw_cap[i].txagg_num ? "":"default by HW"); + if (phl_com->phy_sw_cap[i].txagg_num) + RTW_PRINT_SEL(m, "%d\n", phl_com->phy_sw_cap[i].txagg_num); + else + RTW_PRINT_SEL(m, "\n"); + } + } + + return 0; +} + +ssize_t proc_set_tx_ampdu_num(struct file *file, const char __user *buffer + , size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_phl_com_t *phl_com = NULL; + char tmp[32]; + u8 hw_band_idx; + u32 tx_ampdu_num; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu %u", &hw_band_idx, &tx_ampdu_num); + + if (padapter && (num == 2)) { + if (hw_band_idx < HW_BAND_MAX && hw_band_idx >= HW_BAND_0) { + phl_com = GET_PHL_COM(adapter_to_dvobj(padapter)); + phl_com->phy_cap[hw_band_idx].txagg_num = tx_ampdu_num; + RTW_INFO("[HW Band %d] set phy_cap tx ampdu num = %u\n", + hw_band_idx, tx_ampdu_num); + } else { + RTW_INFO("The input of HW Band index (%u) is invalid !\n", + hw_band_idx); + } + } + } + + return count; +} + +int proc_get_rx_ampdu_density(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + + if (padapter) + RTW_PRINT_SEL(m, "rx ampdu densityg = %x\n", padapter->driver_rx_ampdu_spacing); + + return 0; +} + +ssize_t proc_set_rx_ampdu_density(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 density; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &density); + + if (padapter && (num == 1)) { + RTW_INFO("padapter->driver_rx_ampdu_spacing = %x\n", density); + + if (density > 0x07) + padapter->driver_rx_ampdu_spacing = 0xFF; + else + padapter->driver_rx_ampdu_spacing = density; + } + } + + return count; +} + +int proc_get_tx_ampdu_density(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + + if (padapter) + RTW_PRINT_SEL(m, "tx ampdu density = %x\n", padapter->driver_ampdu_spacing); + + return 0; +} + +ssize_t proc_set_tx_ampdu_density(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 density; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &density); + + if (padapter && (num == 1)) { + RTW_INFO("padapter->driver_ampdu_spacing = %x\n", density); + + if (density > 0x07) + padapter->driver_ampdu_spacing = 0xFF; + else + padapter->driver_ampdu_spacing = density; + } + } + + return count; +} + +int proc_get_tx_quick_addba_req(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (padapter) + RTW_PRINT_SEL(m, "tx_quick_addba_req = %x\n", pregpriv->tx_quick_addba_req); + + return 0; +} + +ssize_t proc_set_tx_quick_addba_req(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 enable; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &enable); + + if (padapter && (num == 1)) { + pregpriv->tx_quick_addba_req = enable; + RTW_INFO("tx_quick_addba_req = %d\n", pregpriv->tx_quick_addba_req); + } + } + + return count; +} +#ifdef CONFIG_TX_AMSDU +int proc_get_tx_amsdu(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct registry_priv *regpriv = &padapter->registrypriv; + int i; + + if (padapter) + { + RTW_PRINT_SEL(m, "regpriv->tx_amsdu_aggnum = %d\n", regpriv->tx_amsdu_aggnum); + RTW_PRINT_SEL(m, "padapter->tx amsdu = %d\n", padapter->tx_amsdu); + RTW_PRINT_SEL(m, "amsdu set timer conut = %u\n", pxmitpriv->amsdu_debug_set_timer); + RTW_PRINT_SEL(m, "amsdu time out count = %u\n", pxmitpriv->amsdu_debug_timeout); + for (i = 0; i < (AMSDU_DEBUG_MAX_COUNT - 1); i++) { + RTW_PRINT_SEL(m, "amsdu coalesce %d count = %u\n", + i + 1, pxmitpriv->amsdu_debug_coalesce[i]); + } + RTW_PRINT_SEL(m, "amsdu coalesce >%d count = %u\n", + i, pxmitpriv->amsdu_debug_coalesce[i]); + RTW_PRINT_SEL(m, "amsdu tasklet count = %u\n", pxmitpriv->amsdu_debug_tasklet); + RTW_PRINT_SEL(m, "amsdu enqueue count = %u\n", pxmitpriv->amsdu_debug_enqueue); + RTW_PRINT_SEL(m, "amsdu dequeue count = %u\n", pxmitpriv->amsdu_debug_dequeue); + } + + return 0; +} + +ssize_t proc_set_tx_amsdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct registry_priv *regpriv = &padapter->registrypriv; + char tmp[32]; + u32 i, amsdu; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &amsdu); + + if (padapter && (num == 1)) { + RTW_INFO("padapter->tx_amsdu = %x\n", amsdu); + + if (amsdu == 255) { + pxmitpriv->amsdu_debug_set_timer = 0; + pxmitpriv->amsdu_debug_timeout = 0; + pxmitpriv->amsdu_debug_tasklet = 0; + pxmitpriv->amsdu_debug_enqueue = 0; + pxmitpriv->amsdu_debug_dequeue = 0; + for (i = 0; i < AMSDU_DEBUG_MAX_COUNT; i++) + pxmitpriv->amsdu_debug_coalesce[i] = 0; + } else { + padapter->tx_amsdu = amsdu; + regpriv->tx_amsdu_aggnum = amsdu; + } + } + } + + return count; +} + +int proc_get_tx_amsdu_rate(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + if (padapter) + RTW_PRINT_SEL(m, "tx amsdu rate = %d Mbps\n", padapter->tx_amsdu_rate); + + return 0; +} + +ssize_t proc_set_tx_amsdu_rate(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 amsdu_rate; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &amsdu_rate); + + if (padapter && (num == 1)) { + RTW_INFO("padapter->tx_amsdu_rate = %x\n", amsdu_rate); + padapter->tx_amsdu_rate = amsdu_rate; + } + } + + return count; +} +#endif /* CONFIG_TX_AMSDU */ +#endif /* CONFIG_80211N_HT */ + +#ifdef CONFIG_80211AC_VHT +int proc_get_vht_24g_enable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct _ADAPTER *a = (struct _ADAPTER *)rtw_netdev_priv(dev); + struct registry_priv *regpriv = &a->registrypriv; + + + if (regpriv) + RTW_PRINT_SEL(m, "%d\n", regpriv->vht_24g_enable); + + return 0; +} + +ssize_t proc_set_vht_24g_enable(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + struct _ADAPTER *a = (struct _ADAPTER *)rtw_netdev_priv(dev); + struct registry_priv *regpriv = &a->registrypriv; + char tmp[32]; + u32 mode; + + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if ((num == 1) && regpriv && (mode < 2)) { + regpriv->vht_24g_enable = mode; + RTW_INFO("vht_24g_enable = %d\n", regpriv->vht_24g_enable); + } + } + + return count; +} +#endif /* CONFIG_80211AC_VHT */ + +ssize_t proc_set_dyn_rrsr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + char tmp[32] = {0}; + u32 num = 0, enable = 0, rrsr_val = 0; /* gpio_mode:0 input 1:output; */ + + if (count < 2) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + num = sscanf(tmp, "%d 0x%x", &enable, &rrsr_val); + RTW_INFO("num=%u enable=%d rrsr_val=0x%x\n", num, enable, rrsr_val); + pregpriv->en_dyn_rrsr = enable; + pregpriv->set_rrsr_value = rrsr_val; + /*rtw_phydm_dyn_rrsr_en(padapter, enable);*/ + /*rtw_phydm_set_rrsr(padapter, rrsr_val, _TRUE);*/ + + } + return count; + +} +int proc_get_dyn_rrsr(struct seq_file *m, void *v) { + + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + u32 init_rrsr =0xFFFFFFFF; + + if (padapter) + RTW_PRINT_SEL(m, "en_dyn_rrsr = %d fixed_rrsr_value =0x%x %s\n" + , pregpriv->en_dyn_rrsr + , pregpriv->set_rrsr_value + , (pregpriv->set_rrsr_value == init_rrsr)?"(default)":"(fixed)" + ); + + return 0; +} + +#ifdef CONFIG_80211N_HT +void rtw_dump_dft_phy_cap(void *sel, _adapter *adapter) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *adapter_link = GET_PRIMARY_LINK(adapter); + struct link_mlme_priv *pmlmepriv = &adapter_link->mlmepriv; + struct ht_priv *phtpriv = &pmlmepriv->htpriv; + #ifdef CONFIG_80211AC_VHT + struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv; + #endif + + #ifdef CONFIG_80211AC_VHT + RTW_PRINT_SEL(sel, "[DFT CAP] VHT STBC Tx : %s\n", (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] VHT STBC Rx : %s\n", (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX)) ? "V" : "X"); + #endif + RTW_PRINT_SEL(sel, "[DFT CAP] HT STBC Tx : %s\n", (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HT STBC Rx : %s\n\n", (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) ? "V" : "X"); + + #ifdef CONFIG_80211AC_VHT + RTW_PRINT_SEL(sel, "[DFT CAP] VHT LDPC Tx : %s\n", (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] VHT LDPC Rx : %s\n", (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX)) ? "V" : "X"); + #endif + RTW_PRINT_SEL(sel, "[DFT CAP] HT LDPC Tx : %s\n", (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HT LDPC Rx : %s\n\n", (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX)) ? "V" : "X"); + + #ifdef CONFIG_BEAMFORMING + #ifdef CONFIG_80211AX_HE + RTW_PRINT_SEL(sel, "[DFT CAP] HE MU Bfer : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_HE_MU_MIMO_AP_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HE MU Bfee : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_HE_MU_MIMO_STA_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HE SU Bfer : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_HE_BEAMFORMER_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HE SU Bfee : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_HE_BEAMFORMEE_ENABLE)) ? "V" : "X"); + #endif + #ifdef CONFIG_80211AC_VHT + RTW_PRINT_SEL(sel, "[DFT CAP] VHT MU Bfer : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] VHT MU Bfee : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] VHT SU Bfer : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] VHT SU Bfee : %s\n", (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) ? "V" : "X"); + #endif + RTW_PRINT_SEL(sel, "[DFT CAP] HT Bfer : %s\n", (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DFT CAP] HT Bfee : %s\n", (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) ? "V" : "X"); + #endif +} + +void rtw_get_dft_phy_cap(void *sel, _adapter *adapter) +{ + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *adapter_link = GET_PRIMARY_LINK(adapter); + RTW_PRINT_SEL(sel, "\n ======== PHY CAP protocol ========\n"); + rtw_ht_use_default_setting(adapter, adapter_link); + #ifdef CONFIG_80211AC_VHT + rtw_vht_get_real_setting(adapter, adapter_link); + #endif + #ifdef CONFIG_80211N_HT + rtw_dump_dft_phy_cap(sel, adapter); + #endif +} + +void rtw_dump_drv_phy_cap(void *sel, _adapter *adapter) +{ + struct registry_priv *pregistry_priv = &adapter->registrypriv; + + RTW_PRINT_SEL(sel, "\n ======== DRV's configuration ========\n"); + #if 0 + RTW_PRINT_SEL(sel, "[DRV CAP] TRx Capability : 0x%08x\n", phy_spec->trx_cap); + RTW_PRINT_SEL(sel, "[DRV CAP] Tx Stream Num Index : %d\n", (phy_spec->trx_cap >> 24) & 0xFF); /*Tx Stream Num Index [31:24]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] Rx Stream Num Index : %d\n", (phy_spec->trx_cap >> 16) & 0xFF); /*Rx Stream Num Index [23:16]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] Tx Path Num Index : %d\n", (phy_spec->trx_cap >> 8) & 0xFF);/*Tx Path Num Index [15:8]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] Rx Path Num Index : %d\n", (phy_spec->trx_cap & 0xFF));/*Rx Path Num Index [7:0]*/ + #endif + #ifdef CONFIG_80211N_HT + RTW_PRINT_SEL(sel, "[DRV CAP] STBC Capability : 0x%04x\n", pregistry_priv->stbc_cap); + RTW_PRINT_SEL(sel, "[DRV CAP] HT STBC Tx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT5)) ? "V" : "X"); /*BIT5: Enable HT STBC Tx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HT STBC Rx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT4)) ? "V" : "X"); /*BIT4: Enable HT STBC Rx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] VHT STBC Tx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT1)) ? "V" : "X"); /*BIT1: Enable VHT STBC Tx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] VHT STBC Rx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT0)) ? "V" : "X"); /*BIT0: Enable VHT STBC Rx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HE STBC Tx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT10)) ? "V" : "X"); /*BIT10: Enable HE STBC Tx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HE STBC Rx : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT8)) ? "V" : "X"); /*BIT8: Enable HE STBC Rx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HE STBC Tx(>80M) : %s\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT11)) ? "V" : "X"); /*BIT11: Enable HE STBC Tx(>80M)*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HE STBC Rx(>80M) : %s\n\n", (TEST_FLAG(pregistry_priv->stbc_cap, BIT9)) ? "V" : "X"); /*BIT9: Enable HE STBC Rx(>80M)*/ + + + RTW_PRINT_SEL(sel, "[DRV CAP] LDPC Capability : 0x%02x\n", pregistry_priv->ldpc_cap); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT LDPC Tx : %s\n", (TEST_FLAG(pregistry_priv->ldpc_cap, BIT1)) ? "V" : "X"); /*BIT1: Enable VHT LDPC Tx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] VHT LDPC Rx : %s\n", (TEST_FLAG(pregistry_priv->ldpc_cap, BIT0)) ? "V" : "X"); /*BIT0: Enable VHT LDPC Rx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HT LDPC Tx : %s\n", (TEST_FLAG(pregistry_priv->ldpc_cap, BIT5)) ? "V" : "X"); /*BIT5: Enable HT LDPC Tx*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HT LDPC Rx : %s\n\n", (TEST_FLAG(pregistry_priv->ldpc_cap, BIT4)) ? "V" : "X"); /*BIT4: Enable HT LDPC Rx*/ + #endif /* CONFIG_80211N_HT */ + #ifdef CONFIG_BEAMFORMING + #if 0 + RTW_PRINT_SEL(sel, "[DRV CAP] TxBF parameter : 0x%08x\n", phy_spec->txbf_param); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT Sounding Dim : %d\n", (phy_spec->txbf_param >> 24) & 0xFF); /*VHT Sounding Dim [31:24]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] VHT Steering Ant : %d\n", (phy_spec->txbf_param >> 16) & 0xFF); /*VHT Steering Ant [23:16]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HT Sounding Dim : %d\n", (phy_spec->txbf_param >> 8) & 0xFF); /*HT Sounding Dim [15:8]*/ + RTW_PRINT_SEL(sel, "[DRV CAP] HT Steering Ant : %d\n", phy_spec->txbf_param & 0xFF); /*HT Steering Ant [7:0]*/ + #endif + + /* + * BIT0: Enable VHT SU Beamformer + * BIT1: Enable VHT SU Beamformee + * BIT2: Enable VHT MU Beamformer, depend on VHT SU Beamformer + * BIT3: Enable VHT MU Beamformee, depend on VHT SU Beamformee + * BIT4: Enable HT Beamformer + * BIT5: Enable HT Beamformee + * BIT6: Enable HE SU Beamformer + * BIT7: Enable HE SU Beamformee + * BIT8: Enable HE MU Beamformer + * BIT9: Enable HE MU Beamformee + */ + RTW_PRINT_SEL(sel, "[DRV CAP] TxBF Capability : 0x%04x\n", pregistry_priv->beamform_cap); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT MU Bfer : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT2)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT MU Bfee : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT3)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT SU Bfer : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT0)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] VHT SU Bfee : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT1)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HT Bfer : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT4)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HT Bfee : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT5)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HE SU Bfer : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT6)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HE SU Bfee : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT7)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HE MU Bfer : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT8)) ? "V" : "X"); + RTW_PRINT_SEL(sel, "[DRV CAP] HE MU Bfee : %s\n", (TEST_FLAG(pregistry_priv->beamform_cap, BIT9)) ? "V" : "X"); + + RTW_PRINT_SEL(sel, "[DRV CAP] Tx Bfer rf_num : %d\n", pregistry_priv->beamformer_rf_num); + RTW_PRINT_SEL(sel, "[DRV CAP] Tx Bfee rf_num : %d\n", pregistry_priv->beamformee_rf_num); + #endif +} + +void rtw_dump_macaddr(void *sel, _adapter *adapter) +{ + int i; + _adapter *iface; + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + u8 mac_addr[ETH_ALEN]; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface) { + RTW_PRINT_SEL(sel, ADPT_FMT"- mac_addr ="MAC_FMT"\n", + ADPT_ARG(iface), MAC_ARG(adapter_mac_addr(iface))); + } + } +} + +int proc_get_stbc_cap(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "0x%04x\n", pregpriv->stbc_cap); + + return 0; +} + +ssize_t proc_set_stbc_cap(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if (num == 1 && pregpriv) { + pregpriv->stbc_cap = mode; + RTW_INFO("stbc_cap = 0x%02x\n", mode); + } + } + + return count; +} + +int proc_get_ldpc_cap(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "0x%02x\n", pregpriv->ldpc_cap); + + return 0; +} + +ssize_t proc_set_ldpc_cap(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if (num == 1 && pregpriv) { + pregpriv->ldpc_cap = mode; + RTW_INFO("ldpc_cap = 0x%02x\n", mode); + } + } + + return count; +} +#ifdef CONFIG_BEAMFORMING +int proc_get_txbf_cap(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "0x%04x\n", pregpriv->beamform_cap); + + return 0; +} + +ssize_t proc_set_txbf_cap(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 mode; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &mode); + + if (num == 1 && pregpriv) { + pregpriv->beamform_cap = mode; + RTW_INFO("beamform_cap = 0x%04x\n", mode); + } + } + + return count; +} +#endif +#endif /* CONFIG_80211N_HT */ + +/*int proc_get_rssi_disp(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + return 0; +} +*/ + +/*ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 enable=0; + + if (count < 1) + { + RTW_INFO("argument size is less than 1\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x", &enable); + + if (num != 1) { + RTW_INFO("invalid set_rssi_disp parameter!\n"); + return count; + } + + if(enable) + { + RTW_INFO("Linked info Function Enable\n"); + padapter->bLinkInfoDump = enable ; + } + else + { + RTW_INFO("Linked info Function Disable\n"); + padapter->bLinkInfoDump = 0 ; + } + + } + + return count; + +} + +*/ +#ifdef CONFIG_AP_MODE + +void dump_phl_tring_status(struct seq_file *m, _adapter *padapter, struct sta_info *psta) +{ + int i = 0; + u16 tring_len = 0; + + RTW_PRINT_SEL(m, "PHL_tring_len="); + for (i = 0; i < MAX_PHL_RING_CAT_NUM; i++) { + tring_len = rtw_phl_tring_rsc(padapter->dvobj->phl, psta->phl_sta->macid, i); + RTW_PRINT_SEL(m, "%d ", tring_len); + } + RTW_PRINT_SEL(m, "\n"); +} + +int proc_get_sta_active_time(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _list *phead, *plist; + struct sta_info *psta; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_priv *pstapriv = &padapter->stapriv; + u32 i, macid_rec_idx = 0; + u8 sta_mac[NUM_STA][ETH_ALEN]={{0}}; + + rtw_stapriv_asoc_list_lock(pstapriv); + phead = &pstapriv->asoc_list; + plist = get_next(phead); + + while((rtw_end_of_queue_search(phead, plist) == _FALSE)){ + psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); + plist = get_next(plist); + _rtw_memcpy(&sta_mac[macid_rec_idx][0], psta->phl_sta->mac_addr, ETH_ALEN); + macid_rec_idx++; + } + rtw_stapriv_asoc_list_unlock(pstapriv); + + for(i = 0; i < macid_rec_idx; i++){ + psta = rtw_get_stainfo(pstapriv, &sta_mac[i][0]); + if(psta){ + _rtw_spinlock_bh(&pstapriv->active_time_lock); + RTW_PRINT_SEL(m, "==============================\n"); + RTW_PRINT_SEL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "start active time: %u\n", psta->start_active_time); + RTW_PRINT_SEL(m, "latest active time: %u\n", psta->latest_active_time); + RTW_PRINT_SEL(m, "==============================\n"); + _rtw_spinunlock_bh(&pstapriv->active_time_lock); + } + } + return 0; +} + +int proc_get_all_sta_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + struct sta_info *psta; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_priv *pstapriv = &padapter->stapriv; + int i; + _list *plist, *phead; + + RTW_MAP_DUMP_SEL_ALWAYS(m, "sta_dz_bitmap=", pstapriv->sta_dz_bitmap, pstapriv->aid_bmp_len); + RTW_MAP_DUMP_SEL_ALWAYS(m, "tim_bitmap=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); + + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + + plist = get_next(plist); + + /* if(extra_arg == psta->phl_sta->aid) */ + { + RTW_PRINT_SEL(m, "==============================\n"); + RTW_PRINT_SEL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "ieee8021x_blocked=%d\n", psta->ieee8021x_blocked); + RTW_PRINT_SEL(m, "rtsen=%d, cts2slef=%d, hw_rts_en=%d\n", + psta->rtsen, psta->cts2self, psta->hw_rts_en); + /* ToDo: need API to query hal_sta->ra_info.rate_id */ + /* RTW_PRINT_SEL(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", + psta->state, psta->phl_sta->aid, psta->phl_sta->macid, psta->phl_sta->hal_sta->ra_info.rate_id); */ + RTW_PRINT_SEL(m, "state=0x%x, aid=%d, macid=%d\n", + psta->state, psta->phl_sta->aid, psta->phl_sta->macid); +#ifdef CONFIG_RTS_FULL_BW + if(psta->vendor_8812) + RTW_PRINT_SEL(m,"Vendor Realtek 8812\n"); +#endif/*CONFIG_RTS_FULL_BW*/ +#ifdef CONFIG_80211N_HT + RTW_PRINT_SEL(m, "qos_en=%d, ht_en=%d, vht_en=%d, he_en=%d, init_rate=%d, bwmode=%d\n", + psta->qos_option, psta->htpriv.ht_option, psta->vhtpriv.vht_option, psta->hepriv.he_option, + psta->init_rate, psta->phl_sta->chandef.bw); + + RTW_PRINT_SEL(m, "ampdu_enable = %d\n", psta->ampdu_priv.ampdu_enable); + RTW_PRINT_SEL(m, "tx_amsdu_enable = %d\n", psta->ampdu_priv.tx_amsdu_enable); + RTW_PRINT_SEL(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->ampdu_priv.agg_enable_bitmap, psta->ampdu_priv.candidate_tid_bitmap); + + if (psta->htpriv.ht_option) { + RTW_PRINT_SEL(m, "ht_ch_offset=%d, ht_is_8K_amsdu=%d\n", + psta->htpriv.ch_offset, + (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_MAX_AMSDU) ? 1 : 0); + + RTW_PRINT_SEL(m, "ht_sgi_20/40m=(%d, %d)\n", + psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); + + RTW_PRINT_SEL(m, "ht_max_bitrate_20/40m=(%u, %u)\n", + rtw_ht_mcs_rate(0, psta->htpriv.sgi_20m, psta->htpriv.ht_cap.supp_mcs_set) / 10, + rtw_ht_mcs_rate(1, psta->htpriv.sgi_40m, psta->htpriv.ht_cap.supp_mcs_set) / 10); + } +#ifdef CONFIG_80211AC_VHT + if (psta->vhtpriv.vht_option) { + RTW_PRINT_SEL(m, "vht_sgi_80/160m=(%d, %d)\n", + psta->vhtpriv.sgi_80m, psta->vhtpriv.sgi_160m); + + RTW_PRINT_SEL(m, "vht_max_bitrate_20/40/80/160m=(%u, %u, %u, %u)\n", + (rtw_vht_mcs_to_data_rate(0, psta->htpriv.sgi_20m, psta->vhtpriv.vht_highest_rate) + 1) >> 1, + (rtw_vht_mcs_to_data_rate(1, psta->htpriv.sgi_40m, psta->vhtpriv.vht_highest_rate) + 1) >> 1, + (rtw_vht_mcs_to_data_rate(2, psta->vhtpriv.sgi_80m, psta->vhtpriv.vht_highest_rate) + 1) >> 1, + (rtw_vht_mcs_to_data_rate(3, psta->vhtpriv.sgi_160m, psta->vhtpriv.vht_highest_rate) + 1) >> 1); + + RTW_PRINT_SEL(m, "vht_ldpc_cap=0x%x, vht_stbc_cap=0x%x, vht_beamform_cap=0x%x\n", psta->vhtpriv.ldpc_cap, psta->vhtpriv.stbc_cap, psta->vhtpriv.beamform_cap); + RTW_PRINT_SEL(m, "vht_mcs_map=0x%x, vht_highest_rate=0x%x, vht_ampdu_len=%d\n", *(u16 *)psta->vhtpriv.vht_mcs_map, psta->vhtpriv.vht_highest_rate, psta->vhtpriv.ampdu_len); + RTW_MAP_DUMP_SEL_ALWAYS(m, "vht_cap=", psta->vhtpriv.vht_cap, 32); + } +#ifdef CONFIG_80211AX_HE + if (psta->hepriv.he_option) { + /* NOTE: ltf_gi is unused in rtw_he_mcs_to_data_rate currently */ + RTW_PRINT_SEL(m, "he_max_bitrate_20/40/80/160m=(%u, %u, %u, %u)\n", + (rtw_he_mcs_to_data_rate(0, psta->phl_sta->asoc_cap.ltf_gi, psta->hepriv.he_highest_rate) + 1) >> 1, + (rtw_he_mcs_to_data_rate(1, psta->phl_sta->asoc_cap.ltf_gi, psta->hepriv.he_highest_rate) + 1) >> 1, + (rtw_he_mcs_to_data_rate(2, psta->phl_sta->asoc_cap.ltf_gi, psta->hepriv.he_highest_rate) + 1) >> 1, + (rtw_he_mcs_to_data_rate(3, psta->phl_sta->asoc_cap.ltf_gi, psta->hepriv.he_highest_rate) + 1) >> 1); + + RTW_MAP_DUMP_SEL_ALWAYS(m, "he_cap=", psta->hepriv.he_cap, HE_CAP_ELE_MAX_LEN); + } +#endif +#endif /* CONFIG_80211N_VHT */ +#endif /* CONFIG_80211N_HT */ + RTW_PRINT_SEL(m, "tx_nss=%d\n", rtw_get_sta_tx_nss(padapter, psta)); + RTW_PRINT_SEL(m, "rx_nss=%d\n", rtw_get_sta_rx_nss(padapter, psta)); + RTW_PRINT_SEL(m, "sleepq_len=%d\n", psta->sleepq_len); + RTW_PRINT_SEL(m, "sta_xmitpriv.vo_q_qcnt=%d\n", psta->sta_xmitpriv.vo_q.qcnt); + RTW_PRINT_SEL(m, "sta_xmitpriv.vi_q_qcnt=%d\n", psta->sta_xmitpriv.vi_q.qcnt); + RTW_PRINT_SEL(m, "sta_xmitpriv.be_q_qcnt=%d\n", psta->sta_xmitpriv.be_q.qcnt); + RTW_PRINT_SEL(m, "sta_xmitpriv.bk_q_qcnt=%d\n", psta->sta_xmitpriv.bk_q.qcnt); + + RTW_PRINT_SEL(m, "capability=0x%x\n", psta->capability); + RTW_PRINT_SEL(m, "flags=0x%x\n", psta->flags); + RTW_PRINT_SEL(m, "isPMF=%d\n", (psta->flags & WLAN_STA_MFP)?1:0); + RTW_PRINT_SEL(m, "wpa_psk=0x%x\n", psta->wpa_psk); + RTW_PRINT_SEL(m, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); + RTW_PRINT_SEL(m, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); + RTW_PRINT_SEL(m, "qos_info=0x%x\n", psta->qos_info); + RTW_PRINT_SEL(m, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); + RTW_PRINT_SEL(m, "AuthAlgrthm=0x%x\n", psta->authalg); +#ifdef CONFIG_RECV_REORDERING_CTRL + sta_rx_reorder_ctl_dump(m, psta); +#endif +#ifdef CONFIG_TDLS + RTW_PRINT_SEL(m, "tdls_sta_state=0x%08x\n", psta->tdls_sta_state); + RTW_PRINT_SEL(m, "PeerKey_Lifetime=%d\n", psta->TDLS_PeerKey_Lifetime); +#endif /* CONFIG_TDLS */ + if(psta->bssratelen >= 0 && psta->bssratelen <= 16) + RTW_MAP_DUMP_SEL_ALWAYS(m, "bssrateset=", psta->bssrateset, psta->bssratelen); + RTW_PRINT_SEL(m, "rx_data_uc_pkts=%llu\n", sta_rx_data_uc_pkts(psta)); + RTW_PRINT_SEL(m, "rx_data_mc_pkts=%llu\n", psta->sta_stats.rx_data_mc_pkts); + RTW_PRINT_SEL(m, "rx_data_bc_pkts=%llu\n", psta->sta_stats.rx_data_bc_pkts); + RTW_PRINT_SEL(m, "rx_uc_bytes=%llu\n", sta_rx_uc_bytes(psta)); + RTW_PRINT_SEL(m, "rx_mc_bytes=%llu\n", psta->sta_stats.rx_mc_bytes); + RTW_PRINT_SEL(m, "rx_bc_bytes=%llu\n", psta->sta_stats.rx_bc_bytes); + if (psta->sta_stats.rx_tp_kbits >> 10) + RTW_PRINT_SEL(m, "rx_tp =%d (Mbps)\n", psta->sta_stats.rx_tp_kbits >> 10); + else + RTW_PRINT_SEL(m, "rx_tp =%d (Kbps)\n", psta->sta_stats.rx_tp_kbits); + + RTW_PRINT_SEL(m, "tx_data_pkts=%llu\n", psta->sta_stats.tx_pkts); + RTW_PRINT_SEL(m, "tx_bytes=%llu\n", psta->sta_stats.tx_bytes); + if (psta->sta_stats.tx_tp_kbits >> 10) + RTW_PRINT_SEL(m, "tx_tp =%d (Mbps)\n", psta->sta_stats.tx_tp_kbits >> 10); + else + RTW_PRINT_SEL(m, "tx_tp =%d (Kbps)\n", psta->sta_stats.tx_tp_kbits); +#if defined(CONFIG_RTW_80211K) || defined(CONFIG_RTW_FSM_RRM) + RTW_PRINT_SEL(m, "rm_en_cap="RM_CAP_FMT"\n", RM_CAP_ARG(psta->rm_en_cap)); +#endif + dump_st_ctl(m, &psta->st_ctl); + + if (STA_OP_WFD_MODE(psta)) + RTW_PRINT_SEL(m, "op_wfd_mode:0x%02x\n", STA_OP_WFD_MODE(psta)); + + RTW_PRINT_SEL(m, "tx_bitrate_100kbps=%u\n", + rtw_desc_rate_to_bitrate(psta->phl_sta->rlink->chandef.bw, + rtw_get_current_tx_rate(padapter, psta), + rtw_get_current_tx_sgi(padapter, psta))); + RTW_PRINT_SEL(m, "rx_bitrate_100kbps=%u\n", + rtw_desc_rate_to_bitrate(psta->phl_sta->rlink->chandef.bw, + psta->curr_rx_rate, psta->curr_rx_gi_ltf)); + + RTW_PRINT_SEL(m, "rssi=%d\n", rtw_phl_get_sta_rssi(psta->phl_sta)); + + dump_phl_tring_status(m, padapter, psta); + RTW_PRINT_SEL(m, "==============================\n"); + } + + } + + } + + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + + return 0; +} + +#endif + +#ifdef CONFIG_RTKM +int proc_get_rtkm_info(struct seq_file *m, void *v) +{ + rtkm_dump_mstatus(m); + return 0; +} + +ssize_t proc_set_rtkm_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + char tmp[32] = { 0 }; + unsigned int mask = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%x", &mask); + + if (num == 1) + rtkm_set_trace(mask); + } + + return count; +} +#endif /* CONFIG_RTKM */ + +#ifdef DBG_MEMORY_LEAK +#include +extern ATOMIC_T _malloc_cnt; +extern ATOMIC_T _malloc_size; + +int proc_get_malloc_cnt(struct seq_file *m, void *v) +{ + RTW_PRINT_SEL(m, "_malloc_cnt=%d\n", atomic_read(&_malloc_cnt)); + RTW_PRINT_SEL(m, "_malloc_size=%d\n", atomic_read(&_malloc_size)); + + return 0; +} +#endif /* DBG_MEMORY_LEAK */ + +#ifdef CONFIG_FIND_BEST_CHANNEL +int proc_get_best_channel(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_chset *chset = adapter_to_chset(padapter); + u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0; + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].flags & RTW_CHF_DIS) + continue; + if (chset->chs[i].ChannelNum == 1) + index_24G = i; + if (chset->chs[i].ChannelNum == 36) + index_5G = i; + } + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].flags & RTW_CHF_DIS) + continue; + /* 2.4G */ + if (chset->chs[i].ChannelNum == 6) { + if (chset->chs[i].rx_count < chset->chs[index_24G].rx_count) { + index_24G = i; + best_channel_24G = chset->chs[i].ChannelNum; + } + } + + /* 5G */ + if (chset->chs[i].ChannelNum >= 36 + && chset->chs[i].ChannelNum < 140) { + /* Find primary channel */ + if (((chset->chs[i].ChannelNum - 36) % 8 == 0) + && (chset->chs[i].rx_count < chset->chs[index_5G].rx_count)) { + index_5G = i; + best_channel_5G = chset->chs[i].ChannelNum; + } + } + + if (chset->chs[i].ChannelNum >= 149 + && chset->chs[i].ChannelNum < 165) { + /* find primary channel */ + if (((chset->chs[i].ChannelNum - 149) % 8 == 0) + && (chset->chs[i].rx_count < chset->chs[index_5G].rx_count)) { + index_5G = i; + best_channel_5G = chset->chs[i].ChannelNum; + } + } +#if 1 /* debug */ + RTW_PRINT_SEL(m, "The rx cnt of channel %3d = %d\n", + chset->chs[i].ChannelNum, chset->chs[i].rx_count); +#endif + } + + RTW_PRINT_SEL(m, "best_channel_5G = %d\n", best_channel_5G); + RTW_PRINT_SEL(m, "best_channel_24G = %d\n", best_channel_24G); + + return 0; +} + +ssize_t proc_set_best_channel(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_chset *chset = adapter_to_chset(padapter); + char tmp[32]; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int i; + for (i = 0; i < chset->chs_len; i++) + chset->chs[i].rx_count = 0; + + RTW_INFO("set %s\n", "Clean Best Channel Count"); + } + + return count; +} +#endif /* CONFIG_FIND_BEST_CHANNEL */ + + +#ifdef CONFIG_PCI_HCI + +ssize_t proc_set_pci_bridge_conf_space(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + PPCI_DATA pci_data = dvobj_to_pci(pdvobjpriv); + struct pci_dev *pdev = pci_data->ppcidev; + struct pci_dev *bridge_pdev = pdev->bus->self; + + char tmp[32] = { 0 }; + int num; + + u32 reg = 0, value = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + num = sscanf(tmp, "%x %x", ®, &value); + if (num != 2) { + RTW_INFO("invalid parameter!\n"); + return count; + } + + if (reg >= 0x1000) { + RTW_INFO("invalid register!\n"); + return count; + } + + if (value > 0xFF) { + RTW_INFO("invalid value! Only one byte\n"); + return count; + } + + RTW_INFO(FUNC_ADPT_FMT ": register 0x%x value 0x%x\n", + FUNC_ADPT_ARG(padapter), reg, value); + + pci_write_config_byte(bridge_pdev, reg, value); + } + return count; +} + + +int proc_get_pci_bridge_conf_space(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *) rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + PPCI_DATA pci_data = dvobj_to_pci(pdvobjpriv); + struct pci_dev *pdev = pci_data->ppcidev; + struct pci_dev *bridge_pdev = pdev->bus->self; + + u32 tmp[4] = { 0 }; + u32 i, j; + + RTW_PRINT_SEL(m, "\n***** PCI Host Device Configuration Space*****\n\n"); + + for (i = 0; i < 0x1000; i += 0x10) { + for (j = 0 ; j < 4 ; j++) + pci_read_config_dword(bridge_pdev, i + j * 4, tmp+j); + + RTW_PRINT_SEL(m, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF, + tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF, + tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF, + tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF); + } + return 0; +} + + +ssize_t proc_set_pci_conf_space(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + PPCI_DATA pci_data = dvobj_to_pci(pdvobjpriv); + struct pci_dev *pdev = pci_data->ppcidev; + + char tmp[32] = { 0 }; + int num; + + u32 reg = 0, value = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + num = sscanf(tmp, "%x %x", ®, &value); + + if (num != 2) { + RTW_INFO("invalid parameter!\n"); + return count; + } + + + if (reg >= 0x1000) { + RTW_INFO("invalid register!\n"); + return count; + } + + if (value > 0xFF) { + RTW_INFO("invalid value! Only one byte\n"); + return count; + } + + RTW_INFO(FUNC_ADPT_FMT ": register 0x%x value 0x%x\n", + FUNC_ADPT_ARG(padapter), reg, value); + + pci_write_config_byte(pdev, reg, value); + + + } + return count; +} + + +int proc_get_pci_conf_space(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *) rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + PPCI_DATA pci_data = dvobj_to_pci(pdvobjpriv); + struct pci_dev *pdev = pci_data->ppcidev; + struct pci_dev *bridge_pdev = pdev->bus->self; + + u32 tmp[4] = { 0 }; + u32 i, j; + + RTW_PRINT_SEL(m, "\n***** PCI Device Configuration Space *****\n\n"); + + for (i = 0; i < 0x1000; i += 0x10) { + for (j = 0 ; j < 4 ; j++) + pci_read_config_dword(pdev, i + j * 4, tmp+j); + + RTW_PRINT_SEL(m, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF, + tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF, + tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF, + tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF); + } + + return 0; +} + + +int proc_get_pci_aspm(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *) rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + PPCI_DATA pci_data = dvobj_to_pci(pdvobjpriv); + struct pci_priv *pcipriv = &(pci_data->pcipriv); + u8 tmp8 = 0; + u16 tmp16 = 0; + u32 tmp32 = 0; + u8 l1_idle = 0; + u32 l1ss_cap_ptr = 0; + + + RTW_PRINT_SEL(m, "***** ASPM Capability *****\n"); + + pci_read_config_dword(pci_data->ppcidev, pcipriv->pciehdr_offset + PCI_EXP_LNKCAP, &tmp32); + + RTW_PRINT_SEL(m, "CLK REQ: %s\n", (tmp32&PCI_EXP_LNKCAP_CLKPM) ? "Enable" : "Disable"); + RTW_PRINT_SEL(m, "ASPM L0s: %s\n", (tmp32&BIT10) ? "Enable" : "Disable"); + RTW_PRINT_SEL(m, "ASPM L1: %s\n", (tmp32&BIT11) ? "Enable" : "Disable"); + + l1ss_cap_ptr = pci_find_ext_capability(pci_data->ppcidev, PCI_EXT_CAP_ID_L1SS); + pci_read_config_byte(pci_data->ppcidev, l1ss_cap_ptr + PCI_L1SS_CAP, &tmp8); + RTW_PRINT_SEL(m, "ASPM L1OFF: %s\n", (tmp8 & (PCI_L1SS_CAP_PCIPM_L1_2 | + PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_2 | + PCI_L1SS_CAP_ASPM_L1_1 | PCI_L1SS_CAP_L1_PM_SS)) ? + "Enable" : "Disable"); + + RTW_PRINT_SEL(m, "***** ASPM CTRL Reg *****\n"); + + pci_read_config_word(pci_data->ppcidev, pcipriv->pciehdr_offset + PCI_EXP_LNKCTL, &tmp16); + + RTW_PRINT_SEL(m, "CLK REQ: %s\n", (tmp16&PCI_EXP_LNKCTL_CLKREQ_EN) ? "Enable" : "Disable"); + RTW_PRINT_SEL(m, "ASPM L0s: %s\n", (tmp16&BIT0) ? "Enable" : "Disable"); + RTW_PRINT_SEL(m, "ASPM L1: %s\n", (tmp16&BIT1) ? "Enable" : "Disable"); + + pci_read_config_byte(pci_data->ppcidev, l1ss_cap_ptr + PCI_L1SS_CTL1, &tmp8); + RTW_PRINT_SEL(m, "ASPM L1OFF: %s\n", (tmp8 & (PCI_L1SS_CTL1_L1SS_MASK)) ? "Enable" : "Disable"); + + RTW_PRINT_SEL(m, "***** ASPM Backdoor *****\n"); + + pci_read_config_byte(pci_data->ppcidev, 0x719, &tmp8); + RTW_PRINT_SEL(m, "CLK REQ: %s\n", (tmp8 & BIT4) ? "Enable" : "Disable"); + + pci_read_config_byte(pci_data->ppcidev, 0x70f, &tmp8); + l1_idle = tmp8 & 0x38; + RTW_PRINT_SEL(m, "ASPM L0s: %s\n", (tmp8 & BIT7) ? "Enable" : "Disable"); + + pci_read_config_byte(pci_data->ppcidev, 0x719, &tmp8); + RTW_PRINT_SEL(m, "ASPM L1: %s\n", (tmp8 & BIT3) ? "Enable" : "Disable"); + + pci_read_config_byte(pci_data->ppcidev, 0x718, &tmp8); + RTW_PRINT_SEL(m, "ASPM L1OFF: %s\n", (tmp8 & BIT5) ? "Enable" : "Disable"); + + RTW_PRINT_SEL(m, "********* MISC **********\n"); + RTW_PRINT_SEL(m, "ASPM L1 Idel Time: 0x%x\n", l1_idle>>3); + RTW_PRINT_SEL(m, "*************************\n"); + + return 0; +} + +int proc_get_rx_ring(struct seq_file *m, void *v) +{ + + return 0; +} + +int proc_get_tx_ring(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *) rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + int i, j, k; + unsigned long sp_flags; + + _rtw_spinlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) { + struct rtw_tx_ring *tx_ring = &pxmitpriv->tx_ring[i]; + + RTW_PRINT_SEL(m, "tx ring[%d] (%p)\n", i, tx_ring); + RTW_PRINT_SEL(m, " dma: 0x%08x\n", (int) tx_ring->dma); + RTW_PRINT_SEL(m, " idx: %d\n", tx_ring->idx); + RTW_PRINT_SEL(m, " entries: %d\n", tx_ring->entries); + /* RTW_PRINT_SEL(m, " queue: %d\n", tx_ring->queue); */ + RTW_PRINT_SEL(m, " qlen: %d\n", tx_ring->qlen); + + for (j = 0; j < pxmitpriv->txringcount[i]; j++) { +#ifdef CONFIG_TRX_BD_ARCH + struct tx_buf_desc *entry = &tx_ring->buf_desc[j]; + RTW_PRINT_SEL(m, " buf_desc[%03d]: %p\n", j, entry); +#else + struct tx_desc *entry = &tx_ring->desc[j]; + RTW_PRINT_SEL(m, " desc[%03d]: %p\n", j, entry); +#endif + + for (k = 0; k < sizeof(*entry) / 4; k++) { + if ((k % 4) == 0) + RTW_PRINT_SEL(m, " 0x%03x", k); + + RTW_PRINT_SEL(m, " 0x%08x ", ((int *) entry)[k]); + + if ((k % 4) == 3) + RTW_PRINT_SEL(m, "\n"); + } + } + } + _rtw_spinunlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + + return 0; +} + +#ifdef DBG_TXBD_DESC_DUMP +int proc_get_tx_ring_ext(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *) rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct rtw_tx_desc_backup *pbuf; + int i, j, k, idx; + unsigned long sp_flags; + + RTW_PRINT_SEL(m, "<<<< tx ring ext dump settings >>>>\n"); + RTW_PRINT_SEL(m, " - backup frame num: %d\n", TX_BAK_FRMAE_CNT); + RTW_PRINT_SEL(m, " - backup max. desc size: %d bytes\n", TX_BAK_DESC_LEN); + RTW_PRINT_SEL(m, " - backup data size: %d bytes\n\n", TX_BAK_DATA_LEN); + + if (!pxmitpriv->dump_txbd_desc) { + RTW_PRINT_SEL(m, "Dump function is disabled.\n"); + return 0; + } + + _rtw_spinlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + for (i = 0; i < HW_QUEUE_ENTRY; i++) { + struct rtw_tx_ring *tx_ring = &pxmitpriv->tx_ring[i]; + + idx = rtw_get_tx_desc_backup(padapter, i, &pbuf); + + RTW_PRINT_SEL(m, "Tx ring[%d]", i); + switch (i) { + case 0: + RTW_PRINT_SEL(m, " (VO)\n"); + break; + case 1: + RTW_PRINT_SEL(m, " (VI)\n"); + break; + case 2: + RTW_PRINT_SEL(m, " (BE)\n"); + break; + case 3: + RTW_PRINT_SEL(m, " (BK)\n"); + break; + case 4: + RTW_PRINT_SEL(m, " (BCN)\n"); + break; + case 5: + RTW_PRINT_SEL(m, " (MGT)\n"); + break; + case 6: + RTW_PRINT_SEL(m, " (HIGH)\n"); + break; + case 7: + RTW_PRINT_SEL(m, " (TXCMD)\n"); + break; + default: + RTW_PRINT_SEL(m, " (?)\n"); + break; + } + + RTW_PRINT_SEL(m, " Entries: %d\n", TX_BAK_FRMAE_CNT); + RTW_PRINT_SEL(m, " Last idx: %d\n", idx); + + for (j = 0; j < TX_BAK_FRMAE_CNT; j++) { + RTW_PRINT_SEL(m, " desc[%03d]:\n", j); + + for (k = 0; k < (pbuf->tx_desc_size) / 4; k++) { + if ((k % 4) == 0) + RTW_PRINT_SEL(m, " 0x%03x", k); + + RTW_PRINT_SEL(m, " 0x%08x ", ((int *)pbuf->tx_bak_desc)[k]); + + if ((k % 4) == 3) + RTW_PRINT_SEL(m, "\n"); + } + +#if 1 /* data dump */ + if (pbuf->tx_desc_size) { + RTW_PRINT_SEL(m, " data[%03d]:\n", j); + + for (k = 0; k < (TX_BAK_DATA_LEN) / 4; k++) { + if ((k % 4) == 0) + RTW_PRINT_SEL(m, " 0x%03x", k); + + RTW_PRINT_SEL(m, " 0x%08x ", ((int *)pbuf->tx_bak_data_hdr)[k]); + + if ((k % 4) == 3) + RTW_PRINT_SEL(m, "\n"); + } + RTW_PRINT_SEL(m, "\n"); + } +#endif + + RTW_PRINT_SEL(m, " R/W pointer: %d/%d\n", pbuf->tx_bak_rp, pbuf->tx_bak_wp); + + pbuf = pbuf + 1; + } + RTW_PRINT_SEL(m, "\n"); + } + _rtw_spinunlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + + return 0; +} + +ssize_t proc_set_tx_ring_ext(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); + char tmp[32]; + u32 reset = 0; + u32 dump = 0; + unsigned long sp_flags; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%u %u", &dump, &reset); + + if (num != 2) { + RTW_INFO("invalid parameter!\n"); + return count; + } + + _rtw_spinlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + pxmitpriv->dump_txbd_desc = (BOOLEAN) dump; + + if (reset == 1) + rtw_tx_desc_backup_reset(); + + _rtw_spinunlock_irq(&dvobj_to_pci(pdvobjpriv)->irq_th_lock, &sp_flags); + + } + + return count; +} + +#endif + +#endif + +#ifdef CONFIG_WOWLAN +int proc_get_wow_enable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *registry_pair = &padapter->registrypriv; + + RTW_PRINT_SEL(m, "wow - %s\n", (registry_pair->wowlan_enable)? "enable" : "disable"); + return 0; +} + +ssize_t proc_set_wow_enable(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *registry_pair = &padapter->registrypriv; + char tmp[8]; + int num = 0; + int mode = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) + num = sscanf(tmp, "%d", &mode); + else + return -EFAULT; + + if (num != 1) { + RTW_ERR("%s: %s - invalid parameter!\n", __func__, tmp); + return -EINVAL; + } + + if (mode == 1) { + RTW_PRINT("%s: wowlan - enable\n", __func__); + } else if (mode == 0) { + RTW_PRINT("%s: wowlan - disable\n", __func__); + } else { + RTW_ERR("%s: %s - invalid parameter!, mode=%d\n", + __func__, tmp, mode); + return -EINVAL; + } + + registry_pair->wowlan_enable = mode; + + return count; +} + +int proc_get_pattern_info(struct seq_file *m, void *v) +{ +// TODO(jw.hou): Get pattern info from PHL. +#if 0 + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + u8 val8; + char str_1[128]; + char *p_str; + int i = 0 , j = 0, k = 0; + int len = 0, max_len = 0, total = 0; + + p_str = str_1; + max_len = sizeof(str_1); + + total = pwrpriv->wowlan_pattern_idx; + + rtw_set_default_pattern(padapter); + + /*show pattern*/ + RTW_PRINT_SEL(m, "\n======[Pattern Info.]======\n"); + RTW_PRINT_SEL(m, "pattern number: %d\n", total); + RTW_PRINT_SEL(m, "support default patterns: %c\n", + (pwrpriv->default_patterns_en) ? 'Y' : 'N'); + + for (k = 0; k < total ; k++) { + RTW_PRINT_SEL(m, "\npattern idx: %d\n", k); + RTW_PRINT_SEL(m, "pattern content:\n"); + + p_str = str_1; + max_len = sizeof(str_1); + for (i = 0 ; i < MAX_WKFM_PATTERN_SIZE / 8 ; i++) { + _rtw_memset(p_str, 0, max_len); + len = 0; + for (j = 0 ; j < 8 ; j++) { + val8 = pwrpriv->patterns[k].content[i * 8 + j]; + len += snprintf(p_str + len, max_len - len, + "%02x ", val8); + } + RTW_PRINT_SEL(m, "%s\n", p_str); + } + RTW_PRINT_SEL(m, "\npattern mask:\n"); + for (i = 0 ; i < MAX_WKFM_SIZE / 8 ; i++) { + _rtw_memset(p_str, 0, max_len); + len = 0; + for (j = 0 ; j < 8 ; j++) { + val8 = pwrpriv->patterns[k].mask[i * 8 + j]; + len += snprintf(p_str + len, max_len - len, + "%02x ", val8); + } + RTW_PRINT_SEL(m, "%s\n", p_str); + } + + RTW_PRINT_SEL(m, "\npriv_pattern_len:\n"); + RTW_PRINT_SEL(m, "pattern_len: %d\n", pwrpriv->patterns[k].len); + RTW_PRINT_SEL(m, "*****************\n"); + } +#endif + + return 0; +} + +ssize_t proc_set_pattern_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *registry_par = &adapter->registrypriv; + struct rtw_wowcam_upd_info wowcam_info = {0}; + u8 tmp[MAX_WKFM_PATTERN_STR_LEN + 1] = {0}; + + if (!(registry_par->wakeup_event & BIT(3))) { + RTW_INFO("%s: customized pattern disabled, wakeup_event: %#2x\n", + __func__, registry_par->wakeup_event); + return -EOPNOTSUPP; + } + + if (count < 1) + return -EINVAL; + + if (count >= sizeof(tmp)) { + RTW_ERR("%s: pattern string is too long, count=%zu\n", + __func__, count); + return -EINVAL; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + if (strncmp(tmp, "clean", 5) == 0) { + rtw_wow_pattern_clean(adapter, RTW_CUSTOMIZED_PATTERN); + } else { + if (rtw_wowlan_parser_pattern_cmd(tmp, + wowcam_info.ptrn, + &wowcam_info.ptrn_len, + wowcam_info.mask)) { + if (_FAIL == rtw_wow_pattern_set(adapter, + &wowcam_info, + RTW_CUSTOMIZED_PATTERN)) + return -EFAULT; + } else { + return -EINVAL; + } + } + } else { + rtw_warn_on(1); + return -EFAULT; + } + + return count; +} + +int proc_get_wakeup_event(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *registry_par = &padapter->registrypriv; + + RTW_PRINT_SEL(m, "wakeup event: %#02x\n", registry_par->wakeup_event); + return 0; +} + +ssize_t proc_set_wakeup_event(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); + struct registry_priv *registry_par = &padapter->registrypriv; + u32 wakeup_event = 0; + + u8 tmp[8] = {0}; + int num = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) + num = sscanf(tmp, "%u", &wakeup_event); + else + return -EFAULT; + + if (num == 1 && wakeup_event <= 0x1f) { + registry_par->wakeup_event = wakeup_event; + + if (!(wakeup_event & BIT(1))) + rtw_wow_pattern_clean(padapter, RTW_DEFAULT_PATTERN); + + if (!(wakeup_event & BIT(3))) + rtw_wow_pattern_clean(padapter, RTW_CUSTOMIZED_PATTERN); + + RTW_INFO("%s: wakeup_event: %#2x\n", + __func__, registry_par->wakeup_event); + } else { + return -EINVAL; + } + + return count; +} + +int proc_get_wakeup_reason(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct wow_priv *wowpriv = adapter_to_wowlan(padapter); + + RTW_PRINT_SEL(m, "last wake reason: 0x%02x\n", wowpriv->wow_wake_reason); + + return 0; +} + +int proc_get_wake_indication(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); +#ifdef RTW_DETECT_HANG + struct dvobj_priv *pdvobjpriv = padapter->dvobj; + struct debug_priv *pdbgpriv = &pdvobjpriv->drv_dbg; + struct hang_info *phang_info = &pdbgpriv->dbg_hang_info; + struct fw_hang_info *pfw_hang_info = &phang_info->dbg_fw_hang_info; + struct rxff_hang_info *prxff_hang_info = &phang_info->dbg_rxff_hang_info; +#endif /* RTW_DETECT_HANG */ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + +#ifdef RTW_DETECT_HANG + if (pfw_hang_info->dbg_is_fw_hang || + pfw_hang_info->dbg_is_fw_gone || + prxff_hang_info->dbg_is_rxff_hang) + RTW_PRINT_SEL(m, "wake indication: -1\n"); + else +#endif /* RTW_DETECT_HANG */ + RTW_PRINT_SEL(m, "wake indication: %#02x\n", !pwrpriv->bInSuspend); + + return 0; +} + +#ifdef CONFIG_GPIO_WAKEUP +int proc_get_wowlan_gpio_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct wow_priv *wowpriv = adapter_to_wowlan(padapter); + struct rtw_wow_gpio_info *wow_gpio = &wowpriv->wow_gpio; + struct rtw_dev2hst_gpio_info *d2h_gpio_info = &wow_gpio->d2h_gpio_info; + + RTW_PRINT_SEL(m, "wakeup_gpio_idx: %d\n", WAKEUP_GPIO_IDX); + RTW_PRINT_SEL(m, "high_active: %d\n", d2h_gpio_info->gpio_active); + + return 0; +} + +ssize_t proc_set_wowlan_gpio_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + void *phl = GET_PHL_INFO(dvobj); + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + struct wow_priv *wowpriv = adapter_to_wowlan(padapter); + struct rtw_wow_gpio_info *wow_gpio = &wowpriv->wow_gpio; + struct rtw_dev2hst_gpio_info *d2h_gpio_info = &wow_gpio->d2h_gpio_info; + char tmp[32] = {0}; + int num = 0; + u32 is_high_active = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + num = sscanf(tmp, "%u", &is_high_active); + + if (num != 1) { + RTW_INFO("Invalid format\n"); + return count; + } + + wow_gpio->dev2hst_high = is_high_active == 0 ? 1 : 0; + d2h_gpio_info->gpio_active = is_high_active; + + status = rtw_phl_cfg_wow_sw_gpio_ctrl(phl, wow_gpio); + + RTW_INFO("set %s %d\n", "gpio_high_active", + d2h_gpio_info->gpio_active); + RTW_INFO("%s: set GPIO_%d %d as default. status=%d\n", + __func__, WAKEUP_GPIO_IDX, wow_gpio->dev2hst_high, status); + } + + return count; +} + +ssize_t proc_set_wow_gpio_duration(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct wow_priv *wowpriv = adapter_to_wowlan(padapter); + struct rtw_wow_gpio_info *wow_gpio = &wowpriv->wow_gpio; + struct rtw_dev2hst_gpio_info *d2h_gpio_info = &wow_gpio->d2h_gpio_info; + u32 wow_cmn_gpio_dur; + u32 wow_custom_gpio_dur; + u8 tmp[8] = {0}; + int ret = 0, num = 0; + u8 index = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) + num = sscanf(tmp, "%u %u", &wow_cmn_gpio_dur, &wow_custom_gpio_dur); + else + return -EFAULT; + + if (num == 2 && wow_cmn_gpio_dur <= 127 && wow_custom_gpio_dur <= 127) { + d2h_gpio_info->gpio_pulse_dura = wow_cmn_gpio_dur; + d2h_gpio_info->gpio_pulse_period = wow_cmn_gpio_dur * 2; + d2h_gpio_info->rsn_a_pulse_duration = wow_custom_gpio_dur; + d2h_gpio_info->rsn_a_pulse_period = wow_custom_gpio_dur * 2; + + RTW_INFO("%s: wow_cmn_gpio_dur: %u, wow_custom_gpio_dur: %u\n", + __func__, d2h_gpio_info->gpio_pulse_dura, + d2h_gpio_info->rsn_a_pulse_duration); + } else { + return -EINVAL; + } + + return count; +} + +int proc_get_wow_gpio_duration(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct wow_priv *wowpriv = adapter_to_wowlan(padapter); + struct rtw_wow_gpio_info *wow_gpio = &wowpriv->wow_gpio; + struct rtw_dev2hst_gpio_info *d2h_gpio_info = &wow_gpio->d2h_gpio_info; + + RTW_PRINT_SEL(m, "wow_cmn_gpio_dur = %u, wow_custom_gpio_dur = %u\n" + "wow_cmn_gpio_period = %u, wow_custom_gpio_period = %u\n", + d2h_gpio_info->gpio_pulse_dura, + d2h_gpio_info->rsn_a_pulse_duration, + d2h_gpio_info->gpio_pulse_period, + d2h_gpio_info->rsn_a_pulse_period); + return 0; +} +#endif /* CONFIG_GPIO_WAKEUP */ + +#ifdef CONFIG_WOW_PERIODIC_WAKE +int proc_get_wow_pw_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_periodic_wake_info *wow_periodic_wake; + struct wow_priv *wowpriv; + + wowpriv = adapter_to_wowlan(padapter); + wow_periodic_wake = &wowpriv->wow_periodic_wake; + + RTW_PRINT_SEL(m, "wake_peirod=%d, wake_duration=%d\n", + wow_periodic_wake->wake_period, + wow_periodic_wake->wake_duration); + + return 0; +} + +ssize_t proc_set_wow_pw_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_periodic_wake_info *wow_periodic_wake; + struct wow_priv *wowpriv; + u32 wake_period; + u32 wake_duration; + + wowpriv = adapter_to_wowlan(padapter); + wow_periodic_wake = &wowpriv->wow_periodic_wake; + + if (count < 2) { + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%u %u", &wake_period, &wake_duration); + if (num != 2) + return -EFAULT; + + if (wake_duration >= wake_period) { + RTW_INFO("wake_duration should be less than wake_period\n"); + return -EINVAL; + } + + wow_periodic_wake->wake_period = wake_period; + wow_periodic_wake->wake_duration = wake_duration; + + RTW_INFO("wake_peirod=%d, wake_duration=%d\n", + wow_periodic_wake->wake_period, + wow_periodic_wake->wake_duration); + } + + return count; +} +#endif /* CONFIG_WOW_PERIODIC_WAKE */ +#endif /*CONFIG_WOWLAN*/ + +#ifdef CONFIG_P2P_WOWLAN +int proc_get_p2p_wowlan_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct wifidirect_info *pwdinfo = &(padapter->wdinfo); + struct p2p_wowlan_info peerinfo = pwdinfo->p2p_wow_info; + if (_TRUE == peerinfo.is_trigger) { + RTW_PRINT_SEL(m, "is_trigger: TRUE\n"); + switch (peerinfo.wowlan_recv_frame_type) { + case P2P_WOWLAN_RECV_NEGO_REQ: + RTW_PRINT_SEL(m, "Frame Type: Nego Request\n"); + break; + case P2P_WOWLAN_RECV_INVITE_REQ: + RTW_PRINT_SEL(m, "Frame Type: Invitation Request\n"); + break; + case P2P_WOWLAN_RECV_PROVISION_REQ: + RTW_PRINT_SEL(m, "Frame Type: Provision Request\n"); + break; + default: + break; + } + RTW_PRINT_SEL(m, "Peer Addr: "MAC_FMT"\n", MAC_ARG(peerinfo.wowlan_peer_addr)); + RTW_PRINT_SEL(m, "Peer WPS Config: %x\n", peerinfo.wowlan_peer_wpsconfig); + RTW_PRINT_SEL(m, "Persistent Group: %d\n", peerinfo.wowlan_peer_is_persistent); + RTW_PRINT_SEL(m, "Intivation Type: %d\n", peerinfo.wowlan_peer_invitation_type); + } else + RTW_PRINT_SEL(m, "is_trigger: False\n"); + return 0; +} +#endif /* CONFIG_P2P_WOWLAN */ + +#ifdef CONFIG_POWER_SAVE +int proc_get_ps_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct rtw_phl_com_t *phl_com = dvobj->phl_com; + struct rtw_ps_cap_t *ps_cap = &phl_com->dev_cap.ps_cap; + u8 ips_mode = ps_cap->ips_en; + u8 lps_mode = ps_cap->lps_en; + u8 lps_cap = ps_cap->lps_cap; + char str[80] = {0}; + + RTW_PRINT_SEL(m, "======Power Saving Info:======\n"); + + RTW_PRINT_SEL(m, "*IPS:\n"); + + if (ips_mode == PS_OP_MODE_DISABLED) + strcpy(str, "IPS_NONE"); + else if (ips_mode == PS_OP_MODE_FORCE_ENABLED) + strcpy(str, "IPS_FORCE_ENABLED"); + else if (ips_mode == PS_OP_MODE_AUTO) + strcpy(str, "IPS_NORMAL"); + else + strcpy(str, "Invalid"); + + RTW_PRINT_SEL(m, " IPS mode: %s\n", str); + + RTW_PRINT_SEL(m, "*LPS:\n"); + + if (lps_mode == PS_OP_MODE_DISABLED) + strcpy(str, "LPS_NONE"); + else if (ips_mode == PS_OP_MODE_FORCE_ENABLED) + strcpy(str, "LPS_FORCE_ENABLED"); + else if (ips_mode == PS_OP_MODE_AUTO) + strcpy(str, "LPS_NORMAL"); + else + strcpy(str, "Invalid"); + + RTW_PRINT_SEL(m, " LPS mode: %s\n", str); + + if (lps_cap & PS_CAP_PWR_GATED) + strcpy(str, "LPS_PG"); + else if (lps_cap & PS_CAP_CLK_GATED) + strcpy(str, "LPS_LCLK"); + else if (lps_cap & PS_CAP_RF_OFF) + strcpy(str, "LPS_NORMAL"); + else + strcpy(str, "Invalid"); + + RTW_PRINT_SEL(m, " LPS level: %s\n", str); + RTW_PRINT_SEL(m, "=============================\n"); + return 0; +} + +ssize_t proc_set_ps_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + struct _ADAPTER *adapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + struct rtw_phl_com_t *phl_com = dvobj->phl_com; + struct rtw_ps_cap_t *ps_cap_p = &phl_com->dev_cap.ps_cap; + struct registry_priv *registry_par = &adapter->registrypriv; + char tmp[32]; + int num = 0, ps_mode = 0, ps_cap = 0; + u8 lps_cap = 0; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (!buffer || copy_from_user(tmp, buffer, count)) + goto exit; + + num = sscanf(tmp, "%d %d", &ps_mode, &ps_cap); + + if (num > 2) { + RTW_ERR("%s: invalid parameter!\n", __FUNCTION__); + goto exit; + } + + if (num == 1 && ps_mode == 0) { + /* back to original LPS/IPS Mode */ + RTW_INFO("%s: back to original LPS/IPS Mode\n", __FUNCTION__); +#ifdef CONFIG_RTW_IPS + if (ps_cap_p->ips_en != registry_par->ips_mode) + rtw_phl_dbg_ps_op_mode(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_IPS, registry_par->ips_mode); +#endif /* CONFIG_RTW_IPS */ +#ifdef CONFIG_RTW_LPS + if (ps_cap_p->lps_en != registry_par->lps_mode) + rtw_phl_dbg_ps_op_mode(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_LPS, registry_par->lps_mode); + + if (ps_cap_p->lps_cap != registry_par->lps_cap) + rtw_phl_dbg_ps_cap(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_LPS, registry_par->lps_cap); +#endif /* CONFIG_RTW_LPS */ + goto exit; + } + + if (ps_mode == 1) { +#ifdef CONFIG_RTW_LPS + switch (ps_cap) { + case 0: + if (ps_cap_p->lps_en == PS_OP_MODE_DISABLED) + goto exit; + break; + case 1: + lps_cap = PS_CAP_PWRON | PS_CAP_RF_OFF; + break; + case 2: + lps_cap = PS_CAP_PWRON | PS_CAP_RF_OFF | PS_CAP_CLK_GATED; + break; + case 3: + lps_cap = PS_CAP_PWRON | PS_CAP_RF_OFF | PS_CAP_CLK_GATED | PS_CAP_PWR_GATED; + break; + default: + goto exit; + } + + if (ps_cap == 0) { + rtw_phl_dbg_ps_op_mode(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_LPS, PS_OP_MODE_DISABLED); + } else { + if (ps_cap_p->lps_en == PS_OP_MODE_DISABLED) + rtw_phl_dbg_ps_op_mode(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_LPS, PS_OP_MODE_AUTO); + if (ps_cap_p->lps_cap != lps_cap) + rtw_phl_dbg_ps_cap(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_LPS, lps_cap); + } +#endif /* CONFIG_RTW_LPS */ + } else if (ps_mode == 2) { +#ifdef CONFIG_RTW_IPS + if (ps_cap_p->ips_en != ps_cap) { + if (ps_cap != 0) + ps_cap = registry_par->ips_mode; + + rtw_phl_dbg_ps_op_mode(GET_PHL_INFO(dvobj), HW_BAND_0, PS_MODE_IPS, ps_cap); + } +#endif /* #ifdef CONFIG_RTW_IPS */ + } + else { + RTW_ERR("%s: invalid parameter, mode = %d!\n", __FUNCTION__, ps_mode); + } +exit: + return count; +} +#endif /* CONFIG_POWER_SAVE */ + +#ifdef CONFIG_TDLS +int proc_get_tdls_enable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "TDLS is %s !\n", (rtw_is_tdls_enabled(padapter) == _TRUE) ? "enabled" : "disabled"); + + return 0; +} + +ssize_t proc_set_tdls_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u32 en_tdls = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d ", &en_tdls); + + if (num == 1 && pregpriv) { + if (en_tdls > 0) + rtw_enable_tdls_func(padapter); + else + rtw_disable_tdls_func(padapter, _TRUE); + } + } + + return count; +} + +static int proc_tdls_display_tdls_function_info(struct seq_file *m) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; + u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE; + u8 SpaceBtwnItemAndValueTmp = 0; + BOOLEAN FirstMatchFound = _FALSE; + int j = 0; + + RTW_PRINT_SEL(m, "============[TDLS Function Info]============\n"); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Enable", (rtw_is_tdls_enabled(padapter) == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Driver Setup", (ptdlsinfo->driver_setup == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Prohibited", (ptdlsinfo->ap_prohibited == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Channel Switch Prohibited", (ptdlsinfo->ch_switch_prohibited == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Link Established", (ptdlsinfo->link_established == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %d/%d\n", SpaceBtwnItemAndValue, "TDLS STA Num (Linked/Allowed)", ptdlsinfo->sta_cnt, MAX_ALLOWED_TDLS_STA_NUM); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Allowed STA Num Reached", (ptdlsinfo->sta_maximum == _TRUE) ? "_TRUE" : "_FALSE"); + +#ifdef CONFIG_TDLS_CH_SW + RTW_PRINT_SEL(m, "%-*s =", SpaceBtwnItemAndValue, "TDLS CH SW State"); + if (ptdlsinfo->chsw_info.ch_sw_state == TDLS_STATE_NONE) + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_STATE_NONE"); + else { + for (j = 0; j < 32; j++) { + if (ptdlsinfo->chsw_info.ch_sw_state & BIT(j)) { + if (FirstMatchFound == _FALSE) { + SpaceBtwnItemAndValueTmp = 1; + FirstMatchFound = _TRUE; + } else + SpaceBtwnItemAndValueTmp = SpaceBtwnItemAndValue + 3; + switch (BIT(j)) { + case TDLS_INITIATOR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_INITIATOR_STATE"); + break; + case TDLS_RESPONDER_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_RESPONDER_STATE"); + break; + case TDLS_LINKED_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_LINKED_STATE"); + break; + case TDLS_WAIT_PTR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_WAIT_PTR_STATE"); + break; + case TDLS_ALIVE_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_ALIVE_STATE"); + break; + case TDLS_CH_SWITCH_ON_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SWITCH_ON_STATE"); + break; + case TDLS_PEER_AT_OFF_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_PEER_AT_OFF_STATE"); + break; + case TDLS_CH_SW_INITIATOR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SW_INITIATOR_STATE"); + break; + case TDLS_WAIT_CH_RSP_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValue, " ", "TDLS_WAIT_CH_RSP_STATE"); + break; + default: + RTW_PRINT_SEL(m, "%-*sBIT(%d)\n", SpaceBtwnItemAndValueTmp, " ", j); + break; + } + } + } + } + + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS CH SW On", (ATOMIC_READ(&ptdlsinfo->chsw_info.chsw_on) == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Off-Channel Num", ptdlsinfo->chsw_info.off_ch_num); + RTW_PRINT_SEL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Channel Offset", ptdlsinfo->chsw_info.ch_offset); + RTW_PRINT_SEL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Current Time", ptdlsinfo->chsw_info.cur_time); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS CH SW Delay Switch Back", (ptdlsinfo->chsw_info.delay_switch_back == _TRUE) ? "_TRUE" : "_FALSE"); + RTW_PRINT_SEL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Dump Back", ptdlsinfo->chsw_info.dump_stack); +#endif + + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Device Discovered", (ptdlsinfo->dev_discovered == _TRUE) ? "_TRUE" : "_FALSE"); + + return 0; +} + +static int proc_tdls_display_network_info(struct seq_file *m) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct wlan_network *cur_network = &(pmlmepriv->cur_network); + int i = 0; + u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE; + char wl_mode[16]; + + /* Display the linked AP/GO info */ + RTW_PRINT_SEL(m, "============[Associated AP/GO Info]============\n"); + + if ((padapter->mlmepriv.fw_state & WIFI_STATION_STATE) && (padapter->mlmepriv.fw_state & WIFI_ASOC_STATE)) { + wireless_mode_to_str(pmlmeext->cur_wireless_mode, wl_mode); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "BSSID", cur_network->network.Ssid.Ssid); + RTW_PRINT_SEL(m, "%-*s = "MAC_FMT"\n", SpaceBtwnItemAndValue, "Mac Address", MAC_ARG(cur_network->network.MacAddress)); + RTW_PRINT_SEL(m, "%-*s = ", SpaceBtwnItemAndValue, "Wireless Mode"); + RTW_PRINT_SEL(m, "0x%x(%s)\n", pmlmeext->cur_wireless_mode, wl_mode); + + RTW_PRINT_SEL(m, "%-*s = ", SpaceBtwnItemAndValue, "Privacy"); + switch (padapter->securitypriv.dot11PrivacyAlgrthm) { + case _NO_PRIVACY_: + RTW_PRINT_SEL(m, "%s\n", "NO PRIVACY"); + break; + case _WEP40_: + RTW_PRINT_SEL(m, "%s\n", "WEP 40"); + break; + case _TKIP_: + RTW_PRINT_SEL(m, "%s\n", "TKIP"); + break; + case _TKIP_WTMIC_: + RTW_PRINT_SEL(m, "%s\n", "TKIP WTMIC"); + break; + case _AES_: + RTW_PRINT_SEL(m, "%s\n", "AES"); + break; + case _WEP104_: + RTW_PRINT_SEL(m, "%s\n", "WEP 104"); + break; +#if 0 /* no this setting */ + case _WEP_WPA_MIXED_: + RTW_PRINT_SEL(m, "%s\n", "WEP/WPA Mixed"); + break; +#endif + case _SMS4_: + RTW_PRINT_SEL(m, "%s\n", "SMS4"); + break; +#ifdef CONFIG_IEEE80211W + case _BIP_CMAC_128_: + RTW_PRINT_SEL(m, "%s\n", "BIP"); + break; +#endif /* CONFIG_IEEE80211W */ + } + + RTW_PRINT_SEL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "Channel", pmlmeext->chandef.chan); + RTW_PRINT_SEL(m, "%-*s = %u\n", SpaceBtwnItemAndValue, "Channel Offset", pmlmeext->chandef.offset); + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "Bandwidth Mode", ch_width_str(pmlmeext->chandef.bw)); + + } else + RTW_PRINT_SEL(m, "No association with AP/GO exists!\n"); + + return 0; +} + +static int proc_tdls_display_tdls_sta_info(struct seq_file *m) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct sta_priv *pstapriv = &padapter->stapriv; + struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; + struct sta_info *psta; + int i = 0, j = 0; + _list *plist, *phead; + u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE; + u8 SpaceBtwnItemAndValueTmp = 0; + u8 NumOfTdlsStaToShow = 0; + BOOLEAN FirstMatchFound = _FALSE; + char wl_mode[16]; + + /* Search for TDLS sta info to display */ + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (i = 0; i < NUM_STA; i++) { + phead = &(pstapriv->sta_hash[i]); + plist = get_next(phead); + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + if (psta->tdls_sta_state != TDLS_STATE_NONE) { + /* We got one TDLS sta info to show */ + RTW_PRINT_SEL(m, "============[TDLS Peer STA Info: STA %d]============\n", ++NumOfTdlsStaToShow); + RTW_PRINT_SEL(m, "%-*s = "MAC_FMT"\n", SpaceBtwnItemAndValue, "Mac Address", MAC_ARG(psta->phl_sta->mac_addr)); + RTW_PRINT_SEL(m, "%-*s =", SpaceBtwnItemAndValue, "TDLS STA State"); + SpaceBtwnItemAndValueTmp = 0; + FirstMatchFound = _FALSE; + for (j = 0; j < 32; j++) { + if (psta->tdls_sta_state & BIT(j)) { + if (FirstMatchFound == _FALSE) { + SpaceBtwnItemAndValueTmp = 1; + FirstMatchFound = _TRUE; + } else + SpaceBtwnItemAndValueTmp = SpaceBtwnItemAndValue + 3; + switch (BIT(j)) { + case TDLS_INITIATOR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_INITIATOR_STATE"); + break; + case TDLS_RESPONDER_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_RESPONDER_STATE"); + break; + case TDLS_LINKED_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_LINKED_STATE"); + break; + case TDLS_WAIT_PTR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_WAIT_PTR_STATE"); + break; + case TDLS_ALIVE_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_ALIVE_STATE"); + break; + case TDLS_CH_SWITCH_ON_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SWITCH_ON_STATE"); + break; + case TDLS_PEER_AT_OFF_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_PEER_AT_OFF_STATE"); + break; + case TDLS_CH_SW_INITIATOR_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SW_INITIATOR_STATE"); + break; + case TDLS_WAIT_CH_RSP_STATE: + RTW_PRINT_SEL(m, "%-*s%s\n", SpaceBtwnItemAndValue, " ", "TDLS_WAIT_CH_RSP_STATE"); + break; + default: + RTW_PRINT_SEL(m, "%-*sBIT(%d)\n", SpaceBtwnItemAndValueTmp, " ", j); + break; + } + } + } + + wireless_mode_to_str(psta->phl_sta->wmode, wl_mode); + RTW_PRINT_SEL(m, "%-*s = ", SpaceBtwnItemAndValue, "Wireless Mode"); + RTW_PRINT_SEL(m, "0x%x(%s)\n", psta->phl_sta->wmode, wl_mode); + + RTW_PRINT_SEL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "Bandwidth Mode", ch_width_str(psta->phl_sta->chandef.bw)); + + RTW_PRINT_SEL(m, "%-*s = ", SpaceBtwnItemAndValue, "Privacy"); + switch (psta->dot118021XPrivacy) { + case _NO_PRIVACY_: + RTW_PRINT_SEL(m, "%s\n", "NO PRIVACY"); + break; + case _WEP40_: + RTW_PRINT_SEL(m, "%s\n", "WEP 40"); + break; + case _TKIP_: + RTW_PRINT_SEL(m, "%s\n", "TKIP"); + break; + case _TKIP_WTMIC_: + RTW_PRINT_SEL(m, "%s\n", "TKIP WTMIC"); + break; + case _AES_: + RTW_PRINT_SEL(m, "%s\n", "AES"); + break; + case _WEP104_: + RTW_PRINT_SEL(m, "%s\n", "WEP 104"); + break; +#if 0 /* no this setting */ + case _WEP_WPA_MIXED_: + RTW_PRINT_SEL(m, "%s\n", "WEP/WPA Mixed"); + break; +#endif + case _SMS4_: + RTW_PRINT_SEL(m, "%s\n", "SMS4"); + break; +#ifdef CONFIG_IEEE80211W + case _BIP_CMAC_128_: + RTW_PRINT_SEL(m, "%s\n", "BIP"); + break; +#endif /* CONFIG_IEEE80211W */ + } + + RTW_PRINT_SEL(m, "%-*s = %d sec/%d sec\n", SpaceBtwnItemAndValue, "TPK Lifetime (Current/Expire)", psta->TPK_count, psta->TDLS_PeerKey_Lifetime); + RTW_PRINT_SEL(m, "%-*s = %llu\n", SpaceBtwnItemAndValue, "Tx Packets Over Direct Link", psta->sta_stats.tx_pkts); + RTW_PRINT_SEL(m, "%-*s = %llu\n", SpaceBtwnItemAndValue, "Rx Packets Over Direct Link", psta->sta_stats.rx_data_pkts); + } + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + if (NumOfTdlsStaToShow == 0) { + RTW_PRINT_SEL(m, "============[TDLS Peer STA Info]============\n"); + RTW_PRINT_SEL(m, "No TDLS direct link exists!\n"); + } + + return 0; +} + +int proc_get_tdls_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct wlan_network *cur_network = &(pmlmepriv->dev_cur_network); + struct sta_priv *pstapriv = &padapter->stapriv; + struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; + struct sta_info *psta; + int i = 0, j = 0; + _list *plist, *phead; + u8 SpaceBtwnItemAndValue = 41; + u8 SpaceBtwnItemAndValueTmp = 0; + u8 NumOfTdlsStaToShow = 0; + BOOLEAN FirstMatchFound = _FALSE; + + if (rtw_hw_chk_wl_func(adapter_to_dvobj(padapter), WL_FUNC_TDLS) == _FALSE) { + RTW_PRINT_SEL(m, "No tdls info can be shown since hal doesn't support tdls\n"); + return 0; + } + + proc_tdls_display_tdls_function_info(m); + proc_tdls_display_network_info(m); + proc_tdls_display_tdls_sta_info(m); + + return 0; +} +#endif + +int proc_get_monitor(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLDL: [currentlty primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (MLME_IS_MONITOR(padapter)) { + RTW_PRINT_SEL(m, "Monitor mode : Enable\n"); + RTW_PRINT_SEL(m, "Device type : %u\n", dev->type); + + RTW_PRINT_SEL(m, "ch=%d, ch_offset=%d, bw=%d\n", + rtw_get_oper_ch(padapter, padapter_link), + rtw_get_oper_choffset(padapter, padapter_link), + rtw_get_oper_bw(padapter, padapter_link)); + } else + RTW_PRINT_SEL(m, "Monitor mode : Disable\n"); + + return 0; +} + +ssize_t proc_set_monitor(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + u16 target_type; + u8 target_band, target_ch, target_offset, target_bw; + /* ToDo CONFIG_RTW_MLDL: [currentlty primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (count < 3) { + RTW_INFO("argument size is less than 3\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = 0; + + num = sscanf(tmp, "type %hu", &target_type); + if ((num == 1) && + ((target_type != ARPHRD_IEEE80211) && + (target_type != ARPHRD_IEEE80211_RADIOTAP))) { + dev->type = ARPHRD_IEEE80211_RADIOTAP; + return count; + } + + num = sscanf(tmp, "%hhu %hhu %hhu %hhu", &target_band, &target_ch, &target_offset, &target_bw); + if (num != 4) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } + + padapter_link->mlmeextpriv.chandef.chan = target_ch; + set_bch_bwmode(padapter, padapter_link, target_band, target_ch, + target_offset, target_bw, RFK_TYPE_FORCE_DO); + } + + return count; +} +#ifdef DBG_XMIT_BLOCK +int proc_get_xmit_block(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + dump_xmit_block(m, padapter); + + return 0; +} + +ssize_t proc_set_xmit_block(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u8 xb_mode, xb_reason; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhx %hhx", &xb_mode, &xb_reason); + + if (num != 2) { + RTW_INFO("invalid parameter!\n"); + return count; + } + + if (xb_mode == 0)/*set*/ + rtw_set_xmit_block(padapter, xb_reason); + else if (xb_mode == 1)/*clear*/ + rtw_clr_xmit_block(padapter, xb_reason); + else + RTW_INFO("invalid parameter!\n"); + } + + return count; +} +#endif + +int proc_get_efuse_map(struct seq_file *m, void *v) +{ +#if 0 + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + HAL_DATA_TYPE *pHalData = GET_PHL_COM(adapter_to_dvobj(padapter)); + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); + PEFUSE_HAL pEfuseHal = &pHalData->EfuseHal; + struct efuse_info *efuse = adapter_to_efuse(padapter); + int i, j; + u16 mapLen; + + EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, _FALSE); + if (mapLen > EFUSE_MAX_MAP_LEN) + mapLen = EFUSE_MAX_MAP_LEN; + + if (efuse->file_status == EFUSE_FILE_LOADED) { + RTW_PRINT_SEL(m, "File eFuse Map loaded! file path:%s\nDriver eFuse Map From File\n", EFUSE_MAP_PATH); + if (efuse->is_autoload_fail) + RTW_PRINT_SEL(m, "File Autoload fail!!!\n"); + } else if (efuse->file_status == EFUSE_FILE_FAILED) { + RTW_PRINT_SEL(m, "Open File eFuse Map Fail ! file path:%s\nDriver eFuse Map From Default\n", EFUSE_MAP_PATH); + if (efuse->is_autoload_fail) + RTW_PRINT_SEL(m, "HW Autoload fail!!!\n"); + } else { + RTW_PRINT_SEL(m, "Driver eFuse Map From HW\n"); + if (efuse->is_autoload_fail) + RTW_PRINT_SEL(m, "HW Autoload fail!!!\n"); + } + for (i = 0; i < mapLen; i += 16) { + RTW_PRINT_SEL(m, "0x%02x\t", i); + for (j = 0; j < 8; j++) + RTW_PRINT_SEL(m, "%02X ", efuse->data[i + j]); + RTW_PRINT_SEL(m, "\t"); + for (; j < 16; j++) + RTW_PRINT_SEL(m, "%02X ", efuse->data[i + j]); + RTW_PRINT_SEL(m, "\n"); + } + + if (rtw_efuse_map_read(padapter, 0, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL) { + RTW_PRINT_SEL(m, "WARN - Read Realmap Failed\n"); + return 0; + } + + RTW_PRINT_SEL(m, "\n"); + RTW_PRINT_SEL(m, "HW eFuse Map\n"); + for (i = 0; i < mapLen; i += 16) { + RTW_PRINT_SEL(m, "0x%02x\t", i); + for (j = 0; j < 8; j++) + RTW_PRINT_SEL(m, "%02X ", pEfuseHal->fakeEfuseInitMap[i + j]); + RTW_PRINT_SEL(m, "\t"); + for (; j < 16; j++) + RTW_PRINT_SEL(m, "%02X ", pEfuseHal->fakeEfuseInitMap[i + j]); + RTW_PRINT_SEL(m, "\n"); + } + +#endif + return 0; +} + +ssize_t proc_set_efuse_map(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ +#if 0 + char tmp[256] = {0}; + u32 addr, cnts; + u8 efuse_data; + + int jj, kk; + + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); + + if (count < 3) { + RTW_INFO("argument size is less than 3\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%x %d %x", &addr, &cnts, &efuse_data); + + if (num != 3) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } + } + if (rtw_efuse_map_write(padapter, addr, cnts, &efuse_data) == _FAIL) + RTW_INFO("WARN - rtw_efuse_map_write error!!\n"); +#endif + return count; +} + +#ifdef CONFIG_IEEE80211W +ssize_t proc_set_tx_sa_query(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct sta_priv *pstapriv = &padapter->stapriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + /* macid_ctl move to phl */ + /* struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); */ + struct sta_info *psta; + _list *plist, *phead; + char tmp[16]; + u8 mac_addr[NUM_STA][ETH_ALEN]; + u32 key_type; + u8 index; + void *phl = GET_PHL_INFO(dvobj); + u16 macid_num = rtw_phl_get_macid_max_num(phl); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + + if (count > 2) { + RTW_INFO("argument size is more than 2\n"); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%x", &key_type); + + if (num != 1) { + RTW_INFO("invalid read_reg parameter!\n"); + return count; + } + RTW_INFO("0: set sa query request , key_type=%d\n", key_type); + } else { + return -EFAULT; + } + + if (MLME_IS_STA(padapter) + && (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) && SEC_IS_BIP_KEY_INSTALLED(&padapter_link->securitypriv) == _TRUE) { + RTW_INFO("STA:"MAC_FMT"\n", MAC_ARG(get_my_bssid(&(pmlmeinfo->network)))); + /* TX unicast sa_query to AP */ + issue_action_SA_Query(padapter, padapter_link, + get_my_bssid(&(pmlmeinfo->network)), 0, 0, (u8)key_type); + } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE && SEC_IS_BIP_KEY_INSTALLED(&padapter_link->securitypriv) == _TRUE) { + /* TX unicast sa_query to every client STA */ + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (index = 0; index < NUM_STA; index++) { + psta = NULL; + + phead = &(pstapriv->sta_hash[index]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + _rtw_memcpy(&mac_addr[psta->phl_sta->macid][0], psta->phl_sta->mac_addr, ETH_ALEN); + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + + for (index = 0; index < macid_num && index < NUM_STA; index++) { + if (rtw_phl_macid_is_used(phl, index) && !rtw_phl_macid_is_bmc(phl, index)) { + if (!_rtw_memcmp(get_my_bssid(&(pmlmeinfo->network)), &mac_addr[index][0], ETH_ALEN) + && !IS_MCAST(&mac_addr[index][0])) { + issue_action_SA_Query(padapter, padapter_link, + &mac_addr[index][0], 0, 0, (u8)key_type); + RTW_INFO("STA[%u]:"MAC_FMT"\n", index , MAC_ARG(&mac_addr[index][0])); + } + } + } + } + + return count; +} + +int proc_get_tx_sa_query(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "%s\n", __func__); + return 0; +} + +ssize_t proc_set_tx_deauth(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct sta_priv *pstapriv = &padapter->stapriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + /* macid_ctl move to phl */ + /* struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); */ + struct sta_info *psta; + _list *plist, *phead; + char tmp[16]; + u8 mac_addr[NUM_STA][ETH_ALEN]; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u32 key_type = 0; + u8 index; + void *phl = GET_PHL_INFO(dvobj); + u16 macid_num = rtw_phl_get_macid_max_num(phl); + + + if (count > 2) { + RTW_INFO("argument size is more than 2\n"); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%x", &key_type); + + if (num != 1) { + RTW_INFO("invalid read_reg parameter!\n"); + return count; + } + RTW_INFO("key_type=%d\n", key_type); + } else { + return -EFAULT; + } + if (key_type > 4) + return count; + + if (MLME_IS_STA(padapter) + && (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)) { + if (key_type == 3) /* key_type 3 only for AP mode */ + return count; + /* TX unicast deauth to AP */ + issue_deauth_11w(padapter, get_my_bssid(&(pmlmeinfo->network)), 0, (u8)key_type); + } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) { + u8 updated = _FALSE; + + if (key_type == 3) + issue_deauth_11w(padapter, bc_addr, 0, IEEE80211W_RIGHT_KEY); + + /* TX unicast deauth to every client STA */ + _rtw_spinlock_bh(&pstapriv->sta_hash_lock); + for (index = 0; index < NUM_STA; index++) { + psta = NULL; + + phead = &(pstapriv->sta_hash[index]); + plist = get_next(phead); + + while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { + psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); + plist = get_next(plist); + _rtw_memcpy(&mac_addr[psta->phl_sta->macid][0], psta->phl_sta->mac_addr, ETH_ALEN); + } + } + _rtw_spinunlock_bh(&pstapriv->sta_hash_lock); + + for (index = 0; index < macid_num && index < NUM_STA; index++) { + if (rtw_phl_macid_is_used(phl, index) && !rtw_phl_macid_is_bmc(phl, index)) { + if (!_rtw_memcmp(get_my_bssid(&(pmlmeinfo->network)), &mac_addr[index][0], ETH_ALEN)) { + if (key_type != 3) + issue_deauth_11w(padapter, &mac_addr[index][0], 0, (u8)key_type); + + psta = rtw_get_stainfo(pstapriv, &mac_addr[index][0]); + if (psta && key_type != IEEE80211W_WRONG_KEY && key_type != IEEE80211W_NO_KEY) { + rtw_stapriv_asoc_list_lock(pstapriv); + if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) { + rtw_stapriv_asoc_list_del(pstapriv, psta); + updated |= ap_free_sta(padapter, psta, _FALSE, 0, WLAN_REASON_PREV_AUTH_NOT_VALID, _TRUE); + + } + rtw_stapriv_asoc_list_unlock(pstapriv); + } + + RTW_INFO("STA[%u]:"MAC_FMT"\n", index , MAC_ARG(&mac_addr[index][0])); + } + } + } + + associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL); + } + + return count; +} + +int proc_get_tx_deauth(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "%s\n", __func__); + return 0; +} + +ssize_t proc_set_tx_auth(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct sta_priv *pstapriv = &padapter->stapriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + /* macid_ctl move to phl */ + /*struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); */ + struct sta_info *psta; + _list *plist, *phead; + char tmp[16]; + u8 mac_addr[NUM_STA][ETH_ALEN]; + u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u32 tx_auth = 0; + u8 index; + + + if (count > 2) { + RTW_INFO("argument size is more than 2\n"); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%x", &tx_auth); + + if (num != 1) { + RTW_INFO("invalid read_reg parameter!\n"); + return count; + } + RTW_INFO("1: setnd auth, 2: send assoc request. tx_auth=%d\n", tx_auth); + } + + if (MLME_IS_STA(padapter) + && (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)) { + if (tx_auth == 1) { + /* TX unicast auth to AP */ + issue_auth(padapter, NULL, 0); + } else if (tx_auth == 2) { + /* TX unicast auth to AP */ + issue_assocreq(padapter); + } + } + + return count; +} + +int proc_get_tx_auth(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + RTW_PRINT_SEL(m, "%s\n", __func__); + return 0; +} +#endif /* CONFIG_IEEE80211W */ + +int proc_get_ack_timeout(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + u8 ack_timeout_val = 0; + u8 ack_timeout_val_cck = 0; + + rtw_hal_get_hwreg(padapter, HW_VAR_ACKTO, &ack_timeout_val); + rtw_hal_get_hwreg(padapter, HW_VAR_ACKTO_CCK, &ack_timeout_val_cck); + + RTW_PRINT_SEL(m, "Current CCK packet ACK Timeout = %d us (0x%x).\n", ack_timeout_val_cck, ack_timeout_val_cck); + RTW_PRINT_SEL(m, "Current non-CCK packet ACK Timeout = %d us (0x%x).\n", ack_timeout_val, ack_timeout_val); + return 0; +} + +ssize_t proc_set_ack_timeout(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 tmp_v1 = 0, tmp_v2 = 0; + u8 ack_to_ms = 0, ack_to_cck_ms = 0; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%u %u", &tmp_v1, &tmp_v2); + + if (num < 1) { + RTW_INFO(FUNC_ADPT_FMT ": input parameters < 1\n", FUNC_ADPT_ARG(padapter)); + return -EINVAL; + } + + if (tmp_v1) { + ack_to_ms = (u8)tmp_v1; + rtw_hal_set_hwreg(padapter, HW_VAR_ACKTO, &ack_to_ms); + } + + if (tmp_v2) { + ack_to_cck_ms = (u8)tmp_v2; + rtw_hal_set_hwreg(padapter, HW_VAR_ACKTO_CCK, &ack_to_cck_ms); + } + /* This register sets the Ack time out value after Tx unicast packet. It is in units of us. */ + /* This register sets the Ack time out value after Tx unicast CCK packet. It is in units of us. */ + RTW_INFO("Set CCK packet ACK Timeout to %d us.\n", ack_to_cck_ms); + RTW_INFO("Set non-CCK packet ACK Timeout to %d us.\n", ack_to_ms); + } + + return count; +} + +int proc_get_fw_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + void *phl = GET_PHL_INFO(adapter_to_dvobj(adapter)); + char fw_ver[20] = {0}; + enum rtw_fw_status fw_sts; + + fw_sts = rtw_phl_get_fw_status(phl); + + if (fw_sts == RTW_FW_STATUS_NOFW) { + RTW_PRINT_SEL(m, "FW not ready\n"); + } else { + rtw_phl_get_fw_ver(GET_PHL_INFO(adapter_to_dvobj(adapter)), fw_ver, 20); + RTW_PRINT_SEL(m, "FW VER %s\n", fw_ver); + } + + return 0; +} + +ssize_t proc_set_fw_offload(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + +#if 0 /*GEORGIA_TODO_FIXIT*/ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + _adapter *pri_adapter = GET_PRIMARY_ADAPTER(adapter); + HAL_DATA_TYPE *hal = GET_PHL_COM(adapter_to_dvobj(adapter)); + char tmp[32]; + u32 iqk_offload_enable = 0, ch_switch_offload_enable = 0; + + if (buffer == NULL) { + RTW_INFO("input buffer is NULL!\n"); + return -EFAULT; + } + + if (count < 1) { + RTW_INFO("input length is 0!\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + RTW_INFO("input length is too large\n"); + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%d %d", &iqk_offload_enable, &ch_switch_offload_enable); + + if (num < 2) { + RTW_INFO("input parameters < 1\n"); + return -EINVAL; + } + + if (hal->RegIQKFWOffload != iqk_offload_enable) { + hal->RegIQKFWOffload = iqk_offload_enable; + rtw_run_in_thread_cmd(pri_adapter, ((void *)(rtw_hal_update_iqk_fw_offload_cap)), pri_adapter); + } + + if (hal->ch_switch_offload != ch_switch_offload_enable) + hal->ch_switch_offload = ch_switch_offload_enable; + } + + return count; +#endif + return 0; +} + +int proc_get_fw_offload(struct seq_file *m, void *v) +{ +#if 0 /*GEORGIA_TODO_FIXIT*/ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + HAL_DATA_TYPE *hal = GET_PHL_COM(adapter_to_dvobj(adapter)); + + + RTW_PRINT_SEL(m, "IQK FW offload:%s\n", hal->RegIQKFWOffload?"enable":"disable"); + RTW_PRINT_SEL(m, "Channel switch FW offload:%s\n", hal->ch_switch_offload?"enable":"disable"); +#endif + return 0; +} + +#ifdef CONFIG_CTRL_TXSS_BY_TP +ssize_t proc_set_txss_tp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + char tmp[32]; + u32 enable = 0; + u32 txss_tx_tp = 0; + int txss_chk_cnt = 0; + + if (buffer == NULL) { + RTW_INFO("input buffer is NULL!\n"); + return -EFAULT; + } + + if (count < 1) { + RTW_INFO("input length is 0!\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + RTW_INFO("input length is too large\n"); + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%u %u %d", + &enable, &txss_tx_tp, &txss_chk_cnt); + + if (num < 1) { + RTW_INFO("input parameters < 1\n"); + return -EINVAL; + } + pmlmeext->txss_ctrl_en = enable; + + if (txss_tx_tp) + pmlmeext->txss_tp_th = txss_tx_tp; + if (txss_chk_cnt) + pmlmeext->txss_tp_chk_cnt = txss_chk_cnt; + + RTW_INFO("%s txss_ctl_en :%s , txss_tp_th:%d, tp_chk_cnt:%d\n", + __func__, pmlmeext->txss_tp_th ? "Y" : "N", + pmlmeext->txss_tp_th, pmlmeext->txss_tp_chk_cnt); + + } + + return count; +} + +int proc_get_txss_tp(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + RTW_PRINT_SEL(m, "TXSS Control - %s\n", pmlmeext->txss_ctrl_en ? "enable" : "disable"); + RTW_PRINT_SEL(m, "TXSS Tx TP TH - %d\n", pmlmeext->txss_tp_th); + RTW_PRINT_SEL(m, "TXSS check cnt - %d\n", pmlmeext->txss_tp_chk_cnt); + + return 0; +} +#ifdef DBG_CTRL_TXSS +ssize_t proc_set_txss_ctrl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + char tmp[32]; + u32 tx_1ss = 0; + + if (buffer == NULL) { + RTW_INFO("input buffer is NULL!\n"); + return -EFAULT; + } + + if (count < 1) { + RTW_INFO("input length is 0!\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + RTW_INFO("input length is too large\n"); + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%u", &tx_1ss); + + if (num < 1) { + RTW_INFO("input parameters < 1\n"); + return -EINVAL; + } + + pmlmeext->txss_ctrl_en = _FALSE; + + dbg_ctrl_txss(adapter, tx_1ss); + + RTW_INFO("%s set tx to 1ss :%s\n", __func__, tx_1ss ? "Y" : "N"); + } + + return count; +} + +int proc_get_txss_ctrl(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + RTW_PRINT_SEL(m, "TXSS 1ss - %s\n", pmlmeext->txss_1ss ? "Y" : "N"); + + return 0; +} +#endif +#endif + +#ifdef CONFIG_DBG_RF_CAL +int proc_get_iqk_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + return 0; +} + +ssize_t proc_set_iqk(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 recovery, clear, segment; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d %d %d", &recovery, &clear, &segment); + + if (num != 3) { + RTW_INFO("Invalid format\n"); + return count; + } + + rtw_hal_iqk_test(padapter, recovery, clear, segment); + } + + return count; + +} + +int proc_get_lck_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + return 0; +} + +ssize_t proc_set_lck(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 trigger; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%d", &trigger); + + if (num != 1) { + RTW_INFO("Invalid format\n"); + return count; + } + + rtw_hal_lck_test(padapter); + } + + return count; +} +#endif /* CONFIG_DBG_RF_CAL */ + +#ifdef CONFIG_SUPPORT_STATIC_SMPS +ssize_t proc_set_smps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + char tmp[32]; + u32 enable = 0; + u32 smps_en, smps_tx_tp = 0, smps_rx_tp = 0; + u32 smps_test = 0, smps_test_en = 0; + + if (buffer == NULL) { + RTW_INFO("input buffer is NULL!\n"); + return -EFAULT; + } + + if (count < 1) { + RTW_INFO("input length is 0!\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + RTW_INFO("input length is too large\n"); + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%u %u %u %u %u", &smps_en, &smps_tx_tp, &smps_rx_tp, + &smps_test, &smps_test_en); + + if (num < 1) { + RTW_INFO("input parameters < 1\n"); + return -EINVAL; + } + + pmlmeext->ssmps_en = smps_en; + if (smps_tx_tp) { + pmlmeext->ssmps_tx_tp_th= smps_tx_tp; + pmlmeext->ssmps_rx_tp_th= smps_tx_tp; + } + if (smps_rx_tp) + pmlmeext->ssmps_rx_tp_th = smps_rx_tp; + + #ifdef DBG_STATIC_SMPS + if (num > 3) { + pmlmeext->ssmps_test = smps_test; + pmlmeext->ssmps_test_en = smps_test_en; + } + #endif + RTW_INFO("SM PS : %s tx_tp_th:%d, rx_tp_th:%d\n", + (smps_en) ? "Enable" : "Disable", + pmlmeext->ssmps_tx_tp_th, + pmlmeext->ssmps_rx_tp_th); + #ifdef DBG_STATIC_SMPS + RTW_INFO("SM PS : %s ssmps_test_en:%d\n", + (smps_test) ? "Enable" : "Disable", + pmlmeext->ssmps_test_en); + #endif + } + + return count; +} + +int proc_get_smps(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + + RTW_PRINT_SEL(m, "Static SMPS %s\n", pmlmeext->ssmps_en ? "enable" : "disable"); + RTW_PRINT_SEL(m, "Tx TP TH %d\n", pmlmeext->ssmps_tx_tp_th); + RTW_PRINT_SEL(m, "Rx TP TH %d\n", pmlmeext->ssmps_rx_tp_th); + #ifdef DBG_STATIC_SMPS + RTW_PRINT_SEL(m, "test %d, test_en:%d\n", pmlmeext->ssmps_test, pmlmeext->ssmps_test_en); + #endif + return 0; +} +#endif /*CONFIG_SUPPORT_STATIC_SMPS*/ + +#ifdef RTW_DETECT_HANG +ssize_t proc_set_hang_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = padapter->dvobj; + struct debug_priv *pdbgpriv = &pdvobjpriv->drv_dbg; + struct hang_info *phang_info = &pdbgpriv->dbg_hang_info; + char tmp[32] = {0}; + int level = 0; + int stop = 0; + int num = 0; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + num = sscanf(tmp, "%d %d", &level, &stop); + if (num == 1) { + RTW_INFO("level configuration is not available now\n"); + } else if (num == 2) { + phang_info->is_stop = stop; + RTW_INFO("level=%d, stop=%d\n", level, + phang_info->is_stop); + } else { + RTW_INFO("argument number is wrong\n"); + return -EFAULT; + } + } + + return count; +} + +int proc_get_hang_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *pdvobjpriv = padapter->dvobj; + struct debug_priv *pdbgpriv = &pdvobjpriv->drv_dbg; + struct hang_info *phang_info = &pdbgpriv->dbg_hang_info; + struct fw_hang_info *pfw_hang_info = &phang_info->dbg_fw_hang_info; + struct rxff_hang_info *prxff_hang_info = &phang_info->dbg_rxff_hang_info; + u8 is_hang = _FALSE; + u8 fw_gone = _FALSE; + + if (phang_info->is_stop) { + RTW_PRINT_SEL(m, "This function is disabled\n"); + goto exit; + } + + if (dev_is_surprise_removed(pdvobjpriv)) + is_hang = _TRUE; + + if (pfw_hang_info->dbg_is_fw_gone && + rtw_hw_get_init_completed(pdvobjpriv) && + !padapter->registrypriv.mp_mode) + fw_gone = _TRUE; + + if (pfw_hang_info->dbg_is_fw_hang || is_hang || fw_gone || + prxff_hang_info->dbg_is_rxff_hang) { + RTW_PRINT_SEL(m, "1\n"); + + if (pfw_hang_info->dbg_is_fw_hang) + RTW_PRINT_SEL(m, "FW hang\n"); + if (prxff_hang_info->dbg_is_rxff_hang) + RTW_PRINT_SEL(m, "RXFF hang\n"); + if (is_hang) + RTW_PRINT_SEL(m, "surprise remove\n"); + if (fw_gone) + RTW_PRINT_SEL(m, "FW gone\n"); + } else { + RTW_PRINT_SEL(m, "0\n"); + } + + RTW_PRINT_SEL(m, "Enter cnt = %d\n", phang_info->enter_cnt); +exit: + return 0; +} +#endif /* RTW_DETECT_HANG */ + +int proc_get_disconnect_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + char *disconnect_reason; + char *illegal_beacon_reason; + + if (pmlmeinfo) { + switch (pmlmeinfo->disconnect_code) { + case DISCONNECTION_NOT_YET_OCCUR: + disconnect_reason = "Disconnection has not yet occurred."; + break; + case DISCONNECTION_BY_SYSTEM_DUE_TO_HIGH_LAYER_COMMAND: + disconnect_reason = "System requests to disconnect by command."; + break; + case DISCONNECTION_BY_SYSTEM_DUE_TO_NET_DEVICE_DOWN: + disconnect_reason = "System makes net_device down to cause disconnection."; + break; + case DISCONNECTION_BY_SYSTEM_DUE_TO_SYSTEM_IN_SUSPEND: + disconnect_reason = "System enters suspend state to cause disconnection."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_CONNECTION_EXIST: + disconnect_reason = "The connection is exist so it triggers disconnection when joinbss."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_EACH_IFACE_CHBW_NOT_SYNC: + disconnect_reason = "Multiple interfaces do not synchronize channel and bandwidth when joinbss."; + break; + /* + case DISCONNECTION_BY_DRIVER_DUE_TO_DFS_DETECTION: + disconnect_reason = "DFS Slave mechanism detects radar to cause disconnection."; + break; + */ + case DISCONNECTION_BY_DRIVER_DUE_TO_IOCTL_DBG_PORT: + disconnect_reason = "Using ioctl dbg port command to accomplish disconnection."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_AP_BEACON_CHANGED: + disconnect_reason = "AP's beacon content was changed to cause disconnection."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_KEEPALIVE_TIMEOUT: + disconnect_reason = "Maybe AP disappears to trigger station keepalive timeout and connection break."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_LAYER2_ROAMING_TERMINATE: + disconnect_reason = "Layer2 roaming terminated to trigger disconnection."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_JOINBSS_TIMEOUT: + disconnect_reason = "Station joinbss process is timeout to trigger disconnection."; + break; + case DISCONNECTION_BY_FW_DUE_TO_FW_DECISION_IN_WOW_RESUME: + disconnect_reason = "FW decides to disconnect in WOW resume flow."; + break; + case DISCONNECTION_BY_AP_DUE_TO_RECEIVE_DISASSOC_IN_WOW_RESUME: + disconnect_reason = "Receiving Disassociation frame from AP to cause disconnection in WOW resume flow."; + break; + case DISCONNECTION_BY_AP_DUE_TO_RECEIVE_DEAUTH_IN_WOW_RESUME: + disconnect_reason = "Receiving Deauth frame from AP to cause disconnection in WOW resume flow."; + break; + case DISCONNECTION_BY_AP_DUE_TO_RECEIVE_DEAUTH: + disconnect_reason = "Receiving Deauth frame from AP to cause disconnection."; + break; + case DISCONNECTION_BY_AP_DUE_TO_RECEIVE_DISASSOC: + disconnect_reason = "Receiving Disassociation frame from AP to cause disconnection."; + break; + /* + case DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_CSA_NON_DFS: + disconnect_reason = "Disconnection due to AP switched to unsupported channel."; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_CSA_DFS: + disconnect_reason = "Disconnection due to AP switched to unsupported DFS channel."; + break; + */ + case DISCONNECTION_BY_DRIVER_DUE_TO_RECEIVE_INVALID_CSA: + disconnect_reason = "Disconnection due to received invalid CSA IE"; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_JOIN_WRONG_CHANNEL: + disconnect_reason = "Disconnection due to joined wrong channel"; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_FT: + disconnect_reason = "Disconnection due to FT"; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_ROAMING: + disconnect_reason = "Disconnection due to roaming"; + break; + case DISCONNECTION_BY_DRIVER_DUE_TO_SA_QUERY_TIMEOUT: + disconnect_reason = "Disconnection due to SA Query timeout"; + break; + default: + disconnect_reason = "Unspecified"; + break; + } + + RTW_PRINT_SEL(m, "occurred disconnection time = %d\n", pmlmeinfo->disconnect_occurred_time); + RTW_PRINT_SEL(m, "disconnect code = %d\n", pmlmeinfo->disconnect_code); + RTW_PRINT_SEL(m, "last disconnect reason: %s\n", disconnect_reason); + RTW_PRINT_SEL(m, "beacon code: %d\n", pmlmeinfo->illegal_beacon_code); + if (pmlmeinfo->disconnect_code == DISCONNECTION_BY_DRIVER_DUE_TO_AP_BEACON_CHANGED) { + if(pmlmeinfo->illegal_beacon_code & SSID_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The SSID of beacon is changed.\n"); + if(pmlmeinfo->illegal_beacon_code & SSID_LENGTH_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The SSID length of beacon is changed.\n"); + if(pmlmeinfo->illegal_beacon_code & BEACON_CHANNEL_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The Beacon channel of beacon is changed.\n"); + if(pmlmeinfo->illegal_beacon_code & ENCRYPT_PROTOCOL_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The Encrypt protocol of beacon is changed.\n"); + if(pmlmeinfo->illegal_beacon_code & PAIRWISE_CIPHER_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The Pairwise cipheris of beacon changed.\n"); + if(pmlmeinfo->illegal_beacon_code & GROUP_CIPHER_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The Group cipher of beacon is changed.\n"); + if(pmlmeinfo->illegal_beacon_code & IS_8021X_CHANGED) + RTW_PRINT_SEL(m, "illegal beacon reason: The 802.1x of beacon is changed.\n"); + } else { + RTW_PRINT_SEL(m, "illegal beacon reason: NA.\n"); + } + + RTW_PRINT_SEL(m, "Wi-Fi reason code: %d\n", + pmlmeinfo->disconnect_code ? pmlmeinfo->wifi_reason_code : 0); + } + + return 0; +} + +ssize_t proc_set_disconnect_info(struct file *file, const char __user *buffer, + size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + char tmp[32]; + u8 clear; + + if (!pmlmeinfo) + return -EPERM; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = sscanf(tmp, "%hhd", &clear); + if (num == 1 && clear == 0) { + pmlmeinfo->disconnect_occurred_time = 0; + pmlmeinfo->disconnect_code = DISCONNECTION_NOT_YET_OCCUR; + pmlmeinfo->illegal_beacon_code = 0; + } + } + + return count; +} + +int proc_get_chan(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct _ADAPTER_LINK *padapter_link; + u8 lidx; + + for (lidx = 0; lidx < padapter->phl_role->rlink_num; lidx++) { + padapter_link = GET_LINK(padapter, lidx); + RTW_PRINT_SEL(m, "ch=%d, ch_offset=%d, bw=%d\n", + rtw_get_oper_ch(padapter, padapter_link), + rtw_get_oper_choffset(padapter, padapter_link), + rtw_get_oper_bw(padapter, padapter_link)); + + RTW_PRINT_SEL(m, "PHL rlink %d ch=%d\n", lidx, + rtw_phl_get_cur_ch(padapter->phl_role, + padapter_link->wrlink)); + } + return 0; +} + +ssize_t proc_set_chan(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + u8 target_band, target_ch, target_offset, target_bw; +#ifdef DBG_CONFIG_CMD_DISP + u8 cmd_type = 0xFF; + u8 cmd_to = 0; +#endif + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (count < 3) { + RTW_INFO("argument size is less than 3\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = 0; +#ifdef DBG_CONFIG_CMD_DISP + num = sscanf(tmp, "%hhu %hhu %hhu %hhu %hhu %hhu", + &target_band, &target_ch, &target_offset, &target_bw, + &cmd_type, &cmd_to); + if (num != 6) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } + + padapter->cmd_type = cmd_type; + padapter->cmd_timeout = cmd_to; +#else + num = sscanf(tmp, "%hhu %hhu %hhu %hhu", + &target_band, &target_ch, &target_offset, &target_bw); + if (num != 4) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } +#endif + set_bch_bwmode(padapter, padapter_link, target_band, target_ch, + target_offset, target_bw, RFK_TYPE_FORCE_NOT_DO); + } + + return count; +} + +int proc_get_mr_test(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + + return 0; +} + +ssize_t proc_set_mr_test(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + char tmp[32]; + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + u8 mode, param, param_1, param_2, param_3; + bool show_caller; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (count < 2) { + RTW_INFO("argument size is less than 3\n"); + return -EFAULT; + } + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + int num = 0; + + num = sscanf(tmp, "%hhu %hhu %hhu %hhu %hhu", &mode, ¶m, ¶m_1, ¶m_2, ¶m_3); + if (num < 2) { + RTW_INFO("invalid write_reg parameter!\n"); + return count; + } +#ifdef PHL_MR_PROC_CMD + if (mode == 1) { + show_caller = (param) ? _TRUE : _FALSE; + rtw_phl_mr_dump_info(dvobj->phl, show_caller); + } + else if (mode == 2) { + show_caller = (param) ? _TRUE : _FALSE; + rtw_phl_mr_dump_band_ctl(dvobj->phl, show_caller); + } + else if (mode == 3) { + if (param == 1) + rtw_phl_mr_dump_mac_addr(dvobj->phl, padapter->phl_role); + else if (param == 2) + rtw_phl_mr_buddy_dump_mac_addr(dvobj->phl, padapter->phl_role); + else if (param == 3) + rtw_mi_dump_mac_addr(padapter); + } + else if (mode == 4) { + show_caller = (param) ? _TRUE : _FALSE; + rtw_phl_sta_dump_info(dvobj->phl, show_caller, padapter->phl_role, param_1); + } + else if (mode == 5 || mode == 6 || mode == 7 || mode == 8 || mode == 9) { + u8 test_mode = 0;/*0-chk, 1-add, 2-del*/ + struct rtw_chan_def new_chdef = {0}; + struct rtw_mr_chctx_info mr_cc_info = {0}; + bool rst; + + if (mode == 5) + test_mode = 0; + else if (mode == 6) + test_mode = 1; + else if (mode == 7) + test_mode = 2; + else if (mode == 8) + test_mode = 3; + else if (mode == 9) + test_mode = 4; + new_chdef.band = param; + new_chdef.chan = param_1; + new_chdef.bw = param_2; + new_chdef.offset = param_3; + + rst = rtw_phl_chanctx_test(dvobj->phl, padapter->phl_role, padapter_link->wrlink, + test_mode, &new_chdef, &mr_cc_info); + RTW_INFO("%s s_band:%d,s_ch:%d,s_bw:%d,s_offset:%d\n", + __func__, param, param_1, param_2, param_3); + } + else if (mode == 10) { + u8 new_port = param; + u8 org_port = padapter_link->wrlink->hw_port; + + rtw_phl_wifi_role_realloc_port(dvobj->phl, padapter->phl_role, padapter_link->wrlink, new_port); + RTW_INFO("%s realloc port from %d to %d\n", + __func__, org_port, new_port); + } + else if (mode == 11) { + rtw_phl_get_addr_cam(dvobj->phl, param, NULL, 0); + } + else if (mode == 12) { + struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *psta; + + psta = rtw_get_stainfo(pstapriv, get_link_bssid(pmlmepriv)); + if (psta) { + if (param == 1) + rtw_ssmps_enter(padapter, psta); + else if (param == 0) + rtw_ssmps_leave(padapter, psta); + } + } + else if (mode == 13) { + #ifdef CONFIG_DBCC_SUPPORT + dvobj->dis_dbcc_scan = param; + RTW_INFO("%s dis_dbcc_scan %d\n", + __func__, dvobj->dis_dbcc_scan); + #endif + } + #ifdef CONFIG_DBCC_P2P_BG_LISTEN + else if (mode == 14) { + /*mode + param - 0: rtw_phl_cmd_dbcc_enable, 1 :rtw_phl_cmd_dbcc_disable + param_1 - iface_id + param_2 - cmd_type : 0:PHL_CMD_DIRECTLY,1:PHL_CMD_NO_WAIT,2:PHL_CMD_WAIT*/ + + _adapter *target_adp = NULL; + struct _ADAPTER_LINK *target_alink; + struct rtw_wifi_role_link_t *target_rlink; + + if (param == 0) + RTW_INFO("%s dbcc enable cmd test - iface_id %d cmd_type:%d\n", + __func__, param_1, param_2); + else /* if (param == 1)*/ + RTW_INFO("%s dbcc disable cmd test - iface_id %d cmd_type:%d\n", + __func__, param_1, param_2); + + target_adp = dvobj->padapters[param_1]; + target_alink = GET_PRIMARY_LINK(target_adp); + target_rlink = target_alink->wrlink; + + RTW_INFO(FUNC_ADPT_FMT" at HW_B(%d)\n", + FUNC_ADPT_ARG(target_adp), target_rlink->hw_band); + if (param == 0) { + rtw_phl_cmd_dbcc_enable(target_adp->phl_role, + target_rlink->hw_band, + param_2, 0); + } else { + rtw_phl_cmd_dbcc_disable(target_adp->phl_role, + target_rlink->hw_band, + param_2, 0); + } + } + #endif +#endif + } + + return count; +} + +int proc_get_deny_legacy(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct registry_priv *pregpriv = &padapter->registrypriv; + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + + if (pregpriv) + RTW_PRINT_SEL(m, "deny_legacy = 0x%x\n", pregpriv->deny_legacy); + + if (pmlmeext) + RTW_PRINT_SEL(m, "cur_wireless_mode = 0x%x\n", pmlmeext->cur_wireless_mode); + + return 0; +} + +ssize_t proc_set_deny_legacy(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u8 legacy; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu ", &legacy); + + if (num == 1 && pregpriv) { + pregpriv->deny_legacy = legacy; + RTW_INFO("deny_legacy=%d\n", legacy); + } + } + + return count; +} + +#ifdef CONFIG_80211AX_HE +int proc_get_tx_ul_mu_disable(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv); + struct rtw_he_actrl_om *cur_om_info = &(pmlmepriv->hepriv.om_info); + + RTW_PRINT_SEL(m, "OM ul_mu_disable = %s\n", cur_om_info->om_actrl_ele.ul_mu_disable ? "True" : "False"); + return 0; +} + +ssize_t proc_set_tx_ul_mu_disable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct rtw_he_actrl_om om_info = {0}; + u8 om_mask = 0; + char tmp[32]; + u8 ul_mu_disable; + /* ToDo CONFIG_RTW_MLD: [currently primary link only] */ + struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter); + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu ", &ul_mu_disable); + + if (num == 1) { + om_mask = om_mask | OM_UL_MU_DIS; + /*om_info.actrl_om_normal_tx = _TRUE;*/ + /*om_info.actrl_om_normal_tx_cnt = 8;*/ + if (ul_mu_disable == _TRUE) + om_info.om_actrl_ele.ul_mu_disable = _TRUE; + else + om_info.om_actrl_ele.ul_mu_disable = _FALSE; + +#if 0 + /*om others control setting*/ + om_mask = om_mask | OM_RX_NSS; + om_info.om_actrl_ele.rx_nss = 1; + om_mask = om_mask | OM_CH_BW; + om_info.om_actrl_ele.channel_width= 2; + om_mask = om_mask | OM_TX_NSTS; + om_info.om_actrl_ele.tx_nsts= 2; + om_mask = om_mask | OM_ER_SU_DIS; + om_info.om_actrl_ele.er_su_disable = _TRUE; + om_mask = om_mask | OM_DL_MU_RR; + om_info.om_actrl_ele.dl_mu_mimo_rr= _TRUE; + om_mask = om_mask | OM_UL_MU_DATA_DIS; + om_info.om_actrl_ele.ul_mu_data_disable= _TRUE; +#endif + rtw_he_set_om_info(padapter, padapter_link, om_mask, &om_info); + issue_qos_nulldata(padapter, padapter_link, + NULL, 0, 0, 3, 10, _TRUE); + } + } + + return count; +} +#endif + +#ifdef CONFIG_RTW_CSI_CHANNEL_INFO +int proc_get_csi_ch_info(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *d = padapter->dvobj; + void *phl = GET_PHL_INFO(d); + struct csi_header_t csi_header; + u8 buff[512] = {0}; + u32 buf_len; + enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE; + + _rtw_memset(&csi_header, 0, sizeof(csi_header)); + status = rtw_phl_query_chan_info(phl, 512, buff, &buf_len, &csi_header); + if (status == RTW_PHL_STATUS_SUCCESS) { + RTW_DUMP_SEL(m, buff, buf_len); + RTW_PRINT_SEL(m, "rxsc=%d\n", csi_header.rxsc); + RTW_PRINT_SEL(m, "nc=%d\n", csi_header.nc); + RTW_PRINT_SEL(m, "nr=%d\n", csi_header.nr); + RTW_PRINT_SEL(m, "avg_idle_noise_pwr=%d\n", csi_header.avg_idle_noise_pwr); + RTW_PRINT_SEL(m, "csi_data_length=%d\n", csi_header.csi_data_length); + RTW_PRINT_SEL(m, "csi_valid=%d\n", csi_header.csi_valid); + RTW_PRINT_SEL(m, "evm[0]=%d\n", csi_header.evm[0]); + RTW_PRINT_SEL(m, "evm[1]=%d\n", csi_header.evm[1]); + RTW_PRINT_SEL(m, "rssi[0]=%d%%\n", csi_header.rssi[0] >> 1); + RTW_PRINT_SEL(m, "rssi[1]=%d%%\n", csi_header.rssi[1] >> 1); + RTW_PRINT_SEL(m, "timestamp=%d\n", csi_header.hw_assigned_timestamp); + RTW_PRINT_SEL(m, "rx_data_rate=%d\n", csi_header.rx_data_rate); + RTW_PRINT_SEL(m, "bandwidth=%d\n", csi_header.bandwidth); + } + return 0; +} + +ssize_t proc_set_csi_ch_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + struct dvobj_priv *d = adapter->dvobj; + void *phl = GET_PHL_INFO(d); + struct _ADAPTER_LINK *adapter_link = NULL; + struct rtw_wifi_role_t *wrole = NULL; + struct rtw_wifi_role_link_t *wrlink = NULL; + struct rtw_phl_stainfo_t *phl_sta = NULL; + struct rtw_chinfo_action_parm act_parm; + char tmp[32]; + u8 en, group_num, accuracy, mode, en_mode, period, addr[ETH_ALEN]; + int i, num; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + adapter_link = GET_PRIMARY_LINK(adapter); + if (adapter_link == NULL) { + RTW_ERR("adapter_link = NULL\n"); + rtw_warn_on(1); + return -EFAULT; + } + + wrole = adapter->phl_role; + if (wrole == NULL) { + RTW_ERR("wrole = NULL\n"); + rtw_warn_on(1); + return -EFAULT; + } + + wrlink = adapter_link->wrlink; + if (wrlink == NULL) { + RTW_ERR("wrlink = NULL\n"); + rtw_warn_on(1); + return -EFAULT; + } + + phl_sta = rtw_phl_get_stainfo_self(phl, wrlink); + if (phl_sta == NULL) { + RTW_ERR("phl_sta = NULL\n"); + rtw_warn_on(1); + return -EFAULT; + } + + RTW_INFO("sta mac addr: "MAC_FMT"\n", MAC_ARG(phl_sta->mac_addr)); + RTW_INFO("sta->wrole mac addr: "MAC_FMT"\n", MAC_ARG(phl_sta->wrole->mac_addr)); + RTW_INFO("sta->rlink mac addr: "MAC_FMT"\n", MAC_ARG(phl_sta->rlink->mac_addr)); + + _rtw_memset(&act_parm, 0, sizeof(struct rtw_chinfo_action_parm)); + + if (buffer && !copy_from_user(tmp, buffer, count)) { + num = sscanf(tmp, "%hhx %hhx %hhx %hhx %hhx %hhd %hhx %hhx %hhx %hhx %hhx %hhx", + &en, &group_num, &accuracy, &mode, &en_mode, &period, + addr, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5); + if ((num == 1) || (num == 6)) + goto csi_set_next; + + num = sscanf(tmp, "%hhx %hhx %hhx %hhx %hhx %hhd %hhx %hhx %hhx %hhx %hhx %hhx", + &en, &group_num, &accuracy, &mode, &en_mode, &period, + addr, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5); + if (num == 12) + goto csi_set_next; + + num = sscanf(tmp, "%hhx %hhx %hhx %hhx %hhx %hhx %hhx", + &en, addr, addr + 1, addr + 2, addr + 3, addr + 4, addr + 5); + if (num == 7) + goto csi_set_next; + +csi_set_next: + RTW_INFO("%s: arguments num=%d\n", __func__, num); + RTW_INFO("%s: client mac addr: "MAC_FMT"\n", __func__, MAC_ARG(addr)); + RTW_INFO("%s: wrole type = %d\n", __func__, wrole->type); + + /* + * num=1: for STA mode, default setting + * num=6: for STA mode, changed setting + * num=7: for softAP mode, default setting + associated client MAC address + * num=12: for softAP mode, changed setting + associated client MAC address + */ + if ((num != 1) && (num != 6) && (num !=7) && (num != 12)) { + RTW_ERR("%s: Wrong setting (%d arguments), only accept 1, 6, 7, or 12 arguments\n", __func__, num); + return -EFAULT; + } + + if (wrole->type == PHL_RTYPE_AP) { + if ((num == 1) || (num == 6)) { + if (en == 1) { + RTW_ERR("%s: Current is AP mode, you need assigned associated client MAC address!\n", __func__); + return -EFAULT; + } + } + } + else if (wrole->type == PHL_RTYPE_STATION) { + if ((num == 7) || (num == 12)) { + RTW_WARN("%s: Current is STA mode, assigned client MAC address will be ignored!\n", __func__); + } + } + else { + RTW_ERR("%s: wrole type %d is not supported!\n", __func__, wrole->type); + return -EFAULT; + } + + + switch (num) { + case 1: + case 7: + /* default setting */ + if (wrole->type == PHL_RTYPE_AP) { + act_parm.ap_csi = true; + _rtw_memcpy(&act_parm.assign_client_mac[0], addr, ETH_ALEN); + } else + act_parm.ap_csi = false; + + act_parm.act = CHINFO_ACT_CFG; + act_parm.group_num = CHINFO_GROUP_NUM_16; + act_parm.accuracy = CHINFO_ACCU_1BYTE; + //act_parm.mode = CHINFO_MODE_MACID; + act_parm.mode = CHINFO_MODE_ACK; + act_parm.enable_mode = CHINFO_EN_RICH_MODE; //if set cause 100ms CSI + act_parm.sta = phl_sta; + act_parm.enable = en; + act_parm.trig_period = 30; + act_parm.tx_nss = 2; + act_parm.rx_nss = 2; + if (act_parm.mode == CHINFO_MODE_ACK) + act_parm.ele_bitmap = 0x0101; /* For ACK, Legacy, only H00, H01 */ + else + act_parm.ele_bitmap = 0x0303; + rtw_phl_cmd_cfg_chinfo(phl, &act_parm, PHL_CMD_WAIT, 500); + act_parm.act = CHINFO_ACT_EN; + rtw_phl_cmd_cfg_chinfo(phl, &act_parm, PHL_CMD_WAIT, 500); + break; + case 6: + case 12: + /* changed setting */ + if (wrole->type == PHL_RTYPE_AP) { + act_parm.ap_csi = true; + _rtw_memcpy(&act_parm.assign_client_mac[0], addr, ETH_ALEN); + } else + act_parm.ap_csi = false; + + /*default: 1 3 0 0*/ + act_parm.act = CHINFO_ACT_CFG; + act_parm.group_num = group_num; /* 0~3: num 1/2/4/16 */ + act_parm.accuracy = accuracy; /* 0: 1byte, 1: 2 bytes */ + //act_parm.mode = CHINFO_MODE_MACID; + act_parm.mode = mode; /* 0: ACK mode, 1: MACID, 2: NDP */ + act_parm.enable_mode = en_mode; /* 0: Light mode, 1: Rich mode, 2: auto mode */ + act_parm.sta = phl_sta; + act_parm.enable = en; + act_parm.trig_period = period; + act_parm.tx_nss = 2; + act_parm.rx_nss = 2; + if (act_parm.mode == CHINFO_MODE_ACK) + act_parm.ele_bitmap = 0x0101; /* For ACK, Legacy, only H00, H01 */ + else + act_parm.ele_bitmap = 0x0303; + rtw_phl_cmd_cfg_chinfo(phl, &act_parm, PHL_CMD_WAIT, 500); + act_parm.act = CHINFO_ACT_EN; + rtw_phl_cmd_cfg_chinfo(phl, &act_parm, PHL_CMD_WAIT, 500); + break; + default: + RTW_ERR("%s: Wrong setting, only accept 1, 6, 7, or 12 arguments\n", __func__); + return -EFAULT; + break; + } + } + + return count; +} +#endif + +#endif /* CONFIG_PROC_DEBUG */ +#define RTW_BUFDUMP_BSIZE 16 +#if 1 +inline void RTW_BUF_DUMP_SEL(uint _loglevel, void *sel, u8 *_titlestring, + bool _idx_show, const u8 *_hexdata, int _hexdatalen) +{ +#ifdef CONFIG_RTW_DEBUG + int __i; + u8 *ptr = (u8 *)_hexdata; + + if (_loglevel <= rtw_drv_log_level) { + if (_titlestring) { + if (sel == RTW_DBGDUMP) + RTW_PRINT(""); + _RTW_PRINT_SEL(sel, "%s", _titlestring); + if (_hexdatalen >= RTW_BUFDUMP_BSIZE) + _RTW_PRINT_SEL(sel, "\n"); + } + + for (__i = 0; __i < _hexdatalen; __i++) { + if (((__i % RTW_BUFDUMP_BSIZE) == 0) && (_hexdatalen >= RTW_BUFDUMP_BSIZE)) { + if (sel == RTW_DBGDUMP) + RTW_PRINT(""); + if (_idx_show) + _RTW_PRINT_SEL(sel, "0x%03X: ", __i); + } + _RTW_PRINT_SEL(sel, "%02X%s", ptr[__i], (((__i + 1) % 4) == 0) ? " " : " "); + if ((__i + 1 < _hexdatalen) && ((__i + 1) % RTW_BUFDUMP_BSIZE) == 0) + _RTW_PRINT_SEL(sel, "\n"); + } + _RTW_PRINT_SEL(sel, "\n"); + } +#endif +} + +inline void RTW_BUF_DUMP_SEL_ALWAYS(void *sel, u8 *_titlestring, + bool _idx_show, const u8 *_hexdata, int _hexdatalen) +{ + int __i; + u8 *ptr = (u8 *)_hexdata; + + if (_titlestring) { + if (sel == RTW_DBGDUMP) + RTW_PRINT(""); + _RTW_PRINT_SEL(sel, "%s", _titlestring); + if (_hexdatalen >= RTW_BUFDUMP_BSIZE) + _RTW_PRINT_SEL(sel, "\n"); + } + + for (__i = 0; __i < _hexdatalen; __i++) { + if (((__i % RTW_BUFDUMP_BSIZE) == 0) && (_hexdatalen >= RTW_BUFDUMP_BSIZE)) { + if (sel == RTW_DBGDUMP) + RTW_PRINT(""); + if (_idx_show) + _RTW_PRINT_SEL(sel, "0x%03X: ", __i); + } + _RTW_PRINT_SEL(sel, "%02X%s", ptr[__i], (((__i + 1) % 4) == 0) ? " " : " "); + if ((__i + 1 < _hexdatalen) && ((__i + 1) % RTW_BUFDUMP_BSIZE) == 0) + _RTW_PRINT_SEL(sel, "\n"); + } + _RTW_PRINT_SEL(sel, "\n"); +} +#else +inline void _RTW_STR_DUMP_SEL(void *sel, char *str_out) +{ + if (sel == RTW_DBGDUMP) + _dbgdump("%s\n", str_out); + #if defined(_seqdump) + else + _seqdump(sel, "%s\n", str_out); + #endif /*_seqdump*/ +} +inline void RTW_BUF_DUMP_SEL(uint _loglevel, void *sel, u8 *_titlestring, + bool _idx_show, u8 *_hexdata, int _hexdatalen) +{ + int __i, len; + int __j, idx; + int block_num, remain_byte; + char str_out[128] = {'\0'}; + char str_val[32] = {'\0'}; + char *p = NULL; + u8 *ptr = (u8 *)_hexdata; + + if (_loglevel <= rtw_drv_log_level) { + /*dump title*/ + p = &str_out[0]; + if (_titlestring) { + if (sel == RTW_DBGDUMP) { + len = snprintf(str_val, sizeof(str_val), "%s", DRIVER_PREFIX); + strncpy(p, str_val, len); + p += len; + } + len = snprintf(str_val, sizeof(str_val), "%s", _titlestring); + strncpy(p, str_val, len); + p += len; + } + if (p != &str_out[0]) { + _RTW_STR_DUMP_SEL(sel, str_out); + _rtw_memset(&str_out, '\0', sizeof(str_out)); + } + + /*dump buffer*/ + block_num = _hexdatalen / RTW_BUFDUMP_BSIZE; + remain_byte = _hexdatalen % RTW_BUFDUMP_BSIZE; + for (__i = 0; __i < block_num; __i++) { + p = &str_out[0]; + if (sel == RTW_DBGDUMP) { + len = snprintf(str_val, sizeof(str_val), "%s", DRIVER_PREFIX); + strncpy(p, str_val, len); + p += len; + } + if (_idx_show) { + len = snprintf(str_val, sizeof(str_val), "0x%03X: ", __i * RTW_BUFDUMP_BSIZE); + strncpy(p, str_val, len); + p += len; + } + for (__j =0; __j < RTW_BUFDUMP_BSIZE; __j++) { + idx = __i * RTW_BUFDUMP_BSIZE + __j; + len = snprintf(str_val, sizeof(str_val), "%02X%s", ptr[idx], (((__j + 1) % 4) == 0) ? " " : " "); + strncpy(p, str_val, len); + p += len; + } + _RTW_STR_DUMP_SEL(sel, str_out); + _rtw_memset(&str_out, '\0', sizeof(str_out)); + } + + p = &str_out[0]; + if ((sel == RTW_DBGDUMP) && remain_byte) { + len = snprintf(str_val, sizeof(str_val), "%s", DRIVER_PREFIX); + strncpy(p, str_val, len); + p += len; + } + if (_idx_show && remain_byte) { + len = snprintf(str_val, sizeof(str_val), "0x%03X: ", block_num * RTW_BUFDUMP_BSIZE); + strncpy(p, str_val, len); + p += len; + } + for (__i = 0; __i < remain_byte; __i++) { + idx = block_num * RTW_BUFDUMP_BSIZE + __i; + len = snprintf(str_val, sizeof(str_val), "%02X%s", ptr[idx], (((__i + 1) % 4) == 0) ? " " : " "); + strncpy(p, str_val, len); + p += len; + } + _RTW_STR_DUMP_SEL(sel, str_out); + } +} + +#endif + +int proc_get_vcs(struct seq_file *m, void *v) +{ + struct net_device *dev = m->private; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + + if (padapter) + { + RTW_PRINT_SEL(m, "vrtl_carrier_sense = %d\n", pregpriv->vrtl_carrier_sense); + RTW_PRINT_SEL(m, "vcs_type = %u\n", pregpriv->vcs_type); + RTW_PRINT_SEL(m, "rts_thresh = %u\n", pregpriv->rts_thresh); + RTW_PRINT_SEL(m, "hw_rts_en = %u\n", pregpriv->hw_rts_en); + } + + return 0; +} + +ssize_t proc_set_vcs(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct registry_priv *pregpriv = &padapter->registrypriv; + char tmp[32]; + u8 vcs, vcs_t, hw_rts; + u16 rts_th; + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) { + rtw_warn_on(1); + return -EFAULT; + } + + if (buffer && !copy_from_user(tmp, buffer, count)) { + + int num = sscanf(tmp, "%hhu %hhu %hhu %hu ", &vcs, &vcs_t, &hw_rts, &rts_th); + + if (padapter && (num == 4)) { + pregpriv->vrtl_carrier_sense = vcs; + pregpriv->vcs_type = vcs_t; + pregpriv->hw_rts_en= hw_rts; + pregpriv->rts_thresh = rts_th; + } + else + RTW_WARN("%s: Wrong setting.\n", __func__); + + } + + return count; +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.c new file mode 100644 index 00000000..cfafa65f --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.c @@ -0,0 +1,1652 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_DFS_C_ + +#include + +bool rtw_chset_is_dfs_range(const struct rtw_chset *chset, u32 hi, u32 lo) +{ + enum band_type band = rtw_freq2band(hi); + u8 hi_ch = rtw_freq2ch(hi); + u8 lo_ch = rtw_freq2ch(lo); + int i; + + for (i = 0; i < chset->chs_len; i++){ + if (!(chset->chs[i].flags & RTW_CHF_DFS)) + continue; + if (band == chset->chs[i].band && hi_ch > chset->chs[i].ChannelNum && lo_ch < chset->chs[i].ChannelNum) + return 1; + } + + return 0; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_dfs_ch(const struct rtw_chset *chset, u8 ch) +{ + int i; + + for (i = 0; i < chset->chs_len; i++){ + if (chset->chs[i].ChannelNum == ch) + return chset->chs[i].flags & RTW_CHF_DFS ? 1 : 0; + } + + return 0; +} + +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_dfs_chbw(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset) +{ + u32 hi, lo; + + if (!rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo)) + return 0; + + return rtw_chset_is_dfs_range(chset, hi, lo); +} +#endif + +bool rtw_chset_is_dfs_bch(const struct rtw_chset *chset, enum band_type band, u8 ch) +{ + int i; + + for (i = 0; i < chset->chs_len; i++){ + if (chset->chs[i].band == band && chset->chs[i].ChannelNum == ch) + return chset->chs[i].flags & RTW_CHF_DFS ? 1 : 0; + } + + return 0; +} + +bool rtw_chset_is_dfs_bchbw(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset) +{ + u32 hi, lo; + + if (!rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo)) + return 0; + + return rtw_chset_is_dfs_range(chset, hi, lo); +} + +#if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ +static bool rtw_chset_get_dfs_frange(const struct rtw_chset *chset + , enum band_type band, u8 ch, u8 bw, u8 offset, u32 *dfs_freq_hi, u32 *dfs_freq_lo) +{ + u32 hi, lo; + u32 freq; + int i; + + *dfs_freq_hi = *dfs_freq_lo = 0; + + if (!rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo)) { + rtw_warn_on(1); + return false; + } + + for (i = 0; i < chset->chs_len; i++){ + if (!(chset->chs[i].flags & RTW_CHF_DFS)) + continue; + freq = rtw_bch2freq(chset->chs[i].band, chset->chs[i].ChannelNum); + if (!freq) { + rtw_warn_on(1); + continue; + } + if (!rtw_is_range_a_in_b(freq + 10, freq - 10, hi, lo)) + continue; + rtw_range_merge(*dfs_freq_hi, *dfs_freq_lo, freq + 10, freq - 10); + } + + return *dfs_freq_hi != 0; +} +#endif /* CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ */ + +enum rtw_dfs_regd rtw_rfctl_get_dfs_domain(struct rf_ctl_t *rfctl) +{ +#ifdef CONFIG_DFS_MASTER + return rfctl->dfs_region_domain; +#else + return RTW_DFS_REGD_NONE; +#endif +} + +bool rtw_rfctl_radar_detect_supported(struct rf_ctl_t *rfctl) +{ +#ifdef CONFIG_DFS_MASTER + enum rtw_dfs_regd domain = rtw_rfctl_get_dfs_domain(rfctl); + + return !RTW_DFS_REGD_IS_UNKNOWN(domain) + && rtw_dfs_hal_region_supported(rfctl_to_dvobj(rfctl), domain); +#else + return false; +#endif +} + +#ifdef CONFIG_DFS_MASTER +bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset) +{ + bool ret = false; + u8 rd_hwband; + u32 hi = 0, lo = 0; + u32 r_hi = 0, r_lo = 0; + + if (band != BAND_ON_5G || !rfctl->radar_detect_enabled) + goto exit; + + if (rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo) == _FALSE) { + rtw_warn_on(1); + goto exit; + } + + rd_hwband = rfctl->radar_detect_hwband; + if (rtw_is_range_overlap(hi, lo, rfctl->radar_detect_freq_hi[rd_hwband], rfctl->radar_detect_freq_lo[rd_hwband])) + ret = true; + +exit: + return ret; +} + +static bool rtw_rfctl_hwband_is_tx_blocked_by_ch_waiting(struct rf_ctl_t *rfctl, enum phl_band_idx hwband) +{ + if (hwband >= HW_BAND_MAX) + return false; + + if (IS_CH_WAITING(rfctl)) { + enum band_type band; + u8 ch, bw, offset; + + if (rtw_get_oper_bchbw_by_hwband(rfctl_to_dvobj(rfctl), hwband + , &band, &ch, &bw, &offset) != _SUCCESS) + return false; + + return rtw_rfctl_overlap_radar_detect_ch(rfctl + , band, ch, bw, offset); + } + return false; +} + +bool adapter_is_tx_blocked_by_ch_waiting(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + struct _ADAPTER_LINK *alink = GET_PRIMARY_LINK(adapter); + + if (!alink) + return false; + + return rtw_rfctl_hwband_is_tx_blocked_by_ch_waiting(rfctl, ALINK_GET_HWBAND(alink)); +} + +bool alink_is_tx_blocked_by_ch_waiting(struct _ADAPTER_LINK *alink) +{ + _adapter *adapter = alink->adapter; + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + return rtw_rfctl_hwband_is_tx_blocked_by_ch_waiting(rfctl, ALINK_GET_HWBAND(alink)); +} + +/** + * rtw_chset_update_cac_state_of_chs - update cac_done according to the given @band, @chs, @chs_len into @chset + * @chset: the given channel set + * @band: band of setting range + * @chs: channel array of setting range + * @chs_len: channel array length + * @done: if CAC done + */ +static void rtw_chset_update_cac_state_of_chs(struct rtw_chset *chset + , u8 chs[], u8 chs_len, bool done) +{ + int i, j; + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != BAND_ON_5G) + continue; + for (j = 0; j < chs_len; j++) { + if (chs[j] == 0) + continue; + if (chset->chs[i].ChannelNum == chs[j]) + chset->chs[i].cac_done = done; + } + } +} + +/** + * rtw_chset_update_cac_state_by_freq - update cac_done according to the given @hi, @lo frequency into @chset + * @chset: the given channel set + * @hi: high frequency of setting range + * @lo: low frequency of setting range + * @done: if CAC done + */ +static void rtw_chset_update_cac_state_by_freq(struct rtw_chset *chset, u32 hi, u32 lo, bool done) +{ + enum band_type band; + int i; + + band = rtw_freq2band(hi); + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != band) + continue; + if (!rtw_bch2freq(band, chset->chs[i].ChannelNum)) { + rtw_warn_on(1); + continue; + } + + if (lo <= rtw_bch2freq(band, chset->chs[i].ChannelNum) + && rtw_bch2freq(band, chset->chs[i].ChannelNum) <= hi) + chset->chs[i].cac_done = done; + } +} + +static void rtw_chset_update_cac_state_by_cch(struct rtw_chset *chset, u8 cch, u8 bw, bool done) +{ + u32 hi, lo; + + if (rtw_bcchbw_to_freq_range(BAND_ON_5G, cch, bw, &hi, &lo)) + rtw_chset_update_cac_state_by_freq(chset, hi, lo, done); +} + +/** + * rtw_chset_is_frange_require_cac - check cac_done according to the given @hi, @lo frequency into @chset + * @chset: the given channel set + * @hi: high frequency of checking range + * @lo: low frequency of checking range + * return: if all channel inside range require CAC (DFS channel and not CAC done) + */ +static bool rtw_chset_is_frange_require_cac(struct rtw_chset *chset, u32 hi, u32 lo) +{ + enum band_type band; + int i; + + band = rtw_freq2band(hi); + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != band) + continue; + if (!(chset->chs[i].flags & RTW_CHF_DFS)) + continue; + if (!rtw_bch2freq(band, chset->chs[i].ChannelNum)) { + rtw_warn_on(1); + continue; + } + if (lo <= rtw_bch2freq(band, chset->chs[i].ChannelNum) + && rtw_bch2freq(band, chset->chs[i].ChannelNum) <= hi + && !chset->chs[i].cac_done) + return true; + } + + return false; +} + +static bool rtw_chset_is_cch_require_cac(struct rtw_chset *chset, u8 cch, u8 bw) +{ + u32 hi, lo; + + if (rtw_bcchbw_to_freq_range(BAND_ON_5G, cch, bw, &hi, &lo)) + return rtw_chset_is_frange_require_cac(chset, hi, lo); + return false; +} + +bool rtw_chset_is_bchbw_non_ocp(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset) +{ + bool ret = _FALSE; + u32 hi = 0, lo = 0; + int i; + + if (rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo) == _FALSE) + goto exit; + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != band) + continue; + if (!rtw_bch2freq(band, chset->chs[i].ChannelNum)) { + rtw_warn_on(1); + continue; + } + + if (!CH_IS_NON_OCP(&chset->chs[i])) + continue; + + if (lo <= rtw_bch2freq(band, chset->chs[i].ChannelNum) + && rtw_bch2freq(band, chset->chs[i].ChannelNum) <= hi + ) { + ret = _TRUE; + break; + } + } + +exit: + return ret; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_chbw_non_ocp(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset) +{ + return rtw_chset_is_bchbw_non_ocp(chset, rtw_is_2g_ch(ch) ? BAND_ON_24G : BAND_ON_5G, ch, bw, offset); +} + +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_ch_non_ocp(const struct rtw_chset *chset, u8 ch) +{ + return rtw_chset_is_chbw_non_ocp(chset, ch, CHANNEL_WIDTH_20, CHAN_OFFSET_NO_EXT); +} +#endif + +bool rtw_chset_is_bch_non_ocp(const struct rtw_chset *chset, enum band_type band, u8 ch) +{ + return rtw_chset_is_bchbw_non_ocp(chset, band, ch, CHANNEL_WIDTH_20, CHAN_OFFSET_NO_EXT); +} + +static u32 rtw_chset_get_bch_non_ocp_ms(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset) +{ + int ms = 0; + systime current_time; + u32 hi = 0, lo = 0; + int i; + + if (rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo) == _FALSE) + goto exit; + + current_time = rtw_get_current_time(); + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != band) + continue; + if (!rtw_bch2freq(band, chset->chs[i].ChannelNum)) { + rtw_warn_on(1); + continue; + } + + if (!CH_IS_NON_OCP(&chset->chs[i])) + continue; + + if (lo <= rtw_bch2freq(band, chset->chs[i].ChannelNum) + && rtw_bch2freq(band, chset->chs[i].ChannelNum) <= hi + ) { + if (rtw_systime_to_ms(chset->chs[i].non_ocp_end_time - current_time) > ms) + ms = rtw_systime_to_ms(chset->chs[i].non_ocp_end_time - current_time); + } + } + +exit: + return ms; +} + +/** + * rtw_chset_update_non_ocp_ms_by_freq - update non_ocp_end_time according to the given @hi, @lo frequency into @ch_set + * @chset: the given channel set + * @hi: high frequency on which radar is detected + * @lo: low frequency on which radar is detected + * @ms: ms to add from now to update non_ocp_end_time, ms < 0 means use NON_OCP_TIME_MS + */ +static bool rtw_chset_update_non_ocp_ms_by_freq(struct rtw_chset *chset, u32 hi, u32 lo, int ms) +{ + enum band_type band; + int i; + bool updated = 0; + + band = rtw_freq2band(hi); + + for (i = 0; i < chset->chs_len; i++) { + if (chset->chs[i].band != band) + continue; + if (!rtw_bch2freq(band, chset->chs[i].ChannelNum)) { + rtw_warn_on(1); + continue; + } + + if (lo <= rtw_bch2freq(band, chset->chs[i].ChannelNum) + && rtw_bch2freq(band, chset->chs[i].ChannelNum) <= hi + ) { + if (ms >= 0) + chset->chs[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(ms); + else + chset->chs[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(NON_OCP_TIME_MS); + if (chset->chs[i].non_ocp_end_time == RTW_NON_OCP_STOPPED) + chset->chs[i].non_ocp_end_time++; + updated = 1; + } + } + + return updated; +} + +static bool rtw_chset_update_non_ocp_ms_by_band_cch(struct rtw_chset *chset, enum band_type band, u8 cch, u8 bw, int ms) +{ + u32 hi, lo; + + if (rtw_bcchbw_to_freq_range(band, cch, bw, &hi, &lo) == _FALSE) + return _FALSE; + + return rtw_chset_update_non_ocp_ms_by_freq(chset, hi, lo, ms); +} + +static bool rtw_chset_update_non_ocp_ms_by_band(struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset, int ms) +{ + u32 hi, lo; + + if (rtw_bchbw_to_freq_range(band, ch, bw, offset, &hi, &lo) == _FALSE) + return _FALSE; + + return rtw_chset_update_non_ocp_ms_by_freq(chset, hi, lo, ms); +} + +static bool rtw_rfctl_chset_chk_non_ocp_finish_for_bchbw(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset) +{ + struct rtw_chset *chset = &rfctl->chset; + RT_CHANNEL_INFO *chinfo; + u8 cch; + u8 *op_chs; + u8 op_ch_num; + int i; + bool ret = 0; + + cch = rtw_get_center_ch_by_band(band, ch, bw, offset); + + if (!rtw_get_op_chs_by_bcch_bw(band, cch, bw, &op_chs, &op_ch_num)) + goto exit; + + for (i = 0; i < op_ch_num; i++) { + if (0) + RTW_INFO("%u,%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", band, ch, bw, offset, cch, bw, *(op_chs + i)); + chinfo = rtw_chset_get_chinfo_by_bch(chset, band, *(op_chs + i), true); + if (!chinfo) + break; + if (CH_IS_NON_OCP_STOPPED(chinfo) || CH_IS_NON_OCP(chinfo)) + break; + } + + if (op_ch_num != 0 && i == op_ch_num) { + ret = 1; + /* set to RTW_NON_OCP_STOPPED */ + for (i = 0; i < op_ch_num; i++) { + chinfo = rtw_chset_get_chinfo_by_bch(chset, band, *(op_chs + i), true); + chinfo->non_ocp_end_time = RTW_NON_OCP_STOPPED; + } + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) /* single chset shared by all hwband */ + rtw_os_indicate_nop_finished(rfctl, i, band, cch, bw); + } + +exit: + return ret; +} + +/* called by watchdog to set RTW_NON_OCP_STOPPED and generate NON_OCP finish event */ +void rtw_rfctl_chset_chk_non_ocp_finish(struct rf_ctl_t *rfctl) +{ + struct rtw_chset *chset = &rfctl->chset; + enum band_type band; + u8 ch, bw, offset; + int i; + + bw = CHANNEL_WIDTH_160; + while (1) { + for (i = 0; i < chset->chs_len; i++) { + band = chset->chs[i].band; + ch = chset->chs[i].ChannelNum; + if (CH_IS_NON_OCP_STOPPED(&chset->chs[i])) + continue; + if (!rtw_get_offset_by_bchbw(band, ch, bw, &offset)) + continue; + + rtw_rfctl_chset_chk_non_ocp_finish_for_bchbw(rfctl, band, ch, bw, offset); + } + if (bw-- == CHANNEL_WIDTH_20) + break; + } +} + +/* +* For ioctl debug usage, will not change current CAC status +* Don't use on current operating channels +*/ +void rtw_rfctl_force_update_non_ocp_ms(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset, int ms) +{ + struct rtw_chset *chset = &rfctl->chset; + bool updated; + + if (bw == CHANNEL_WIDTH_20) + updated = rtw_chset_update_non_ocp_ms_by_band(chset + , band, ch, bw, CHAN_OFFSET_NO_EXT, ms); + else + updated = rtw_chset_update_non_ocp_ms_by_band(chset + , band, ch, bw, offset, ms); + + if (updated) { + u8 i; + u8 cch = rtw_get_center_ch_by_band(band, ch, bw, offset); + + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) + rtw_os_indicate_nop_started(rfctl, i, band, cch, bw, false); + } +} + +static u32 _rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset, bool in_self_rd_range, u32 *r_non_ocp_ms, u32 *r_cac_ms) +{ + struct rtw_chset *chset = &rfctl->chset; + u32 non_ocp_ms; + u32 cac_ms; + + if (rtw_chset_is_bchbw_non_ocp(chset, band, ch, bw, offset)) + non_ocp_ms = rtw_chset_get_bch_non_ocp_ms(chset, band, ch, bw, offset); + else + non_ocp_ms = 0; + + if (!rtw_chset_is_dfs_bchbw(chset, band, ch, bw, offset)) + cac_ms = 0; + else if (in_self_rd_range && !non_ocp_ms) { + if (IS_CH_WAITING(rfctl)) + cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time()); + else + cac_ms = 0; + } else if (rtw_is_long_cac_bch(band, ch, bw, offset, rtw_rfctl_get_dfs_domain(rfctl))) + cac_ms = CAC_TIME_CE_MS; + else + cac_ms = CAC_TIME_MS; + + if (r_non_ocp_ms) + *r_non_ocp_ms = non_ocp_ms; + if (r_cac_ms) + *r_cac_ms = cac_ms; + + return non_ocp_ms + cac_ms; +} + +u32 rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset, u32 *r_non_ocp_ms, u32 *r_cac_ms) +{ + bool in_self_rd_range = false; + + if (rfctl->radar_detect_enabled) { + u32 hi, lo; + u8 rd_hwband = rfctl->radar_detect_hwband; + + if (rtw_chset_get_dfs_frange(&rfctl->chset, band, ch, bw, offset, &hi, &lo) + && rtw_is_range_a_in_b(hi, lo, rfctl->radar_detect_freq_hi[rd_hwband], rfctl->radar_detect_freq_lo[rd_hwband])) + in_self_rd_range = 1; + } + + return _rtw_get_ch_waiting_ms(rfctl, band, ch, bw, offset, in_self_rd_range, r_non_ocp_ms, r_cac_ms); +} + +static void rtw_reset_cac(struct rf_ctl_t *rfctl, u8 op_ch, u8 op_bw, u8 op_offset) +{ +#define RD_CONFIG_INT_MS 2000 + u32 non_ocp_ms; + u32 cac_ms; + u32 rd_ready_ms = 0; + + _rtw_get_ch_waiting_ms(rfctl, BAND_ON_5G, op_ch, op_bw, op_offset, false + , &non_ocp_ms, &cac_ms); + if (non_ocp_ms < RD_CONFIG_INT_MS) + rd_ready_ms = RD_CONFIG_INT_MS - non_ocp_ms; + + rfctl->non_ocp_finished = non_ocp_ms ? false : true; + rfctl->cac_start_time = rtw_get_current_time() + rtw_ms_to_systime(non_ocp_ms); + rfctl->cac_end_time = rfctl->cac_start_time + rtw_ms_to_systime(rd_ready_ms + cac_ms); + + /* skip special value */ + if (rfctl->cac_start_time == RTW_CAC_STOPPED) { + rfctl->cac_start_time++; + rfctl->cac_end_time++; + } + if (rfctl->cac_end_time == RTW_CAC_STOPPED) + rfctl->cac_end_time++; +} + +u32 rtw_force_stop_cac(struct rf_ctl_t *rfctl, u32 timeout_ms) +{ + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + systime start; + u32 pass_ms; + + start = rtw_get_current_time(); + + rfctl->cac_force_stop = 1; + + while (rtw_get_passing_time_ms(start) <= timeout_ms + && IS_UNDER_CAC(rfctl) + ) { + if (dev_is_surprise_removed(dvobj) || dev_is_drv_stopped(dvobj)) + break; + rtw_msleep_os(20); + } + + if (IS_UNDER_CAC(rfctl)) { + if (!dev_is_surprise_removed(dvobj) && !dev_is_drv_stopped(dvobj)) + RTW_INFO("%s waiting for cac stop timeout!\n", __func__); + } + + rfctl->cac_force_stop = 0; + + pass_ms = rtw_get_passing_time_ms(start); + + return pass_ms; +} + +static void rtw_dfs_ch_switch_hdl(struct dvobj_priv *dvobj, u8 band_idx) +{ + _adapter *m_iface = rtw_mi_get_ap_mesh_iface_by_hwband(dvobj, band_idx); + u8 ifbmp_m; + u8 ifbmp_s; + u8 i; + + if (!m_iface) { + RTW_WARN(FUNC_HWBAND_FMT" can't get ap/mesh iface\n", FUNC_HWBAND_ARG(band_idx)); + rtw_warn_on(1); + return; + } + + ifbmp_m = rtw_mi_get_ap_mesh_ifbmp_by_hwband(dvobj, band_idx); + ifbmp_s = rtw_mi_get_ld_sta_ifbmp_by_hwband(dvobj, band_idx); + + rtw_dfs_hal_csa_mg_tx_pause(dvobj, band_idx, true); + +#ifdef CONFIG_AP_MODE + if (ifbmp_m) { + RTW_INFO(FUNC_HWBAND_FMT" ch sel by AP/MESH ifaces\n", FUNC_HWBAND_ARG(band_idx)); + /* trigger channel selection with consideraton of asoc STA ifaces */ + rtw_change_bss_bchbw_cmd(m_iface, RTW_CMDF_DIRECTLY + , ifbmp_m, ifbmp_s, REQ_BAND_NONE, REQ_CH_NONE, REQ_BW_ORI, REQ_OFFSET_NONE); + } +#endif + + rtw_dfs_hal_csa_mg_tx_pause(dvobj, band_idx, false); + + rtw_mi_os_xmit_schedule(m_iface); +} + +u8 rtw_dfs_rd_hdl(struct dvobj_priv *dvobj, enum phl_band_idx hwband, u8 radar_cch, enum channel_width radar_bw) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + bool detected; + + if (!rfctl->radar_detect_enabled || rfctl->radar_detect_hwband != hwband) + goto exit; + + if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl)) { + /* non_ocp, ignore radar detect */ + goto cac_status_chk; + } else if (IS_UNDER_CAC(rfctl) && !rfctl->non_ocp_finished) { + /* from NON_OCP to CAC, indicate CAC started event */ + rtw_os_indicate_cac_started(rfctl, hwband, 0xFF + , rfctl->radar_detect_cch[hwband], rfctl->radar_detect_bw[hwband]); + rfctl->non_ocp_finished = true; + } + + detected = (radar_cch > 0 && radar_bw != CHANNEL_WIDTH_MAX) ? true : false; + if (!rfctl->dbg_dfs_fake_radar_detect_cnt && !detected) + goto cac_status_chk; + + if (!rfctl->dbg_dfs_fake_radar_detect_cnt + && rfctl->dbg_dfs_radar_detect_trigger_non + ) { + /* radar detect debug mode, trigger no mlme flow */ + RTW_INFO(FUNC_HWBAND_FMT" radar detected on test mode, trigger no mlme flow\n", FUNC_HWBAND_ARG(hwband)); + goto cac_status_chk; + } + + if (rfctl->dbg_dfs_fake_radar_detect_cnt != 0) { + RTW_INFO(FUNC_HWBAND_FMT" fake radar detected, cnt:%d\n", FUNC_HWBAND_ARG(hwband) + , rfctl->dbg_dfs_fake_radar_detect_cnt); + rfctl->dbg_dfs_fake_radar_detect_cnt--; + + /* TODO: fack radar detected with specific range */ + radar_cch = rfctl->radar_detect_cch[hwband]; + radar_bw = rfctl->radar_detect_bw[hwband]; + + } else + RTW_INFO(FUNC_HWBAND_FMT" radar detected\n", FUNC_HWBAND_ARG(hwband)); + + rfctl->radar_detected = 1; + + rtw_chset_update_non_ocp_ms_by_band_cch(&rfctl->chset, BAND_ON_5G + , radar_cch, radar_bw, -1); + + rtw_os_indicate_radar_detected(rfctl, hwband, radar_cch, radar_bw); + rtw_os_indicate_nop_started(rfctl, hwband, BAND_ON_5G, radar_cch, radar_bw, true); + + rtw_dfs_ch_switch_hdl(dvobj, hwband); + + if (rfctl->radar_detect_enabled) + goto set_timer; + goto exit; + +cac_status_chk: + + if (!IS_CAC_STOPPED(rfctl) + && ((IS_UNDER_CAC(rfctl) && rfctl->cac_force_stop) + || !IS_CH_WAITING(rfctl) + ) + ) { + _adapter *m_iface; + + rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED; + rtw_chset_update_cac_state_by_cch(&rfctl->chset + , rfctl->radar_detect_cch[hwband], rfctl->radar_detect_bw[hwband], true); + rtw_dfs_hal_set_cac_status(dvobj, hwband, false); + + m_iface = rtw_mi_get_ap_mesh_iface_by_hwband(dvobj, hwband); + if (m_iface) { + if (!rtw_mi_check_fwstate_by_hwband(dvobj, hwband, WIFI_UNDER_LINKING|WIFI_UNDER_SURVEY)) { + struct _ADAPTER_LINK *alink = rtw_get_adapter_link_by_hwband(m_iface, hwband); + enum band_type u_band; + u8 u_ch, u_bw, u_offset; + + if (rtw_mi_get_bch_setting_union_by_hwband(dvobj, hwband, &u_band, &u_ch, &u_bw, &u_offset)) + set_bch_bwmode(m_iface, alink, u_band, u_ch, u_offset, u_bw, RFK_TYPE_FORCE_DO); + else + rtw_warn_on(1); + } + } else + RTW_ERR(FUNC_HWBAND_FMT" can't get ap/mesh iface\n", FUNC_HWBAND_ARG(hwband)); + + rtw_os_indicate_cac_finished(rfctl, hwband, 0xFF + , rfctl->radar_detect_cch[hwband], rfctl->radar_detect_bw[hwband]); + } + +set_timer: + _set_timer(&rfctl->radar_detect_timer + , rtw_dfs_hal_radar_detect_polling_int_ms(dvobj)); + +exit: + return H2C_SUCCESS; +} + +static u8 rtw_dfs_rd_cmd(struct dvobj_priv *dvobj, enum phl_band_idx hwband) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct cmd_priv *cmdpriv = &dvobj->cmdpriv; + _adapter *adapter = dvobj_get_primary_adapter(dvobj); + u8 res = _FAIL; + + cmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) + goto exit; + cmdobj->padapter = adapter; + + parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + rtw_mfree(cmdobj, sizeof(struct cmd_obj)); + goto exit; + } + + parm->ec_id = DFS_RADAR_DETECT_WK_CID; + parm->type = hwband; + parm->size = 0; + parm->pbuf = NULL; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + CMD_OBJ_SET_HWBAND(cmdobj, hwband); + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + +exit: + return res; +} + +static void rtw_dfs_rd_timer_hdl(void *ctx) +{ + struct rf_ctl_t *rfctl = (struct rf_ctl_t *)ctx; + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + + rtw_dfs_rd_cmd(dvobj, rfctl->radar_detect_hwband); +} +#endif /* CONFIG_DFS_MASTER */ + +#if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ +static void rtw_dfs_update_rd_range_status(struct rf_ctl_t *rfctl, u8 band_idx + , u8 op_ch, enum channel_width op_bw, enum chan_offset op_offset, u32 rd_freq_hi, u32 rd_freq_lo, bool by_others) +{ +#define RD_RANGE_OPCH_NUM_MAX (160 / 20) +#ifdef CONFIG_DFS_MASTER + bool new_self_rd_ch = false; + bool cover_non_ocp = op_ch && rtw_chset_is_bchbw_non_ocp(&rfctl->chset, BAND_ON_5G, op_ch, op_bw, op_offset); +#endif + u8 cch = 0; + enum channel_width bw = CHANNEL_WIDTH_MAX; + +#ifndef CONFIG_DFS_MASTER + if (rd_freq_hi && !by_others) { + rtw_warn_on(1); + rd_freq_hi = 0; + } +#endif + + if (rd_freq_hi) { + cch = rtw_freq2ch((rd_freq_hi + rd_freq_lo) / 2); + bw = rtw_frange_to_bw(rd_freq_hi, rd_freq_lo); + rtw_warn_on(cch == 0); + rtw_warn_on(bw == CHANNEL_WIDTH_MAX); + } + +#ifdef CONFIG_DFS_MASTER + if (rfctl->radar_detect_cch[band_idx] != cch + || rfctl->radar_detect_bw[band_idx] != bw + ) { + /* coverage range changed */ + u8 *op_chs; + u8 op_ch_num; + u8 rd_cch; + enum channel_width rd_bw; + u8 i, j, k; + + if (rfctl->radar_detect_cch[band_idx]) { + u8 clr_chs[RD_RANGE_OPCH_NUM_MAX]; + + /* init clr_chs from original coverage of this hwband */ + if (!rtw_get_op_chs_by_bcch_bw(BAND_ON_5G + , rfctl->radar_detect_cch[band_idx], rfctl->radar_detect_bw[band_idx], &op_chs, &op_ch_num) + ) { + RTW_WARN(FUNC_HWBAND_FMT" rtw_get_op_chs_by_bcch_bw() fail on cch:%u bw:%u\n", FUNC_HWBAND_ARG(band_idx) + , rfctl->radar_detect_cch[band_idx], rfctl->radar_detect_bw[band_idx]); + rtw_warn_on(1); + goto handle_add_chs; + } + _rtw_memset(clr_chs, 0, RD_RANGE_OPCH_NUM_MAX); + for (i = 0; i < op_ch_num; i++) + clr_chs[i] = op_chs[i]; + + /* remove op chs of new coverages from clr_chs */ + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) { + if (i == band_idx && cch) { + rd_cch = cch; + rd_bw = bw; + } else if (i != band_idx && rfctl->radar_detect_cch[i]) { + rd_cch = rfctl->radar_detect_cch[i]; + rd_bw = rfctl->radar_detect_bw[i]; + } else + continue; + + if (!rtw_get_op_chs_by_bcch_bw(BAND_ON_5G, rd_cch, rd_bw, &op_chs, &op_ch_num)) { + RTW_WARN(FUNC_HWBAND_FMT" rtw_get_op_chs_by_bcch_bw() fail on cch:%u bw:%u\n" + , FUNC_HWBAND_ARG(i), rd_cch, rd_bw); + rtw_warn_on(1); + continue; + } + for (j = 0; j < RD_RANGE_OPCH_NUM_MAX; j++) + for (k = 0; k < op_ch_num; k++) + if (clr_chs[j] == op_chs[k]) + clr_chs[j] = 0; + } + + /* clear CAC_DONE of clr_chs */ + rtw_chset_update_cac_state_of_chs(&rfctl->chset, clr_chs, RD_RANGE_OPCH_NUM_MAX, false); + } + +handle_add_chs: + if (cch && !by_others && !cover_non_ocp) { + u8 add_chs[RD_RANGE_OPCH_NUM_MAX]; + + /* init add_chs from new coverage of this hwband */ + if (!rtw_get_op_chs_by_bcch_bw(BAND_ON_5G, cch, bw, &op_chs, &op_ch_num)) { + RTW_WARN(FUNC_HWBAND_FMT" rtw_get_op_chs_by_bcch_bw() fail on cch:%u bw:%u\n" + , FUNC_HWBAND_ARG(band_idx), cch, bw); + rtw_warn_on(1); + goto update_ch_cac; + } + _rtw_memset(add_chs, 0, RD_RANGE_OPCH_NUM_MAX); + for (i = 0; i < op_ch_num; i++) + add_chs[i] = op_chs[i]; + + /* remove op chs of original coverages from add_chs */ + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) { + if (rfctl->radar_detect_cch[i]) { + rd_cch = rfctl->radar_detect_cch[i]; + rd_bw = rfctl->radar_detect_bw[i]; + } else + continue; + + if (!rtw_get_op_chs_by_bcch_bw(BAND_ON_5G, rd_cch, rd_bw, &op_chs, &op_ch_num)) { + RTW_WARN(FUNC_HWBAND_FMT" rtw_get_op_chs_by_bcch_bw() fail on cch:%u bw:%u\n" + , FUNC_HWBAND_ARG(i), rd_cch, rd_bw); + rtw_warn_on(1); + continue; + } + for (j = 0; j < RD_RANGE_OPCH_NUM_MAX; j++) + for (k = 0; k < op_ch_num; k++) + if (add_chs[j] == op_chs[k]) + add_chs[j] = 0; + } + + for (i = 0; i < RD_RANGE_OPCH_NUM_MAX; i++) + if (add_chs[i]) + break; + if (i < RD_RANGE_OPCH_NUM_MAX) + new_self_rd_ch = true; + } + } + +update_ch_cac: + if (cch && by_others) { + /* new coverage of this hwband is detected by others, set CAC_DONE directly */ + rtw_chset_update_cac_state_by_cch(&rfctl->chset, cch, bw, true); + } + + + /* hwband CAC status update */ + if (cover_non_ocp) { + RTW_INFO(FUNC_HWBAND_FMT" cover NON_OCP channel\n", FUNC_HWBAND_ARG(band_idx)); + if (IS_UNDER_CAC(rfctl)) { + RTW_INFO(FUNC_HWBAND_FMT" CAC abort\n", FUNC_HWBAND_ARG(band_idx)); + rtw_os_indicate_cac_aborted(rfctl, band_idx, 0xFF + , rfctl->radar_detect_cch[band_idx], rfctl->radar_detect_bw[band_idx]); + } + rtw_reset_cac(rfctl, op_ch, op_bw, op_offset); + + } else if (new_self_rd_ch) { + /* if having new rd chs and not detected by others, reset CAC of detecting hwband */ + RTW_INFO(FUNC_HWBAND_FMT" have new detect range\n", FUNC_HWBAND_ARG(band_idx)); + rtw_reset_cac(rfctl, op_ch, op_bw, op_offset); + rtw_os_indicate_cac_started(rfctl, band_idx, 0xFF, cch, bw); + + } else { + u8 rd_cch; + enum channel_width rd_bw; + u8 i; + bool require_cac[HW_BAND_MAX]; + + if (IS_UNDER_CAC(rfctl) && cch == 0 && rfctl->radar_detect_cch[band_idx] + && !rfctl->radar_detect_by_others[band_idx] + ) { + /* from detecting by self to no detecting (by self/others), CAC abort */ + RTW_INFO(FUNC_HWBAND_FMT" disable detect, CAC abort\n", FUNC_HWBAND_ARG(band_idx)); + rtw_os_indicate_cac_aborted(rfctl, band_idx, 0xFF + , rfctl->radar_detect_cch[band_idx], rfctl->radar_detect_bw[band_idx]); + } + + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) { + if (i == band_idx && cch) { + rd_cch = cch; + rd_bw = bw; + } else if (i != band_idx && rfctl->radar_detect_cch[i]) { + rd_cch = rfctl->radar_detect_cch[i]; + rd_bw = rfctl->radar_detect_bw[i]; + } else { + require_cac[i] = false; + continue; + } + + require_cac[i] = rtw_chset_is_cch_require_cac(&rfctl->chset, rd_cch, rd_bw); + if (!require_cac[i]) { + if (IS_UNDER_CAC(rfctl)) + RTW_INFO(FUNC_HWBAND_FMT" detect range already CAC done\n", FUNC_HWBAND_ARG(i)); + /* if new coverage of detecting hwband CAC_DONE, force CAC finish */ + rtw_os_force_cac_finished(rfctl, i, 0xFF, rd_cch, rd_bw); + } + } + + if (!IS_CAC_STOPPED(rfctl)) { + /* set CAC stop if no hwband needed */ + for (i = HW_BAND_0; i < HW_BAND_MAX; i++) + if (require_cac[i]) + break; + if (i >= HW_BAND_MAX) + rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED; + } + } +#endif /* CONFIG_DFS_MASTER */ + + rfctl->radar_detect_by_others[band_idx] = by_others; + rfctl->radar_detect_cch[band_idx] = cch; + rfctl->radar_detect_bw[band_idx] = bw; + rfctl->radar_detect_freq_hi[band_idx] = rd_freq_hi; + rfctl->radar_detect_freq_lo[band_idx] = rd_freq_lo; +} + +static void rtw_dfs_rd_enable(struct rf_ctl_t *rfctl, u8 band_idx, u8 op_ch, u8 op_bw, u8 op_offset + , u32 rd_freq_hi, u32 rd_freq_lo, bool by_others) +{ +#ifdef CONFIG_DFS_MASTER + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + + RTW_INFO(FUNC_HWBAND_FMT" on %u,%u,%u\n", FUNC_HWBAND_ARG(band_idx), op_ch, op_bw, op_offset); + + if (rfctl->radar_detect_enabled && rfctl->radar_detect_hwband != band_idx) { + RTW_WARN(FUNC_HWBAND_FMT" radar_detect has been enabled for "HWBAND_FMT"\n" + , FUNC_HWBAND_ARG(band_idx), HWBAND_ARG(rfctl->radar_detect_hwband)); + rtw_warn_on(1); + return; + } + + if (!rfctl->radar_detect_enabled) { + RTW_INFO(FUNC_HWBAND_FMT" set radar_detect_enabled\n", FUNC_HWBAND_ARG(band_idx)); + rfctl->radar_detect_hwband = band_idx; + rfctl->radar_detect_enabled = 1; + //#ifdef CONFIG_LPS + //LPS_Leave(adapter, "RADAR_DETECT_EN"); + //#endif + _set_timer(&rfctl->radar_detect_timer + , rtw_dfs_hal_radar_detect_polling_int_ms(dvobj)); + } + rfctl->radar_detected = 0; + + rtw_dfs_update_rd_range_status(rfctl, band_idx, op_ch, op_bw, op_offset + , rd_freq_hi, rd_freq_lo, by_others); + + rtw_dfs_hal_update_region(dvobj, band_idx, rtw_rfctl_get_dfs_domain(rfctl)); + rtw_dfs_hal_radar_detect_enable(dvobj, band_idx, IS_CH_WAITING(rfctl), rd_freq_hi, rd_freq_lo); +#else + rtw_warn_on(1); +#endif +} + +static void rtw_dfs_rd_disable(struct rf_ctl_t *rfctl, u8 band_idx, u8 op_ch, u8 op_bw, u8 op_offset + , u32 rd_freq_hi, u32 rd_freq_lo, bool by_others) +{ +#ifdef CONFIG_DFS_MASTER + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + + if (rfctl->radar_detect_hwband == band_idx) { + if (rfctl->radar_detect_enabled) { + RTW_INFO(FUNC_HWBAND_FMT" clear radar_detect_enabled\n", FUNC_HWBAND_ARG(band_idx)); + rfctl->radar_detect_enabled = 0; + rfctl->radar_detected = 0; + _cancel_timer_ex(&rfctl->radar_detect_timer); + } + + rtw_dfs_hal_radar_detect_disable(dvobj, band_idx); + } +#endif + + if (by_others) { + rtw_dfs_update_rd_range_status(rfctl, band_idx, op_ch, op_bw, op_offset + , rd_freq_hi, rd_freq_lo, true); + } else + rtw_dfs_update_rd_range_status(rfctl, band_idx, 0, 0, 0, 0, 0, false); +} + +static bool _rtw_dfs_rd_en_decision(struct rf_ctl_t *rfctl, struct mi_state *mstate + , enum band_type u_band, u8 u_ch, enum channel_width u_bw, enum chan_offset u_offset + , u32 *rd_freq_hi, u32 *rd_freq_lo, bool *lgd_sta_in_dfs) +{ + bool overlap_dfs = u_ch ? rtw_chset_get_dfs_frange(&rfctl->chset, u_band, u_ch, u_bw, u_offset, rd_freq_hi, rd_freq_lo) : false; + bool needed = false; + + if (MSTATE_STA_LG_NUM(mstate) > 0) { + /* STA mode is linking */ + if (overlap_dfs) + *lgd_sta_in_dfs = true; + goto exit; + } + + if (MSTATE_STA_LD_NUM(mstate) > 0) { + if (overlap_dfs) { + /* + * if operate as slave w/o radar detect, + * rely on AP on which STA mode connects + */ + if (IS_DFS_SLAVE_WITH_RD(rfctl) && rtw_rfctl_radar_detect_supported(rfctl)) + needed = true; + *lgd_sta_in_dfs = true; + } + goto exit; + } + + if (!MSTATE_AP_NUM(mstate) && !MSTATE_MESH_NUM(mstate)) { + /* No working AP/Mesh mode */ + goto exit; + } + + if (!overlap_dfs) + goto exit; + + needed = true; + +exit: + return needed; +} + +static void rtw_dfs_rd_en_decision(struct dvobj_priv *dvobj, enum phl_band_idx hwband + , _adapter *adapter, struct _ADAPTER_LINK *alink, u8 mlme_act, u8 excl_ifbmp) +{ + struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj); + u8 band_idx; + + for (band_idx = HW_BAND_0; band_idx < HW_BAND_MAX; band_idx++) { + struct mi_state mstate; + u8 ifbmp; + enum band_type u_band; + u8 u_ch, u_bw, u_offset; + u32 rd_freq_hi, rd_freq_lo; + bool lgd_sta_in_dfs; + bool needed; + + /* hwband < HW_BAND_MAX means specific hwband */ + if (hwband < HW_BAND_MAX && hwband != band_idx) + continue; + + /* alink != NULL means specific hwband */ + if (alink && band_idx != ALINK_GET_HWBAND(alink)) + continue; + + rd_freq_hi = rd_freq_lo = 0; + lgd_sta_in_dfs = false; + needed = false; + + if (mlme_act == MLME_ACTION_NONE + || mlme_act == MLME_OPCH_SWITCH + ) { + ifbmp = ~excl_ifbmp; + rtw_mi_status_by_hwband_ifbmp(dvobj, band_idx, ifbmp, &mstate); + rtw_mi_get_bch_setting_union_by_hwband_ifbmp(dvobj, band_idx, ifbmp, &u_band, &u_ch, &u_bw, &u_offset); + + } else { + struct _ADAPTER_LINK *alink_by_hwband; + + if (alink) + alink_by_hwband = alink; + else + alink_by_hwband = rtw_get_adapter_link_by_hwband(adapter, band_idx); + + ifbmp = ~excl_ifbmp & ~BIT(adapter->iface_id); + rtw_mi_status_by_hwband_ifbmp(dvobj, band_idx, ifbmp, &mstate); + rtw_mi_get_bch_setting_union_by_hwband_ifbmp(dvobj, band_idx, ifbmp, &u_band, &u_ch, &u_bw, &u_offset); + + switch (mlme_act) { + case MLME_STA_CONNECTING: + MSTATE_STA_LG_NUM(&mstate)++; + break; + case MLME_STA_CONNECTED: + MSTATE_STA_LD_NUM(&mstate)++; + break; + case MLME_STA_DISCONNECTED: + break; + #ifdef CONFIG_AP_MODE + case MLME_AP_STARTED: + MSTATE_AP_NUM(&mstate)++; + break; + case MLME_AP_STOPPED: + break; + #endif + #ifdef CONFIG_RTW_MESH + case MLME_MESH_STARTED: + MSTATE_MESH_NUM(&mstate)++; + break; + case MLME_MESH_STOPPED: + break; + #endif + default: + rtw_warn_on(1); + break; + } + + if (alink_by_hwband) { + enum band_type band = ALINK_GET_BAND(alink_by_hwband); + u8 ch = ALINK_GET_CH(alink_by_hwband); + u8 bw = ALINK_GET_BW(alink_by_hwband); + u8 offset = ALINK_GET_OFFSET(alink_by_hwband); + + if (u_ch) { + if (!MLME_IS_OPCH_SW(adapter) && CHK_MLME_STATE(adapter, WIFI_UNDER_LINKING | WIFI_ASOC_STATE)) { + if (!rtw_is_bchbw_grouped(band, ch, bw, offset, u_band, u_ch, u_bw, u_offset)) { + RTW_WARN(FUNC_HWBAND_FMT" "ADPT_FMT" can't sync %u,%u,%u,%u with %u,%u,%u,%u\n" + , FUNC_HWBAND_ARG(band_idx), ADPT_ARG(adapter) + , band, ch, bw, offset, u_band, u_ch, u_bw, u_offset); + goto apply; + } + + rtw_sync_bchbw(&band, &ch, &bw, &offset, &u_band, &u_ch, &u_bw, &u_offset); + } + } else { + u_band = band; + u_ch = ch; + u_bw = bw; + u_offset = offset; + } + } + } + + needed = _rtw_dfs_rd_en_decision(rfctl, &mstate, u_band, u_ch, u_bw, u_offset + , &rd_freq_hi, &rd_freq_lo, &lgd_sta_in_dfs); + +apply: + if (adapter) + RTW_INFO(FUNC_HWBAND_FMT" needed:%d, lgd_sta_in_dfs:%d, "ADPT_FMT" mlme_act:%u, excl_ifbmp:0x%02x\n" + , FUNC_HWBAND_ARG(band_idx), needed, lgd_sta_in_dfs, ADPT_ARG(adapter), mlme_act, excl_ifbmp); + else + RTW_INFO(FUNC_HWBAND_FMT" needed:%d, lgd_sta_in_dfs:%d, excl_ifbmp:0x%02x\n" + , FUNC_HWBAND_ARG(band_idx), needed, lgd_sta_in_dfs, excl_ifbmp); + + RTW_INFO(FUNC_HWBAND_FMT" ld_sta:%u, lg_sta:%u, ap:%u, mesh:%u, %u,%u,%u,%u, rd_freq:%u~%u\n" + , FUNC_HWBAND_ARG(band_idx), MSTATE_STA_LD_NUM(&mstate), MSTATE_STA_LG_NUM(&mstate) + , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate) + , u_band, u_ch, u_bw, u_offset, rd_freq_lo, rd_freq_hi); + + if (needed && rtw_rfctl_radar_detect_supported(rfctl)) + rtw_dfs_rd_enable(rfctl, band_idx, u_ch, u_bw, u_offset, rd_freq_hi, rd_freq_lo, lgd_sta_in_dfs); + else { + rtw_dfs_rd_disable(rfctl, band_idx, u_ch, u_bw, u_offset, rd_freq_hi, rd_freq_lo, lgd_sta_in_dfs); + if (needed) { + _adapter *m_iface = rtw_mi_get_ap_mesh_iface_by_hwband(dvobj, band_idx); + u8 ifbmp_m = rtw_mi_get_ap_mesh_ifbmp_by_hwband(dvobj, band_idx); + u8 ifbmp_s = rtw_mi_get_lgd_sta_ifbmp_by_hwband(dvobj, band_idx); + + RTW_INFO(FUNC_HWBAND_FMT" radart detect for this region not supported\n", FUNC_HWBAND_ARG(band_idx)); + + if (!m_iface) { + rtw_warn_on(1); + return; + } + + if (rtw_hal_is_csa_support(m_iface) && !rtw_mr_is_ecsa_running(m_iface)) { + if (!rtw_hal_dfs_trigger_csa(m_iface, CSA_STA_DISCONNECT_ON_DFS, + band_idx, u_ch, u_bw, u_offset)) + RTW_ERR(FUNC_HWBAND_FMT" trigger ECSA fail", FUNC_HWBAND_ARG(band_idx)); + } else { + rtw_change_bss_bchbw_cmd(m_iface, RTW_CMDF_DIRECTLY + , ifbmp_m, ifbmp_s, REQ_BAND_NONE, REQ_CH_NONE, REQ_BW_ORI, REQ_OFFSET_NONE); + } + } + } + } +} + +void rtw_dfs_rd_en_dec_on_mlme_act(_adapter *adapter, struct _ADAPTER_LINK *alink, u8 mlme_act, u8 excl_ifbmp) +{ + if (adapter && mlme_act != MLME_ACTION_NONE) + rtw_dfs_rd_en_decision(adapter_to_dvobj(adapter), HW_BAND_MAX, adapter, alink, mlme_act, excl_ifbmp); + + rtw_warn_on(!adapter); + rtw_warn_on(mlme_act == MLME_ACTION_NONE); +} + +void dump_radar_detect_status(void *sel, struct rf_ctl_t *rfctl, const char *title) +{ + u8 hwband; + +#ifdef CONFIG_DFS_MASTER + for (hwband = HW_BAND_0; hwband < HW_BAND_MAX; hwband++) { + if (rfctl->radar_detect_enabled && hwband == rfctl->radar_detect_hwband) + break; + } +#else + hwband = HW_BAND_MAX; +#endif + if (hwband >= HW_BAND_MAX) { + for (hwband = HW_BAND_0; hwband < HW_BAND_MAX; hwband++) + if (rfctl->radar_detect_by_others[hwband]) + break; + } + + if (hwband < HW_BAND_MAX) { /* by self or only by others */ + RTW_PRINT_SEL(sel, "%s cch %u-%s" + , title + , rfctl->radar_detect_cch[hwband] + , ch_width_str(rfctl->radar_detect_bw[hwband]) + ); + +#ifdef CONFIG_DFS_MASTER + if (rfctl->radar_detect_enabled) { + u32 non_ocp_ms = 0; + u32 cac_ms = 0; + u8 dfs_domain = rtw_rfctl_get_dfs_domain(rfctl); + + _RTW_PRINT_SEL(sel, ", domain:%s(%u)", rtw_dfs_regd_str(dfs_domain), dfs_domain); + + if (IS_CH_WAITING(rfctl)) { + if (!IS_UNDER_CAC(rfctl)) { + non_ocp_ms = rtw_systime_to_ms(rfctl->cac_start_time - rtw_get_current_time()); + cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rfctl->cac_start_time); + } else + cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time()); + } + + if (non_ocp_ms) + _RTW_PRINT_SEL(sel, ", non_ocp:%d", non_ocp_ms); + if (cac_ms) + _RTW_PRINT_SEL(sel, ", cac:%d", cac_ms); + } else +#endif + _RTW_PRINT_SEL(sel, ", by AP of STA link"); + + _RTW_PRINT_SEL(sel, "\n"); + } +} +#endif /* CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ */ + +#ifdef CONFIG_DFS_MASTER +void rtw_dfs_rd_en_dec_update(struct dvobj_priv *dvobj, enum phl_band_idx hwband) +{ + rtw_dfs_rd_en_decision(dvobj, hwband, NULL, NULL, MLME_ACTION_NONE, 0); +} + +u8 rtw_dfs_rd_en_decision_cmd(struct dvobj_priv *dvobj, enum phl_band_idx hwband) +{ + struct cmd_obj *cmdobj; + struct drvextra_cmd_parm *parm; + struct cmd_priv *cmdpriv = &dvobj->cmdpriv; + _adapter *adapter = dvobj_get_primary_adapter(dvobj); + u8 res = _FAIL; + + cmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); + if (cmdobj == NULL) + goto exit; + + cmdobj->padapter = adapter; + + parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (parm == NULL) { + rtw_mfree(cmdobj, sizeof(struct cmd_obj)); + goto exit; + } + + parm->ec_id = DFS_RADAR_DETECT_EN_DEC_WK_CID; + parm->type = hwband; + parm->size = 0; + parm->pbuf = NULL; + + init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_DRV_EXTRA); + CMD_OBJ_SET_HWBAND(cmdobj, hwband); + res = rtw_enqueue_cmd(cmdpriv, cmdobj); + +exit: + return res; +} + +void rtw_indicate_cac_state_on_bss_start(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (IS_UNDER_CAC(rfctl)) { + u8 rd_hwband = rfctl->radar_detect_hwband; + + if (rtw_iface_is_operate_at_hwband(adapter, rd_hwband)) + rtw_os_indicate_cac_started(rfctl, rd_hwband, BIT(adapter->iface_id) + , rfctl->radar_detect_cch[rd_hwband], rfctl->radar_detect_bw[rd_hwband]); + } else { + u8 band_idx; + + for (band_idx = HW_BAND_0; band_idx < HW_BAND_MAX; band_idx++) { + if (!rfctl->radar_detect_by_others[band_idx]) + continue; + if (!rtw_iface_is_operate_at_hwband(adapter, band_idx)) + continue; + rtw_os_force_cac_finished(rfctl, band_idx, BIT(adapter->iface_id) + , rfctl->radar_detect_cch[band_idx], rfctl->radar_detect_bw[band_idx]); + } + } +} + +void rtw_indicate_cac_state_on_bss_stop(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (IS_UNDER_CAC(rfctl)) { + u8 rd_hwband = rfctl->radar_detect_hwband; + + if (rtw_iface_is_operate_at_hwband(adapter, rd_hwband)) + rtw_os_indicate_cac_aborted(rfctl, rd_hwband, BIT(adapter->iface_id) + , rfctl->radar_detect_cch[rd_hwband], rfctl->radar_detect_bw[rd_hwband]); + } +} +#endif /* CONFIG_DFS_MASTER */ + +/* choose channel with shortest waiting (non ocp + cac) time */ +static bool rtw_choose_shortest_waiting_ch(struct rf_ctl_t *rfctl + , enum band_type sel_band, u8 sel_ch, u8 max_bw, enum chan_offset sel_offset + , enum band_type *dec_band, u8 *dec_ch, u8 *dec_bw, u8 *dec_offset + , u8 e_flags, u8 d_flags, enum band_type cur_band, u8 cur_ch, enum chan_offset cur_offset + , bool by_int_info, u8 mesh_only) +{ +#ifndef DBG_CHOOSE_SHORTEST_WAITING_CH +#define DBG_CHOOSE_SHORTEST_WAITING_CH 0 +#endif + struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); + struct rtw_chset *chset = &rfctl->chset; + struct registry_priv *regsty = dvobj_to_regsty(dvobj); + enum band_type band; + u8 ch, bw, offset, r_offset[2], r_offset_num; + enum band_type band_c = BAND_MAX; + u8 ch_c = 0, bw_c = 0, offset_c = 0; + int i, j; + u32 min_waiting_ms = 0; + u16 int_factor_c = 0; + bool within_same_band = rfctl->ch_sel_within_same_band; + + if (!dec_ch || !dec_bw || !dec_offset) { + rtw_warn_on(1); + return _FALSE; + } + + RTW_INFO("%s: sel_ch:%s-%u(%u) max_bw:%u e_flags:0x%02x d_flags:0x%02x cur_ch:%s-%u(%u) within_sb:%d%s%s\n" + , __func__, band_str(sel_band), sel_ch, sel_offset, max_bw, e_flags, d_flags + , band_str(cur_band), cur_ch, cur_offset, within_same_band + , by_int_info ? " int" : "", mesh_only ? " mesh_only" : ""); + + if (sel_band != BAND_MAX && rtw_rfctl_is_regu_forbid_bss(rfctl, sel_band)) + goto exit; + if (sel_band == BAND_MAX && within_same_band && rtw_rfctl_is_regu_forbid_bss(rfctl, cur_band)) { + RTW_INFO("%s: cancel within_sb because REGU_FORBID for %s BSS", __func__, band_str(cur_band)); + within_same_band = false; + } + + /* full search and narrow bw judegement first to avoid potetial judegement timing issue */ + for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) { + if (!rtw_hw_is_bw_support(dvobj, bw)) + continue; + + for (i = 0; i < chset->chs_len; i++) { + u32 non_ocp_ms = 0; + u32 cac_ms = 0; + u32 waiting_ms = 0; + u16 int_factor = 0; + bool dfs_ch; + + if (chset->chs[i].flags & RTW_CHF_DIS) + continue; + + band = chset->chs[i].band; + ch = chset->chs[i].ChannelNum; + if (rtw_rfctl_is_regu_forbid_bss(rfctl, band)) + continue; + if (sel_band != BAND_MAX) { + if (band != sel_band) + continue; + } else if (within_same_band && cur_band != band) + continue; + if (sel_ch) { + if (ch != sel_ch) + continue; + } + + if (band == BAND_ON_24G) { + if (bw > REGSTY_BW_2G(regsty)) + continue; + #if CONFIG_IEEE80211_BAND_5GHZ + } else if (band == BAND_ON_5G) { + if (bw > REGSTY_BW_5G(regsty)) + continue; + #endif + #if CONFIG_IEEE80211_BAND_6GHZ + } else if (band == BAND_ON_6G) { + if (bw > REGSTY_BW_6G(regsty)) + continue; + #endif + } + + if (mesh_only && band == BAND_ON_24G && ch >= 5 && ch <= 9 && bw > CHANNEL_WIDTH_20) + continue; + + if (sel_offset == CHAN_OFFSET_NO_EXT || bw == CHANNEL_WIDTH_20) { + if (!rtw_get_offsets_by_bchbw(band, ch, bw, r_offset, &r_offset_num)) + continue; + } else { + r_offset[0] = sel_offset; + r_offset_num = 1; + } + + for (j = 0; j < r_offset_num; j++) { + offset = r_offset[j]; + if (!rtw_chset_is_bchbw_valid(chset, band, ch, bw, offset, 0, 0)) + continue; + + if ((e_flags & RTW_CHF_DFS) || (d_flags & RTW_CHF_DFS)) { + dfs_ch = rtw_chset_is_dfs_bchbw(chset, band, ch, bw, offset); + if (((e_flags & RTW_CHF_DFS) && !dfs_ch) + || ((d_flags & RTW_CHF_DFS) && dfs_ch)) + continue; + } + + #ifdef CONFIG_DFS_MASTER + waiting_ms = rtw_get_ch_waiting_ms(rfctl, band, ch, bw, offset, &non_ocp_ms, &cac_ms); + #endif + + #if 0 /* def CONFIG_RTW_ACS */ + if (by_int_info) { + /* for now, consider only primary channel */ + int_factor = hal_data->acs.interference_time[i]; + } + #endif + + if (DBG_CHOOSE_SHORTEST_WAITING_CH) + RTW_INFO("%s:%s,%u,%u,%u %u(non_ocp:%u, cac:%u), int:%u\n" + , __func__, band_str(band), ch, bw, offset, waiting_ms, non_ocp_ms, cac_ms, int_factor); + + if (ch_c == 0 + /* first: smaller wating time */ + || min_waiting_ms > waiting_ms + /* then: less interference */ + || (min_waiting_ms == waiting_ms && int_factor_c > int_factor) + /* then: wider bw */ + || (min_waiting_ms == waiting_ms && int_factor_c == int_factor && bw > bw_c) + /* if all condition equal, same channel&offset -> same channel -> same band prefer */ + || (min_waiting_ms == waiting_ms && int_factor_c == int_factor && bw == bw_c + && (((cur_band != band_c || cur_ch != ch_c || cur_offset != offset_c) + && (cur_band == band && cur_ch == ch && cur_offset == offset)) + || ((cur_band != band_c || cur_ch != ch_c) && (cur_band == band && cur_ch == ch)) + || (cur_band != band_c && cur_band == band)) + ) + ) { + band_c = band; + ch_c = ch; + bw_c = bw; + offset_c = offset; + min_waiting_ms = waiting_ms; + int_factor_c = int_factor; + } + } + } + } + +exit: + if (ch_c != 0) { + RTW_INFO("%s: select %s,%u,%u,%u waiting_ms:%u\n" + , __func__, band_str(band_c), ch_c, bw_c, offset_c, min_waiting_ms); + if (dec_band) + *dec_band = band_c; + *dec_ch = ch_c; + *dec_bw = bw_c; + *dec_offset = offset_c; + return _TRUE; + } else { + RTW_INFO("%s: not found\n", __func__); + if (d_flags == 0) + rtw_warn_on(1); + } + + return _FALSE; +} + +bool rtw_rfctl_choose_bchbw(struct rf_ctl_t *rfctl + , enum band_type sel_band, u8 sel_ch, u8 max_bw, enum chan_offset sel_offset + , enum band_type cur_band, u8 cur_ch, enum chan_offset cur_offset + , enum band_type *band, u8 *ch, u8 *bw, u8 *offset + , bool by_int_info, u8 mesh_only, const char *caller) +{ + bool ch_avail = _FALSE; + +#if defined(CONFIG_DFS_MASTER) + if (rtw_rfctl_radar_detect_supported(rfctl)) { + if (rfctl->radar_detected + && rfctl->dbg_dfs_choose_dfs_ch_first + ) { + ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_band, sel_ch, max_bw, sel_offset + , band, ch, bw, offset + , RTW_CHF_DFS, 0 + , cur_band, cur_ch, cur_offset, by_int_info, mesh_only); + if (ch_avail == _TRUE) { + RTW_INFO("%s choose 5G DFS channel for debug\n", caller); + goto exit; + } + } + + if (rfctl->radar_detected + && (rfctl->dfs_ch_sel_e_flags || rfctl->dfs_ch_sel_d_flags) + ) { + ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_band, sel_ch, max_bw, sel_offset + , band, ch, bw, offset + , rfctl->dfs_ch_sel_e_flags, rfctl->dfs_ch_sel_d_flags + , cur_band, cur_ch, cur_offset, by_int_info, mesh_only); + if (ch_avail == _TRUE) { + RTW_INFO("%s choose with dfs_ch_sel_ e_flags:0x%02x d_flags:0x%02x for debug\n" + , caller, rfctl->dfs_ch_sel_e_flags, rfctl->dfs_ch_sel_d_flags); + goto exit; + } + } + + ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_band, sel_ch, max_bw, sel_offset + , band, ch, bw, offset + , 0, 0 + , cur_band, cur_ch, cur_offset, by_int_info, mesh_only); + } else +#endif /* defined(CONFIG_DFS_MASTER) */ + { + ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_band, sel_ch, max_bw, sel_offset + , band, ch, bw, offset + , 0, RTW_CHF_DFS + , cur_band, cur_ch, cur_offset, by_int_info, mesh_only); + } +#if defined(CONFIG_DFS_MASTER) +exit: +#endif + if (ch_avail == _FALSE) + RTW_WARN("%s no available channel\n", caller); + + return ch_avail; +} + +#if CONFIG_ALLOW_FUNC_2G_5G_ONLY +RTW_FUNC_2G_5G_ONLY bool rtw_rfctl_choose_chbw(struct rf_ctl_t *rfctl, u8 sel_ch, u8 max_bw, enum chan_offset sel_offset + , u8 cur_ch, enum chan_offset cur_offset, u8 *ch, u8 *bw, u8 *offset, bool by_int_info, u8 mesh_only, const char *caller) +{ + enum band_type sel_band = sel_ch ? (rtw_is_2g_ch(sel_ch) ? BAND_ON_24G : BAND_ON_5G) : BAND_MAX; + enum band_type cur_band = rtw_is_2g_ch(cur_ch) ? BAND_ON_24G : BAND_ON_5G; + enum band_type *band = NULL; + + return rtw_rfctl_choose_bchbw(rfctl + , sel_band, sel_ch, max_bw, sel_offset + , cur_band, cur_ch, cur_offset + , band, ch, bw, offset + , by_int_info, mesh_only, caller); +} +#endif + +void rtw_rfctl_dfs_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty) +{ + rfctl->ch_sel_within_same_band = 1; + +#ifdef CONFIG_DFS_MASTER + rfctl->dfs_region_domain = regsty->dfs_region_domain; + if (!rtw_dfs_hal_region_supported(rfctl_to_dvobj(rfctl), rfctl->dfs_region_domain)) { + RTW_WARN("%s DFS region domain: %s is not supported by HAL, set to %s\n", __func__ + , rtw_dfs_regd_str(rfctl->dfs_region_domain), rtw_dfs_regd_str(RTW_DFS_REGD_NONE)); + rfctl->dfs_region_domain = RTW_DFS_REGD_NONE; + } + rfctl->non_ocp_finished = true; + rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED; + rtw_init_timer(&(rfctl->radar_detect_timer), rtw_dfs_rd_timer_hdl, rfctl); +#endif + +#if CONFIG_DFS_SLAVE_WITH_RADAR_DETECT + rfctl->dfs_slave_with_rd = 1; +#endif +} + diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.h b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.h new file mode 100644 index 00000000..f726c12d --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_dfs.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2022 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef __RTW_DFS_H__ +#define __RTW_DFS_H__ + +#define CAC_TIME_MS (60*1000) +#define CAC_TIME_CE_MS (10*60*1000) +#define NON_OCP_TIME_MS (30*60*1000) + +#define RTW_CAC_STOPPED 0 /* used by cac_start_time, cac_end_time time stamps */ +#define RTW_NON_OCP_STOPPED 0 /* used by non_ocp_end_time time stamps */ + +bool rtw_chset_is_dfs_range(const struct rtw_chset *chset, u32 hi, u32 lo); +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_dfs_ch(const struct rtw_chset *chset, u8 ch); +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_dfs_chbw(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset); +bool rtw_chset_is_dfs_bch(const struct rtw_chset *chset, enum band_type band, u8 ch); +bool rtw_chset_is_dfs_bchbw(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset); + +enum rtw_dfs_regd rtw_rfctl_get_dfs_domain(struct rf_ctl_t *rfctl); +bool rtw_rfctl_radar_detect_supported(struct rf_ctl_t *rfctl); + +#ifdef CONFIG_DFS_MASTER +struct rf_ctl_t; +enum phl_band_idx; + +#define CH_IS_NON_OCP_STOPPED(rt_ch_info) ((rt_ch_info)->non_ocp_end_time == RTW_NON_OCP_STOPPED) +#define CH_IS_NON_OCP(rt_ch_info) (!CH_IS_NON_OCP_STOPPED(rt_ch_info) && rtw_time_after((rt_ch_info)->non_ocp_end_time, rtw_get_current_time())) + +bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset); +bool adapter_is_tx_blocked_by_ch_waiting(_adapter *adapter); +bool alink_is_tx_blocked_by_ch_waiting(struct _ADAPTER_LINK *alink); + +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_chbw_non_ocp(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset); +RTW_FUNC_2G_5G_ONLY bool rtw_chset_is_ch_non_ocp(const struct rtw_chset *chset, u8 ch); +bool rtw_chset_is_bchbw_non_ocp(const struct rtw_chset *chset, enum band_type band, u8 ch, u8 bw, u8 offset); +bool rtw_chset_is_bch_non_ocp(const struct rtw_chset *chset, enum band_type band, u8 ch); + +void rtw_rfctl_chset_chk_non_ocp_finish(struct rf_ctl_t *rfctl); + +void rtw_rfctl_force_update_non_ocp_ms(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset, int ms); + +u32 rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, enum band_type band, u8 ch, u8 bw, u8 offset, u32 *r_non_ocp_ms, u32 *r_cac_ms); + +u32 rtw_force_stop_cac(struct rf_ctl_t *rfctl, u32 timeout_ms); + +u8 rtw_dfs_rd_hdl(struct dvobj_priv *dvobj, enum phl_band_idx hwband, u8 radar_cch, enum channel_width radar_bw); + +void rtw_dfs_rd_en_dec_update(struct dvobj_priv *dvobj, enum phl_band_idx hwband); +u8 rtw_dfs_rd_en_decision_cmd(struct dvobj_priv *dvobj, enum phl_band_idx hwband); + +void rtw_indicate_cac_state_on_bss_start(_adapter *adapter); +void rtw_indicate_cac_state_on_bss_stop(_adapter *adapter); + +#else +#define CH_IS_NON_OCP(rt_ch_info) 0 +#define adapter_is_tx_blocked_by_ch_waiting(adapter) false +#define alink_is_tx_blocked_by_ch_waiting(alink) false + +RTW_FUNC_2G_5G_ONLY static inline bool rtw_chset_is_chbw_non_ocp(const struct rtw_chset *chset, u8 ch, u8 bw, u8 offset) { return false; } +RTW_FUNC_2G_5G_ONLY static inline bool rtw_chset_is_ch_non_ocp(const struct rtw_chset *chset, u8 ch) { return false; } +#define rtw_chset_is_bchbw_non_ocp(chset, band, ch, bw, offset) false +#define rtw_chset_is_bch_non_ocp(chset, band, ch) false +#endif /* CONFIG_DFS_MASTER */ + +#if CONFIG_DFS && CONFIG_IEEE80211_BAND_5GHZ +void rtw_dfs_rd_en_dec_on_mlme_act(_adapter *adapter, struct _ADAPTER_LINK *alink, u8 mlme_act, u8 excl_ifbmp); +void dump_radar_detect_status(void *sel, struct rf_ctl_t *rfctl, const char *title); +#endif + +bool rtw_rfctl_choose_bchbw(struct rf_ctl_t *rfctl + , enum band_type sel_band, u8 sel_ch, u8 max_bw, enum chan_offset sel_offset + , enum band_type cur_band, u8 cur_ch, enum chan_offset cur_offset + , enum band_type *band, u8 *ch, u8 *bw, u8 *offset + , bool by_int_info, u8 mesh_only, const char *caller); + +RTW_FUNC_2G_5G_ONLY bool rtw_rfctl_choose_chbw(struct rf_ctl_t *rfctl, u8 sel_ch, u8 max_bw, enum chan_offset sel_offset + , u8 cur_ch, enum chan_offset cur_offset, u8 *ch, u8 *bw, u8 *offset, bool by_int_info, u8 mesh_only, const char *caller); + +void rtw_rfctl_dfs_init(struct rf_ctl_t *rfctl, struct registry_priv *regsty); + +#endif /* __RTW_DFS_H__ */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_eht.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_eht.c new file mode 100644 index 00000000..0d92c764 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_eht.c @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _RTW_EHT_C + +#include + +#ifdef CONFIG_80211BE_EHT + +void rtw_set_assoc_status(_adapter *padapter, struct rtw_phl_mld_t *pmld, u8 link_id, u16 status) +{ + u8 i; + for (i = 0; i < padapter->phl_role->rlink_num; i++) { + if (pmld->assoc_status[i].used) + continue; + pmld->assoc_status[i].link_id = link_id; + pmld->assoc_status[i].status = status; + pmld->assoc_status[i].used = 1; + break; + } +} + +void rtw_update_ies_with_inheritance(u8 *cur_ies, u32 *cur_ies_len, u8 *inh_ies, u8 inh_ies_len) +{ + u8 *non_inh_ele, non_inh_ele_len; + u8 i, j; + struct _NDIS_802_11_VARIABLE_IEs *pIE = NULL; + + /* Remove the non-inherited elements*/ + for (i = 0; i < inh_ies_len;) { + pIE = (struct _NDIS_802_11_VARIABLE_IEs *)(inh_ies + i); + + if (pIE->ElementID == WLAN_EID_EXTENSION && + pIE->data[0] == EID_EXT_NON_INHERITANCE) { + /* Non-inherited elements */ + non_inh_ele = &pIE->data[0] + 1; + non_inh_ele_len = *non_inh_ele++; + for (j = 0; j < non_inh_ele_len; j++) { + rtw_ies_remove_ie(cur_ies, cur_ies_len, 0, *non_inh_ele, NULL, 0); + non_inh_ele++; + } + /* Non-inherited extension elements */ + non_inh_ele_len = *non_inh_ele++; + for (j = 0; j < non_inh_ele_len; j++) { + rtw_ies_remove_ie(cur_ies, cur_ies_len, 0, WLAN_EID_EXTENSION, non_inh_ele, 1); + non_inh_ele++; + } + } else if (pIE->ElementID == WLAN_EID_EXTENSION) { /* Update extension IEs */ + rtw_ies_remove_ie(cur_ies, cur_ies_len, 0, WLAN_EID_EXTENSION, &pIE->data[0], 1); + rtw_set_ie(cur_ies + *cur_ies_len, WLAN_EID_EXTENSION, + pIE->Length, pIE->data, cur_ies_len); + } else { /* Update IEs */ + rtw_ies_remove_ie(cur_ies, cur_ies_len, 0, pIE->ElementID, NULL, 0); + rtw_set_ie(cur_ies + *cur_ies_len, pIE->ElementID, + pIE->Length, pIE->data, cur_ies_len); + } + i += (pIE->Length + 2); + } +} + +void assoc_rsp_per_sta_profile_handler(_adapter *padapter, + struct rtw_phl_per_sta_profile_element *profile, + u8 *primary_ies, u32 primary_ies_len) +{ + struct _ADAPTER_LINK *cur_link = NULL; + u8 cur_ies[MAX_IE_SZ]; + u32 cur_ies_len = 0; + struct rtw_phl_mld_t *pmld = NULL; + unsigned short status; + u8 eid_eht_ml = EID_EXT_MULTI_LINK; + + pmld = rtw_phl_get_mld_self(GET_PHL_INFO(adapter_to_dvobj(padapter)), padapter->phl_role); + cur_link = rtw_get_adapter_link_by_linkid(padapter, profile->link_id); + + if (!cur_link) + goto _exit; + + /* status */ + status = le16_to_cpu(*(unsigned short *)(profile->sta_profile + 2)); + rtw_set_assoc_status(padapter, pmld, profile->link_id, status); + if (status != _STATS_SUCCESSFUL_) { + RTW_INFO("assoc reject for link (link_id = %d), status code: %d\n", + profile->link_id, status); + goto _exit; + } + cur_link->mlmepriv.is_accepted = _TRUE; + /* get capabilities */ + cur_link->mlmeextpriv.mlmext_info.capability = + le16_to_cpu(*(unsigned short *)(profile->sta_profile)); + /* set slot time */ + cur_link->mlmeextpriv.mlmext_info.slotTime = + (cur_link->mlmeextpriv.mlmext_info.capability & BIT(10)) ? 9 : 20; + + _rtw_memcpy(cur_ies, primary_ies, primary_ies_len); + cur_ies_len = primary_ies_len; + + + /* Remove ML IEs for other links */ + rtw_ies_remove_ie(cur_ies, &cur_ies_len, 0, WLAN_EID_EXTENSION, &eid_eht_ml, 1); + + /* Update cur_ies */ + rtw_update_ies_with_inheritance(cur_ies, &cur_ies_len, + profile->sta_profile + 4, profile->sta_profile_len - 4); + + rtw_ie_handler(padapter, cur_link, cur_ies, cur_ies_len); + +_exit: + return; +} + +u32 rtw_parse_ml_ie(_adapter *padapter, u8 *ies, u32 ies_len, + struct rtw_phl_ml_element *ml_ele) +{ + struct rtw_phl_com_t *phl_com = GET_PHL_COM(adapter_to_dvobj(padapter)); + u8 eid_eht_ml = EID_EXT_MULTI_LINK; + u32 eht_ml_ie_len; + u8 *p; + + p = rtw_get_ie_ex(ies, ies_len, WLAN_EID_EXTENSION, + &eid_eht_ml, 1, NULL, &eht_ml_ie_len); + + if (p == NULL || eht_ml_ie_len < EHT_ML_BASIC_MIN_LEN) + return 0; + + rtw_phl_parse_ml_ie(phl_com, p + 3, eht_ml_ie_len - 3, ml_ele); + return eht_ml_ie_len; +} + +void EHT_ml_ie_handler(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *primary_ies, u32 primary_ies_len) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlo_priv *pmlopriv = &pmlmepriv->mlopriv; + struct rtw_phl_ml_element ml_ele = {0}; + u8 lidx; + + if (!rtw_parse_ml_ie(padapter, primary_ies, primary_ies_len, &ml_ele)) + return; + + for (lidx = 0; lidx < ml_ele.profile_num; lidx++) + assoc_rsp_per_sta_profile_handler(padapter, &ml_ele.profile[lidx], + primary_ies, primary_ies_len); + +} + +void EHT_tid2link_ie_handler(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *ies, u32 ies_len) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlo_priv *pmlopriv = &pmlmepriv->mlopriv; + struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv; + struct link_mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + WLAN_BSSID_EX *cur_network = &pmlmeinfo->network; + struct sta_info *psta = NULL; + u8 eid_eht_tid2link = EID_EXT_TID_TO_LINK_MAPPING; + u32 eht_tid2link_ie_len; + u8 *p; + + if (pmlopriv->tid2link_nego == _FALSE) + return; + + psta = rtw_get_stainfo(&padapter->stapriv, cur_network->MacAddress); + + if (!psta) + return; + + /* TID-To_Link Mapping IE */ + p = rtw_get_ie_ex(ies, ies_len, WLAN_EID_EXTENSION, + &eid_eht_tid2link, 1, NULL, &eht_tid2link_ie_len); + + if (p == NULL) + rtw_phl_tid2link_not_present(psta->phl_sta, pmlopriv->tid2link_nego); + else + rtw_phl_parse_tid2link(psta->phl_sta, p + 3, eht_tid2link_ie_len - 3); +} + +void rtw_eht_ml_ies_handler(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, + u8 *ies, u32 ies_len) +{ + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlo_priv *pmlopriv = &pmlmepriv->mlopriv; + + if (pmlopriv->mlo_option == _FALSE) + return; + + /* ML IE */ + EHT_ml_ie_handler(padapter, padapter_link, ies, ies_len); + + /* TID-to-Link IE */ + EHT_tid2link_ie_handler(padapter, padapter_link, ies, ies_len); +} + +u8 build_inherited_ies(u8 *cur_ies, u32 cur_ies_len, u8 *primary_ies, u32 primary_ies_len, u8 *sta_ies) +{ + PNDIS_802_11_VARIABLE_IEs sIE = NULL; + u8 *p; + u32 i; + u32 len; + u8 nih_eles[256]; + u8 nih_eles_len = 0; + u8 nih_ext_eles[256]; + u8 nih_ext_eles_len = 0; + u32 sta_ies_len = 0; + + /* Build per sta IEs */ + for (i = 0; i < cur_ies_len;) { + sIE = (struct _NDIS_802_11_VARIABLE_IEs *)(cur_ies + i); + if (sIE->ElementID == WLAN_EID_EXTENSION) { + p = rtw_get_ie_ex(primary_ies, primary_ies_len, + WLAN_EID_EXTENSION, &sIE->data[0], 1, NULL, &len); + len -= 2; + } + else + p = rtw_get_ie(primary_ies, sIE->ElementID, &len, primary_ies_len); + + /* Skip the same IEs */ + if (p == NULL) /* Element only exists in cur_ies */ + rtw_set_ie(sta_ies + sta_ies_len, sIE->ElementID, sIE->Length, sIE->data, &sta_ies_len); + else if ((sIE->Length != len || !_rtw_memcmp(sIE->data, p + 2, len)) /* Element is different between primary_ies and cur_ies */ + && (sIE->ElementID != WLAN_EID_VENDOR_SPECIFIC)) /* skip vendor specific */ + rtw_set_ie(sta_ies + sta_ies_len, sIE->ElementID, sIE->Length, sIE->data, &sta_ies_len); + + i += (sIE->Length + 2); + } + + /* Get non-inherited elements */ + nih_eles[nih_eles_len++] = EID_EXT_NON_INHERITANCE; + nih_eles_len++; /* Skip length first */ + for (i = 0; i < primary_ies_len;) { + sIE = (struct _NDIS_802_11_VARIABLE_IEs *)(primary_ies + i); + if (sIE->ElementID == WLAN_EID_EXTENSION) { + p = rtw_get_ie_ex(cur_ies, cur_ies_len, + WLAN_EID_EXTENSION, &sIE->data[0], 1, NULL, &len); + if (p == NULL) + nih_ext_eles[nih_ext_eles_len++] = sIE->data[0]; + } + else { + p = rtw_get_ie(cur_ies, sIE->ElementID, &len, cur_ies_len); + if (p == NULL) + nih_eles[nih_eles_len++] = sIE->ElementID; + } + i += (sIE->Length + 2); + } + + /* Append non-inherited element IE */ + nih_eles[1] = nih_eles_len - 2; + nih_eles[nih_eles_len++] = nih_ext_eles_len; + for (i = 0; i < nih_ext_eles_len; i++) + nih_eles[nih_eles_len++] = nih_ext_eles[i]; + if (nih_eles_len > 3) /* non-inherited elements exist */ + rtw_set_ie(sta_ies + sta_ies_len, WLAN_EID_EXTENSION, nih_eles_len, nih_eles, &sta_ies_len); + + return (u8)sta_ies_len; +} + +int build_link_assocreq_ies(_adapter *padapter, struct _ADAPTER_LINK *cur_link, u8 *cur_ies, u32 *cur_ies_len, u8 is_reassoc) +{ + struct pkt_attrib cur_attrib = {0}; + int ret; + + cur_attrib.adapter_link = cur_link; + ret = rtw_build_assocreq_ies(padapter, cur_link, cur_ies, &cur_attrib, is_reassoc); + *cur_ies_len = cur_attrib.pktlen; + + return ret; +} + +void build_link_probersp_ies(_adapter *padapter, struct _ADAPTER_LINK *cur_link, u8 *cur_ies, u32 *cur_ies_len, + u8 is_valid_p2p_probereq) +{ + struct pkt_attrib cur_attrib = {0}; + + cur_attrib.adapter_link = cur_link; + rtw_build_probersp_ies(padapter, cur_link, cur_ies, &cur_attrib, is_valid_p2p_probereq); + *cur_ies_len = cur_attrib.pktlen; + +} + +u8 _build_ml_sta_profile(_adapter *padapter, struct _ADAPTER_LINK *cur_link, struct sta_info *cur_sta, + enum phl_packet_type pkt_type, u8 *primary_ies, u32 primary_ies_len, u8 *ies, u8 reserved) +{ + u8 cur_ies[MAX_IE_SZ] = {0}; + u32 cur_ies_len = 0; + u8 offset; + u8 ies_len = 0; + + switch(pkt_type) { + case PACKET_ASSOC_REQUEST: + if (reserved) /* reassoc_req */ + offset = _REASOCREQ_IE_OFFSET_; + else + offset = _ASOCREQ_IE_OFFSET_; + if (build_link_assocreq_ies(padapter, cur_link, cur_ies, &cur_ies_len, reserved) + != _SUCCESS) /* don't request the current link if no joint supported rate */ + goto _exit; + /* capability */ + _rtw_memcpy(ies, cur_ies, 2); + ies_len += 2; + /* skip listen interval and current AP field */ + ies_len += build_inherited_ies(cur_ies + offset, cur_ies_len - offset, + primary_ies + offset, primary_ies_len - offset, + ies + ies_len); + break; + case PACKET_ASSOC_RESPONSE: + /* ToDo */ + break; + case PACKET_PROBE_RESPONSE_ML: + offset = _PROBERSP_IE_OFFSET_; + build_link_probersp_ies(padapter, cur_link, cur_ies, &cur_ies_len, reserved); + /* copy capabilities */ + _rtw_memcpy(ies, (unsigned char *)(rtw_get_capability_from_ie(cur_ies)) , 2); + ies_len += 2; + ies_len += build_inherited_ies(cur_ies + offset, cur_ies_len - offset, + primary_ies + offset, primary_ies_len - offset, + ies + ies_len); + break; + default: + break; + } + +_exit: + return ies_len; +} + +u8 *rtw_build_ml_ies(_adapter *padapter, struct sta_info *psta, u8 *pframe, struct pkt_attrib *pattrib, + enum phl_packet_type pkt_type, u8 *primary_ies, u32 primary_ies_len, u8 reserved) +{ + struct dvobj_priv *d = adapter_to_dvobj(padapter); + struct _ADAPTER_LINK *padapter_link = pattrib->adapter_link; + u32 len = 0; + struct rtw_phl_ml_ie_info info = {0}; + u8 lidx; + u8 profiles[256] = {0}; + struct rtw_phl_mld_t *pmld; + u8 critical_update = 0; + u32 total_len = 0; + + if (psta) + info.mld = psta->phl_sta->mld; + else + info.mld = rtw_phl_get_mld_self(GET_PHL_INFO(d), padapter->phl_role); + info.pkt_type = pkt_type; + info.rlink = padapter_link->wrlink; + + /* The following types need to append link info */ + switch(pkt_type) { + case PACKET_BEACON: + /* ToDo CONFIG_RTW_MLD: Get the critical update value */ + info.critical_update = critical_update; + break; + case PACKET_ASSOC_REQUEST: + /* Multilink Element */ + /* Append the to_join link info */ + for (lidx = 0; lidx < padapter->adapter_link_num; lidx++) { + struct _ADAPTER_LINK *alink = NULL; + struct rtw_phl_per_sta_profile_info ml_sta_info = {0}; + u8 sta_profile[256] = {0}; + + alink = GET_LINK(padapter, lidx); + if (alink == padapter_link || !alink->mlmepriv.to_join) + continue; + + ml_sta_info.pkt_type = pkt_type; + ml_sta_info.mld = rtw_phl_get_mld_self(GET_PHL_INFO(d), padapter->phl_role); + ml_sta_info.rlink = alink->wrlink; + ml_sta_info.link_id = alink->mlmepriv.link_id; + ml_sta_info.sta_profile_len = _build_ml_sta_profile(padapter, alink, NULL, pkt_type, primary_ies, + primary_ies_len, sta_profile, reserved); + ml_sta_info.sta_profile = sta_profile; + len = rtw_phl_build_per_sta_profile(GET_PHL_COM(d), &ml_sta_info, profiles + info.opt_len); + info.opt_len += len; + } + info.opt = profiles; + total_len += rtw_phl_build_ml_ie(GET_PHL_COM(d), &info, pframe); + + /* TID-to-Link Mapping Element */ + if (padapter->mlmepriv.mlopriv.tid2link_nego) + total_len += rtw_phl_build_tid2link(padapter_link->wrlink, pframe + total_len); + + break; + case PACKET_ASSOC_RESPONSE: + /* ToDo */ + break; + case PACKET_PROBE_RESPONSE_ML: + for (lidx = 0; lidx < padapter->adapter_link_num; lidx++) { + struct _ADAPTER_LINK *alink = NULL; + struct rtw_phl_per_sta_profile_info ml_sta_info = {0}; + u8 sta_profile[256] = {0}; + + alink = GET_LINK(padapter, lidx); + /* Skip the primary adapter_link and the link without ready content */ + if (alink == padapter_link || !alink->mlmepriv.cur_network.join_res) + continue; + + ml_sta_info.pkt_type = pkt_type; + ml_sta_info.mld = rtw_phl_get_mld_self(GET_PHL_INFO(d), padapter->phl_role); + ml_sta_info.rlink = alink->wrlink; + ml_sta_info.link_id = alink->wrlink->id; + ml_sta_info.complete_profile = _TRUE; + ml_sta_info.sta_profile_len = _build_ml_sta_profile(padapter, alink, NULL, pkt_type, primary_ies, + primary_ies_len, sta_profile, reserved); + ml_sta_info.sta_profile = sta_profile; + len = rtw_phl_build_per_sta_profile(GET_PHL_COM(d), &ml_sta_info, profiles + info.opt_len); + info.opt_len += len; + } + info.opt = profiles; + total_len += rtw_phl_build_ml_ie(GET_PHL_COM(d), &info, pframe); + break; + default: + total_len += rtw_phl_build_ml_ie(GET_PHL_COM(d), &info, pframe); + break; + } + + pattrib->pktlen += total_len; + + return pframe + total_len; +} + +u32 rtw_restructure_ml_ie(_adapter *padapter, + struct _ADAPTER_LINK *padapter_link, + u8 *in_ie, u8 *out_ie, uint in_len, + uint *pout_len) +{ + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlo_priv *pmlopriv = &pmlmepriv->mlopriv; + struct rtw_phl_ml_ie_info info = {0}; + struct rtw_phl_ml_element ml_ele = {0}; + + if (!rtw_parse_ml_ie(padapter, in_ie + _FIXED_IE_LENGTH_, in_len - _FIXED_IE_LENGTH_, &ml_ele)) + goto exit; + + pmlopriv->mlo_option = _TRUE; + + if (ml_ele.common_info.basic_ml.mld_cap.tid_to_link_nego_support) + pmlopriv->tid2link_nego = _TRUE; + + info.mld = rtw_phl_get_mld_self(GET_PHL_INFO(adapter_to_dvobj(padapter)), padapter->phl_role); + info.pkt_type = PACKET_BEACON; + info.rlink = padapter_link->wrlink; + + *pout_len += rtw_phl_build_ml_ie(GET_PHL_COM(adapter_to_dvobj(padapter)), &info, out_ie + *pout_len); + +exit: + return pmlopriv->mlo_option; +} + +#endif /* CONFIG_80211BE_EHT */ diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fake_ap.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fake_ap.c new file mode 100755 index 00000000..98d47dfe --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fake_ap.c @@ -0,0 +1,480 @@ +/****************************************************************************** + * + * Copyright(c) 2019 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#include + +static const u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +#ifdef RTW_PHL_TEST_FPGA +static const u8 ap_addr[ETH_ALEN] = {0x00, 0xe0, 0x4c, 0x88, 0x52, 0xa0}; +u8 ap_ssid[] = {'p','h','l','-','5','g'}; +#else +static const u8 ap_addr[ETH_ALEN] = {0x00, 0xe0, 0x4c, 0x12, 0x34, 0x56}; +u8 ap_ssid[] = {'f','a','k','e','a','p'}; +#endif +u8 ap_ch = 1; +u16 ap_beacon_interval = 100; /* unit: ms */ +u16 ap_capability_info = 0x0001; +u8 ap_datarate[] = {0x82, 0x84, 0x8b, 0x96, 0xc, 0x12, 0x18, 0x24}; + +int rtw_fakeap_tx(struct _ADAPTER *a, struct xmit_frame *frame) +{ + u8 *data = frame->buf_addr + TXDESC_OFFSET; + u32 data_len = frame->attrib.last_txcmdsz; + struct sk_buff *skb; + u8 *buf; + + + if (GetFrameType(data) != WIFI_MGT_TYPE) + return _FAIL; + + switch (get_frame_sub_type(data)) { + case WIFI_AUTH: + case WIFI_ASSOCREQ: + case WIFI_REASSOCREQ: + case WIFI_PROBEREQ: + break; + + default: + return _FAIL; + } + + skb = rtw_skb_alloc(data_len); + buf = skb_put(skb, data_len); + _rtw_memcpy(buf, data, data_len); + rtw_free_xmitbuf(&a->xmitpriv, frame->pxmitbuf); + rtw_free_xmitframe(&a->xmitpriv, frame); + + skb_queue_tail(&adapter_to_dvobj(a)->fakeap.rxq, skb); + _set_workitem(&adapter_to_dvobj(a)->fakeap.work); + + return _SUCCESS; +} + +static void add_ie(struct sk_buff *skb, u8 index, u8 len, const u8 *source) +{ + u8 *buf; + + + buf = skb_put(skb, 2 + len); + *buf = index; + *(buf + 1) = len; + if (len > 0) + _rtw_memcpy(buf + 2, source, len); +} + +void rtw_fakeap_bcn_timer_hdl(void *p) +{ + struct dvobj_priv *d; + struct sk_buff *skb; + struct rtw_ieee80211_hdr *wlanhdr; + int len; + u8 *buf; + u8 hdrlen; + + + d = (struct dvobj_priv*)p; + hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + len = hdrlen + _FIXED_IE_LENGTH_ + + 2 + sizeof(ap_ssid) + + 2 + sizeof(ap_datarate) + + 2 + 1; + skb = rtw_skb_alloc(len); + _rtw_memset(skb->data, 0, len); + + buf = skb_put(skb, hdrlen); + wlanhdr = (struct rtw_ieee80211_hdr*)buf; + set_frame_sub_type(&wlanhdr->frame_ctl, WIFI_BEACON); + _rtw_memcpy(wlanhdr->addr1, bcast_addr, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr2, ap_addr, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr3, ap_addr, ETH_ALEN); + + buf = skb_put(skb, _FIXED_IE_LENGTH_); + /* timestamp: 8 bytes */ + /* beacon interval: 2 bytes */ + *(u16*)(buf + 8) = ap_beacon_interval; + /* capability info: 2 bytes */ + *(u16*)(buf + 10) = ap_capability_info; + + /* SSID */ + add_ie(skb, _SSID_IE_, sizeof(ap_ssid), ap_ssid); + + /* supported rates... */ + add_ie(skb, _SUPPORTEDRATES_IE_, sizeof(ap_datarate), ap_datarate); + + /* DS parameter set */ + add_ie(skb, _DSSET_IE_, 1, &ap_ch); + + skb_queue_tail(&d->fakeap.rxq, skb); + _set_workitem(&d->fakeap.work); +} + +static void rx_prepare(struct _ADAPTER *adapter, union recv_frame *r) +{ + struct rx_pkt_attrib *a; + + + /* init recv_frame */ + _rtw_init_listhead(&r->u.hdr.list); + r->u.hdr.len = 0; + a = &r->u.hdr.attrib; + _rtw_memset(a, 0, sizeof(*a)); + + /* fill sec related attrib, iv_len and icv_len will be filled by + * validate_recv_data_frame() */ + a->crc_err = 0; + a->icv_err = 0; + a->encrypt = 0; + + /* fill rx pkt attrib */ + a->hdrlen = 0; + a->bw = CHANNEL_WIDTH_MAX; + a->pkt_len = 0; + a->pkt_rpt_type = NORMAL_RX; + a->drvinfo_sz = 0; + a->bdecrypted = 0; + a->qos = 0; + a->priority = 0; + a->amsdu = 0; + a->mdata = 0; + a->mfrag = 0; + a->seq_num = 0; + a->frag_num = 0; + a->data_rate = DESC_RATE6M; + a->ppdu_cnt = 1; + a->free_cnt = 0; +} + +static union recv_frame* gen_probersp(struct _ADAPTER *a) +{ + union recv_frame *r; + u32 len; + struct sk_buff *skb; + struct rtw_ieee80211_hdr *wlanhdr; + u8 *buf; + u8 hdrlen; + u8 ielen; + + + r = rtw_alloc_recvframe(&a->recvpriv.free_recv_queue); + if (!r) { + RTW_ERR("%s: alloc recvframe failed!\n", __func__); + return NULL; + } + rtw_init_recvframe(r, &a->recvpriv); + rx_prepare(a, r); + + hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + len = RXDESC_OFFSET + hdrlen + _CAPABILITY_ + _STATUS_CODE_ + _ASOC_ID_ + + 2 + sizeof(ap_ssid) + + 2 + sizeof(ap_datarate) + + 2 + 1; + skb = rtw_skb_alloc(len); + _rtw_memset(skb->data, 0, len); + skb->dev = a->pnetdev; + skb_reserve(skb, RXDESC_OFFSET); + r->u.hdr.pkt = skb; + + buf = skb_put(skb, hdrlen); + wlanhdr = (struct rtw_ieee80211_hdr*)buf; + set_frame_sub_type(&wlanhdr->frame_ctl, WIFI_PROBERSP); + _rtw_memcpy(wlanhdr->addr1, adapter_mac_addr(a), ETH_ALEN); + _rtw_memcpy(wlanhdr->addr2, ap_addr, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr3, ap_addr, ETH_ALEN); + + buf = skb_put(skb, _FIXED_IE_LENGTH_); + /* timestamp: 8 bytes */ + /* beacon interval: 2 bytes */ + *(u16*)(buf + 8) = ap_beacon_interval; + /* capability info: 2 bytes */ + *(u16*)(buf + 10) = ap_capability_info; + + /* SSID */ + add_ie(skb, _SSID_IE_, sizeof(ap_ssid), ap_ssid); + + /* supported rates... */ + add_ie(skb, _SUPPORTEDRATES_IE_, sizeof(ap_datarate), ap_datarate); + + /* DS parameter set */ + add_ie(skb, _DSSET_IE_, 1, &ap_ch); + + /* handle r->u.hdr.attrib */ + + /* handle recv_frame pointer */ + r->u.hdr.len = skb->len; + r->u.hdr.rx_head = skb->head; + r->u.hdr.rx_data = skb->data; + r->u.hdr.rx_tail = skb_tail_pointer(skb); + r->u.hdr.rx_end = skb_end_pointer(skb); + + return r; +} + +static union recv_frame* gen_beacon(struct _ADAPTER *a, struct sk_buff *beacon) +{ + union recv_frame *r; + u32 len; + struct sk_buff *skb; + struct rtw_ieee80211_hdr *wlanhdr; + u8 *buf; + u8 hdrlen; + + + r = rtw_alloc_recvframe(&a->recvpriv.free_recv_queue); + if (!r) { + RTW_ERR("%s: alloc recvframe failed!\n", __func__); + return NULL; + } + rtw_init_recvframe(r, &a->recvpriv); + rx_prepare(a, r); + + hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + len = RXDESC_OFFSET + beacon->len; + skb = rtw_skb_alloc(len); + _rtw_memset(skb->data, 0, len); + skb->dev = a->pnetdev; + skb_reserve(skb, RXDESC_OFFSET); + r->u.hdr.pkt = skb; + + buf = skb_put(skb, beacon->len); + _rtw_memcpy(buf, beacon->data, beacon->len); + + /* handle r->u.hdr.attrib */ + + /* handle recv_frame pointer */ + r->u.hdr.len = skb->len; + r->u.hdr.rx_head = skb->head; + r->u.hdr.rx_data = skb->data; + r->u.hdr.rx_tail = skb_tail_pointer(skb); + r->u.hdr.rx_end = skb_end_pointer(skb); + + return r; +} + +static union recv_frame *gen_auth(struct _ADAPTER *a, u8 *bssid) +{ + union recv_frame *r; + u32 len; + struct sk_buff *skb; + struct rtw_ieee80211_hdr *wlanhdr; + u8 *buf; + u8 hdrlen; + + + r = rtw_alloc_recvframe(&a->recvpriv.free_recv_queue); + if (!r) { + RTW_ERR("%s: alloc recvframe failed!\n", __func__); + return NULL; + } + rtw_init_recvframe(r, &a->recvpriv); + rx_prepare(a, r); + + hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + len = RXDESC_OFFSET + hdrlen + + _AUTH_ALGM_NUM_ + _AUTH_SEQ_NUM_ + _STATUS_CODE_; + skb = rtw_skb_alloc(len); + _rtw_memset(skb->data, 0, len); + skb->dev = a->pnetdev; + skb_reserve(skb, RXDESC_OFFSET); + r->u.hdr.pkt = skb; + + buf = skb_put(skb, hdrlen); + wlanhdr = (struct rtw_ieee80211_hdr*)buf; + set_frame_sub_type(&wlanhdr->frame_ctl, WIFI_AUTH); + _rtw_memcpy(wlanhdr->addr1, adapter_mac_addr(a), ETH_ALEN); + _rtw_memcpy(wlanhdr->addr2, bssid, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr3, bssid, ETH_ALEN); + + /* setting auth algo number */ + buf = skb_put(skb, _AUTH_ALGM_NUM_); + *(u16*)buf = cpu_to_le16(0);; + + /* setting auth seq number */ + buf = skb_put(skb, _AUTH_SEQ_NUM_); + *(u16*)buf = cpu_to_le16(2); + + /* setting status code... */ + buf = skb_put(skb, _STATUS_CODE_); + *(u16*)buf = cpu_to_le16(0); + + /* handle r->u.hdr.attrib */ + + /* handle recv_frame pointer */ + r->u.hdr.len = skb->len; + r->u.hdr.rx_head = skb->head; + r->u.hdr.rx_data = skb->data; + r->u.hdr.rx_tail = skb_tail_pointer(skb); + r->u.hdr.rx_end = skb_end_pointer(skb); + + return r; +} + +static union recv_frame *gen_assocrsp(struct _ADAPTER *a, u8 *bssid) +{ + union recv_frame *r; + u32 len; + struct sk_buff *skb; + struct rtw_ieee80211_hdr *wlanhdr; + u8 *buf; + u8 hdrlen; + + + r = rtw_alloc_recvframe(&a->recvpriv.free_recv_queue); + if (!r) { + RTW_ERR("%s: alloc recvframe failed!\n", __func__); + return NULL; + } + rtw_init_recvframe(r, &a->recvpriv); + rx_prepare(a, r); + + hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + len = RXDESC_OFFSET + hdrlen + + _CAPABILITY_ + _STATUS_CODE_ + _ASOC_ID_ + + 2 + sizeof(ap_datarate); + skb = rtw_skb_alloc(len); + _rtw_memset(skb->data, 0, len); + skb->dev = a->pnetdev; + skb_reserve(skb, RXDESC_OFFSET); + r->u.hdr.pkt = skb; + + buf = skb_put(skb, hdrlen); + wlanhdr = (struct rtw_ieee80211_hdr*)buf; + set_frame_sub_type(&wlanhdr->frame_ctl, WIFI_ASSOCRSP); + _rtw_memcpy(wlanhdr->addr1, adapter_mac_addr(a), ETH_ALEN); + _rtw_memcpy(wlanhdr->addr2, bssid, ETH_ALEN); + _rtw_memcpy(wlanhdr->addr3, bssid, ETH_ALEN); + + + /* capability info: 2 bytes */ + buf = skb_put(skb, _CAPABILITY_); + *(u16*)buf = ap_capability_info; + + /* status code: 2 bytes */ + buf = skb_put(skb, _STATUS_CODE_); + *(u16*)buf = 0; + + /* AID: 2 bytes */ + buf = skb_put(skb, _ASOC_ID_); + *(u16*)buf = 100; + + /* supported rates... */ + add_ie(skb, _SUPPORTEDRATES_IE_, sizeof(ap_datarate), ap_datarate); + + /* handle r->u.hdr.attrib */ + + /* handle recv_frame pointer */ + r->u.hdr.len = skb->len; + r->u.hdr.rx_head = skb->head; + r->u.hdr.rx_data = skb->data; + r->u.hdr.rx_tail = skb_tail_pointer(skb); + r->u.hdr.rx_end = skb_end_pointer(skb); + +// recvframe_put(r, buflen); +// pre_recv_entry(r, NULL); + + return r; +} + +static union recv_frame* fakeap_dispatcher(struct _ADAPTER *a, + struct sk_buff *skb) +{ + u8 *pframe; + union recv_frame *rframe = NULL; + + + pframe = skb->data; + RTW_INFO("A1-" MAC_FMT "\n", MAC_ARG(GetAddr1Ptr(pframe))); + RTW_INFO("A2-" MAC_FMT "\n", MAC_ARG(get_addr2_ptr(pframe))); + RTW_INFO("A3-" MAC_FMT "\n", MAC_ARG(GetAddr3Ptr(pframe))); + + if (GetFrameType(pframe) != WIFI_MGT_TYPE) + return NULL; + + switch (get_frame_sub_type(pframe)) { + case WIFI_AUTH: + { + u16 algo, seq; + + algo = le16_to_cpu(*(u16 *)(pframe + WLAN_HDR_A3_LEN)); + seq = le16_to_cpu(*(u16 *)(pframe + WLAN_HDR_A3_LEN + 2)); + + if ((algo == 0) && (seq == 1)) + rframe = gen_auth(a, GetAddr1Ptr(pframe)); + } + break; + + case WIFI_ASSOCREQ: + case WIFI_REASSOCREQ: + rframe = gen_assocrsp(a, GetAddr1Ptr(pframe)); + break; + + case WIFI_PROBEREQ: + rframe = gen_probersp(a); + break; + + case WIFI_BEACON: + rframe = gen_beacon(a, skb); + + default: + break; + } + + return rframe; +} + +extern sint validate_recv_frame(struct _ADAPTER*, union recv_frame**); +void rtw_fakeap_work(struct work_struct *work) +{ + struct dvobj_priv *d; + struct _ADAPTER *a; + struct sk_buff_head *pktq; + struct sk_buff *skb, *tmp; + u8 *ta, *ra; + union recv_frame *rframe; + int i; + + + d = container_of(work, struct dvobj_priv, fakeap.work); + + pktq = &d->fakeap.rxq; + skb_queue_walk_safe(pktq, skb, tmp) { + __skb_unlink(skb, pktq); + + ta = get_addr2_ptr(skb->data); + ra = GetAddr1Ptr(skb->data); + if (is_broadcast_mac_addr(ra) + && (_rtw_memcmp(ta, ap_addr, ETH_ALEN)==_TRUE) + && (get_frame_sub_type(skb->data) == WIFI_BEACON)) { + for (i = 0; i < d->iface_nums; i++) { + a = d->padapters[i]; + if (a) { + rframe = fakeap_dispatcher(a, skb); + if (rframe) { + validate_recv_frame(a, &rframe); + rframe = NULL; + } + } + } + } else { + a = rtw_get_iface_by_macddr(dvobj_get_primary_adapter(d), + ta); + if (a) + rframe = fakeap_dispatcher(a, skb); + } + rtw_skb_free(skb); + if (rframe) { + validate_recv_frame(a, &rframe); + rframe = NULL; + } + } +} diff --git a/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm.c b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm.c new file mode 100644 index 00000000..866b8002 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8852ce/core/rtw_fsm.c @@ -0,0 +1,1983 @@ +/****************************************************************************** + * + * Copyright(c) 2019 - 2020 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Author: vincent_fann@realtek.com + * + *****************************************************************************/ +#include +#include + +#ifdef CONFIG_RTW_FSM + +/* #define USE_PHL_CMD_DISPR */ + +#define CLOCK_NUM 3 +#define CLOCK_UNIT 10 +#define IS_CLK_OFF(clk) (clk->remain < 0) /* Negative value means disabled */ +#define IS_CLK_ON(clk) (clk->remain >= 0) +#define IS_CLK_EXP(clk) (clk->remain < (CLOCK_UNIT >> 1)) /* expire */ + +#ifndef MAX +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) +#endif +#define pstr(s) (s +strlen((u8 *)s)) +#define lstr(s, l) (size_t)(l - strlen((u8 *)s)) + +static struct fsm_obj *fsm_get_obj(struct fsm_main *fsm, u32 oid, u16 cid); + +//#define FSM_DBG_MEM_OVERWRITE +#ifdef FSM_DBG_MEM_OVERWRITE +void *fsm_kmalloc(u32 sz) +{ + char *ptr; + + ptr = kmalloc(sz+4, GFP_KERNEL); + memset(ptr+sz, 0xff, 4); + RTW_INFO("+AA %p %d\n", ptr, sz); + return ptr; +} + +void fsm_kfree(void *ptr, u32 sz) +{ + u32 ptn = 0xffffffff; + u32 *p = (u32 *)(ptr+sz); + + RTW_INFO("-AA %p %d", ptr, sz); + if ((*p&ptn) != ptn) { + RTW_ERR("- %p %d", ptr, sz); + RTW_ERR("OVER WRITE %x\n", ptn); + } + kfree(ptr); +} +#define _os_kmem_alloc(a, b) fsm_kmalloc(b) +#define _os_kmem_free(a, b, c) fsm_kfree(b, c) +#endif + +struct fsm_event_ent int_event_tbl[] = { + EV_DBG(FSM_INT_EV_MASK), + EV_DBG(FSM_EV_ABORT), + EV_DBG(FSM_EV_TIMER_EXPIRE), + EV_DBG(FSM_EV_END), + + //EV_DBG(FSM_EV_SWITCH_IN), + //EV_DBG(FSM_EV_SWITCH_OUT), + EV_DBG(FSM_EV_STATE_IN), + EV_DBG(FSM_EV_STATE_OUT), + + EV_DBG(FSM_EV_NEW_OBJ), + EV_DBG(FSM_EV_DEL_OBJ), + + EV_DBG(FSM_EV_INT_MAX), + + EV_DBG(FSM_GBL_EV_MASK), + EV_DBG(FSM_EV_CONNECTED), + EV_DBG(FSM_EV_CONNECT_FAIL), + EV_DBG(FSM_EV_DISCONNECTED), + EV_DBG(FSM_EV_SCAN_START), + EV_DBG(FSM_EV_SCAN_DONE), + + EV_DBG(FSM_EV_GBL_MAX) +}; + +/* + * FSM status + */ +enum FSM_STATUS { + FSM_STATUS_NONE, /* default value */ + + FSM_STATUS_INITIALIZED, /* insert module ok, + * mem/queue/timer were allocated + */ + + FSM_STATUS_ENABLE, /* run msg */ + + FSM_STATUS_DISABLE, /* Does NOT run and receiv msg, + * thread will remove all NON INT event + * after dequeue msg + */ +}; + +/* @obj: obj that will be infomred to when time's up + * @counter: clock time period + * @event: event that will delivered when time's up + * @end: end time + * @pause: stop countdown + */ +struct fsm_clk { + u16 event; + void *priv; + u8 pause; + u32 start; + u32 end; + int remain; /* ms */ +}; + +struct fsm_queue { + struct list_head q; + _lock lock; +}; + +struct fsm_main { + struct list_head list; + char name[FSM_NAME_LEN]; + u8 status; + u8 obj_cnt; + u8 en_clock_num; + + _timer fsm_timer; /* unit in ms */ + + struct fsm_root *root; + struct fsm_queue obj_queue; + struct fsm_queue msg_queue; + struct fsm_queue clk_queue; + + /* extra custom queue; for fsm private */ + struct fsm_queue ext_queue; + + struct rtw_fsm_tb tb; +}; + +/* @obj_id: object id + * @state: current state + * @prive: object's private date + */ +struct fsm_obj { + struct list_head list; + u32 oid; + u16 cid; /* customer id */ + u8 state; + u8 valid; /* framework */ + char name[FSM_NAME_LEN]; + struct fsm_clocks *clocks; + struct fsm_main *fsm; + + void *custom_obj; + int custom_len; /* custom obj length */ + + struct sta_info *psta; +}; + +struct fsm_clocks { + struct list_head list; + struct fsm_clk clk[CLOCK_NUM]; + struct fsm_obj *obj; +}; + +/* Main structure to handle all standalone fsm */ +struct fsm_root { + struct task_struct * thread; + struct list_head list; + struct fsm_queue q_share_thd; + u8 thread_should_stop; + + _adapter *a; + u32 oid_seq; /* starts from 1 */ + + _sema msg_ready; + + u32 status; /* refer to enum FSM_ROOT_STATUS_FLAGS */ +}; + +/* Static function porto type */ +static int fsm_handler(struct fsm_main *fsm); +static char *fsm_state_name(struct fsm_main *fsm, u8 state); +static u8 get_evt_level(struct fsm_main *fsm, u16 event); +static void fsm_destory_obj(struct fsm_obj *obj); +static int fsm_start_fsm(struct fsm_main *fsm); +static int fsm_stop_fsm(struct fsm_main *fsm); +static void fsm_user_evt_handler(struct fsm_main *fsm); +static int fsm_enqueue_list(struct fsm_queue *queue, struct list_head *list); + +u8 fsm_post_event_hdl(_adapter *padapter, u8 *pbuf) +{ +#ifdef USE_PHL_CMD_DISPR + struct fsm_msg *msg = (struct fsm_msg *)pbuf; + + fsm_enqueue_list(&msg->fsm->msg_queue, &msg->list); + fsm_user_evt_handler(msg->fsm); +#endif + return H2C_SUCCESS; +} + +static void fsm_status_set(struct fsm_main *fsm, enum FSM_STATUS status) +{ + fsm->status = status; +} + +static enum FSM_STATUS fsm_status(struct fsm_main *fsm) +{ + return fsm->status; +} + +/* unit ms */ +u32 rtw_fsm_time_pass(u32 start) +{ + u32 now = rtw_systime_to_ms(rtw_get_current_time()); + u32 pass; + + if (start <= now) + pass = now - start; + else + pass = 0xffffffff - start + now; + + return pass; +} + +u32 rtw_fsm_time_left(u32 start, u32 end) +{ + u32 total, pass; + int left = 0; + + pass = rtw_fsm_time_pass(start); + + if (end >= start) + total = end - start; + else + total = 0xffffffff - start + end; + + left = total - pass; + + if (left < 0) + left = 0; + + return (u32)left; +} + +static struct fsm_msg *fsm_dequeue_msg(struct fsm_main *fsm) +{ + struct fsm_msg *msg; + + if (list_empty(&fsm->msg_queue.q)) + return NULL; + + _rtw_spinlock_bh(&fsm->msg_queue.lock); + msg = list_first_entry(&fsm->msg_queue.q, struct fsm_msg, list); + list_del(&msg->list); + _rtw_spinunlock_bh(&fsm->msg_queue.lock); + return msg; +} + +#if 0 +static struct fsm_clk *fsm_dequeue_clk(struct fsm_main *fsm) +{ + struct fsm_clk *clk; + + if (list_empty(&fsm->clk_queue.q)) + return NULL; + + _rtw_spinlock_bh(&fsm->clk_queue.lock); + clk = list_first_entry(&fsm->clk_queue.q, struct fsm_clk, list); + list_del(&clk->list); + _rtw_spinunlock_bh(&fsm->clk_queue.lock); + return clk; +} +#endif + +/* For EXTERNAL application to get adapter (expose) */ +void *fsm_to_priv(struct fsm_main *fsm) +{ + return fsm->tb.priv; /* xxx_priv */ +} + +struct sta_info *obj_to_sta(struct fsm_obj *obj) +{ + return obj->psta; +} + +_adapter *fsm_to_adapter(struct fsm_main *fsm) +{ + return fsm->root->a; +} + +/* For EXTERNAL application to enqueue message to extra queue (expose) + * + * @fsm: fsm that object belonged to + * @msg: message to be enqueued + * @to_head: enqueue message to the head + */ +int rtw_fsm_enqueue_ext(struct fsm_main *fsm, struct fsm_msg *msg, u8 to_head) +{ + struct fsm_queue *queue = &fsm->ext_queue; + + _rtw_spinlock_bh(&queue->lock); + if (to_head) + list_add(&msg->list, &queue->q); + else + list_add_tail(&msg->list, &queue->q); + _rtw_spinunlock_bh(&queue->lock); + + return 0; +} + +/* For EXTERNAL application to dequeue message from extra queue (expose) + * + * @fsm: fsm that object belonged to + */ +struct fsm_msg *rtw_fsm_dequeue_ext(struct fsm_main *fsm) +{ + struct fsm_msg *msg; + + if (list_empty(&fsm->ext_queue.q)) + return NULL; + + _rtw_spinlock_bh(&fsm->ext_queue.lock); + msg = list_first_entry(&fsm->ext_queue.q, struct fsm_msg, list); + list_del(&msg->list); + _rtw_spinunlock_bh(&fsm->ext_queue.lock); + return msg; +} + +/* For EXTERNAL application to dequeue message from extra queue (expose) + * + * @fsm: fsm that object belonged to + */ +int rtw_fsm_is_ext_queue_empty(struct fsm_main *fsm) +{ + return list_empty(&fsm->ext_queue.q); +} + +static u32 fsm_new_oid(struct fsm_main *fsm) +{ + /* TODO: how to handle redendent oid ? */ + do { + fsm->root->oid_seq++; + } while (fsm->root->oid_seq == 0); + + return fsm->root->oid_seq; +} + +static int fsm_enqueue_list(struct fsm_queue *queue, struct list_head *list) +{ + _rtw_spinlock_bh(&queue->lock); + list_add_tail(list, &queue->q); + _rtw_spinunlock_bh(&queue->lock); + return 0; +} + +static int fsm_state_run(struct fsm_obj *obj, u16 event, void *param) +{ + struct fsm_main *fsm = obj->fsm; + + FSM_EV_MSG_(fsm, get_evt_level(fsm, event), + "%s %-18s %s\n", obj->name, + fsm_state_name(fsm, obj->state), fsm_evt_name(obj->fsm, event)); + + return fsm->tb.state_tbl[obj->state].fsm_func(obj->custom_obj, + event, param); +} + +static void fsm_remove_all_queuing_msg(struct fsm_main *fsm) +{ + struct fsm_msg *msg; + //struct fsm_evt *evt; + struct fsm_obj *obj; + + /* go through msg queue and free everything */ + while ((msg = fsm_dequeue_msg(fsm)) != NULL) { + obj = fsm_get_obj(fsm, 0, msg->cid); + if (msg->param) + rtw_mfree((void *)msg->param, msg->param_sz); + rtw_mfree((void *)msg, sizeof(*msg)); + } + + /* go through event queue and free everything */ +#if 0 + while ((evt = fsm_dequeue_clk(fsm)) != NULL) { + if (evt->param) + rtw_mfree((void *)evt->param, evt->param_sz); + rtw_mfree((void *)evt, sizeof(*evt)); + } +#endif + + /* go through ext queue and free everything */ + while ((msg = rtw_fsm_dequeue_ext(fsm)) != NULL) { + if (msg->param) + rtw_mfree((void *)msg->param, msg->param_sz); + rtw_mfree((void *)msg, sizeof(*msg)); + } +} + +static int fsm_abort_all_running_obj(struct fsm_main *fsm) +{ + struct fsm_obj *obj; + + if (list_empty(&fsm->obj_queue.q)) + return 0; + + list_for_each_entry(obj, &fsm->obj_queue.q, list) { + fsm_gen_msg(obj, NULL, 0, FSM_EV_ABORT); + } + + return 0; +} + +u8 fsm_dbg_lv(struct fsm_main *fsm, u8 level) +{ + if (fsm->tb.dbg_level >= level) + return fsm->tb.dbg_level; + + return 0; +} + +u8 fsm_evt_lv(struct fsm_main *fsm, u8 level) +{ + if (fsm->tb.evt_level >= level) + return fsm->tb.evt_level; + + return 0; +} + +static u8 get_evt_level(struct fsm_main *fsm, u16 event) +{ + u16 ev; + + /* fsm global event */ + if (event & FSM_GBL_EV_MASK) { + ev = (u8)((event & ~(FSM_GBL_EV_MASK)) + 1 + + (FSM_EV_INT_MAX & ~(FSM_INT_EV_MASK))); + return int_event_tbl[ev].evt_level; + } + + /* fsm internal event */ + if (event & FSM_INT_EV_MASK) { + ev = (u8)(event & ~(FSM_INT_EV_MASK)); + return int_event_tbl[ev].evt_level; + } + + if (event == FSM_EV_UNKNOWN) + return FSM_LV_INFO; + + if (event > fsm->tb.max_event) + return FSM_LV_INFO; + + /* user event */ + return fsm->tb.evt_tbl[event].evt_level; +} + +static void fsm_init_queue(struct fsm_queue *queue) +{ + INIT_LIST_HEAD(&queue->q); + _rtw_spinlock_init(&queue->lock); +} + +static void fsm_deinit_queue(struct fsm_queue *queue) +{ + _rtw_spinlock_free(&queue->lock); +} + + +#ifndef USE_PHL_CMD_DISPR +int fsm_thread_share(void *param) +{ + struct fsm_obj *obj; + struct fsm_main *fsm, *fsm_t; + struct fsm_root *root = (struct fsm_root *)param; + int rtn; + + while (1) { + + //while (down_timeout(&root->msg_ready, 100)) { + rtn = down_interruptible(&root->msg_ready); + + if (root->thread_should_stop) + goto exit; + + list_for_each_entry(fsm, &root->q_share_thd.q, list) { + fsm_handler(fsm); + } + } +exit: + while (!kthread_should_stop()) { + RTW_INFO("fsm: [FSM] thread wait stop\n"); + rtw_msleep_os(10); + } + RTW_INFO("fsm: [FSM] thread down\n"); + + return 0; +} +#endif + +/* cid customer cid */ +static struct fsm_obj *fsm_get_obj(struct fsm_main *fsm, u32 oid, u16 cid) +{ + struct fsm_obj *obj, *obj_t; + + if (list_empty(&fsm->obj_queue.q)) + return NULL; + + _rtw_spinlock_bh(&fsm->obj_queue.lock); + list_for_each_entry(obj, &fsm->obj_queue.q, list) { + if ((oid && (oid == obj->oid)) || + (cid && (cid == obj->cid))) { + _rtw_spinunlock_bh(&fsm->obj_queue.lock); + return obj; + } + } + _rtw_spinunlock_bh(&fsm->obj_queue.lock); + return NULL; +} + +struct fsm_msg *fsm_new_msg(struct fsm_obj *obj, u16 event) +{ + struct fsm_msg *msg = NULL; + + msg = (struct fsm_msg *)rtw_zmalloc(sizeof(*msg)); + + if (msg == NULL) + return NULL; + + _rtw_memset(msg, 0, sizeof(*msg)); + msg->event = event; + + if (obj) { + msg->fsm = obj->fsm; + msg->oid = obj->oid; + msg->cid = obj->cid; + } + return msg; +} + +#ifdef USE_PHL_CMD_DISPR +static int rtw_fsm_send_cmd_msg(struct fsm_main *fsm, struct fsm_msg *msg) +{ + struct cmd_obj *pcmd = NULL; + _adapter *padapter = fsm_to_adapter(fsm); + struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv; + + pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (pcmd == NULL) + goto fail; + + pcmd->padapter = padapter; + init_h2fwcmd_w_parm_no_rsp(pcmd, msg, CMD_RM_POST_EVENT); + return rtw_enqueue_cmd(pcmdpriv, pcmd); +fail: + if (msg->param && msg->param_sz) + rtw_mfree(msg->param, msg->param_sz); + rtw_mfree(msg, sizeof(*msg)); + + if (pcmd) + rtw_mfree(pcmd, sizeof(*pcmd)); + return _FAIL; +} +#endif + +int fsm_send_msg(struct fsm_main *fsm, struct fsm_msg *msg) +{ + + if ((fsm_status(fsm) != FSM_STATUS_ENABLE) && + !(msg->event & FSM_INT_EV_MASK)) { + RTW_WARN("fsm: %s is out of service, drop message %s!\n", + fsm->name, fsm_evt_name(fsm, msg->event)); + if (msg->param && msg->param_sz) + rtw_mfree(msg->param, msg->param_sz); + rtw_mfree(msg, sizeof(*msg)); + return _FAIL; + + } +#ifdef USE_PHL_CMD_DISPR + rtw_fsm_send_cmd_msg(fsm, msg); +#else + fsm_enqueue_list(&fsm->msg_queue, &msg->list); + _rtw_up_sema(&fsm->root->msg_ready); +#endif + return _SUCCESS; +} + +void fsm_timer_callback(void *context) +{ + struct fsm_main *fsm = (struct fsm_main *)context; + struct fsm_clk *clk; + struct fsm_clocks *clocks; + int i = 0; + + _set_timer(&fsm->fsm_timer, CLOCK_UNIT); + + _rtw_spinlock_bh(&fsm->clk_queue.lock); + + if (fsm->en_clock_num == 0) + goto done; + + /* go through clock and descrease timer + * if timer was expired, issue event + */ + list_for_each_entry(clocks, &fsm->clk_queue.q, list) { + for (i = 0; i < CLOCK_NUM; i++) { + + clk = &clocks->clk[i]; + + if (IS_CLK_OFF(clk) || clk->pause) + continue; + + clk->remain = (int)rtw_fsm_time_left(clk->start, clk->end); + + /* timer expired */ + if (!IS_CLK_EXP(clk)) + continue; + + FSM_TRACE_(fsm, "%s: expire in %d ms\n", + fsm_evt_name(clocks->obj->fsm, clk->event), + rtw_fsm_time_pass(clk->start)); + + clk->end = 0; + clk->remain = -1; + /* send message to obj */ + + /* check fsm status before posting */ + if (fsm_status(fsm) == FSM_STATUS_ENABLE) { + fsm_gen_msg(clocks->obj, NULL, 0, clk->event); + if (--fsm->en_clock_num == 0) + break; + } + } + } +done: + _rtw_spinunlock_bh(&fsm->clk_queue.lock); +} + +/* allocate and init fsm resource */ +struct fsm_main *rtw_fsm_register_fsm(struct fsm_root *root, + const char *name, struct rtw_fsm_tb *tb) +{ + struct fsm_main *fsm; + + /* check event table */ + if (tb->evt_tbl[tb->max_event-1].event != tb->max_event-1) { + RTW_ERR("Event mismatch ? Is max event = %d != %d ?\n", + tb->evt_tbl[tb->max_event-1].event, + tb->max_event-1); + return NULL; + } + + /* check state table */ + if (tb->state_tbl[tb->max_state-1].state != tb->max_state-1) { + RTW_ERR("State mismatch ? Is max state = %d != %d) ?\n", + tb->state_tbl[tb->max_state-1].state, + tb->max_state-1); + return NULL; + } + + fsm = (struct fsm_main *)rtw_zmalloc(sizeof(*fsm)); + + if (fsm == NULL) + return NULL; + + _rtw_memset(fsm, 0, sizeof(*fsm)); + _rtw_memcpy(&fsm->tb, (void *)tb, sizeof(*tb)); + _rtw_memcpy(&fsm->name, (void *)name, + MIN(FSM_NAME_LEN-1, strlen((u8 *)name))); + + fsm->root = root; + fsm_init_queue(&(fsm->obj_queue)); + fsm_init_queue(&(fsm->msg_queue)); + fsm_init_queue(&(fsm->clk_queue)); + fsm_init_queue(&(fsm->ext_queue)); + + if (tb->init_priv) + tb->init_priv(tb->priv); + + rtw_init_timer(&fsm->fsm_timer, fsm_timer_callback, fsm); + + /* link fsm_main to fsm_root */ + fsm_enqueue_list(&root->q_share_thd, &fsm->list); + + FSM_INFO_(fsm, "fsm: [%s] %s()\n", fsm->name, __func__); + fsm_status_set(fsm, FSM_STATUS_INITIALIZED); + return fsm; +} + +void fsm_deinit_fsm(struct fsm_main *fsm) +{ + _adapter *a; + struct fsm_obj *obj, *obj_t; + + if (!fsm) + return; + + _cancel_timer_ex(&fsm->fsm_timer); + a = fsm_to_adapter(fsm); + + if (!list_empty(&fsm->obj_queue.q)) { + list_for_each_entry_safe(obj, obj_t, &fsm->obj_queue.q, list) { + fsm_destory_obj(obj); + } + } + + FSM_INFO_(fsm, "fsm: [%s] "FUNC_NDEV_FMT"\n", fsm->name, FUNC_NDEV_ARG(a->pnetdev)); + + fsm_deinit_queue(&(fsm->obj_queue)); + fsm_deinit_queue(&(fsm->msg_queue)); + fsm_deinit_queue(&(fsm->clk_queue)); + fsm_deinit_queue(&(fsm->ext_queue)); + rtw_mfree(fsm, sizeof(*fsm)); + + return; +} + +char *fsm_evt_name(struct fsm_main *fsm, u16 event) +{ + u8 ev; + + /* fsm global event */ + if (event & FSM_GBL_EV_MASK) { + ev = (u8)((event & ~(FSM_GBL_EV_MASK)) + 1 + + (FSM_EV_INT_MAX & ~(FSM_INT_EV_MASK))); + return int_event_tbl[ev].name; + } + + /* fsm internal event */ + if (event & FSM_INT_EV_MASK) { + ev = (u8)(event & ~(FSM_INT_EV_MASK)); + return int_event_tbl[ev].name; + } + + if (event == FSM_EV_UNKNOWN) + return "FSM_EV_UNKNOWN"; + + if (event > fsm->tb.max_event) + return "undefine"; + + /* user event */ + return fsm->tb.evt_tbl[event].name; +} + +static char *fsm_state_name(struct fsm_main *fsm, u8 state) +{ + if (state > fsm->tb.max_state) + return "unknown"; + + return fsm->tb.state_tbl[state].name; +} + +/* For EXTERNAL application to get custom obj (expose) + * + * @obj: cid to get obj + */ +void *rtw_fsm_get_obj(struct fsm_main *fsm, u16 cid) +{ + struct fsm_obj *obj = NULL; + + obj = fsm_get_obj(fsm, 0, cid); + + if (obj) + return obj->custom_obj; + return NULL; +} + +/** init obj internal variable + * + * @fsm: fsm that object belonged to + * default init to the 1st state in state_tbl + + */ +static void fsm_obj_switch_in(struct fsm_obj *obj, struct fsm_msg *msg) +{ + struct fsm_main *fsm = obj->fsm; + + if (obj->fsm->tb.active_obj) + obj->fsm->tb.active_obj(obj->fsm->tb.priv, obj->custom_obj); + + /* default init to the 1st state in state_tbl */ + obj->state = fsm->tb.state_tbl[0].state; + + FSM_DBG_(fsm, "%s %-21s %s(cid=0x%04x oid=0x%08x)\n", obj->name, + fsm_state_name(fsm, obj->state), "new obj", obj->cid, obj->oid); + + obj->valid = 1; + /* Make it alive! Hello obj! */ + fsm_state_run(obj, FSM_EV_STATE_IN, msg->param); +} + +/** deinit obj internal variable + * + * @fsm: fsm that object belonged to + * default init to the 1st state in state_tbl + + */ +static void fsm_obj_switch_out(struct fsm_obj *obj, struct fsm_msg *msg) +{ + struct fsm_main *fsm = obj->fsm; + + if (fsm->tb.deactive_obj) + fsm->tb.deactive_obj(fsm->tb.priv, obj->custom_obj); + + fsm_state_run(obj, FSM_EV_STATE_OUT, msg->param); + + FSM_DBG_(fsm, "%s %-21s %s(cid=0x%04x oid=0x%08x)\n", obj->name, + fsm_state_name(fsm, obj->state), "del obj", obj->cid, obj->oid); + + obj->valid = 0; + /* Let it go! Goodbye obj! */ + fsm_destory_obj(obj); +} + +/* For EXTERNAL application to new a fsm object (expose) + * + * @fsm: fsm that object belonged to + * @fsm_obj: obj param when calling FSM framework function + * @priv_len: custom obj length + * + * return value: NULL :fail + * other :cusomer obj handler (success) + */ +void *rtw_fsm_new_obj(struct fsm_main *fsm, + struct sta_info *psta, u16 cid, void **custom_obj, int sz) +{ + struct fsm_obj *obj; + struct fsm_clocks *clocks; + int i; + + *custom_obj = NULL; + obj = (struct fsm_obj *)rtw_zmalloc(sizeof(*obj)); + if (obj == NULL) + return NULL; + _rtw_memset(obj, 0, sizeof(*obj)); + + clocks = (struct fsm_clocks *)rtw_zmalloc(sizeof(*clocks)); + if (clocks == NULL) { + rtw_mfree(obj, sizeof(*obj)); + return NULL; + } + _rtw_memset(clocks, 0, sizeof(*clocks)); + clocks->obj = obj; + for (i = 0; i < CLOCK_NUM; i++) + clocks->clk[i].remain = -1; /* Negative means disable */ + + obj->custom_obj = rtw_zmalloc(sz); + if (obj->custom_obj == NULL) { + rtw_mfree(clocks, sizeof(*clocks)); + rtw_mfree(obj, sizeof(*obj)); + return NULL; + } + _rtw_memset(obj->custom_obj, 0, sz); + obj->clocks = clocks; + obj->custom_len = sz; + obj->oid = fsm_new_oid(fsm); + obj->cid = cid; + obj->fsm = fsm; + obj->state = fsm->tb.state_tbl[0].state; + obj->psta = psta; + + _rtw_memset(obj->name, 0, FSM_NAME_LEN); + snprintf(obj->name, FSM_NAME_LEN, + "%s-%04x", obj->fsm->name, obj->cid); + *custom_obj = obj->custom_obj; + fsm_enqueue_list(&fsm->obj_queue, &obj->list); + fsm_enqueue_list(&fsm->clk_queue, &clocks->list); + + return obj; +} + +/* For EXTERNAL application to destory a fsm object (expose) + * + * @fsm_obj: obj param when calling FSM framework function + */ +static void fsm_destory_obj(struct fsm_obj *obj) +{ + struct fsm_main *fsm = obj->fsm; + struct fsm_clocks *clocks = obj->clocks; + + list_del(&obj->list); + + /* free clocks */ + _rtw_spinlock_bh(&fsm->clk_queue.lock); + list_del(&clocks->list); + _rtw_spinunlock_bh(&fsm->clk_queue.lock); + + rtw_mfree(clocks, sizeof(struct fsm_clocks)); + + /* free custom_obj */ + rtw_mfree(obj->custom_obj, obj->custom_len); + + /* free fsm_obj */ + rtw_mfree(obj, sizeof(*obj)); +} + +void fsm_del_obj(struct fsm_obj *obj) +{ + struct fsm_main *fsm = obj->fsm; + + /* only allow to del an inactive obj */ + if (obj->valid != 0) { + FSM_ERR_(obj->fsm, "%s: free an actived obj\n", fsm_obj_name(obj)); + return; + } + fsm_destory_obj(obj); +} + +void fsm_activate_obj(struct fsm_obj *obj) +{ + fsm_gen_msg(obj, NULL, 0, FSM_EV_NEW_OBJ); +} + +void fsm_deactivate_obj(struct fsm_obj *obj) +{ + fsm_gen_msg(obj, NULL, 0, FSM_EV_DEL_OBJ); +} + +bool fsm_is_alarm_off_ext(struct fsm_obj *obj, u8 id) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + + return IS_CLK_OFF(clk); +} + +bool fsm_is_alarm_off(struct fsm_obj *obj) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[0]; + + return IS_CLK_OFF(clk); +} + +static void _fsm_set_alarm(struct fsm_obj *obj, int ms, + u16 event, u8 id, void *priv) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + u32 now; + +#if 0 + if (ms == 0) + fsm_post_event(obj, event, priv); +#endif + + now = rtw_systime_to_ms(rtw_get_current_time()); + + _rtw_spinlock_bh(&obj->fsm->clk_queue.lock); + /* turn on clock from off */ + if (IS_CLK_OFF(clk)) + obj->fsm->en_clock_num++; + + clk->event = event; + clk->priv = priv; + clk->start = now; + clk->end = now + ms; + clk->remain = (int)rtw_fsm_time_left(clk->start, clk->end); + _rtw_spinunlock_bh(&obj->fsm->clk_queue.lock); +#if 0 + FSM_DBG_(obj->fsm, "%s:%s now=0x%08x, end=0x%08x, remain=0x%08x\n", + fsm_obj_name(obj), fsm_evt_name(obj->fsm, event), + clk->start, clk->end, clk->remain); +#endif +} + +/* For EXTERNAL application to extend alarm time (expose) + * + * @obj: obj param when calling FSM framework function + * @event: alarm will issue this event while timer expired + * @ms: time period for the alarm + * remain time does not less than 'ms' + * @id: alarm id; start from 1 + */ +void fsm_extend_alarm_ext(struct fsm_obj *obj, int ms, u8 id) + +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + int remain = ms; + + if (id == 0 || id >= CLOCK_NUM) { + RTW_ERR("%s: %s_%d fail\n", + fsm_obj_name(obj), __func__, id); + return; + } + + if (IS_CLK_OFF(clk)) + return; + + remain = MAX((int)rtw_fsm_time_left(clk->start, clk->end), ms); + fsm_set_alarm_ext(obj, remain, clk->event, id, clk->priv); +} + +/* For EXTERNAL application to setup alarm (expose) + * + * @obj: obj param when calling FSM framework function + * @event: alarm will issue this event while timer expired + * @ms: time period for the alarm + * @id: alarm id; start from 1 + */ +void fsm_set_alarm(struct fsm_obj *obj, int ms, u16 event) +{ + _fsm_set_alarm(obj, ms, event, 0, NULL); +} + +/* For EXTERNAL application to setup alarm_ext (expose) + * + * @obj: obj param when calling FSM framework function + * @event: alarm will issue this event while timer expired + * @ms: time period for the alarm + * @id: alarm id; start from 1 + * @priv: priv from caller + */ +void fsm_set_alarm_ext(struct fsm_obj *obj, + int ms, u16 event, u8 id, void *priv) +{ + if (id >= CLOCK_NUM) { + RTW_ERR("%s: set alarm_ext_%d to %d ms fail\n", + fsm_obj_name(obj), id, ms); + return; + } + _fsm_set_alarm(obj, ms, event, id, priv); +} + +static void _fsm_cancel_alarm(struct fsm_obj *obj, u8 id) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + + _rtw_spinlock_bh(&obj->fsm->clk_queue.lock); + /* turn off clock from on */ + if (IS_CLK_ON(clk)) + obj->fsm->en_clock_num--; + + clk->end = 0; + clk->remain = -1; + clk->pause = 0; + _rtw_spinunlock_bh(&obj->fsm->clk_queue.lock); +} + +/* For EXTERNAL application to cancel alarm (expose) + * + * @obj: obj param when calling FSM framework function + */ +void fsm_cancel_alarm(struct fsm_obj *obj) +{ + _fsm_cancel_alarm(obj, 0); +} + +/* For EXTERNAL application to cancel alarm_ext (expose) + * + * @obj: obj param when calling FSM framework function + * @id: alarm id; start from 1 + */ +void fsm_cancel_alarm_ext(struct fsm_obj *obj, u8 id) +{ + if (id == 0 || id >= CLOCK_NUM) { + RTW_ERR("%s: cancel alarm_ext_%d fail\n", + fsm_obj_name(obj), id); + return; + } + _fsm_cancel_alarm(obj, id); +} + +static void _fsm_pause_alarm(struct fsm_obj *obj, u8 id) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + + _rtw_spinlock_bh(&obj->fsm->clk_queue.lock); + clk[id].pause = 1; + _rtw_spinunlock_bh(&obj->fsm->clk_queue.lock); +} + +/* For EXTERNAL application to pause alarm (expose) + * + * @obj: obj param when calling FSM framework function + */ +void fsm_pause_alarm(struct fsm_obj *obj) +{ + _fsm_pause_alarm(obj, 0); +} + +/* For EXTERNAL application to pause alarm_ext (expose) + * + * @obj: obj param when calling FSM framework function + * @id: alarm id; start from 1 + */ +void fsm_pause_alarm_ext(struct fsm_obj *obj, u8 id) +{ + if (id == 0 || id >= CLOCK_NUM) { + RTW_ERR("%s: pause alarm_%d fail\n", fsm_obj_name(obj), id); + return; + } + _fsm_pause_alarm(obj, id); +} + +static void _fsm_resume_alarm(struct fsm_obj *obj, u8 id) +{ + struct fsm_clocks *clocks = obj->clocks; + struct fsm_clk *clk = &clocks->clk[id]; + u32 cur = rtw_systime_to_ms(rtw_get_current_time()); + + /* extrend end time */ + _rtw_spinlock_bh(&obj->fsm->clk_queue.lock); + clk->end = cur + clk->remain; + clk->pause = 0; + _rtw_spinunlock_bh(&obj->fsm->clk_queue.lock); +} + +/* For EXTERNAL application to resume alarm (expose) + * + * @obj: obj param when calling FSM framework function + */ +void fsm_resume_alarm(struct fsm_obj *obj) +{ + _fsm_resume_alarm(obj, 0); +} + +/* For EXTERNAL application to resume alarm_ext (expose) + * + * @obj: obj param when calling FSM framework function + * @id: alarm id; start from 1 + */ +void fsm_resume_alarm_ext(struct fsm_obj *obj, u8 id) +{ + if (id == 0 || id >= CLOCK_NUM) { + RTW_ERR("%s: resume alarm_ext_%d fail\n", + fsm_obj_name(obj), id); + return; + } + _fsm_resume_alarm(obj, id); +} + +/* For EXTERNAL application to change state (expose) + * + * @obj: obj that changes state + * @new_state: new state + */ +void fsm_state_goto(struct fsm_obj *obj, u8 new_state) +{ + struct fsm_main *fsm = NULL; + + if (obj->state == new_state) + return; + + fsm = obj->fsm; + + fsm_state_run(obj, FSM_EV_STATE_OUT, NULL); + + FSM_MSG_(fsm, FSM_LV_DBG, "\n"); + FSM_MSG_(fsm, FSM_LV_DBG, "%s %-18s -> %s\n", obj->name, + fsm_state_name(fsm, obj->state), + fsm_state_name(fsm, new_state)); + + obj->state = new_state; /* new state */ + fsm_state_run(obj, FSM_EV_STATE_IN, NULL); +} + +static int fsm_int_evt_handler(struct fsm_obj *obj, struct fsm_msg *msg) +{ + switch(msg->event) { + case FSM_EV_NEW_OBJ: + fsm_obj_switch_in(obj, msg); + break; + case FSM_EV_DEL_OBJ: + fsm_obj_switch_out(obj, msg); + break; + default: + FSM_WARN_(obj->fsm, "unexpect event %04x(%s)\n", + msg->event, fsm_evt_name(obj->fsm, msg->event)); + return _FALSE; + break; + } + return _SUCCESS; +} + +static void fsm_free_msg(struct fsm_msg *msg) +{ + if (msg && msg->param && msg->param_sz) + rtw_mfree((void *)msg->param, msg->param_sz); +#ifndef USE_PHL_CMD_DISPR + if (msg) + rtw_mfree((void *)msg, sizeof(*msg)); +#endif + +} + +static void fsm_user_evt_handler(struct fsm_main *fsm) +{ + struct fsm_msg *msg; + struct fsm_obj *obj; + + while ((msg = fsm_dequeue_msg(fsm)) != NULL) { + + obj = fsm_get_obj(fsm, msg->oid, 0); + + if (obj == NULL) { + FSM_WARN_(fsm, "%s: obj (cid=0x%04x, oid=0x%8x) not found, ignore %s\n", + fsm->name, msg->cid, msg->oid, fsm_evt_name(fsm, msg->event)); + fsm_free_msg(msg); + continue; + } + + if (msg->event & FSM_INT_EV_MASK) { + /* Allow INT_EV even FSM_STATUS_DISABLE + * for ABORT and DEL_OBJ to run. Free ALL user and + * Global evt to empty msg queue. + */ + if (fsm_int_evt_handler(obj, msg)) { + fsm_free_msg(msg); + continue; + } + } + + if ((fsm_status(fsm) != FSM_STATUS_ENABLE)) { + fsm_free_msg(msg); + continue; + } + + /* pre handle events */ + switch(msg->event) { + case FSM_EV_CONNECTED: + case FSM_EV_DISCONNECTED: + if (msg->param && !msg->param_sz) + obj->psta = (struct sta_info *)msg->param; + break; + default: + break; + } + + if (!obj->valid) { + FSM_WARN_(fsm, "%s: invalid, ignore %s\n", + fsm_obj_name(obj), fsm_evt_name(fsm, msg->event)); + fsm_free_msg(msg); + continue; + } + + /* run state machine */ + fsm_state_run(obj, msg->event, msg->param); + fsm_free_msg(msg); + } + return; +} + +static int fsm_handler(struct fsm_main *fsm) +{ + /* USER EVENT */ + if (list_empty(&fsm->msg_queue.q)) + return 0; + + fsm_user_evt_handler(fsm); + + return 0; +} + +/* For EXTERNAL application to get fsm name (expose) + * @fsm: fsm to be get name + */ +char *rtw_fsm_fsm_name(struct fsm_main *fsm) +{ + return fsm->name; +} + +/* For EXTERNAL application to get obj name (expose) + * @obj: obj to be get name + * For example: scan-1 (sacn obj with object id 1) + */ +char *fsm_obj_name(struct fsm_obj *obj) +{ + return obj->name; +} + +/* For EXTERNAL application to cancel sma (expose) + * @obj: obj job will be cancelled + */ +int fsm_abort_obj(struct fsm_obj *obj) +{ + struct fsm_msg *msg; + + /* NEW message to cancel obj task */ + msg = fsm_new_msg(obj, FSM_EV_ABORT); + if (msg == NULL) { + RTW_ERR("%s: alloc msg fail\n", obj->fsm->name); + return _FAIL; + } + return fsm_send_msg(obj->fsm, msg); +} + +int fsm_init_custom(struct fsm_priv *fsmpriv) +{ + int rtn = _FAIL; + +#ifdef CONFIG_RTW_FSM_XXX + if (rtw_xxx_reg_fsm(fsmpriv) == _FAIL) + goto exit; +#endif +#ifdef CONFIG_RTW_FSM_RRM + if (rtw_rrm_reg_fsm(fsmpriv) == _FAIL) + goto exit; +#endif +#ifdef CONFIG_RTW_FSM_BTM + if (rtw_btm_reg_fsm(fsmpriv) == _FAIL) + goto exit; +#endif + rtn = _SUCCESS;; +exit: + return rtn; +} + +void fsm_deinit_custom(struct fsm_priv *fsmpriv) +{ + struct fsm_root *root = fsmpriv->root; + struct fsm_main *fsm, *fsm_t; + + if (list_empty(&root->q_share_thd.q)) + return; + + list_for_each_entry_safe(fsm, fsm_t, &root->q_share_thd.q, list) { + list_del(&fsm->list); + /* csutom deinit fsm */ + if (fsm->tb.deinit_priv) + fsm->tb.deinit_priv(fsm->tb.priv); + fsm_deinit_fsm(fsm); + } +} + +/* For EXTERNAL application to init FSM framework (expose) */ +/* @obj: obj job will be cancelled + */ +int rtw_fsm_init(struct fsm_priv *fsmpriv, void *priv) +{ + struct fsm_root *root; + int max, i, g, size; + + /* check size of internal event table */ + i = FSM_EV_INT_MAX & ~FSM_INT_EV_MASK; + g = FSM_EV_GBL_MAX & ~FSM_GBL_EV_MASK; + max = i + g + 2; + size = sizeof(int_event_tbl)/sizeof(int_event_tbl)[0]; + if (size != max) { + RTW_ERR("fsm: int_event_tbl[%d] != %d size mismatch!!", + size, max); + WARN_ON(1); + return _FAIL; + } + root = (struct fsm_root *)rtw_zmalloc(sizeof(*root)); + if (root == NULL) + return _FAIL; + + _rtw_memset(root, 0, sizeof(*root)); + fsm_init_queue(&(root->q_share_thd)); + _rtw_init_sema(&root->msg_ready, 0); + root->a = priv; + root->oid_seq = 1; + + fsmpriv->root = root; + + RTW_INFO("fsm: [FSM] %s()\n", __func__); + + return fsm_init_custom(fsmpriv); +} + +/* For EXTERNAL application to deinit FSM framework (expose) + * @root: FSM framework handler + */ +void rtw_fsm_deinit(struct fsm_priv *fsmpriv) +{ + _adapter *a; + void *c = NULL; + struct fsm_root *root = fsmpriv->root; + + if (!root) { + RTW_ERR("fsm: root hasn't initialized!\n"); + return; + } + fsm_deinit_custom(fsmpriv); + a = (_adapter *)root->a; + + FSM_INFO_(c, "fsm: [FSM] "FUNC_NDEV_FMT"\n",FUNC_NDEV_ARG(a->pnetdev)); + + fsm_deinit_queue(&(root->q_share_thd)); + _rtw_free_sema(&root->msg_ready); + + /* free fsm_root */ + rtw_mfree(root, sizeof(*root)); + fsmpriv->root = NULL; + +} + +void fsm_start_custom(struct fsm_priv *fsmpriv) +{ + struct fsm_root *root = fsmpriv->root; + struct fsm_main *fsm, *fsm_t; + + if (list_empty(&root->q_share_thd.q)) + return; + + list_for_each_entry_safe(fsm, fsm_t, &root->q_share_thd.q, list) { + fsm_start_fsm(fsm); + } +} + +void fsm_stop_custom(struct fsm_priv *fsmpriv) +{ + struct fsm_root *root = fsmpriv->root; + struct fsm_main *fsm, *fsm_t; + int sleep_count; + + if (list_empty(&root->q_share_thd.q)) + return; + + list_for_each_entry_safe(fsm, fsm_t, &root->q_share_thd.q, list) { + fsm_stop_fsm(fsm); + } + list_for_each_entry_safe(fsm, fsm_t, &root->q_share_thd.q, list) { + sleep_count = 100; + /* Max wait 1000ms until queue is empty */ + while (!list_empty(&fsm->msg_queue.q) && sleep_count--) + rtw_msleep_os(10); + + if (sleep_count <= 0) { + FSM_WARN_(fsm, "msg queue is not empty!\n"); + } + fsm_remove_all_queuing_msg(fsm); + } +} + +/* For EXTERNAL application to start fsm root (expose) + * @fsm: see struct fsm_main + */ +void rtw_fsm_start(struct fsm_priv *fsmpriv) +{ + struct fsm_root *root = fsmpriv->root; + _adapter *a = (_adapter *)root->a; + +#ifndef USE_PHL_CMD_DISPR + if (root->thread) { + RTW_WARN("fsm: thread is running\n"); + return; + } + root->thread_should_stop = 0; + root->thread = kthread_create(fsm_thread_share, root, "fsm_thread"); + wake_up_process(root->thread); +#endif + RTW_INFO("fsm: [FSM] "FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(a->pnetdev)); + + fsm_start_custom(fsmpriv); + return; +} + +/* For EXTERNAL application to stop fsm root (expose) + * @fsm: see struct fsm_main + */ +void rtw_fsm_stop(struct fsm_priv *fsmpriv) +{ + void *c = NULL; + struct fsm_root *root = fsmpriv->root; + _adapter *a = (_adapter *)root->a; + +#ifdef USE_PHL_CMD_DISPR + fsm_stop_custom(fsmpriv); +#else + if (!root->thread) { + RTW_INFO("fsm: thread was down\n"); + return; + } + fsm_stop_custom(fsmpriv); + + root->thread_should_stop = 1; + _rtw_up_sema(&root->msg_ready); + + kthread_stop(root->thread); + root->thread = NULL; +#endif + RTW_INFO("fsm: [FSM] "FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(a->pnetdev)); + + return; +} + +static int fsm_start_fsm(struct fsm_main *fsm) +{ + _adapter *a = fsm_to_adapter(fsm); + + _set_timer(&fsm->fsm_timer, CLOCK_UNIT); + fsm_status_set(fsm, FSM_STATUS_ENABLE); + + FSM_INFO_(fsm, "fsm: [%s] "FUNC_NDEV_FMT"\n", fsm->name, FUNC_NDEV_ARG(a->pnetdev)); + + return _SUCCESS; +} + +static int fsm_stop_fsm(struct fsm_main *fsm) +{ + struct fsm_obj *obj; + _adapter *a = fsm_to_adapter(fsm); + + _cancel_timer_ex(&fsm->fsm_timer); + + /* Stop receiving message */ + fsm_status_set(fsm, FSM_STATUS_DISABLE); + + /* ABORT all objs within fsm */ + fsm_abort_all_running_obj(fsm); + + FSM_INFO_(fsm, "fsm: [%s] "FUNC_NDEV_FMT"\n", fsm->name, FUNC_NDEV_ARG(a->pnetdev)); + + return _SUCCESS; +} + +/* For EXTERNAL application to generate message buffer (expose) + * Generate message quickly and simply + * @obj: fsm_obj (msg receiver) + * @pbuf: message parameter + * @sz: message parameter size + * @event: event for the message + */ +int fsm_gen_msg(struct fsm_obj *obj, void *pbuf, u32 sz, u16 event) +{ + void *param = NULL; + struct fsm_msg *msg; + + /* NEW mem for message */ + msg = fsm_new_msg(obj, event); + if (msg == NULL) { + FSM_ERR_(obj->fsm, "%s: alloc msg %s fail\n", + fsm_obj_name(obj), + fsm_evt_name(obj->fsm, event)); + goto msg_fail; + } + + /* NEW mem for param */ + if (pbuf && sz) { + param = rtw_zmalloc(sz); + if (param == NULL) { + FSM_ERR_(obj->fsm, + "%s: alloc param %s fail\n", + fsm_obj_name(obj), + fsm_evt_name(obj->fsm, event)); + rtw_mfree(msg, sizeof(*msg)); + goto msg_fail; + } + _rtw_memcpy(param, pbuf, sz); + msg->param = (void *)param; + msg->param_sz = sz; + } else { + msg->param = (void *)pbuf; + msg->param_sz = sz; + } + + return fsm_send_msg(obj->fsm, msg); + +msg_fail: + return _FAIL; +} + +static void fsm_bcast_msg(struct fsm_priv *fsmpriv, + struct sta_info *psta, char *pbuf, u32 sz, u16 event) +{ + struct fsm_root *root = fsmpriv->root; + struct fsm_main *fsm; + struct fsm_obj *obj; + + list_for_each_entry(fsm, &root->q_share_thd.q, list) { + if (fsm_status(fsm) != FSM_STATUS_ENABLE) + continue; + list_for_each_entry(obj, &fsm->obj_queue.q, list) { + if (!psta || (psta && obj->psta == psta)) + fsm_gen_msg(obj, pbuf, sz, event); + } + } +} + +void rtw_fsm_notify_connect(struct fsm_priv *fsmpriv, struct sta_info *psta, int res) +{ + _adapter *a = fsmpriv->root->a; + struct sta_info *pself; + + pself = rtw_get_stainfo(&a->stapriv, a->phl_role->mac_addr); + if (res >= 0) /* success */ + fsm_bcast_msg(fsmpriv, pself, (char *)psta, 0, FSM_EV_CONNECTED); + else + fsm_bcast_msg(fsmpriv, pself, (char *)psta, 0, FSM_EV_CONNECT_FAIL); +} + +void rtw_fsm_notify_disconnect(struct fsm_priv *fsmpriv, struct sta_info *psta) +{ + _adapter *a = fsmpriv->root->a; + struct sta_info *pself; + + pself = rtw_get_stainfo(&a->stapriv, a->phl_role->mac_addr); + if (pself) + fsm_bcast_msg(fsmpriv, psta, (char *)pself, 0, FSM_EV_DISCONNECTED); +} + +void rtw_fsm_notify_scan_start(struct fsm_priv *fsmpriv, struct sta_info *psta) +{ + fsm_bcast_msg(fsmpriv, psta, NULL, 0, FSM_EV_SCAN_START); +} + +void rtw_fsm_notify_scan_done(struct fsm_priv *fsmpriv, struct sta_info *psta) +{ + fsm_bcast_msg(fsmpriv, psta, NULL, 0, FSM_EV_SCAN_DONE); +} + +/** Debug funcitons + * + */ +#ifdef RTW_DEBUG_FSM +static void fsm_dbg_dump_fsm_queue(struct fsm_queue *fsmq, + char *s, int *sz,bool detail) +{ + struct fsm_main *fsm, *fsm_t; + + char *ptr = s; + int len = *sz; + + list_for_each_entry(fsm, &fsmq->q, list) { + _os_snprintf(pstr(ptr), lstr(ptr, len), "\t%4s : %s\n", fsm->name, + fsm->tb.mode ? "STANDALONE":"SHARE"); + + if (fsm->tb.dump_fsm && detail) { + len = lstr(ptr, len); + ptr = pstr(ptr); + fsm->tb.dump_fsm(fsm, ptr, &len); + } + } + *sz = len; +} + +static void fsm_dbg_help(struct fsm_main *fsm, char *s, int *sz, bool detail); +static void fsm_dbg_dump_fsm(struct fsm_main *fsm, + char *s, int *sz, bool detail) +{ + int len = *sz; + char *ptr = s; + + _os_snprintf(pstr(ptr), lstr(ptr, len), "\t%4s : %s\n", fsm->name, + fsm->tb.mode ? "STANDALONE":"SHARE"); + + if (fsm->tb.dump_fsm && detail) { + len = lstr(ptr, len); + ptr = pstr(ptr); + fsm->tb.dump_fsm(fsm, ptr, &len); + } + +} + +static void fsm_dbg_dump_state(struct fsm_main *fsm, + char *s, int *sz, bool detail) +{ + int i; + int len = *sz; + + _os_snprintf(pstr(s), lstr(s, len), + "[%s] state table\n", fsm->name); + for (i = 0; i < fsm->tb.max_state; i++) + _os_snprintf(pstr(s), lstr(s, len), "\t%4d : %s\n", + i, fsm->tb.state_tbl[i].name); + *sz = len; +} + +static void fsm_dbg_dump_event(struct fsm_main *fsm, + char *s, int *sz, bool detail) +{ + int i, max; + int len = *sz; + + /* internal event */ + _os_snprintf(pstr(s), lstr(s, len), "[Internal] event table\n"); + + max = FSM_EV_END & ~(int_event_tbl[0].event); /* FSM_INT_EV_MASK */ + for (i = 1; i < max; i++) + _os_snprintf(pstr(s), lstr(s, len), "\t0x%4x : %s\n", + int_event_tbl[i].event, int_event_tbl[i].name); + + /* user event */ + _os_snprintf(pstr(s), lstr(s, len), "\n[%s] event table max %d\n", fsm->name, fsm->tb.max_event); + for (i = 0; i < fsm->tb.max_event-1; i++) + _os_snprintf(pstr(s), lstr(s, len), "\t0x%4x : %s\n", + fsm->tb.evt_tbl[i].event, fsm->tb.evt_tbl[i].name); + *sz = len; +} + +static void fsm_dbg_dump_obj(struct fsm_main *fsm, + char *s, int *sz, bool detail) +{ + struct fsm_obj *obj, *obj_t; + int len = *sz; + char *ptr = s; + + list_for_each_entry(obj, &fsm->obj_queue.q, list) { + + _os_snprintf(pstr(ptr), lstr(ptr, len), "%s : state %s", + obj->name, fsm_state_name(fsm, obj->state)); + + if (fsm->tb.dump_obj && detail) { + len = lstr(ptr, len); + ptr = pstr(ptr); + fsm->tb.dump_obj(obj->custom_obj, ptr, &len); + } + } + *sz = len; +} + +static void fsm_dbg_max(struct fsm_main *fsm, char *s, int *sz, bool detail) +{ + int len = *sz; + + _os_snprintf(pstr(s), lstr(s, len), + "ERR: fsm %s sould not run to here!!\n", __func__); + *sz = len; +} + +struct fsm_debug_ent { + char *opt; + void (*func)(struct fsm_main *fsm, char *s, int *sz, bool detail); + char *desc; +}; + +struct fsm_debug_ent debug_opt[] = { + {"help", fsm_dbg_help, "help message"}, + {"fsm", fsm_dbg_dump_fsm, "all fsm name"}, + {"st", fsm_dbg_dump_state, "state name"}, + {"ev", fsm_dbg_dump_event, "event name"}, + {"obj", fsm_dbg_dump_obj, "obj detail"}, + {"max", fsm_dbg_max, "max_opt"} +}; + +static void _fsm_dbg_help(struct fsm_root *root, char *s, int *sz, bool detail) +{ + int i, max_opt; + int len = *sz; + char *ptr = s; + + _os_snprintf(pstr(ptr), lstr(ptr, len), + "usage:\tfsm d