diff --git a/core/rtw_chplan.c b/core/rtw_chplan.c index 82b3671..2754b0a 100644 --- a/core/rtw_chplan.c +++ b/core/rtw_chplan.c @@ -1,2516 +1,2516 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2018 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 - -#define RTW_DOMAIN_MAP_VER "54" -#define RTW_DOMAIN_MAP_M_VER "g" -#define RTW_COUNTRY_MAP_VER "27" - -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 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_00 = 0, - RTW_CHD_2G_01 = 1, - RTW_CHD_2G_02 = 2, - RTW_CHD_2G_03 = 3, - RTW_CHD_2G_04 = 4, - RTW_CHD_2G_05 = 5, - RTW_CHD_2G_06 = 6, - - RTW_CHD_2G_MAX, - RTW_CHD_2G_NULL = RTW_CHD_2G_00, -}; - -enum rtw_chd_5g { - RTW_CHD_5G_00 = 0, - RTW_CHD_5G_01 = 1, - RTW_CHD_5G_02 = 2, - RTW_CHD_5G_03 = 3, - RTW_CHD_5G_04 = 4, - RTW_CHD_5G_05 = 5, - RTW_CHD_5G_06 = 6, - RTW_CHD_5G_07 = 7, - RTW_CHD_5G_08 = 8, - RTW_CHD_5G_09 = 9, - RTW_CHD_5G_10 = 10, - RTW_CHD_5G_11 = 11, - RTW_CHD_5G_12 = 12, - RTW_CHD_5G_13 = 13, - RTW_CHD_5G_14 = 14, - RTW_CHD_5G_15 = 15, - RTW_CHD_5G_16 = 16, - RTW_CHD_5G_17 = 17, - RTW_CHD_5G_18 = 18, - RTW_CHD_5G_19 = 19, - RTW_CHD_5G_20 = 20, - RTW_CHD_5G_21 = 21, - RTW_CHD_5G_22 = 22, - RTW_CHD_5G_23 = 23, - RTW_CHD_5G_24 = 24, - RTW_CHD_5G_25 = 25, - RTW_CHD_5G_26 = 26, - RTW_CHD_5G_27 = 27, - RTW_CHD_5G_28 = 28, - RTW_CHD_5G_29 = 29, - RTW_CHD_5G_30 = 30, - RTW_CHD_5G_31 = 31, - RTW_CHD_5G_32 = 32, - RTW_CHD_5G_33 = 33, - RTW_CHD_5G_34 = 34, - RTW_CHD_5G_35 = 35, - RTW_CHD_5G_36 = 36, - RTW_CHD_5G_37 = 37, - RTW_CHD_5G_38 = 38, - RTW_CHD_5G_39 = 39, - RTW_CHD_5G_40 = 40, - RTW_CHD_5G_41 = 41, - RTW_CHD_5G_42 = 42, - RTW_CHD_5G_43 = 43, - RTW_CHD_5G_44 = 44, - RTW_CHD_5G_45 = 45, - RTW_CHD_5G_46 = 46, - RTW_CHD_5G_47 = 47, - RTW_CHD_5G_48 = 48, - RTW_CHD_5G_49 = 49, - RTW_CHD_5G_50 = 50, - RTW_CHD_5G_51 = 51, - - RTW_CHD_5G_MAX, - RTW_CHD_5G_NULL = RTW_CHD_5G_00, -}; - -static const struct ch_list_t rtw_channel_def_2g[] = { - /* 0, RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), - /* 1, 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), - /* 2, RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), - /* 3, RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), - /* 4, RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), - /* 5, RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), - /* 6, 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[] = { - /* 0, RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), - /* 1, 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), - /* 2, 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), - /* 3, 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), - /* 4, 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), - /* 5, 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), - /* 6, RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), - /* 7, 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), - /* 8, RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), - /* 9, RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), - /* 10, RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), - /* 11, RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), - /* 12, 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), - /* 13, RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), - /* 14, RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), - /* 15, RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), - /* 16, RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), - /* 17, 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), - /* 18, 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), - /* 19, 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), - /* 20, 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), - /* 21, 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), - /* 22, 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), - /* 23, 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), - /* 24, 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), - /* 25, 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), - /* 26, 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), - /* 27, 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), - /* 28, 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), - /* 29, 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), - /* 30, 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), - /* 31, 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), - /* 32, RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), - /* 33, 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), - /* 34, 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), - /* 35, RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), - /* 36, 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), - /* 37, RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), - /* 38, 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), - /* 39, 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), - /* 40, 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), - /* 41, 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), - /* 42, 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), - /* 43, 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), - /* 44, 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), - /* 45, 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), - /* 46, RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), - /* 47, 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), - /* 48, 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), - /* 49, 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), - /* 50, 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), - /* 51, 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), -}; -#endif /* CONFIG_IEEE80211_BAND_5GHZ */ - -struct chplan_ent_t { - u8 regd_2g; /* value of REGULATION_TXPWR_LMT */ - u8 chd_2g; -#if CONFIG_IEEE80211_BAND_5GHZ - u8 regd_5g; /* value of REGULATION_TXPWR_LMT */ - u8 chd_5g; -#endif -}; - -#if CONFIG_IEEE80211_BAND_5GHZ -#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = _regd_2g, .chd_2g = _chd_2g, .regd_5g = _regd_5g, .chd_5g = _chd_5g} -#else -#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = _regd_2g, .chd_2g = _chd_2g} -#endif - -#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_NULL, TXPWR_LMT_NONE, RTW_CHD_5G_NULL) - -static const struct chplan_ent_t RTW_ChannelPlanMap[] = { - /* 0x00 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_49), - /* 0x01 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_50), - /* 0x02 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_03, TXPWR_LMT_ETSI, RTW_CHD_5G_07), - /* 0x03 */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_02, TXPWR_LMT_ACMA, RTW_CHD_5G_33), - /* 0x04 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_51), - /* 0x05 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x06 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x07 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x08 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x09 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0A */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0B */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0C */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0D */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0E */ CHPLAN_ENT_NOT_DEFINED, - /* 0x0F */ CHPLAN_ENT_NOT_DEFINED, - /* 0x10 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x11 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x12 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x13 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x14 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x15 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x16 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x17 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x18 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x19 */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1A */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1B */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1C */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1D */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1E */ CHPLAN_ENT_NOT_DEFINED, - /* 0x1F */ CHPLAN_ENT_NOT_DEFINED, - /* 0x20 */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_01, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x21 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x22 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x23 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x24 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_05, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x25 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_03), - /* 0x26 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_02), - /* 0x27 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_02), - /* 0x28 */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_01, TXPWR_LMT_KCC, RTW_CHD_5G_05), - /* 0x29 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_06), - /* 0x2A */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x2B */ CHPLAN_ENT(TXPWR_LMT_IC, RTW_CHD_2G_02, TXPWR_LMT_IC, RTW_CHD_5G_33), - /* 0x2C */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x2D */ CHPLAN_ENT(TXPWR_LMT_CHILE, RTW_CHD_2G_01, TXPWR_LMT_CHILE, RTW_CHD_5G_22), - /* 0x2E */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_03, TXPWR_LMT_WW, RTW_CHD_5G_37), - /* 0x2F */ CHPLAN_ENT(TXPWR_LMT_CHILE, RTW_CHD_2G_01, TXPWR_LMT_CHILE, RTW_CHD_5G_38), - /* 0x30 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_07), - /* 0x31 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_08), - /* 0x32 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_09), - /* 0x33 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_10), - /* 0x34 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_01), - /* 0x35 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_03), - /* 0x36 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_04), - /* 0x37 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_10), - /* 0x38 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_11), - /* 0x39 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_12), - /* 0x3A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_02), - /* 0x3B */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_02, TXPWR_LMT_ACMA, RTW_CHD_5G_01), - /* 0x3C */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_10), - /* 0x3D */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_15), - /* 0x3E */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_02, TXPWR_LMT_KCC, RTW_CHD_5G_03), - /* 0x3F */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_22), - /* 0x40 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_13), - /* 0x41 */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_06, TXPWR_LMT_NONE, RTW_CHD_5G_00), - /* 0x42 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_14), - /* 0x43 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_06), - /* 0x44 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_09), - /* 0x45 */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_01, TXPWR_LMT_ACMA, RTW_CHD_5G_01), - /* 0x46 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_15), - /* 0x47 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_10), - /* 0x48 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_07), - /* 0x49 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_06), - /* 0x4A */ CHPLAN_ENT(TXPWR_LMT_IC, RTW_CHD_2G_03, TXPWR_LMT_IC, RTW_CHD_5G_33), - /* 0x4B */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_02, TXPWR_LMT_KCC, RTW_CHD_5G_22), - /* 0x4C */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_28), - /* 0x4D */ CHPLAN_ENT(TXPWR_LMT_MEXICO, RTW_CHD_2G_02, TXPWR_LMT_MEXICO, RTW_CHD_5G_01), - /* 0x4E */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_42), - /* 0x4F */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_MKK, RTW_CHD_5G_43), - /* 0x50 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_16), - /* 0x51 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_09), - /* 0x52 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_17), - /* 0x53 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_18), - /* 0x54 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_15), - /* 0x55 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_01), - /* 0x56 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_19), - /* 0x57 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_20), - /* 0x58 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_14), - /* 0x59 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_21), - /* 0x5A */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_44), - /* 0x5B */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_45), - /* 0x5C */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_43), - /* 0x5D */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_08), - /* 0x5E */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_03), - /* 0x5F */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_47), - /* 0x60 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_09), - /* 0x61 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_01), - /* 0x62 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_03), - /* 0x63 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_23), - /* 0x64 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_24), - /* 0x65 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_24), - /* 0x66 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_27), - /* 0x67 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_25), - /* 0x68 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_27), - /* 0x69 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_25), - /* 0x6A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_25), - /* 0x6B */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_29), - /* 0x6C */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_26), - /* 0x6D */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_28), - /* 0x6E */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_25), - /* 0x6F */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_06), - /* 0x70 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_30), - /* 0x71 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_25), - /* 0x72 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_31), - /* 0x73 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_01), - /* 0x74 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_19), - /* 0x75 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_32), - /* 0x76 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_22), - /* 0x77 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_34), - /* 0x78 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_35), - /* 0x79 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_02), - /* 0x7A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_28), - /* 0x7B */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_46), - /* 0x7C */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_47), - /* 0x7D */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_48), - /* 0x7E */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_48), - /* 0x7F */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_03), -}; - -const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); - -u8 rtw_chplan_get_default_regd_2g(u8 id) -{ - return RTW_ChannelPlanMap[id].regd_2g; -} - -u8 rtw_chplan_get_default_regd_5g(u8 id) -{ -#if CONFIG_IEEE80211_BAND_5GHZ - return RTW_ChannelPlanMap[id].regd_5g; -#else - return TXPWR_LMT_NONE; -#endif -} - -u8 rtw_chplan_get_default_regd(u8 id) -{ - u8 regd_2g = rtw_chplan_get_default_regd_2g(id); - u8 regd_5g = rtw_chplan_get_default_regd_5g(id); - - if (regd_2g != TXPWR_LMT_NONE && regd_5g != TXPWR_LMT_NONE) { - if (regd_2g != regd_5g) - RTW_WARN("channel_plan:0x%02x, regd_2g:%u, regd_5g:%u not the same\n", id, regd_2g, regd_5g); - return regd_5g; - } - return regd_2g != TXPWR_LMT_NONE ? regd_2g : regd_5g; -} - -bool rtw_chplan_is_empty(u8 id) -{ - const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; - - if (chplan_map->chd_2g == RTW_CHD_2G_NULL - #if CONFIG_IEEE80211_BAND_5GHZ - && chplan_map->chd_5g == RTW_CHD_5G_NULL - #endif - ) - return _TRUE; - - return _FALSE; -} - -bool rtw_is_channel_plan_valid(u8 id) -{ - return id < RTW_ChannelPlanMap_size && !rtw_chplan_is_empty(id); -} - -bool rtw_regsty_is_excl_chs(struct registry_priv *regsty, u8 ch) -{ - int i; - - for (i = 0; i < MAX_CHANNEL_NUM; i++) { - if (regsty->excl_chs[i] == 0) - break; - if (regsty->excl_chs[i] == ch) - return _TRUE; - } - return _FALSE; -} - -const char *_regd_src_str[] = { - [REGD_SRC_RTK_PRIV] = "RTK_PRIV", - [REGD_SRC_OS] = "OS", - [REGD_SRC_NUM] = "UNKNOWN", -}; - -static u8 init_channel_set_from_rtk_priv(_adapter *padapter, RT_CHANNEL_INFO *channel_set) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - struct registry_priv *regsty = adapter_to_regsty(padapter); - u8 ChannelPlan = rfctl->ChannelPlan; - u8 index, chanset_size = 0; - u8 b5GBand = _FALSE, b2_4GBand = _FALSE; - u8 ch, attrib; -#ifdef CONFIG_DFS_MASTER - int i; -#endif - - if (!rtw_is_channel_plan_valid(ChannelPlan)) { - RTW_ERR("ChannelPlan ID 0x%02X error !!!!!\n", ChannelPlan); - return chanset_size; - } - - _rtw_memset(channel_set, 0, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); - - if (IsSupported24G(regsty->wireless_mode) && hal_chk_band_cap(padapter, BAND_CAP_2G)) - b2_4GBand = _TRUE; - - if (is_supported_5g(regsty->wireless_mode) && hal_chk_band_cap(padapter, BAND_CAP_5G)) - b5GBand = _TRUE; - - if (b2_4GBand == _FALSE && b5GBand == _FALSE) { - RTW_WARN("HW band_cap has no intersection with SW wireless_mode setting\n"); - return chanset_size; - } - - if (b2_4GBand) { - u8 chd_2g = RTW_ChannelPlanMap[ChannelPlan].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++) { - ch = CH_LIST_CH(rtw_channel_def_2g[chd_2g], index); - if (rtw_regsty_is_excl_chs(regsty, ch) == _TRUE) - continue; - - if (chanset_size >= MAX_CHANNEL_NUM) { - RTW_WARN("chset size can't exceed MAX_CHANNEL_NUM(%u)\n", MAX_CHANNEL_NUM); - break; - } - - channel_set[chanset_size].ChannelNum = ch; - - if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) - channel_set[chanset_size].flags |= RTW_CHF_NO_IR; - - if (channel_set[chanset_size].flags & RTW_CHF_NO_IR) { - if (rfctl->country_ent || ch <= 11) - RTW_INFO("ch%u is PASSIVE\n", ch); - } - - chanset_size++; - } - } - -#if CONFIG_IEEE80211_BAND_5GHZ - if (b5GBand) { - bool dfs; - u8 chd_5g = RTW_ChannelPlanMap[ChannelPlan].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++) { - ch = CH_LIST_CH(rtw_channel_def_5g[chd_5g], index); - if (rtw_regsty_is_excl_chs(regsty, ch) == _TRUE) - continue; - dfs = (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)); - #if !CONFIG_DFS - if (dfs) - continue; - #endif - - if (chanset_size >= MAX_CHANNEL_NUM) { - RTW_WARN("chset size can't exceed MAX_CHANNEL_NUM(%u)\n", MAX_CHANNEL_NUM); - break; - } - - channel_set[chanset_size].ChannelNum = ch; - - 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 */ - ) - channel_set[chanset_size].flags |= RTW_CHF_NO_IR; - - if (dfs) - channel_set[chanset_size].flags |= RTW_CHF_DFS; - - if (channel_set[chanset_size].flags & RTW_CHF_NO_IR) { - if (rfctl->country_ent || (channel_set[chanset_size].flags & RTW_CHF_DFS)) - RTW_INFO("ch%u is PASSIVE%s\n", ch, dfs ? " DFS" : ""); - } - - chanset_size++; - } - } - - #ifdef CONFIG_DFS_MASTER - for (i = 0; i < chanset_size; i++) - channel_set[i].non_ocp_end_time = rtw_get_current_time(); - #endif -#endif /* CONFIG_IEEE80211_BAND_5GHZ */ - - if (chanset_size) - RTW_INFO(FUNC_ADPT_FMT" ChannelPlan ID:0x%02x, ch num:%d\n" - , FUNC_ADPT_ARG(padapter), ChannelPlan, chanset_size); - else - RTW_WARN(FUNC_ADPT_FMT" ChannelPlan ID:0x%02x, final chset has no channel\n" - , FUNC_ADPT_ARG(padapter), ChannelPlan); - - return chanset_size; -} - -u8 init_channel_set(_adapter *adapter) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - - if (rfctl->regd_src == REGD_SRC_RTK_PRIV) - return init_channel_set_from_rtk_priv(adapter, rfctl->channel_set); -#ifdef CONFIG_REGD_SRC_FROM_OS - else if (rfctl->regd_src == REGD_SRC_OS) - return rtw_os_init_channel_set(adapter, rfctl->channel_set); -#endif - else - rtw_warn_on(1); - - return 0; -} - -bool rtw_chset_is_dfs_range(struct _RT_CHANNEL_INFO *chset, u32 hi, u32 lo) -{ - u8 hi_ch = rtw_freq2ch(hi); - u8 lo_ch = rtw_freq2ch(lo); - int i; - - for (i = 0; i < MAX_CHANNEL_NUM && chset[i].ChannelNum != 0; i++){ - if (!(chset[i].flags & RTW_CHF_DFS)) - continue; - if (hi_ch > chset[i].ChannelNum && lo_ch < chset[i].ChannelNum) - return 1; - } - - return 0; -} - -bool rtw_chset_is_dfs_ch(struct _RT_CHANNEL_INFO *chset, u8 ch) -{ - int i; - - for (i = 0; i < MAX_CHANNEL_NUM && chset[i].ChannelNum != 0; i++){ - if (chset[i].ChannelNum == ch) - return chset[i].flags & RTW_CHF_DFS ? 1 : 0; - } - - return 0; -} - -bool rtw_chset_is_dfs_chbw(struct _RT_CHANNEL_INFO *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); -} - -u8 rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss) -{ -#ifndef RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE -#define RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE 0 -#endif - -#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 - - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - RT_CHANNEL_INFO *chset = rfctl->channel_set; - u8 ch = bss->Configuration.DSConfig; - int chset_idx = rtw_chset_search_ch(chset, ch); - u8 act_cnt = 0; - - if (chset_idx < 0) - goto exit; - - if ((chset[chset_idx].flags & RTW_CHF_NO_IR) - && (RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE || !rfctl->country_ent || IS_ALPHA2_WORLDWIDE(rfctl->country_ent->alpha2)) - && (RTW_CHPLAN_BEACON_HINT_ON_2G_CH_1_11 || !(ch <= 11)) - && (RTW_CHPLAN_BEACON_HINT_ON_DFS_CH || !(chset[chset_idx].flags & RTW_CHF_DFS)) - ) { - RTW_INFO("%s: change ch:%d to active\n", __func__, ch); - chset[chset_idx].flags &= ~RTW_CHF_NO_IR; - act_cnt++; - } - -exit: - return act_cnt; -} - -const char *_rtw_dfs_regd_str[] = { - [RTW_DFS_REGD_NONE] = "NONE", - [RTW_DFS_REGD_FCC] = "FCC", - [RTW_DFS_REGD_MKK] = "MKK", - [RTW_DFS_REGD_ETSI] = "ETSI", -}; - -#ifdef CONFIG_80211AC_VHT -#define COUNTRY_CHPLAN_ASSIGN_EN_11AC(_val) , .en_11ac = (_val) -#else -#define COUNTRY_CHPLAN_ASSIGN_EN_11AC(_val) -#endif - -#define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _en_11ac) \ - {.alpha2 = (_alpha2), .chplan = (_chplan) \ - COUNTRY_CHPLAN_ASSIGN_EN_11AC(_en_11ac) \ - } - -#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP - -#include "../platform/custom_country_chplan.h" - -#elif RTW_DEF_MODULE_REGULATORY_CERT - -#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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x34, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x30, 1), - COUNTRY_CHPLAN_ENT("CN", 0x51, 1), - COUNTRY_CHPLAN_ENT("CO", 0x34, 1), - COUNTRY_CHPLAN_ENT("CR", 0x34, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x34, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x34, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x34, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x47, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x34, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x34, 1), - COUNTRY_CHPLAN_ENT("PE", 0x34, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x34, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x34, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("UA", 0x36, 0), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x34, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 0), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("UA", 0x36, 0), - COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x34, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 0), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("UA", 0x36, 0), - COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AW", 0x34, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BB", 0x34, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BN", 0x47, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x20, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x34, 1), - COUNTRY_CHPLAN_ENT("CR", 0x34, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x34, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x34, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GD", 0x76, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GN", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x34, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HT", 0x34, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x34, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x34, 1), - COUNTRY_CHPLAN_ENT("PE", 0x34, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x34, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x34, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("RW", 0x26, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SC", 0x34, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VC", 0x34, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AW", 0x34, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BS", 0x34, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x20, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x34, 1), - COUNTRY_CHPLAN_ENT("CR", 0x34, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x34, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x34, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GD", 0x76, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x34, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MG", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x34, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x34, 1), - COUNTRY_CHPLAN_ENT("PE", 0x34, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x34, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x34, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("RW", 0x26, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BB", 0x34, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x20, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x34, 1), - COUNTRY_CHPLAN_ENT("CR", 0x34, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x34, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x34, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x34, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HT", 0x34, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x34, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x34, 1), - COUNTRY_CHPLAN_ENT("PE", 0x34, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x34, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x34, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("YE", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AW", 0x34, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x20, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x34, 1), - COUNTRY_CHPLAN_ENT("CR", 0x34, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x34, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x34, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("EH", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GD", 0x76, 1), - COUNTRY_CHPLAN_ENT("GF", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x34, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x34, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x34, 1), - COUNTRY_CHPLAN_ENT("PE", 0x34, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x34, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x34, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("RW", 0x26, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SC", 0x34, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("ST", 0x34, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TF", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x39, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x34, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("YT", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x2A, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x76, 1), - COUNTRY_CHPLAN_ENT("CR", 0x76, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x76, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x76, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x61, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x34, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NA", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x76, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x76, 1), - COUNTRY_CHPLAN_ENT("PE", 0x76, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x76, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x76, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x76, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("US", 0x76, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BB", 0x76, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BM", 0x76, 1), - COUNTRY_CHPLAN_ENT("BN", 0x47, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BS", 0x76, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x76, 1), - COUNTRY_CHPLAN_ENT("CR", 0x76, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x76, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x76, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("EH", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GE", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GI", 0x26, 1), - COUNTRY_CHPLAN_ENT("GL", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GN", 0x26, 1), - COUNTRY_CHPLAN_ENT("GP", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x61, 1), - COUNTRY_CHPLAN_ENT("GU", 0x76, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HT", 0x76, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MG", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MO", 0x35, 1), - COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NA", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x76, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x76, 1), - COUNTRY_CHPLAN_ENT("PE", 0x76, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x76, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x76, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SC", 0x76, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("ST", 0x76, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TF", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), - COUNTRY_CHPLAN_ENT("TW", 0x76, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x76, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("YT", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BB", 0x76, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BM", 0x76, 1), - COUNTRY_CHPLAN_ENT("BN", 0x47, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BS", 0x76, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x76, 1), - COUNTRY_CHPLAN_ENT("CR", 0x76, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x76, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x76, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("EH", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GE", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GI", 0x26, 1), - COUNTRY_CHPLAN_ENT("GL", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GN", 0x26, 1), - COUNTRY_CHPLAN_ENT("GP", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x61, 1), - COUNTRY_CHPLAN_ENT("GU", 0x76, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HT", 0x76, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x28, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MG", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MO", 0x35, 1), - COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NA", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x76, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x76, 1), - COUNTRY_CHPLAN_ENT("PE", 0x76, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x76, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x76, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SC", 0x76, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("ST", 0x76, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TF", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TW", 0x76, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x76, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("YT", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), - COUNTRY_CHPLAN_ENT("AW", 0x76, 1), - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), - COUNTRY_CHPLAN_ENT("BB", 0x76, 1), - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("BM", 0x76, 1), - COUNTRY_CHPLAN_ENT("BN", 0x47, 1), - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), - COUNTRY_CHPLAN_ENT("BS", 0x76, 1), - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), - COUNTRY_CHPLAN_ENT("CO", 0x76, 1), - COUNTRY_CHPLAN_ENT("CR", 0x76, 1), - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), - COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), - COUNTRY_CHPLAN_ENT("DO", 0x76, 1), - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), - COUNTRY_CHPLAN_ENT("EC", 0x76, 1), - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), - COUNTRY_CHPLAN_ENT("EH", 0x47, 1), - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), - COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), - COUNTRY_CHPLAN_ENT("GE", 0x26, 1), - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), - COUNTRY_CHPLAN_ENT("GI", 0x26, 1), - COUNTRY_CHPLAN_ENT("GL", 0x26, 1), - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), - COUNTRY_CHPLAN_ENT("GN", 0x26, 1), - COUNTRY_CHPLAN_ENT("GP", 0x26, 1), - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), - COUNTRY_CHPLAN_ENT("GT", 0x61, 1), - COUNTRY_CHPLAN_ENT("GU", 0x76, 1), - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), - COUNTRY_CHPLAN_ENT("HT", 0x76, 1), - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), - COUNTRY_CHPLAN_ENT("KM", 0x26, 1), - COUNTRY_CHPLAN_ENT("KR", 0x4B, 1), - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), - COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), - COUNTRY_CHPLAN_ENT("MG", 0x26, 1), - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), - COUNTRY_CHPLAN_ENT("MO", 0x35, 1), - COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), - COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("NA", 0x26, 1), - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), - COUNTRY_CHPLAN_ENT("NI", 0x76, 1), - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), - COUNTRY_CHPLAN_ENT("PA", 0x76, 1), - COUNTRY_CHPLAN_ENT("PE", 0x76, 1), - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), - COUNTRY_CHPLAN_ENT("PR", 0x76, 1), - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), - COUNTRY_CHPLAN_ENT("PY", 0x76, 1), - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), - COUNTRY_CHPLAN_ENT("SC", 0x76, 1), - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), - COUNTRY_CHPLAN_ENT("ST", 0x76, 1), - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), - COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), - COUNTRY_CHPLAN_ENT("TF", 0x26, 1), - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), - COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), - COUNTRY_CHPLAN_ENT("TW", 0x76, 1), - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), - COUNTRY_CHPLAN_ENT("US", 0x76, 1), - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), - COUNTRY_CHPLAN_ENT("YT", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), - COUNTRY_CHPLAN_ENT("ZW", 0x26, 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; -} -#else - -static const struct country_chplan country_chplan_map[] = { - COUNTRY_CHPLAN_ENT("AD", 0x26, 1), /* Andorra */ - COUNTRY_CHPLAN_ENT("AE", 0x35, 1), /* United Arab Emirates */ - COUNTRY_CHPLAN_ENT("AF", 0x42, 1), /* Afghanistan */ - COUNTRY_CHPLAN_ENT("AG", 0x76, 1), /* Antigua & Barbuda */ - COUNTRY_CHPLAN_ENT("AI", 0x26, 1), /* Anguilla(UK) */ - COUNTRY_CHPLAN_ENT("AL", 0x26, 1), /* Albania */ - COUNTRY_CHPLAN_ENT("AM", 0x26, 1), /* Armenia */ - COUNTRY_CHPLAN_ENT("AN", 0x76, 1), /* Netherlands Antilles */ - COUNTRY_CHPLAN_ENT("AO", 0x47, 1), /* Angola */ - COUNTRY_CHPLAN_ENT("AQ", 0x26, 1), /* Antarctica */ - COUNTRY_CHPLAN_ENT("AR", 0x61, 1), /* Argentina */ - COUNTRY_CHPLAN_ENT("AS", 0x76, 1), /* American Samoa */ - COUNTRY_CHPLAN_ENT("AT", 0x26, 1), /* Austria */ - COUNTRY_CHPLAN_ENT("AU", 0x45, 1), /* Australia */ - COUNTRY_CHPLAN_ENT("AW", 0x76, 1), /* Aruba */ - COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), /* Azerbaijan */ - COUNTRY_CHPLAN_ENT("BA", 0x26, 1), /* Bosnia & Herzegovina */ - COUNTRY_CHPLAN_ENT("BB", 0x76, 1), /* Barbados */ - COUNTRY_CHPLAN_ENT("BD", 0x26, 1), /* Bangladesh */ - COUNTRY_CHPLAN_ENT("BE", 0x26, 1), /* Belgium */ - COUNTRY_CHPLAN_ENT("BF", 0x26, 1), /* Burkina Faso */ - COUNTRY_CHPLAN_ENT("BG", 0x26, 1), /* Bulgaria */ - COUNTRY_CHPLAN_ENT("BH", 0x48, 1), /* Bahrain */ - COUNTRY_CHPLAN_ENT("BI", 0x26, 1), /* Burundi */ - COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), /* Benin */ - COUNTRY_CHPLAN_ENT("BM", 0x76, 1), /* Bermuda (UK) */ - COUNTRY_CHPLAN_ENT("BN", 0x47, 1), /* Brunei */ - COUNTRY_CHPLAN_ENT("BO", 0x73, 1), /* Bolivia */ - COUNTRY_CHPLAN_ENT("BR", 0x62, 1), /* Brazil */ - COUNTRY_CHPLAN_ENT("BS", 0x76, 1), /* Bahamas */ - COUNTRY_CHPLAN_ENT("BT", 0x26, 1), /* Bhutan */ - COUNTRY_CHPLAN_ENT("BV", 0x26, 1), /* Bouvet Island (Norway) */ - COUNTRY_CHPLAN_ENT("BW", 0x35, 1), /* Botswana */ - COUNTRY_CHPLAN_ENT("BY", 0x26, 1), /* Belarus */ - COUNTRY_CHPLAN_ENT("BZ", 0x76, 1), /* Belize */ - COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), /* Canada */ - COUNTRY_CHPLAN_ENT("CC", 0x26, 1), /* Cocos (Keeling) Islands (Australia) */ - COUNTRY_CHPLAN_ENT("CD", 0x26, 1), /* Congo, Republic of the */ - COUNTRY_CHPLAN_ENT("CF", 0x26, 1), /* Central African Republic */ - COUNTRY_CHPLAN_ENT("CG", 0x26, 1), /* Congo, Democratic Republic of the. Zaire */ - COUNTRY_CHPLAN_ENT("CH", 0x26, 1), /* Switzerland */ - COUNTRY_CHPLAN_ENT("CI", 0x42, 1), /* Cote d'Ivoire */ - COUNTRY_CHPLAN_ENT("CK", 0x26, 1), /* Cook Islands */ - COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), /* Chile */ - COUNTRY_CHPLAN_ENT("CM", 0x26, 1), /* Cameroon */ - COUNTRY_CHPLAN_ENT("CN", 0x48, 1), /* China */ - COUNTRY_CHPLAN_ENT("CO", 0x76, 1), /* Colombia */ - COUNTRY_CHPLAN_ENT("CR", 0x76, 1), /* Costa Rica */ - COUNTRY_CHPLAN_ENT("CV", 0x26, 1), /* Cape Verde */ - COUNTRY_CHPLAN_ENT("CX", 0x45, 1), /* Christmas Island (Australia) */ - COUNTRY_CHPLAN_ENT("CY", 0x26, 1), /* Cyprus */ - COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), /* Czech Republic */ - COUNTRY_CHPLAN_ENT("DE", 0x26, 1), /* Germany */ - COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), /* Djibouti */ - COUNTRY_CHPLAN_ENT("DK", 0x26, 1), /* Denmark */ - COUNTRY_CHPLAN_ENT("DM", 0x76, 1), /* Dominica */ - COUNTRY_CHPLAN_ENT("DO", 0x76, 1), /* Dominican Republic */ - COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), /* Algeria */ - COUNTRY_CHPLAN_ENT("EC", 0x76, 1), /* Ecuador */ - COUNTRY_CHPLAN_ENT("EE", 0x26, 1), /* Estonia */ - COUNTRY_CHPLAN_ENT("EG", 0x47, 1), /* Egypt */ - COUNTRY_CHPLAN_ENT("EH", 0x47, 1), /* Western Sahara */ - COUNTRY_CHPLAN_ENT("ER", 0x26, 1), /* Eritrea */ - COUNTRY_CHPLAN_ENT("ES", 0x26, 1), /* Spain, Canary Islands, Ceuta, Melilla */ - COUNTRY_CHPLAN_ENT("ET", 0x26, 1), /* Ethiopia */ - COUNTRY_CHPLAN_ENT("FI", 0x26, 1), /* Finland */ - COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), /* Fiji */ - COUNTRY_CHPLAN_ENT("FK", 0x26, 1), /* Falkland Islands (Islas Malvinas) (UK) */ - COUNTRY_CHPLAN_ENT("FM", 0x76, 1), /* Micronesia, Federated States of (USA) */ - COUNTRY_CHPLAN_ENT("FO", 0x26, 1), /* Faroe Islands (Denmark) */ - COUNTRY_CHPLAN_ENT("FR", 0x26, 1), /* France */ - COUNTRY_CHPLAN_ENT("GA", 0x26, 1), /* Gabon */ - COUNTRY_CHPLAN_ENT("GB", 0x26, 1), /* Great Britain (United Kingdom; England) */ - COUNTRY_CHPLAN_ENT("GD", 0x76, 1), /* Grenada */ - COUNTRY_CHPLAN_ENT("GE", 0x26, 1), /* Georgia */ - COUNTRY_CHPLAN_ENT("GF", 0x26, 1), /* French Guiana */ - COUNTRY_CHPLAN_ENT("GG", 0x26, 1), /* Guernsey (UK) */ - COUNTRY_CHPLAN_ENT("GH", 0x26, 1), /* Ghana */ - COUNTRY_CHPLAN_ENT("GI", 0x26, 1), /* Gibraltar (UK) */ - COUNTRY_CHPLAN_ENT("GL", 0x26, 1), /* Greenland (Denmark) */ - COUNTRY_CHPLAN_ENT("GM", 0x26, 1), /* Gambia */ - COUNTRY_CHPLAN_ENT("GN", 0x26, 1), /* Guinea */ - COUNTRY_CHPLAN_ENT("GP", 0x26, 1), /* Guadeloupe (France) */ - COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), /* Equatorial Guinea */ - COUNTRY_CHPLAN_ENT("GR", 0x26, 1), /* Greece */ - COUNTRY_CHPLAN_ENT("GS", 0x26, 1), /* South Georgia and the Sandwich Islands (UK) */ - COUNTRY_CHPLAN_ENT("GT", 0x61, 1), /* Guatemala */ - COUNTRY_CHPLAN_ENT("GU", 0x76, 1), /* Guam (USA) */ - COUNTRY_CHPLAN_ENT("GW", 0x26, 1), /* Guinea-Bissau */ - COUNTRY_CHPLAN_ENT("GY", 0x44, 1), /* Guyana */ - COUNTRY_CHPLAN_ENT("HK", 0x35, 1), /* Hong Kong */ - COUNTRY_CHPLAN_ENT("HM", 0x45, 1), /* Heard and McDonald Islands (Australia) */ - COUNTRY_CHPLAN_ENT("HN", 0x32, 1), /* Honduras */ - COUNTRY_CHPLAN_ENT("HR", 0x26, 1), /* Croatia */ - COUNTRY_CHPLAN_ENT("HT", 0x76, 1), /* Haiti */ - COUNTRY_CHPLAN_ENT("HU", 0x26, 1), /* Hungary */ - COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), /* Indonesia */ - COUNTRY_CHPLAN_ENT("IE", 0x26, 1), /* Ireland */ - COUNTRY_CHPLAN_ENT("IL", 0x47, 1), /* Israel */ - COUNTRY_CHPLAN_ENT("IM", 0x26, 1), /* Isle of Man (UK) */ - COUNTRY_CHPLAN_ENT("IN", 0x48, 1), /* India */ - COUNTRY_CHPLAN_ENT("IO", 0x26, 1), /* British Indian Ocean Territory (UK) */ - COUNTRY_CHPLAN_ENT("IQ", 0x26, 1), /* Iraq */ - COUNTRY_CHPLAN_ENT("IR", 0x26, 0), /* Iran */ - COUNTRY_CHPLAN_ENT("IS", 0x26, 1), /* Iceland */ - COUNTRY_CHPLAN_ENT("IT", 0x26, 1), /* Italy */ - COUNTRY_CHPLAN_ENT("JE", 0x26, 1), /* Jersey (UK) */ - COUNTRY_CHPLAN_ENT("JM", 0x32, 1), /* Jamaica */ - COUNTRY_CHPLAN_ENT("JO", 0x49, 1), /* Jordan */ - COUNTRY_CHPLAN_ENT("JP", 0x27, 1), /* Japan- Telec */ - COUNTRY_CHPLAN_ENT("KE", 0x47, 1), /* Kenya */ - COUNTRY_CHPLAN_ENT("KG", 0x26, 1), /* Kyrgyzstan */ - COUNTRY_CHPLAN_ENT("KH", 0x26, 1), /* Cambodia */ - COUNTRY_CHPLAN_ENT("KI", 0x26, 1), /* Kiribati */ - COUNTRY_CHPLAN_ENT("KM", 0x26, 1), /* Comoros */ - COUNTRY_CHPLAN_ENT("KN", 0x76, 1), /* Saint Kitts and Nevis */ - COUNTRY_CHPLAN_ENT("KR", 0x4B, 1), /* South Korea */ - COUNTRY_CHPLAN_ENT("KW", 0x26, 1), /* Kuwait */ - COUNTRY_CHPLAN_ENT("KY", 0x76, 1), /* Cayman Islands (UK) */ - COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), /* Kazakhstan */ - COUNTRY_CHPLAN_ENT("LA", 0x26, 1), /* Laos */ - COUNTRY_CHPLAN_ENT("LB", 0x26, 1), /* Lebanon */ - COUNTRY_CHPLAN_ENT("LC", 0x76, 1), /* Saint Lucia */ - COUNTRY_CHPLAN_ENT("LI", 0x26, 1), /* Liechtenstein */ - COUNTRY_CHPLAN_ENT("LK", 0x26, 1), /* Sri Lanka */ - COUNTRY_CHPLAN_ENT("LR", 0x26, 1), /* Liberia */ - COUNTRY_CHPLAN_ENT("LS", 0x26, 1), /* Lesotho */ - COUNTRY_CHPLAN_ENT("LT", 0x26, 1), /* Lithuania */ - COUNTRY_CHPLAN_ENT("LU", 0x26, 1), /* Luxembourg */ - COUNTRY_CHPLAN_ENT("LV", 0x26, 1), /* Latvia */ - COUNTRY_CHPLAN_ENT("LY", 0x26, 1), /* Libya */ - COUNTRY_CHPLAN_ENT("MA", 0x47, 1), /* Morocco */ - COUNTRY_CHPLAN_ENT("MC", 0x26, 1), /* Monaco */ - COUNTRY_CHPLAN_ENT("MD", 0x26, 1), /* Moldova */ - COUNTRY_CHPLAN_ENT("ME", 0x26, 1), /* Montenegro */ - COUNTRY_CHPLAN_ENT("MF", 0x76, 1), /* Saint Martin */ - COUNTRY_CHPLAN_ENT("MG", 0x26, 1), /* Madagascar */ - COUNTRY_CHPLAN_ENT("MH", 0x76, 1), /* Marshall Islands (USA) */ - COUNTRY_CHPLAN_ENT("MK", 0x26, 1), /* Republic of Macedonia (FYROM) */ - COUNTRY_CHPLAN_ENT("ML", 0x26, 1), /* Mali */ - COUNTRY_CHPLAN_ENT("MM", 0x26, 1), /* Burma (Myanmar) */ - COUNTRY_CHPLAN_ENT("MN", 0x26, 1), /* Mongolia */ - COUNTRY_CHPLAN_ENT("MO", 0x35, 1), /* Macau */ - COUNTRY_CHPLAN_ENT("MP", 0x76, 1), /* Northern Mariana Islands (USA) */ - COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), /* Martinique (France) */ - COUNTRY_CHPLAN_ENT("MR", 0x26, 1), /* Mauritania */ - COUNTRY_CHPLAN_ENT("MS", 0x26, 1), /* Montserrat (UK) */ - COUNTRY_CHPLAN_ENT("MT", 0x26, 1), /* Malta */ - COUNTRY_CHPLAN_ENT("MU", 0x26, 1), /* Mauritius */ - COUNTRY_CHPLAN_ENT("MV", 0x47, 1), /* Maldives */ - COUNTRY_CHPLAN_ENT("MW", 0x26, 1), /* Malawi */ - COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), /* Mexico */ - COUNTRY_CHPLAN_ENT("MY", 0x63, 1), /* Malaysia */ - COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), /* Mozambique */ - COUNTRY_CHPLAN_ENT("NA", 0x26, 1), /* Namibia */ - COUNTRY_CHPLAN_ENT("NC", 0x26, 1), /* New Caledonia */ - COUNTRY_CHPLAN_ENT("NE", 0x26, 1), /* Niger */ - COUNTRY_CHPLAN_ENT("NF", 0x45, 1), /* Norfolk Island (Australia) */ - COUNTRY_CHPLAN_ENT("NG", 0x75, 1), /* Nigeria */ - COUNTRY_CHPLAN_ENT("NI", 0x76, 1), /* Nicaragua */ - COUNTRY_CHPLAN_ENT("NL", 0x26, 1), /* Netherlands */ - COUNTRY_CHPLAN_ENT("NO", 0x26, 1), /* Norway */ - COUNTRY_CHPLAN_ENT("NP", 0x48, 1), /* Nepal */ - COUNTRY_CHPLAN_ENT("NR", 0x26, 1), /* Nauru */ - COUNTRY_CHPLAN_ENT("NU", 0x45, 1), /* Niue */ - COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), /* New Zealand */ - COUNTRY_CHPLAN_ENT("OM", 0x26, 1), /* Oman */ - COUNTRY_CHPLAN_ENT("PA", 0x76, 1), /* Panama */ - COUNTRY_CHPLAN_ENT("PE", 0x76, 1), /* Peru */ - COUNTRY_CHPLAN_ENT("PF", 0x26, 1), /* French Polynesia (France) */ - COUNTRY_CHPLAN_ENT("PG", 0x35, 1), /* Papua New Guinea */ - COUNTRY_CHPLAN_ENT("PH", 0x35, 1), /* Philippines */ - COUNTRY_CHPLAN_ENT("PK", 0x51, 1), /* Pakistan */ - COUNTRY_CHPLAN_ENT("PL", 0x26, 1), /* Poland */ - COUNTRY_CHPLAN_ENT("PM", 0x26, 1), /* Saint Pierre and Miquelon (France) */ - COUNTRY_CHPLAN_ENT("PR", 0x76, 1), /* Puerto Rico */ - COUNTRY_CHPLAN_ENT("PT", 0x26, 1), /* Portugal */ - COUNTRY_CHPLAN_ENT("PW", 0x76, 1), /* Palau */ - COUNTRY_CHPLAN_ENT("PY", 0x76, 1), /* Paraguay */ - COUNTRY_CHPLAN_ENT("QA", 0x35, 1), /* Qatar */ - COUNTRY_CHPLAN_ENT("RE", 0x26, 1), /* Reunion (France) */ - COUNTRY_CHPLAN_ENT("RO", 0x26, 1), /* Romania */ - COUNTRY_CHPLAN_ENT("RS", 0x26, 1), /* Serbia, Kosovo */ - COUNTRY_CHPLAN_ENT("RU", 0x59, 1), /* Russia(fac/gost), Kaliningrad */ - COUNTRY_CHPLAN_ENT("RW", 0x26, 1), /* Rwanda */ - COUNTRY_CHPLAN_ENT("SA", 0x35, 1), /* Saudi Arabia */ - COUNTRY_CHPLAN_ENT("SB", 0x26, 1), /* Solomon Islands */ - COUNTRY_CHPLAN_ENT("SC", 0x76, 1), /* Seychelles */ - COUNTRY_CHPLAN_ENT("SE", 0x26, 1), /* Sweden */ - COUNTRY_CHPLAN_ENT("SG", 0x35, 1), /* Singapore */ - COUNTRY_CHPLAN_ENT("SH", 0x26, 1), /* Saint Helena (UK) */ - COUNTRY_CHPLAN_ENT("SI", 0x26, 1), /* Slovenia */ - COUNTRY_CHPLAN_ENT("SJ", 0x26, 1), /* Svalbard (Norway) */ - COUNTRY_CHPLAN_ENT("SK", 0x26, 1), /* Slovakia */ - COUNTRY_CHPLAN_ENT("SL", 0x26, 1), /* Sierra Leone */ - COUNTRY_CHPLAN_ENT("SM", 0x26, 1), /* San Marino */ - COUNTRY_CHPLAN_ENT("SN", 0x26, 1), /* Senegal */ - COUNTRY_CHPLAN_ENT("SO", 0x26, 1), /* Somalia */ - COUNTRY_CHPLAN_ENT("SR", 0x74, 1), /* Suriname */ - COUNTRY_CHPLAN_ENT("ST", 0x76, 1), /* Sao Tome and Principe */ - COUNTRY_CHPLAN_ENT("SV", 0x30, 1), /* El Salvador */ - COUNTRY_CHPLAN_ENT("SX", 0x76, 1), /* Sint Marteen */ - COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), /* Swaziland */ - COUNTRY_CHPLAN_ENT("TC", 0x26, 1), /* Turks and Caicos Islands (UK) */ - COUNTRY_CHPLAN_ENT("TD", 0x26, 1), /* Chad */ - COUNTRY_CHPLAN_ENT("TF", 0x26, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ - COUNTRY_CHPLAN_ENT("TG", 0x26, 1), /* Togo */ - COUNTRY_CHPLAN_ENT("TH", 0x35, 1), /* Thailand */ - COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), /* Tajikistan */ - COUNTRY_CHPLAN_ENT("TK", 0x45, 1), /* Tokelau */ - COUNTRY_CHPLAN_ENT("TM", 0x26, 1), /* Turkmenistan */ - COUNTRY_CHPLAN_ENT("TN", 0x47, 1), /* Tunisia */ - COUNTRY_CHPLAN_ENT("TO", 0x26, 1), /* Tonga */ - COUNTRY_CHPLAN_ENT("TR", 0x26, 1), /* Turkey, Northern Cyprus */ - COUNTRY_CHPLAN_ENT("TT", 0x76, 1), /* Trinidad & Tobago */ - COUNTRY_CHPLAN_ENT("TV", 0x21, 0), /* Tuvalu */ - COUNTRY_CHPLAN_ENT("TW", 0x76, 1), /* Taiwan */ - COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), /* Tanzania */ - COUNTRY_CHPLAN_ENT("UA", 0x35, 1), /* Ukraine */ - COUNTRY_CHPLAN_ENT("UG", 0x26, 1), /* Uganda */ - COUNTRY_CHPLAN_ENT("US", 0x76, 1), /* United States of America (USA) */ - COUNTRY_CHPLAN_ENT("UY", 0x30, 1), /* Uruguay */ - COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), /* Uzbekistan */ - COUNTRY_CHPLAN_ENT("VA", 0x26, 1), /* Holy See (Vatican City) */ - COUNTRY_CHPLAN_ENT("VC", 0x76, 1), /* Saint Vincent and the Grenadines */ - COUNTRY_CHPLAN_ENT("VE", 0x30, 1), /* Venezuela */ - COUNTRY_CHPLAN_ENT("VG", 0x76, 1), /* British Virgin Islands (UK) */ - COUNTRY_CHPLAN_ENT("VI", 0x76, 1), /* United States Virgin Islands (USA) */ - COUNTRY_CHPLAN_ENT("VN", 0x35, 1), /* Vietnam */ - COUNTRY_CHPLAN_ENT("VU", 0x26, 1), /* Vanuatu */ - COUNTRY_CHPLAN_ENT("WF", 0x26, 1), /* Wallis and Futuna (France) */ - COUNTRY_CHPLAN_ENT("WS", 0x76, 1), /* Samoa */ - COUNTRY_CHPLAN_ENT("YE", 0x26, 1), /* Yemen */ - COUNTRY_CHPLAN_ENT("YT", 0x26, 1), /* Mayotte (France) */ - COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), /* South Africa */ - COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), /* Zambia */ - COUNTRY_CHPLAN_ENT("ZW", 0x26, 1), /* Zimbabwe */ -}; -#endif /* CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP or RTW_DEF_MODULE_REGULATORY_CERT or newest */ - -/* -* rtw_get_chplan_from_country - -* @country_code: string of country code -* -* Return pointer of struct country_chplan entry or NULL when unsupported country_code is given -*/ -const struct country_chplan *rtw_get_chplan_from_country(const char *country_code) -{ - const struct country_chplan *ent = NULL; - const struct country_chplan *map = NULL; - u16 map_sz = 0; - char code[2]; - int i; - - code[0] = alpha_to_upper(country_code[0]); - code[1] = alpha_to_upper(country_code[1]); - -#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP - map = CUSTOMIZED_country_chplan_map; - map_sz = sizeof(CUSTOMIZED_country_chplan_map) / sizeof(struct country_chplan); -#elif RTW_DEF_MODULE_REGULATORY_CERT - map_sz = rtw_def_module_country_chplan_map(&map); -#else - map = country_chplan_map; - map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); -#endif - - for (i = 0; i < map_sz; i++) { - if (strncmp(code, map[i].alpha2, 2) == 0) { - ent = &map[i]; - break; - } - } - - return ent; -} - -void dump_country_chplan(void *sel, const struct country_chplan *ent) -{ - char buf[16]; - - if (ent->chplan == RTW_CHPLAN_UNSPECIFIED) - sprintf(buf, "NA"); - else - sprintf(buf, "0x%02X", ent->chplan); - - RTW_PRINT_SEL(sel, "\"%c%c\", %s%s\n" - , ent->alpha2[0], ent->alpha2[1], buf - , COUNTRY_CHPLAN_EN_11AC(ent) ? " ac" : "" - ); -} - -void dump_country_chplan_map(void *sel) -{ - const 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 - - for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { - for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { - ent = rtw_get_chplan_from_country(code); - if (!ent) - continue; - - dump_country_chplan(sel, ent); - } - } -} - -void dump_chplan_id_list(void *sel) -{ - u8 first = 1; - int i; - - for (i = 0; i < RTW_ChannelPlanMap_size; 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); - } -} - -#ifdef CONFIG_RTW_DEBUG -void dump_chplan_test(void *sel) -{ - int i, j; - - /* check redundent */ - for (i = 0; i < RTW_CHD_2G_MAX; i++) { - for (j = 0; 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 invalid channel */ - for (i = 0; i < RTW_CHD_2G_MAX; i++) { - for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { - if (rtw_ch2freq(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 redundent */ - for (i = 0; i < RTW_CHD_5G_MAX; i++) { - for (j = 0; 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 invalid channel */ - for (i = 0; i < RTW_CHD_5G_MAX; i++) { - for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { - if (rtw_ch2freq(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 - - /* check 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); - } - } -} -#endif /* CONFIG_RTW_DEBUG */ - -void dump_chplan_ver(void *sel) -{ - RTW_PRINT_SEL(sel, "%s%s-%s\n", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER); -} +/****************************************************************************** + * + * Copyright(c) 2007 - 2018 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 + +#define RTW_DOMAIN_MAP_VER "54" +#define RTW_DOMAIN_MAP_M_VER "g" +#define RTW_COUNTRY_MAP_VER "27" + +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 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_00 = 0, + RTW_CHD_2G_01 = 1, + RTW_CHD_2G_02 = 2, + RTW_CHD_2G_03 = 3, + RTW_CHD_2G_04 = 4, + RTW_CHD_2G_05 = 5, + RTW_CHD_2G_06 = 6, + + RTW_CHD_2G_MAX, + RTW_CHD_2G_NULL = RTW_CHD_2G_00, +}; + +enum rtw_chd_5g { + RTW_CHD_5G_00 = 0, + RTW_CHD_5G_01 = 1, + RTW_CHD_5G_02 = 2, + RTW_CHD_5G_03 = 3, + RTW_CHD_5G_04 = 4, + RTW_CHD_5G_05 = 5, + RTW_CHD_5G_06 = 6, + RTW_CHD_5G_07 = 7, + RTW_CHD_5G_08 = 8, + RTW_CHD_5G_09 = 9, + RTW_CHD_5G_10 = 10, + RTW_CHD_5G_11 = 11, + RTW_CHD_5G_12 = 12, + RTW_CHD_5G_13 = 13, + RTW_CHD_5G_14 = 14, + RTW_CHD_5G_15 = 15, + RTW_CHD_5G_16 = 16, + RTW_CHD_5G_17 = 17, + RTW_CHD_5G_18 = 18, + RTW_CHD_5G_19 = 19, + RTW_CHD_5G_20 = 20, + RTW_CHD_5G_21 = 21, + RTW_CHD_5G_22 = 22, + RTW_CHD_5G_23 = 23, + RTW_CHD_5G_24 = 24, + RTW_CHD_5G_25 = 25, + RTW_CHD_5G_26 = 26, + RTW_CHD_5G_27 = 27, + RTW_CHD_5G_28 = 28, + RTW_CHD_5G_29 = 29, + RTW_CHD_5G_30 = 30, + RTW_CHD_5G_31 = 31, + RTW_CHD_5G_32 = 32, + RTW_CHD_5G_33 = 33, + RTW_CHD_5G_34 = 34, + RTW_CHD_5G_35 = 35, + RTW_CHD_5G_36 = 36, + RTW_CHD_5G_37 = 37, + RTW_CHD_5G_38 = 38, + RTW_CHD_5G_39 = 39, + RTW_CHD_5G_40 = 40, + RTW_CHD_5G_41 = 41, + RTW_CHD_5G_42 = 42, + RTW_CHD_5G_43 = 43, + RTW_CHD_5G_44 = 44, + RTW_CHD_5G_45 = 45, + RTW_CHD_5G_46 = 46, + RTW_CHD_5G_47 = 47, + RTW_CHD_5G_48 = 48, + RTW_CHD_5G_49 = 49, + RTW_CHD_5G_50 = 50, + RTW_CHD_5G_51 = 51, + + RTW_CHD_5G_MAX, + RTW_CHD_5G_NULL = RTW_CHD_5G_00, +}; + +static const struct ch_list_t rtw_channel_def_2g[] = { + /* 0, RTW_CHD_2G_00 */ CH_LIST_ENT(0, 0), + /* 1, 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), + /* 2, RTW_CHD_2G_02 */ CH_LIST_ENT(13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0), + /* 3, RTW_CHD_2G_03 */ CH_LIST_ENT(11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0), + /* 4, RTW_CHD_2G_04 */ CH_LIST_ENT(14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0), + /* 5, RTW_CHD_2G_05 */ CH_LIST_ENT(4, 10, 11, 12, 13, 0), + /* 6, 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[] = { + /* 0, RTW_CHD_5G_00 */ CH_LIST_ENT(0, 0), + /* 1, 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), + /* 2, 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), + /* 3, 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), + /* 4, 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), + /* 5, 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), + /* 6, RTW_CHD_5G_06 */ CH_LIST_ENT(9, 36, 40, 44, 48, 149, 153, 157, 161, 165, 0), + /* 7, 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), + /* 8, RTW_CHD_5G_08 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_DFS), + /* 9, RTW_CHD_5G_09 */ CH_LIST_ENT(5, 149, 153, 157, 161, 165, 0), + /* 10, RTW_CHD_5G_10 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B2_DFS), + /* 11, RTW_CHD_5G_11 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, CLA_5G_B3_DFS), + /* 12, 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), + /* 13, RTW_CHD_5G_13 */ CH_LIST_ENT(8, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* 14, RTW_CHD_5G_14 */ CH_LIST_ENT(4, 36, 40, 44, 48, 0), + /* 15, RTW_CHD_5G_15 */ CH_LIST_ENT(4, 149, 153, 157, 161, 0), + /* 16, RTW_CHD_5G_16 */ CH_LIST_ENT(11, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0), + /* 17, 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), + /* 18, 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), + /* 19, 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), + /* 20, 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), + /* 21, 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), + /* 22, 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), + /* 23, 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), + /* 24, 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), + /* 25, 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), + /* 26, 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), + /* 27, 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), + /* 28, 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), + /* 29, 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), + /* 30, 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), + /* 31, 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), + /* 32, RTW_CHD_5G_32 */ CH_LIST_ENT(9, 52, 56, 60, 64, 149, 153, 157, 161, 165, CLA_5G_B2_DFS), + /* 33, 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), + /* 34, 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), + /* 35, RTW_CHD_5G_35 */ CH_LIST_ENT(8, 100, 104, 108, 112, 116, 132, 136, 140, CLA_5G_B3_DFS), + /* 36, 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), + /* 37, RTW_CHD_5G_37 */ CH_LIST_ENT(8, 36, 40, 44, 48, 52, 56, 60, 64, CLA_5G_B1_PASSIVE | CLA_5G_B2_PASSIVE), + /* 38, 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), + /* 39, 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), + /* 40, 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), + /* 41, 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), + /* 42, 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), + /* 43, 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), + /* 44, 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), + /* 45, 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), + /* 46, RTW_CHD_5G_46 */ CH_LIST_ENT(12, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, CLA_5G_B2_PASSIVE), + /* 47, 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), + /* 48, 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), + /* 49, 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), + /* 50, 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), + /* 51, 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), +}; +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + +struct chplan_ent_t { + u8 regd_2g; /* value of REGULATION_TXPWR_LMT */ + u8 chd_2g; +#if CONFIG_IEEE80211_BAND_5GHZ + u8 regd_5g; /* value of REGULATION_TXPWR_LMT */ + u8 chd_5g; +#endif +}; + +#if CONFIG_IEEE80211_BAND_5GHZ +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = _regd_2g, .chd_2g = _chd_2g, .regd_5g = _regd_5g, .chd_5g = _chd_5g} +#else +#define CHPLAN_ENT(_regd_2g, _chd_2g, _regd_5g, _chd_5g) {.regd_2g = _regd_2g, .chd_2g = _chd_2g} +#endif + +#define CHPLAN_ENT_NOT_DEFINED CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_NULL, TXPWR_LMT_NONE, RTW_CHD_5G_NULL) + +static const struct chplan_ent_t RTW_ChannelPlanMap[] = { + /* 0x00 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_49), + /* 0x01 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_50), + /* 0x02 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_03, TXPWR_LMT_ETSI, RTW_CHD_5G_07), + /* 0x03 */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_02, TXPWR_LMT_ACMA, RTW_CHD_5G_33), + /* 0x04 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_51), + /* 0x05 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x06 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x07 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x08 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x09 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0A */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0B */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0C */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0D */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0E */ CHPLAN_ENT_NOT_DEFINED, + /* 0x0F */ CHPLAN_ENT_NOT_DEFINED, + /* 0x10 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x11 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x12 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x13 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x14 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x15 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x16 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x17 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x18 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x19 */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1A */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1B */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1C */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1D */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1E */ CHPLAN_ENT_NOT_DEFINED, + /* 0x1F */ CHPLAN_ENT_NOT_DEFINED, + /* 0x20 */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_01, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x21 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x22 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x23 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x24 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_05, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x25 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_03), + /* 0x26 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_02), + /* 0x27 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_02), + /* 0x28 */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_01, TXPWR_LMT_KCC, RTW_CHD_5G_05), + /* 0x29 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_06), + /* 0x2A */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x2B */ CHPLAN_ENT(TXPWR_LMT_IC, RTW_CHD_2G_02, TXPWR_LMT_IC, RTW_CHD_5G_33), + /* 0x2C */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x2D */ CHPLAN_ENT(TXPWR_LMT_CHILE, RTW_CHD_2G_01, TXPWR_LMT_CHILE, RTW_CHD_5G_22), + /* 0x2E */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_03, TXPWR_LMT_WW, RTW_CHD_5G_37), + /* 0x2F */ CHPLAN_ENT(TXPWR_LMT_CHILE, RTW_CHD_2G_01, TXPWR_LMT_CHILE, RTW_CHD_5G_38), + /* 0x30 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_07), + /* 0x31 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_08), + /* 0x32 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_09), + /* 0x33 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_10), + /* 0x34 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_01), + /* 0x35 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_03), + /* 0x36 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_04), + /* 0x37 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_10), + /* 0x38 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_11), + /* 0x39 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_12), + /* 0x3A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_02), + /* 0x3B */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_02, TXPWR_LMT_ACMA, RTW_CHD_5G_01), + /* 0x3C */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_10), + /* 0x3D */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_15), + /* 0x3E */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_02, TXPWR_LMT_KCC, RTW_CHD_5G_03), + /* 0x3F */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_22), + /* 0x40 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_13), + /* 0x41 */ CHPLAN_ENT(TXPWR_LMT_WW, RTW_CHD_2G_06, TXPWR_LMT_NONE, RTW_CHD_5G_00), + /* 0x42 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_14), + /* 0x43 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_06), + /* 0x44 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_09), + /* 0x45 */ CHPLAN_ENT(TXPWR_LMT_ACMA, RTW_CHD_2G_01, TXPWR_LMT_ACMA, RTW_CHD_5G_01), + /* 0x46 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_15), + /* 0x47 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_10), + /* 0x48 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_07), + /* 0x49 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_06), + /* 0x4A */ CHPLAN_ENT(TXPWR_LMT_IC, RTW_CHD_2G_03, TXPWR_LMT_IC, RTW_CHD_5G_33), + /* 0x4B */ CHPLAN_ENT(TXPWR_LMT_KCC, RTW_CHD_2G_02, TXPWR_LMT_KCC, RTW_CHD_5G_22), + /* 0x4C */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_28), + /* 0x4D */ CHPLAN_ENT(TXPWR_LMT_MEXICO, RTW_CHD_2G_02, TXPWR_LMT_MEXICO, RTW_CHD_5G_01), + /* 0x4E */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_42), + /* 0x4F */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_MKK, RTW_CHD_5G_43), + /* 0x50 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_16), + /* 0x51 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_09), + /* 0x52 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_17), + /* 0x53 */ CHPLAN_ENT(TXPWR_LMT_NCC, RTW_CHD_2G_03, TXPWR_LMT_NCC, RTW_CHD_5G_18), + /* 0x54 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_15), + /* 0x55 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_01), + /* 0x56 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_19), + /* 0x57 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_20), + /* 0x58 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_14), + /* 0x59 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_21), + /* 0x5A */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_44), + /* 0x5B */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_45), + /* 0x5C */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_FCC, RTW_CHD_5G_43), + /* 0x5D */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_08), + /* 0x5E */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_03), + /* 0x5F */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_47), + /* 0x60 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_09), + /* 0x61 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_01), + /* 0x62 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_03), + /* 0x63 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_23), + /* 0x64 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_24), + /* 0x65 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_24), + /* 0x66 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_27), + /* 0x67 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_25), + /* 0x68 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_27), + /* 0x69 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_25), + /* 0x6A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_25), + /* 0x6B */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_29), + /* 0x6C */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_26), + /* 0x6D */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_28), + /* 0x6E */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_25), + /* 0x6F */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_06), + /* 0x70 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_30), + /* 0x71 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_25), + /* 0x72 */ CHPLAN_ENT(TXPWR_LMT_NONE, RTW_CHD_2G_00, TXPWR_LMT_ETSI, RTW_CHD_5G_31), + /* 0x73 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_01), + /* 0x74 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_19), + /* 0x75 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_32), + /* 0x76 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_02, TXPWR_LMT_FCC, RTW_CHD_5G_22), + /* 0x77 */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_01, TXPWR_LMT_ETSI, RTW_CHD_5G_34), + /* 0x78 */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_03, TXPWR_LMT_FCC, RTW_CHD_5G_35), + /* 0x79 */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_02), + /* 0x7A */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_28), + /* 0x7B */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_46), + /* 0x7C */ CHPLAN_ENT(TXPWR_LMT_ETSI, RTW_CHD_2G_02, TXPWR_LMT_ETSI, RTW_CHD_5G_47), + /* 0x7D */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_04, TXPWR_LMT_MKK, RTW_CHD_5G_48), + /* 0x7E */ CHPLAN_ENT(TXPWR_LMT_MKK, RTW_CHD_2G_02, TXPWR_LMT_MKK, RTW_CHD_5G_48), + /* 0x7F */ CHPLAN_ENT(TXPWR_LMT_FCC, RTW_CHD_2G_01, TXPWR_LMT_FCC, RTW_CHD_5G_03), +}; + +const int RTW_ChannelPlanMap_size = sizeof(RTW_ChannelPlanMap) / sizeof(RTW_ChannelPlanMap[0]); + +u8 rtw_chplan_get_default_regd_2g(u8 id) +{ + return RTW_ChannelPlanMap[id].regd_2g; +} + +u8 rtw_chplan_get_default_regd_5g(u8 id) +{ +#if CONFIG_IEEE80211_BAND_5GHZ + return RTW_ChannelPlanMap[id].regd_5g; +#else + return TXPWR_LMT_NONE; +#endif +} + +u8 rtw_chplan_get_default_regd(u8 id) +{ + u8 regd_2g = rtw_chplan_get_default_regd_2g(id); + u8 regd_5g = rtw_chplan_get_default_regd_5g(id); + + if (regd_2g != TXPWR_LMT_NONE && regd_5g != TXPWR_LMT_NONE) { + if (regd_2g != regd_5g) + RTW_WARN("channel_plan:0x%02x, regd_2g:%u, regd_5g:%u not the same\n", id, regd_2g, regd_5g); + return regd_5g; + } + return regd_2g != TXPWR_LMT_NONE ? regd_2g : regd_5g; +} + +bool rtw_chplan_is_empty(u8 id) +{ + const struct chplan_ent_t *chplan_map = &RTW_ChannelPlanMap[id]; + + if (chplan_map->chd_2g == RTW_CHD_2G_NULL + #if CONFIG_IEEE80211_BAND_5GHZ + && chplan_map->chd_5g == RTW_CHD_5G_NULL + #endif + ) + return _TRUE; + + return _FALSE; +} + +bool rtw_is_channel_plan_valid(u8 id) +{ + return id < RTW_ChannelPlanMap_size && !rtw_chplan_is_empty(id); +} + +bool rtw_regsty_is_excl_chs(struct registry_priv *regsty, u8 ch) +{ + int i; + + for (i = 0; i < MAX_CHANNEL_NUM; i++) { + if (regsty->excl_chs[i] == 0) + break; + if (regsty->excl_chs[i] == ch) + return _TRUE; + } + return _FALSE; +} + +const char *_regd_src_str[] = { + [REGD_SRC_RTK_PRIV] = "RTK_PRIV", + [REGD_SRC_OS] = "OS", + [REGD_SRC_NUM] = "UNKNOWN", +}; + +static u8 init_channel_set_from_rtk_priv(_adapter *padapter, RT_CHANNEL_INFO *channel_set) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); + struct registry_priv *regsty = adapter_to_regsty(padapter); + u8 ChannelPlan = rfctl->ChannelPlan; + u8 index, chanset_size = 0; + u8 b5GBand = _FALSE, b2_4GBand = _FALSE; + u8 ch, attrib; +#ifdef CONFIG_DFS_MASTER + int i; +#endif + + if (!rtw_is_channel_plan_valid(ChannelPlan)) { + RTW_ERR("ChannelPlan ID 0x%02X error !!!!!\n", ChannelPlan); + return chanset_size; + } + + _rtw_memset(channel_set, 0, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); + + if (IsSupported24G(regsty->wireless_mode) && hal_chk_band_cap(padapter, BAND_CAP_2G)) + b2_4GBand = _TRUE; + + if (is_supported_5g(regsty->wireless_mode) && hal_chk_band_cap(padapter, BAND_CAP_5G)) + b5GBand = _TRUE; + + if (b2_4GBand == _FALSE && b5GBand == _FALSE) { + RTW_WARN("HW band_cap has no intersection with SW wireless_mode setting\n"); + return chanset_size; + } + + if (b2_4GBand) { + u8 chd_2g = RTW_ChannelPlanMap[ChannelPlan].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++) { + ch = CH_LIST_CH(rtw_channel_def_2g[chd_2g], index); + if (rtw_regsty_is_excl_chs(regsty, ch) == _TRUE) + continue; + + if (chanset_size >= MAX_CHANNEL_NUM) { + RTW_WARN("chset size can't exceed MAX_CHANNEL_NUM(%u)\n", MAX_CHANNEL_NUM); + break; + } + + channel_set[chanset_size].ChannelNum = ch; + + if (ch >= 12 && ch <= 14 && (attrib & CLA_2G_12_14_PASSIVE)) + channel_set[chanset_size].flags |= RTW_CHF_NO_IR; + + if (channel_set[chanset_size].flags & RTW_CHF_NO_IR) { + if (rfctl->country_ent || ch <= 11) + RTW_INFO("ch%u is PASSIVE\n", ch); + } + + chanset_size++; + } + } + +#if CONFIG_IEEE80211_BAND_5GHZ + if (b5GBand) { + bool dfs; + u8 chd_5g = RTW_ChannelPlanMap[ChannelPlan].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++) { + ch = CH_LIST_CH(rtw_channel_def_5g[chd_5g], index); + if (rtw_regsty_is_excl_chs(regsty, ch) == _TRUE) + continue; + dfs = (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)); + #if !CONFIG_DFS + if (dfs) + continue; + #endif + + if (chanset_size >= MAX_CHANNEL_NUM) { + RTW_WARN("chset size can't exceed MAX_CHANNEL_NUM(%u)\n", MAX_CHANNEL_NUM); + break; + } + + channel_set[chanset_size].ChannelNum = ch; + + 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 */ + ) + channel_set[chanset_size].flags |= RTW_CHF_NO_IR; + + if (dfs) + channel_set[chanset_size].flags |= RTW_CHF_DFS; + + if (channel_set[chanset_size].flags & RTW_CHF_NO_IR) { + if (rfctl->country_ent || (channel_set[chanset_size].flags & RTW_CHF_DFS)) + RTW_INFO("ch%u is PASSIVE%s\n", ch, dfs ? " DFS" : ""); + } + + chanset_size++; + } + } + + #ifdef CONFIG_DFS_MASTER + for (i = 0; i < chanset_size; i++) + channel_set[i].non_ocp_end_time = rtw_get_current_time(); + #endif +#endif /* CONFIG_IEEE80211_BAND_5GHZ */ + + if (chanset_size) + RTW_INFO(FUNC_ADPT_FMT" ChannelPlan ID:0x%02x, ch num:%d\n" + , FUNC_ADPT_ARG(padapter), ChannelPlan, chanset_size); + else + RTW_WARN(FUNC_ADPT_FMT" ChannelPlan ID:0x%02x, final chset has no channel\n" + , FUNC_ADPT_ARG(padapter), ChannelPlan); + + return chanset_size; +} + +u8 init_channel_set(_adapter *adapter) +{ + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + + if (rfctl->regd_src == REGD_SRC_RTK_PRIV) + return init_channel_set_from_rtk_priv(adapter, rfctl->channel_set); +#ifdef CONFIG_REGD_SRC_FROM_OS + else if (rfctl->regd_src == REGD_SRC_OS) + return rtw_os_init_channel_set(adapter, rfctl->channel_set); +#endif + else + rtw_warn_on(1); + + return 0; +} + +bool rtw_chset_is_dfs_range(struct _RT_CHANNEL_INFO *chset, u32 hi, u32 lo) +{ + u8 hi_ch = rtw_freq2ch(hi); + u8 lo_ch = rtw_freq2ch(lo); + int i; + + for (i = 0; i < MAX_CHANNEL_NUM && chset[i].ChannelNum != 0; i++){ + if (!(chset[i].flags & RTW_CHF_DFS)) + continue; + if (hi_ch > chset[i].ChannelNum && lo_ch < chset[i].ChannelNum) + return 1; + } + + return 0; +} + +bool rtw_chset_is_dfs_ch(struct _RT_CHANNEL_INFO *chset, u8 ch) +{ + int i; + + for (i = 0; i < MAX_CHANNEL_NUM && chset[i].ChannelNum != 0; i++){ + if (chset[i].ChannelNum == ch) + return chset[i].flags & RTW_CHF_DFS ? 1 : 0; + } + + return 0; +} + +bool rtw_chset_is_dfs_chbw(struct _RT_CHANNEL_INFO *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); +} + +u8 rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss) +{ +#ifndef RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE +#define RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE 0 +#endif + +#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 + + struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); + RT_CHANNEL_INFO *chset = rfctl->channel_set; + u8 ch = bss->Configuration.DSConfig; + int chset_idx = rtw_chset_search_ch(chset, ch); + u8 act_cnt = 0; + + if (chset_idx < 0) + goto exit; + + if ((chset[chset_idx].flags & RTW_CHF_NO_IR) + && (RTW_CHPLAN_BEACON_HINT_NON_WORLD_WIDE || !rfctl->country_ent || IS_ALPHA2_WORLDWIDE(rfctl->country_ent->alpha2)) + && (RTW_CHPLAN_BEACON_HINT_ON_2G_CH_1_11 || !(ch <= 11)) + && (RTW_CHPLAN_BEACON_HINT_ON_DFS_CH || !(chset[chset_idx].flags & RTW_CHF_DFS)) + ) { + RTW_INFO("%s: change ch:%d to active\n", __func__, ch); + chset[chset_idx].flags &= ~RTW_CHF_NO_IR; + act_cnt++; + } + +exit: + return act_cnt; +} + +const char *_rtw_dfs_regd_str[] = { + [RTW_DFS_REGD_NONE] = "NONE", + [RTW_DFS_REGD_FCC] = "FCC", + [RTW_DFS_REGD_MKK] = "MKK", + [RTW_DFS_REGD_ETSI] = "ETSI", +}; + +#ifdef CONFIG_80211AC_VHT +#define COUNTRY_CHPLAN_ASSIGN_EN_11AC(_val) , .en_11ac = (_val) +#else +#define COUNTRY_CHPLAN_ASSIGN_EN_11AC(_val) +#endif + +#define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _en_11ac) \ + {.alpha2 = (_alpha2), .chplan = (_chplan) \ + COUNTRY_CHPLAN_ASSIGN_EN_11AC(_en_11ac) \ + } + +#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP + +#include "../platform/custom_country_chplan.h" + +#elif RTW_DEF_MODULE_REGULATORY_CERT + +#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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x30, 1), + COUNTRY_CHPLAN_ENT("CN", 0x51, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x47, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0), + COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x34, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 0), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("UA", 0x36, 0), + COUNTRY_CHPLAN_ENT("US", 0x34, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BB", 0x34, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HT", 0x34, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SC", 0x34, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VC", 0x34, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BS", 0x34, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BB", 0x34, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HT", 0x34, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("YE", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AW", 0x34, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x20, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x34, 1), + COUNTRY_CHPLAN_ENT("CR", 0x34, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x34, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x34, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GD", 0x76, 1), + COUNTRY_CHPLAN_ENT("GF", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x34, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x34, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x34, 1), + COUNTRY_CHPLAN_ENT("PE", 0x34, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x34, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x34, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("RW", 0x26, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SC", 0x34, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("ST", 0x34, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x39, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x34, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2A, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x34, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("ID", 0x3D, 0), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x28, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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, 1), + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), + COUNTRY_CHPLAN_ENT("AW", 0x76, 1), + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), + COUNTRY_CHPLAN_ENT("BB", 0x76, 1), + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("BM", 0x76, 1), + COUNTRY_CHPLAN_ENT("BN", 0x47, 1), + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), + COUNTRY_CHPLAN_ENT("BS", 0x76, 1), + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), + COUNTRY_CHPLAN_ENT("CO", 0x76, 1), + COUNTRY_CHPLAN_ENT("CR", 0x76, 1), + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), + COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), + COUNTRY_CHPLAN_ENT("DO", 0x76, 1), + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), + COUNTRY_CHPLAN_ENT("EC", 0x76, 1), + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), + COUNTRY_CHPLAN_ENT("EH", 0x47, 1), + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), + COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), + COUNTRY_CHPLAN_ENT("GE", 0x26, 1), + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), + COUNTRY_CHPLAN_ENT("GI", 0x26, 1), + COUNTRY_CHPLAN_ENT("GL", 0x26, 1), + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), + COUNTRY_CHPLAN_ENT("GN", 0x26, 1), + COUNTRY_CHPLAN_ENT("GP", 0x26, 1), + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), + COUNTRY_CHPLAN_ENT("GT", 0x61, 1), + COUNTRY_CHPLAN_ENT("GU", 0x76, 1), + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), + COUNTRY_CHPLAN_ENT("HT", 0x76, 1), + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), + COUNTRY_CHPLAN_ENT("KM", 0x26, 1), + COUNTRY_CHPLAN_ENT("KR", 0x4B, 1), + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), + COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), + COUNTRY_CHPLAN_ENT("MG", 0x26, 1), + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), + COUNTRY_CHPLAN_ENT("MO", 0x35, 1), + COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), + COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("NA", 0x26, 1), + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), + COUNTRY_CHPLAN_ENT("NI", 0x76, 1), + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), + COUNTRY_CHPLAN_ENT("PA", 0x76, 1), + COUNTRY_CHPLAN_ENT("PE", 0x76, 1), + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), + COUNTRY_CHPLAN_ENT("PR", 0x76, 1), + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), + COUNTRY_CHPLAN_ENT("PY", 0x76, 1), + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), + COUNTRY_CHPLAN_ENT("SC", 0x76, 1), + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), + COUNTRY_CHPLAN_ENT("ST", 0x76, 1), + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), + COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), + COUNTRY_CHPLAN_ENT("TF", 0x26, 1), + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), + COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), + COUNTRY_CHPLAN_ENT("TW", 0x76, 1), + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), + COUNTRY_CHPLAN_ENT("US", 0x76, 1), + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), + COUNTRY_CHPLAN_ENT("YT", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), + COUNTRY_CHPLAN_ENT("ZW", 0x26, 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; +} +#else + +static const struct country_chplan country_chplan_map[] = { + COUNTRY_CHPLAN_ENT("AD", 0x26, 1), /* Andorra */ + COUNTRY_CHPLAN_ENT("AE", 0x35, 1), /* United Arab Emirates */ + COUNTRY_CHPLAN_ENT("AF", 0x42, 1), /* Afghanistan */ + COUNTRY_CHPLAN_ENT("AG", 0x76, 1), /* Antigua & Barbuda */ + COUNTRY_CHPLAN_ENT("AI", 0x26, 1), /* Anguilla(UK) */ + COUNTRY_CHPLAN_ENT("AL", 0x26, 1), /* Albania */ + COUNTRY_CHPLAN_ENT("AM", 0x26, 1), /* Armenia */ + COUNTRY_CHPLAN_ENT("AN", 0x76, 1), /* Netherlands Antilles */ + COUNTRY_CHPLAN_ENT("AO", 0x47, 1), /* Angola */ + COUNTRY_CHPLAN_ENT("AQ", 0x26, 1), /* Antarctica */ + COUNTRY_CHPLAN_ENT("AR", 0x61, 1), /* Argentina */ + COUNTRY_CHPLAN_ENT("AS", 0x76, 1), /* American Samoa */ + COUNTRY_CHPLAN_ENT("AT", 0x26, 1), /* Austria */ + COUNTRY_CHPLAN_ENT("AU", 0x45, 1), /* Australia */ + COUNTRY_CHPLAN_ENT("AW", 0x76, 1), /* Aruba */ + COUNTRY_CHPLAN_ENT("AZ", 0x26, 1), /* Azerbaijan */ + COUNTRY_CHPLAN_ENT("BA", 0x26, 1), /* Bosnia & Herzegovina */ + COUNTRY_CHPLAN_ENT("BB", 0x76, 1), /* Barbados */ + COUNTRY_CHPLAN_ENT("BD", 0x26, 1), /* Bangladesh */ + COUNTRY_CHPLAN_ENT("BE", 0x26, 1), /* Belgium */ + COUNTRY_CHPLAN_ENT("BF", 0x26, 1), /* Burkina Faso */ + COUNTRY_CHPLAN_ENT("BG", 0x26, 1), /* Bulgaria */ + COUNTRY_CHPLAN_ENT("BH", 0x48, 1), /* Bahrain */ + COUNTRY_CHPLAN_ENT("BI", 0x26, 1), /* Burundi */ + COUNTRY_CHPLAN_ENT("BJ", 0x26, 1), /* Benin */ + COUNTRY_CHPLAN_ENT("BM", 0x76, 1), /* Bermuda (UK) */ + COUNTRY_CHPLAN_ENT("BN", 0x47, 1), /* Brunei */ + COUNTRY_CHPLAN_ENT("BO", 0x73, 1), /* Bolivia */ + COUNTRY_CHPLAN_ENT("BR", 0x62, 1), /* Brazil */ + COUNTRY_CHPLAN_ENT("BS", 0x76, 1), /* Bahamas */ + COUNTRY_CHPLAN_ENT("BT", 0x26, 1), /* Bhutan */ + COUNTRY_CHPLAN_ENT("BV", 0x26, 1), /* Bouvet Island (Norway) */ + COUNTRY_CHPLAN_ENT("BW", 0x35, 1), /* Botswana */ + COUNTRY_CHPLAN_ENT("BY", 0x26, 1), /* Belarus */ + COUNTRY_CHPLAN_ENT("BZ", 0x76, 1), /* Belize */ + COUNTRY_CHPLAN_ENT("CA", 0x2B, 1), /* Canada */ + COUNTRY_CHPLAN_ENT("CC", 0x26, 1), /* Cocos (Keeling) Islands (Australia) */ + COUNTRY_CHPLAN_ENT("CD", 0x26, 1), /* Congo, Republic of the */ + COUNTRY_CHPLAN_ENT("CF", 0x26, 1), /* Central African Republic */ + COUNTRY_CHPLAN_ENT("CG", 0x26, 1), /* Congo, Democratic Republic of the. Zaire */ + COUNTRY_CHPLAN_ENT("CH", 0x26, 1), /* Switzerland */ + COUNTRY_CHPLAN_ENT("CI", 0x42, 1), /* Cote d'Ivoire */ + COUNTRY_CHPLAN_ENT("CK", 0x26, 1), /* Cook Islands */ + COUNTRY_CHPLAN_ENT("CL", 0x2D, 1), /* Chile */ + COUNTRY_CHPLAN_ENT("CM", 0x26, 1), /* Cameroon */ + COUNTRY_CHPLAN_ENT("CN", 0x48, 1), /* China */ + COUNTRY_CHPLAN_ENT("CO", 0x76, 1), /* Colombia */ + COUNTRY_CHPLAN_ENT("CR", 0x76, 1), /* Costa Rica */ + COUNTRY_CHPLAN_ENT("CV", 0x26, 1), /* Cape Verde */ + COUNTRY_CHPLAN_ENT("CX", 0x45, 1), /* Christmas Island (Australia) */ + COUNTRY_CHPLAN_ENT("CY", 0x26, 1), /* Cyprus */ + COUNTRY_CHPLAN_ENT("CZ", 0x26, 1), /* Czech Republic */ + COUNTRY_CHPLAN_ENT("DE", 0x26, 1), /* Germany */ + COUNTRY_CHPLAN_ENT("DJ", 0x26, 1), /* Djibouti */ + COUNTRY_CHPLAN_ENT("DK", 0x26, 1), /* Denmark */ + COUNTRY_CHPLAN_ENT("DM", 0x76, 1), /* Dominica */ + COUNTRY_CHPLAN_ENT("DO", 0x76, 1), /* Dominican Republic */ + COUNTRY_CHPLAN_ENT("DZ", 0x00, 1), /* Algeria */ + COUNTRY_CHPLAN_ENT("EC", 0x76, 1), /* Ecuador */ + COUNTRY_CHPLAN_ENT("EE", 0x26, 1), /* Estonia */ + COUNTRY_CHPLAN_ENT("EG", 0x47, 1), /* Egypt */ + COUNTRY_CHPLAN_ENT("EH", 0x47, 1), /* Western Sahara */ + COUNTRY_CHPLAN_ENT("ER", 0x26, 1), /* Eritrea */ + COUNTRY_CHPLAN_ENT("ES", 0x26, 1), /* Spain, Canary Islands, Ceuta, Melilla */ + COUNTRY_CHPLAN_ENT("ET", 0x26, 1), /* Ethiopia */ + COUNTRY_CHPLAN_ENT("FI", 0x26, 1), /* Finland */ + COUNTRY_CHPLAN_ENT("FJ", 0x76, 1), /* Fiji */ + COUNTRY_CHPLAN_ENT("FK", 0x26, 1), /* Falkland Islands (Islas Malvinas) (UK) */ + COUNTRY_CHPLAN_ENT("FM", 0x76, 1), /* Micronesia, Federated States of (USA) */ + COUNTRY_CHPLAN_ENT("FO", 0x26, 1), /* Faroe Islands (Denmark) */ + COUNTRY_CHPLAN_ENT("FR", 0x26, 1), /* France */ + COUNTRY_CHPLAN_ENT("GA", 0x26, 1), /* Gabon */ + COUNTRY_CHPLAN_ENT("GB", 0x26, 1), /* Great Britain (United Kingdom; England) */ + COUNTRY_CHPLAN_ENT("GD", 0x76, 1), /* Grenada */ + COUNTRY_CHPLAN_ENT("GE", 0x26, 1), /* Georgia */ + COUNTRY_CHPLAN_ENT("GF", 0x26, 1), /* French Guiana */ + COUNTRY_CHPLAN_ENT("GG", 0x26, 1), /* Guernsey (UK) */ + COUNTRY_CHPLAN_ENT("GH", 0x26, 1), /* Ghana */ + COUNTRY_CHPLAN_ENT("GI", 0x26, 1), /* Gibraltar (UK) */ + COUNTRY_CHPLAN_ENT("GL", 0x26, 1), /* Greenland (Denmark) */ + COUNTRY_CHPLAN_ENT("GM", 0x26, 1), /* Gambia */ + COUNTRY_CHPLAN_ENT("GN", 0x26, 1), /* Guinea */ + COUNTRY_CHPLAN_ENT("GP", 0x26, 1), /* Guadeloupe (France) */ + COUNTRY_CHPLAN_ENT("GQ", 0x26, 1), /* Equatorial Guinea */ + COUNTRY_CHPLAN_ENT("GR", 0x26, 1), /* Greece */ + COUNTRY_CHPLAN_ENT("GS", 0x26, 1), /* South Georgia and the Sandwich Islands (UK) */ + COUNTRY_CHPLAN_ENT("GT", 0x61, 1), /* Guatemala */ + COUNTRY_CHPLAN_ENT("GU", 0x76, 1), /* Guam (USA) */ + COUNTRY_CHPLAN_ENT("GW", 0x26, 1), /* Guinea-Bissau */ + COUNTRY_CHPLAN_ENT("GY", 0x44, 1), /* Guyana */ + COUNTRY_CHPLAN_ENT("HK", 0x35, 1), /* Hong Kong */ + COUNTRY_CHPLAN_ENT("HM", 0x45, 1), /* Heard and McDonald Islands (Australia) */ + COUNTRY_CHPLAN_ENT("HN", 0x32, 1), /* Honduras */ + COUNTRY_CHPLAN_ENT("HR", 0x26, 1), /* Croatia */ + COUNTRY_CHPLAN_ENT("HT", 0x76, 1), /* Haiti */ + COUNTRY_CHPLAN_ENT("HU", 0x26, 1), /* Hungary */ + COUNTRY_CHPLAN_ENT("ID", 0x5D, 1), /* Indonesia */ + COUNTRY_CHPLAN_ENT("IE", 0x26, 1), /* Ireland */ + COUNTRY_CHPLAN_ENT("IL", 0x47, 1), /* Israel */ + COUNTRY_CHPLAN_ENT("IM", 0x26, 1), /* Isle of Man (UK) */ + COUNTRY_CHPLAN_ENT("IN", 0x48, 1), /* India */ + COUNTRY_CHPLAN_ENT("IO", 0x26, 1), /* British Indian Ocean Territory (UK) */ + COUNTRY_CHPLAN_ENT("IQ", 0x26, 1), /* Iraq */ + COUNTRY_CHPLAN_ENT("IR", 0x26, 0), /* Iran */ + COUNTRY_CHPLAN_ENT("IS", 0x26, 1), /* Iceland */ + COUNTRY_CHPLAN_ENT("IT", 0x26, 1), /* Italy */ + COUNTRY_CHPLAN_ENT("JE", 0x26, 1), /* Jersey (UK) */ + COUNTRY_CHPLAN_ENT("JM", 0x32, 1), /* Jamaica */ + COUNTRY_CHPLAN_ENT("JO", 0x49, 1), /* Jordan */ + COUNTRY_CHPLAN_ENT("JP", 0x27, 1), /* Japan- Telec */ + COUNTRY_CHPLAN_ENT("KE", 0x47, 1), /* Kenya */ + COUNTRY_CHPLAN_ENT("KG", 0x26, 1), /* Kyrgyzstan */ + COUNTRY_CHPLAN_ENT("KH", 0x26, 1), /* Cambodia */ + COUNTRY_CHPLAN_ENT("KI", 0x26, 1), /* Kiribati */ + COUNTRY_CHPLAN_ENT("KM", 0x26, 1), /* Comoros */ + COUNTRY_CHPLAN_ENT("KN", 0x76, 1), /* Saint Kitts and Nevis */ + COUNTRY_CHPLAN_ENT("KR", 0x4B, 1), /* South Korea */ + COUNTRY_CHPLAN_ENT("KW", 0x26, 1), /* Kuwait */ + COUNTRY_CHPLAN_ENT("KY", 0x76, 1), /* Cayman Islands (UK) */ + COUNTRY_CHPLAN_ENT("KZ", 0x26, 1), /* Kazakhstan */ + COUNTRY_CHPLAN_ENT("LA", 0x26, 1), /* Laos */ + COUNTRY_CHPLAN_ENT("LB", 0x26, 1), /* Lebanon */ + COUNTRY_CHPLAN_ENT("LC", 0x76, 1), /* Saint Lucia */ + COUNTRY_CHPLAN_ENT("LI", 0x26, 1), /* Liechtenstein */ + COUNTRY_CHPLAN_ENT("LK", 0x26, 1), /* Sri Lanka */ + COUNTRY_CHPLAN_ENT("LR", 0x26, 1), /* Liberia */ + COUNTRY_CHPLAN_ENT("LS", 0x26, 1), /* Lesotho */ + COUNTRY_CHPLAN_ENT("LT", 0x26, 1), /* Lithuania */ + COUNTRY_CHPLAN_ENT("LU", 0x26, 1), /* Luxembourg */ + COUNTRY_CHPLAN_ENT("LV", 0x26, 1), /* Latvia */ + COUNTRY_CHPLAN_ENT("LY", 0x26, 1), /* Libya */ + COUNTRY_CHPLAN_ENT("MA", 0x47, 1), /* Morocco */ + COUNTRY_CHPLAN_ENT("MC", 0x26, 1), /* Monaco */ + COUNTRY_CHPLAN_ENT("MD", 0x26, 1), /* Moldova */ + COUNTRY_CHPLAN_ENT("ME", 0x26, 1), /* Montenegro */ + COUNTRY_CHPLAN_ENT("MF", 0x76, 1), /* Saint Martin */ + COUNTRY_CHPLAN_ENT("MG", 0x26, 1), /* Madagascar */ + COUNTRY_CHPLAN_ENT("MH", 0x76, 1), /* Marshall Islands (USA) */ + COUNTRY_CHPLAN_ENT("MK", 0x26, 1), /* Republic of Macedonia (FYROM) */ + COUNTRY_CHPLAN_ENT("ML", 0x26, 1), /* Mali */ + COUNTRY_CHPLAN_ENT("MM", 0x26, 1), /* Burma (Myanmar) */ + COUNTRY_CHPLAN_ENT("MN", 0x26, 1), /* Mongolia */ + COUNTRY_CHPLAN_ENT("MO", 0x35, 1), /* Macau */ + COUNTRY_CHPLAN_ENT("MP", 0x76, 1), /* Northern Mariana Islands (USA) */ + COUNTRY_CHPLAN_ENT("MQ", 0x26, 1), /* Martinique (France) */ + COUNTRY_CHPLAN_ENT("MR", 0x26, 1), /* Mauritania */ + COUNTRY_CHPLAN_ENT("MS", 0x26, 1), /* Montserrat (UK) */ + COUNTRY_CHPLAN_ENT("MT", 0x26, 1), /* Malta */ + COUNTRY_CHPLAN_ENT("MU", 0x26, 1), /* Mauritius */ + COUNTRY_CHPLAN_ENT("MV", 0x47, 1), /* Maldives */ + COUNTRY_CHPLAN_ENT("MW", 0x26, 1), /* Malawi */ + COUNTRY_CHPLAN_ENT("MX", 0x4D, 1), /* Mexico */ + COUNTRY_CHPLAN_ENT("MY", 0x63, 1), /* Malaysia */ + COUNTRY_CHPLAN_ENT("MZ", 0x26, 1), /* Mozambique */ + COUNTRY_CHPLAN_ENT("NA", 0x26, 1), /* Namibia */ + COUNTRY_CHPLAN_ENT("NC", 0x26, 1), /* New Caledonia */ + COUNTRY_CHPLAN_ENT("NE", 0x26, 1), /* Niger */ + COUNTRY_CHPLAN_ENT("NF", 0x45, 1), /* Norfolk Island (Australia) */ + COUNTRY_CHPLAN_ENT("NG", 0x75, 1), /* Nigeria */ + COUNTRY_CHPLAN_ENT("NI", 0x76, 1), /* Nicaragua */ + COUNTRY_CHPLAN_ENT("NL", 0x26, 1), /* Netherlands */ + COUNTRY_CHPLAN_ENT("NO", 0x26, 1), /* Norway */ + COUNTRY_CHPLAN_ENT("NP", 0x48, 1), /* Nepal */ + COUNTRY_CHPLAN_ENT("NR", 0x26, 1), /* Nauru */ + COUNTRY_CHPLAN_ENT("NU", 0x45, 1), /* Niue */ + COUNTRY_CHPLAN_ENT("NZ", 0x45, 1), /* New Zealand */ + COUNTRY_CHPLAN_ENT("OM", 0x26, 1), /* Oman */ + COUNTRY_CHPLAN_ENT("PA", 0x76, 1), /* Panama */ + COUNTRY_CHPLAN_ENT("PE", 0x76, 1), /* Peru */ + COUNTRY_CHPLAN_ENT("PF", 0x26, 1), /* French Polynesia (France) */ + COUNTRY_CHPLAN_ENT("PG", 0x35, 1), /* Papua New Guinea */ + COUNTRY_CHPLAN_ENT("PH", 0x35, 1), /* Philippines */ + COUNTRY_CHPLAN_ENT("PK", 0x51, 1), /* Pakistan */ + COUNTRY_CHPLAN_ENT("PL", 0x26, 1), /* Poland */ + COUNTRY_CHPLAN_ENT("PM", 0x26, 1), /* Saint Pierre and Miquelon (France) */ + COUNTRY_CHPLAN_ENT("PR", 0x76, 1), /* Puerto Rico */ + COUNTRY_CHPLAN_ENT("PT", 0x26, 1), /* Portugal */ + COUNTRY_CHPLAN_ENT("PW", 0x76, 1), /* Palau */ + COUNTRY_CHPLAN_ENT("PY", 0x76, 1), /* Paraguay */ + COUNTRY_CHPLAN_ENT("QA", 0x35, 1), /* Qatar */ + COUNTRY_CHPLAN_ENT("RE", 0x26, 1), /* Reunion (France) */ + COUNTRY_CHPLAN_ENT("RO", 0x26, 1), /* Romania */ + COUNTRY_CHPLAN_ENT("RS", 0x26, 1), /* Serbia, Kosovo */ + COUNTRY_CHPLAN_ENT("RU", 0x59, 1), /* Russia(fac/gost), Kaliningrad */ + COUNTRY_CHPLAN_ENT("RW", 0x26, 1), /* Rwanda */ + COUNTRY_CHPLAN_ENT("SA", 0x35, 1), /* Saudi Arabia */ + COUNTRY_CHPLAN_ENT("SB", 0x26, 1), /* Solomon Islands */ + COUNTRY_CHPLAN_ENT("SC", 0x76, 1), /* Seychelles */ + COUNTRY_CHPLAN_ENT("SE", 0x26, 1), /* Sweden */ + COUNTRY_CHPLAN_ENT("SG", 0x35, 1), /* Singapore */ + COUNTRY_CHPLAN_ENT("SH", 0x26, 1), /* Saint Helena (UK) */ + COUNTRY_CHPLAN_ENT("SI", 0x26, 1), /* Slovenia */ + COUNTRY_CHPLAN_ENT("SJ", 0x26, 1), /* Svalbard (Norway) */ + COUNTRY_CHPLAN_ENT("SK", 0x26, 1), /* Slovakia */ + COUNTRY_CHPLAN_ENT("SL", 0x26, 1), /* Sierra Leone */ + COUNTRY_CHPLAN_ENT("SM", 0x26, 1), /* San Marino */ + COUNTRY_CHPLAN_ENT("SN", 0x26, 1), /* Senegal */ + COUNTRY_CHPLAN_ENT("SO", 0x26, 1), /* Somalia */ + COUNTRY_CHPLAN_ENT("SR", 0x74, 1), /* Suriname */ + COUNTRY_CHPLAN_ENT("ST", 0x76, 1), /* Sao Tome and Principe */ + COUNTRY_CHPLAN_ENT("SV", 0x30, 1), /* El Salvador */ + COUNTRY_CHPLAN_ENT("SX", 0x76, 1), /* Sint Marteen */ + COUNTRY_CHPLAN_ENT("SZ", 0x26, 1), /* Swaziland */ + COUNTRY_CHPLAN_ENT("TC", 0x26, 1), /* Turks and Caicos Islands (UK) */ + COUNTRY_CHPLAN_ENT("TD", 0x26, 1), /* Chad */ + COUNTRY_CHPLAN_ENT("TF", 0x26, 1), /* French Southern and Antarctic Lands (FR Southern Territories) */ + COUNTRY_CHPLAN_ENT("TG", 0x26, 1), /* Togo */ + COUNTRY_CHPLAN_ENT("TH", 0x35, 1), /* Thailand */ + COUNTRY_CHPLAN_ENT("TJ", 0x26, 1), /* Tajikistan */ + COUNTRY_CHPLAN_ENT("TK", 0x45, 1), /* Tokelau */ + COUNTRY_CHPLAN_ENT("TM", 0x26, 1), /* Turkmenistan */ + COUNTRY_CHPLAN_ENT("TN", 0x47, 1), /* Tunisia */ + COUNTRY_CHPLAN_ENT("TO", 0x26, 1), /* Tonga */ + COUNTRY_CHPLAN_ENT("TR", 0x26, 1), /* Turkey, Northern Cyprus */ + COUNTRY_CHPLAN_ENT("TT", 0x76, 1), /* Trinidad & Tobago */ + COUNTRY_CHPLAN_ENT("TV", 0x21, 0), /* Tuvalu */ + COUNTRY_CHPLAN_ENT("TW", 0x76, 1), /* Taiwan */ + COUNTRY_CHPLAN_ENT("TZ", 0x26, 1), /* Tanzania */ + COUNTRY_CHPLAN_ENT("UA", 0x35, 1), /* Ukraine */ + COUNTRY_CHPLAN_ENT("UG", 0x26, 1), /* Uganda */ + COUNTRY_CHPLAN_ENT("US", 0x76, 1), /* United States of America (USA) */ + COUNTRY_CHPLAN_ENT("UY", 0x30, 1), /* Uruguay */ + COUNTRY_CHPLAN_ENT("UZ", 0x47, 1), /* Uzbekistan */ + COUNTRY_CHPLAN_ENT("VA", 0x26, 1), /* Holy See (Vatican City) */ + COUNTRY_CHPLAN_ENT("VC", 0x76, 1), /* Saint Vincent and the Grenadines */ + COUNTRY_CHPLAN_ENT("VE", 0x30, 1), /* Venezuela */ + COUNTRY_CHPLAN_ENT("VG", 0x76, 1), /* British Virgin Islands (UK) */ + COUNTRY_CHPLAN_ENT("VI", 0x76, 1), /* United States Virgin Islands (USA) */ + COUNTRY_CHPLAN_ENT("VN", 0x35, 1), /* Vietnam */ + COUNTRY_CHPLAN_ENT("VU", 0x26, 1), /* Vanuatu */ + COUNTRY_CHPLAN_ENT("WF", 0x26, 1), /* Wallis and Futuna (France) */ + COUNTRY_CHPLAN_ENT("WS", 0x76, 1), /* Samoa */ + COUNTRY_CHPLAN_ENT("YE", 0x26, 1), /* Yemen */ + COUNTRY_CHPLAN_ENT("YT", 0x26, 1), /* Mayotte (France) */ + COUNTRY_CHPLAN_ENT("ZA", 0x35, 1), /* South Africa */ + COUNTRY_CHPLAN_ENT("ZM", 0x26, 1), /* Zambia */ + COUNTRY_CHPLAN_ENT("ZW", 0x26, 1), /* Zimbabwe */ +}; +#endif /* CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP or RTW_DEF_MODULE_REGULATORY_CERT or newest */ + +/* +* rtw_get_chplan_from_country - +* @country_code: string of country code +* +* Return pointer of struct country_chplan entry or NULL when unsupported country_code is given +*/ +const struct country_chplan *rtw_get_chplan_from_country(const char *country_code) +{ + const struct country_chplan *ent = NULL; + const struct country_chplan *map = NULL; + u16 map_sz = 0; + char code[2]; + int i; + + code[0] = alpha_to_upper(country_code[0]); + code[1] = alpha_to_upper(country_code[1]); + +#ifdef CONFIG_CUSTOMIZED_COUNTRY_CHPLAN_MAP + map = CUSTOMIZED_country_chplan_map; + map_sz = sizeof(CUSTOMIZED_country_chplan_map) / sizeof(struct country_chplan); +#elif RTW_DEF_MODULE_REGULATORY_CERT + map_sz = rtw_def_module_country_chplan_map(&map); +#else + map = country_chplan_map; + map_sz = sizeof(country_chplan_map) / sizeof(struct country_chplan); +#endif + + for (i = 0; i < map_sz; i++) { + if (strncmp(code, map[i].alpha2, 2) == 0) { + ent = &map[i]; + break; + } + } + + return ent; +} + +void dump_country_chplan(void *sel, const struct country_chplan *ent) +{ + char buf[16]; + + if (ent->chplan == RTW_CHPLAN_UNSPECIFIED) + sprintf(buf, "NA"); + else + sprintf(buf, "0x%02X", ent->chplan); + + RTW_PRINT_SEL(sel, "\"%c%c\", %s%s\n" + , ent->alpha2[0], ent->alpha2[1], buf + , COUNTRY_CHPLAN_EN_11AC(ent) ? " ac" : "" + ); +} + +void dump_country_chplan_map(void *sel) +{ + const 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 + + for (code[0] = 'A'; code[0] <= 'Z'; code[0]++) { + for (code[1] = 'A'; code[1] <= 'Z'; code[1]++) { + ent = rtw_get_chplan_from_country(code); + if (!ent) + continue; + + dump_country_chplan(sel, ent); + } + } +} + +void dump_chplan_id_list(void *sel) +{ + u8 first = 1; + int i; + + for (i = 0; i < RTW_ChannelPlanMap_size; 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); + } +} + +#ifdef CONFIG_RTW_DEBUG +void dump_chplan_test(void *sel) +{ + int i, j; + + /* check redundent */ + for (i = 0; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; 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 invalid channel */ + for (i = 0; i < RTW_CHD_2G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_2g[i]); j++) { + if (rtw_ch2freq(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 redundent */ + for (i = 0; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; 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 invalid channel */ + for (i = 0; i < RTW_CHD_5G_MAX; i++) { + for (j = 0; j < CH_LIST_LEN(rtw_channel_def_5g[i]); j++) { + if (rtw_ch2freq(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 + + /* check 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); + } + } +} +#endif /* CONFIG_RTW_DEBUG */ + +void dump_chplan_ver(void *sel) +{ + RTW_PRINT_SEL(sel, "%s%s-%s\n", RTW_DOMAIN_MAP_VER, RTW_DOMAIN_MAP_M_VER, RTW_COUNTRY_MAP_VER); +} diff --git a/core/rtw_chplan.h b/core/rtw_chplan.h index bfe1ab2..f780239 100644 --- a/core/rtw_chplan.h +++ b/core/rtw_chplan.h @@ -1,95 +1,95 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2018 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_UNSPECIFIED 0xFF - -u8 rtw_chplan_get_default_regd(u8 id); -bool rtw_chplan_is_empty(u8 id); -bool rtw_is_channel_plan_valid(u8 id); -bool rtw_regsty_is_excl_chs(struct registry_priv *regsty, u8 ch); - -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]) - -struct _RT_CHANNEL_INFO; -u8 init_channel_set(_adapter *adapter); -bool rtw_chset_is_dfs_range(struct _RT_CHANNEL_INFO *chset, u32 hi, u32 lo); -bool rtw_chset_is_dfs_ch(struct _RT_CHANNEL_INFO *chset, u8 ch); -bool rtw_chset_is_dfs_chbw(struct _RT_CHANNEL_INFO *chset, u8 ch, u8 bw, u8 offset); -u8 rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss); - -#define IS_ALPHA2_NO_SPECIFIED(_alpha2) ((*((u16 *)(_alpha2))) == 0xFFFF) -#define IS_ALPHA2_WORLDWIDE(_alpha2) (strncmp(_alpha2, "00", 2) == 0) - -#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 */ - -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_NUM, - RTW_DFS_REGD_AUTO = 0xFF, /* follow channel plan */ -}; - -extern const char *_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)]) - -struct country_chplan { - char alpha2[2]; /* "00" means worldwide */ - u8 chplan; -#ifdef CONFIG_80211AC_VHT - u8 en_11ac; -#endif -}; - -#ifdef CONFIG_80211AC_VHT -#define COUNTRY_CHPLAN_EN_11AC(_ent) ((_ent)->en_11ac) -#else -#define COUNTRY_CHPLAN_EN_11AC(_ent) 0 -#endif - -const struct country_chplan *rtw_get_chplan_from_country(const char *country_code); - -void dump_country_chplan(void *sel, const struct country_chplan *ent); -void dump_country_chplan_map(void *sel); -void dump_chplan_id_list(void *sel); -#ifdef CONFIG_RTW_DEBUG -void dump_chplan_test(void *sel); -#endif -void dump_chplan_ver(void *sel); - -#endif /* __RTW_CHPLAN_H__ */ +/****************************************************************************** + * + * Copyright(c) 2007 - 2018 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_UNSPECIFIED 0xFF + +u8 rtw_chplan_get_default_regd(u8 id); +bool rtw_chplan_is_empty(u8 id); +bool rtw_is_channel_plan_valid(u8 id); +bool rtw_regsty_is_excl_chs(struct registry_priv *regsty, u8 ch); + +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]) + +struct _RT_CHANNEL_INFO; +u8 init_channel_set(_adapter *adapter); +bool rtw_chset_is_dfs_range(struct _RT_CHANNEL_INFO *chset, u32 hi, u32 lo); +bool rtw_chset_is_dfs_ch(struct _RT_CHANNEL_INFO *chset, u8 ch); +bool rtw_chset_is_dfs_chbw(struct _RT_CHANNEL_INFO *chset, u8 ch, u8 bw, u8 offset); +u8 rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss); + +#define IS_ALPHA2_NO_SPECIFIED(_alpha2) ((*((u16 *)(_alpha2))) == 0xFFFF) +#define IS_ALPHA2_WORLDWIDE(_alpha2) (strncmp(_alpha2, "00", 2) == 0) + +#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 */ + +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_NUM, + RTW_DFS_REGD_AUTO = 0xFF, /* follow channel plan */ +}; + +extern const char *_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)]) + +struct country_chplan { + char alpha2[2]; /* "00" means worldwide */ + u8 chplan; +#ifdef CONFIG_80211AC_VHT + u8 en_11ac; +#endif +}; + +#ifdef CONFIG_80211AC_VHT +#define COUNTRY_CHPLAN_EN_11AC(_ent) ((_ent)->en_11ac) +#else +#define COUNTRY_CHPLAN_EN_11AC(_ent) 0 +#endif + +const struct country_chplan *rtw_get_chplan_from_country(const char *country_code); + +void dump_country_chplan(void *sel, const struct country_chplan *ent); +void dump_country_chplan_map(void *sel); +void dump_chplan_id_list(void *sel); +#ifdef CONFIG_RTW_DEBUG +void dump_chplan_test(void *sel); +#endif +void dump_chplan_ver(void *sel); + +#endif /* __RTW_CHPLAN_H__ */ diff --git a/core/rtw_roch.c b/core/rtw_roch.c index 2674fe6..ecd2089 100644 --- a/core/rtw_roch.c +++ b/core/rtw_roch.c @@ -1,591 +1,591 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 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. - * - *****************************************************************************/ - -#include - -#ifdef CONFIG_IOCTL_CFG80211 -u8 rtw_roch_stay_in_cur_chan(_adapter *padapter) -{ - int i; - _adapter *iface; - struct mlme_priv *pmlmepriv; - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - u8 rst = _FALSE; - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - if (iface) { - pmlmepriv = &iface->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) { - RTW_INFO(ADPT_FMT"- WIFI_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n", - ADPT_ARG(iface), get_fwstate(&iface->mlmepriv)); - rst = _TRUE; - break; - } - #ifdef CONFIG_AP_MODE - if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) { - if (rtw_ap_sta_states_check(iface) == _TRUE) { - rst = _TRUE; - break; - } - } - #endif - } - } - - return rst; -} - -static int rtw_ro_ch_handler(_adapter *adapter, u8 *buf) -{ - int ret = H2C_SUCCESS; - struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf; - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter); - struct roch_info *prochinfo = &adapter->rochinfo; -#ifdef CONFIG_CONCURRENT_MODE - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; -#endif - u8 ready_on_channel = _FALSE; - u8 remain_ch; - unsigned int duration; - - _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); - - if (rtw_cfg80211_get_is_roch(adapter) != _TRUE) - goto exit; - - remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq); - duration = roch_parm->duration; - - RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n" - , FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie); - - if (roch_parm->wdev && roch_parm->cookie) { - if (prochinfo->ro_ch_wdev != roch_parm->wdev) { - RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n" - , FUNC_ADPT_ARG(adapter), prochinfo->ro_ch_wdev, roch_parm->wdev); - rtw_warn_on(1); - } - - if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) { - RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n" - , FUNC_ADPT_ARG(adapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie); - rtw_warn_on(1); - } - } - - if (rtw_roch_stay_in_cur_chan(adapter) == _TRUE) { - remain_ch = rtw_mi_get_union_chan(adapter); - RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch); - } - - #ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) { - if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) { - if (remain_ch != pmlmeext->cur_channel - #ifdef RTW_ROCH_BACK_OP - || ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1 - #endif - ) { - rtw_leave_opch(adapter); - - #ifdef RTW_ROCH_BACK_OP - RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, prochinfo->max_away_dur); - ATOMIC_SET(&pwdev_priv->switch_ch_to, 0); - /* remain_ch is not same as union channel. duration is max_away_dur to - * back to AP's channel. - */ - _set_timer(&prochinfo->ap_roch_ch_switch_timer, prochinfo->max_away_dur); - #endif - } - } - ready_on_channel = _TRUE; - } else - #endif /* CONFIG_CONCURRENT_MODE */ - { - if (remain_ch != rtw_get_oper_ch(adapter)) - ready_on_channel = _TRUE; - } - - if (ready_on_channel == _TRUE) { - #ifndef RTW_SINGLE_WIPHY - if (!check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) - #endif - { - #ifdef CONFIG_CONCURRENT_MODE - if (rtw_get_oper_ch(adapter) != remain_ch) - #endif - { - /* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */ - set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - } - } - } - - #ifdef CONFIG_BT_COEXIST - rtw_btcoex_ScanNotify(adapter, _TRUE); - #endif - - RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration); - _set_timer(&prochinfo->remain_on_ch_timer, duration); - -exit: - _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); - - return ret; -} - -static int rtw_cancel_ro_ch_handler(_adapter *padapter, u8 *buf) -{ - int ret = H2C_SUCCESS; - struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf; - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); - struct roch_info *prochinfo = &padapter->rochinfo; - struct wireless_dev *wdev; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; -#endif - u8 ch, bw, offset; - - _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); - - if (rtw_cfg80211_get_is_roch(padapter) != _TRUE) - goto exit; - - if (roch_parm->wdev && roch_parm->cookie) { - if (prochinfo->ro_ch_wdev != roch_parm->wdev) { - RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n" - , FUNC_ADPT_ARG(padapter), prochinfo->ro_ch_wdev, roch_parm->wdev); - rtw_warn_on(1); - } - - if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) { - RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n" - , FUNC_ADPT_ARG(padapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie); - rtw_warn_on(1); - } - } - -#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) - _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer); - ATOMIC_SET(&pwdev_priv->switch_ch_to, 1); -#endif - - if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) { - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), ch, bw, offset); -#ifdef CONFIG_P2P - } else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) { - ch = pwdinfo->listen_channel; - bw = CHANNEL_WIDTH_20; - offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), ch, bw, offset); -#endif - } else { - ch = prochinfo->restore_channel; - bw = CHANNEL_WIDTH_20; - offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), ch, bw, offset); - } - - set_channel_bwmode(padapter, ch, offset, bw); - rtw_back_opch(padapter); -#ifdef CONFIG_P2P - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); -#ifdef CONFIG_DEBUG_CFG80211 - RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo)); -#endif -#endif - - wdev = prochinfo->ro_ch_wdev; - - rtw_cfg80211_set_is_roch(padapter, _FALSE); - prochinfo->ro_ch_wdev = NULL; - rtw_cfg80211_set_last_ro_ch_time(padapter); - - rtw_cfg80211_remain_on_channel_expired(wdev - , prochinfo->remain_on_ch_cookie - , &prochinfo->remain_on_ch_channel - , prochinfo->remain_on_ch_type, GFP_KERNEL); - - RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n" - , prochinfo->remain_on_ch_cookie); - -#ifdef CONFIG_BT_COEXIST - rtw_btcoex_ScanNotify(padapter, _FALSE); -#endif - -exit: - _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); - - return ret; -} - -static void rtw_ro_ch_timer_process(void *FunctionContext) -{ - _adapter *adapter = (_adapter *)FunctionContext; - - rtw_cancel_roch_cmd(adapter, 0, NULL, 0); -} -#endif /* CONFIG_IOCTL_CFG80211 */ - -#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) -s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf) -{ - int ret = H2C_SUCCESS; - - switch (intCmdType) { - -#ifdef CONFIG_IOCTL_CFG80211 - case ROCH_RO_CH_WK: - ret = rtw_ro_ch_handler(padapter, buf); - break; - case ROCH_CANCEL_RO_CH_WK: - ret = rtw_cancel_ro_ch_handler(padapter, buf); - break; -#endif - -#ifdef CONFIG_CONCURRENT_MODE - case ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK: - rtw_concurrent_handler(padapter); - break; -#endif - - default: - rtw_warn_on(1); - break; - } - - return ret; -} - -static int get_roch_parm_size(struct rtw_roch_parm *roch_parm) -{ -#ifdef CONFIG_IOCTL_CFG80211 - return (roch_parm ? sizeof(*roch_parm) : 0); -#else - rtw_warn_on(roch_parm); - return 0; -#endif -} - -u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags) -{ - struct cmd_obj *ph2c = NULL; - struct drvextra_cmd_parm *pdrvextra_cmd_parm = NULL; - struct cmd_priv *pcmdpriv = &padapter->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 != rtw_roch_wk_hdl(padapter, intCmdType, (u8 *)roch_parm)) - res = _FAIL; - goto free_parm; - } else { - ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (!ph2c) { - res = _FAIL; - goto free_parm; - } - - pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); - if (!pdrvextra_cmd_parm) { - res = _FAIL; - goto free_parm; - } - - pdrvextra_cmd_parm->ec_id = ROCH_WK_CID; - pdrvextra_cmd_parm->type = intCmdType; - pdrvextra_cmd_parm->size = get_roch_parm_size(roch_parm); - pdrvextra_cmd_parm->pbuf = (u8 *)roch_parm; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); - - if (flags & RTW_CMDF_WAIT_ACK) { - ph2c->sctx = &sctx; - rtw_sctx_init(&sctx, 10 * 1000); - } - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - - if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { - rtw_sctx_wait(&sctx, __func__); - _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL); - if (sctx.status == RTW_SCTX_SUBMITTED) - ph2c->sctx = NULL; - _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL); - if (sctx.status != RTW_SCTX_DONE_SUCCESS) - res = _FAIL; - } - } - - return res; - -free_parm: - if (roch_parm) - rtw_mfree((u8 *)roch_parm, get_roch_parm_size(roch_parm)); - if (ph2c) - rtw_mfree((u8 *)ph2c, sizeof(*ph2c)); - - return res; -} - -#ifdef CONFIG_CONCURRENT_MODE -void rtw_ap_roch_ch_switch_timer_process(void *ctx) -{ - _adapter *adapter = (_adapter *)ctx; -#ifdef CONFIG_IOCTL_CFG80211 - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter); -#endif - -#ifdef CONFIG_IOCTL_CFG80211 - ATOMIC_SET(&pwdev_priv->switch_ch_to, 1); -#endif - - rtw_roch_wk_cmd(adapter, ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK, NULL, 0); -} - -static bool chk_need_stay_in_cur_chan(_adapter *padapter) -{ -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - /* When CONFIG_FULL_CH_IN_P2P_HANDSHAKE is defined and the - * interface is in the P2P_STATE_GONEGO_OK state, do not let the - * interface switch to the listen channel, because the interface will - * switch to the OP channel after the GO negotiation is successful. - */ - if (padapter->registrypriv.full_ch_in_p2p_handshake == 1 && rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK)) { - RTW_INFO("%s, No linked interface now, but go nego ok, do not back to listen channel\n", __func__); - return _TRUE; - } -#endif - - return _FALSE; -} - -static bool chk_driver_interface(_adapter *padapter, u8 driver_interface) -{ -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - - if (pwdinfo->driver_interface == driver_interface) - return _TRUE; -#elif defined(CONFIG_IOCTL_CFG80211) - if (driver_interface == DRIVER_CFG80211) - return _TRUE; -#endif - - return _FALSE; -} - -static u8 get_remain_ch(_adapter *padapter) -{ - struct roch_info *prochinfo = &padapter->rochinfo; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; -#endif - u8 remain_ch; - -#ifdef CONFIG_P2P - remain_ch = pwdinfo->listen_channel; -#elif defined(CONFIG_IOCTL_CFG80211) - if (chk_driver_interface(padapter, DRIVER_CFG80211)) - remain_ch = ieee80211_frequency_to_channel(prochinfo->remain_on_ch_channel.center_freq); - else - rtw_warn_on(1); -#endif - - return remain_ch; -} - -void rtw_concurrent_handler(_adapter *padapter) -{ -#ifdef CONFIG_IOCTL_CFG80211 - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); -#endif - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - struct roch_info *prochinfo = &padapter->rochinfo; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - u8 val8; -#endif - u8 remain_ch = get_remain_ch(padapter); - -#ifdef CONFIG_IOCTL_CFG80211 - if (chk_driver_interface(padapter, DRIVER_CFG80211) - && !rtw_cfg80211_get_is_roch(padapter)) - return; -#endif - - if (rtw_mi_check_status(padapter, MI_LINKED)) { - u8 union_ch = rtw_mi_get_union_chan(padapter); - u8 union_bw = rtw_mi_get_union_bw(padapter); - u8 union_offset = rtw_mi_get_union_offset(padapter); - unsigned int duration; - - #ifdef CONFIG_P2P - pwdinfo->operating_channel = union_ch; - #endif - - if (chk_driver_interface(padapter, DRIVER_CFG80211)) { - #ifdef CONFIG_IOCTL_CFG80211 - _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); - - if (rtw_get_oper_ch(padapter) != union_ch) { - /* Current channel is not AP's channel - switching to AP's channel */ - RTW_INFO("%s, switch ch back to union=%u,%u, %u\n" - , __func__, union_ch, union_bw, union_offset); - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - rtw_back_opch(padapter); - - /* Now, the driver stays on AP's channel. We should stay on AP's - * channel for min_home_dur (duration) and next switch channel is - * listen channel. - */ - duration = prochinfo->min_home_dur; - } else { - /* Current channel is AP's channel - switching to listen channel */ - RTW_INFO("%s, switch ch to roch=%u\n" - , __func__, remain_ch); - rtw_leave_opch(padapter); - set_channel_bwmode(padapter, - remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - - /* Now, the driver stays on listen channel. We should stay on listen - * channel for max_away_dur (duration) and next switch channel is AP's - * channel. - */ - duration = prochinfo->max_away_dur; - } - - /* set channel switch timer */ - ATOMIC_SET(&pwdev_priv->switch_ch_to, 0); - _set_timer(&prochinfo->ap_roch_ch_switch_timer, duration); - RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration); - - _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); - #endif - } - #ifdef CONFIG_P2P - else if (chk_driver_interface(padapter, DRIVER_WEXT)) { - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) { - /* Now, the driver stays on the AP's channel. */ - /* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */ - if (pwdinfo->ext_listen_period > 0) { - RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period); - - if (union_ch != pwdinfo->listen_channel) { - rtw_leave_opch(padapter); - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - } - - rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); - - if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) { - val8 = 1; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - } - /* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */ - _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_period); - } - - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) || - rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) || - (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) || - rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) { - /* Now, the driver is in the listen state of P2P mode. */ - RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval); - - /* Commented by Albert 2012/11/01 */ - /* If the AP's channel is the same as the listen channel, we should still be in the listen state */ - /* Other P2P device is still able to find this device out even this device is in the AP's channel. */ - /* So, configure this device to be able to receive the probe request frame and set it to listen state. */ - if (union_ch != pwdinfo->listen_channel) { - - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - if (!rtw_mi_check_status(padapter, MI_AP_MODE)) { - val8 = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - } - rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE); - rtw_back_opch(padapter); - } - - /* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */ - _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_interval); - - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) { - /* The driver had finished the P2P handshake successfully. */ - val8 = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - rtw_back_opch(padapter); - - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) { - val8 = 1; - set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) { - val8 = 1; - set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) { - /* - val8 = 1; - set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); - */ - } - } - #endif /* CONFIG_P2P */ - } else if (!chk_need_stay_in_cur_chan(padapter)) { - set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - } -} -#endif /* CONFIG_CONCURRENT_MODE */ - -void rtw_init_roch_info(_adapter *padapter) -{ - struct roch_info *prochinfo = &padapter->rochinfo; - - _rtw_memset(prochinfo, 0x00, sizeof(struct roch_info)); - -#ifdef CONFIG_CONCURRENT_MODE - rtw_init_timer(&prochinfo->ap_roch_ch_switch_timer, padapter, rtw_ap_roch_ch_switch_timer_process, padapter); -#ifdef CONFIG_IOCTL_CFG80211 - prochinfo->min_home_dur = 1500; /* min duration for traffic, home_time */ - prochinfo->max_away_dur = 250; /* max acceptable away duration, home_away_time */ -#endif -#endif - -#ifdef CONFIG_IOCTL_CFG80211 - rtw_init_timer(&prochinfo->remain_on_ch_timer, padapter, rtw_ro_ch_timer_process, padapter); -#endif -} -#endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */ \ No newline at end of file +/****************************************************************************** + * + * Copyright(c) 2007 - 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. + * + *****************************************************************************/ + +#include + +#ifdef CONFIG_IOCTL_CFG80211 +u8 rtw_roch_stay_in_cur_chan(_adapter *padapter) +{ + int i; + _adapter *iface; + struct mlme_priv *pmlmepriv; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + u8 rst = _FALSE; + + for (i = 0; i < dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + if (iface) { + pmlmepriv = &iface->mlmepriv; + + if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) { + RTW_INFO(ADPT_FMT"- WIFI_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n", + ADPT_ARG(iface), get_fwstate(&iface->mlmepriv)); + rst = _TRUE; + break; + } + #ifdef CONFIG_AP_MODE + if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) { + if (rtw_ap_sta_states_check(iface) == _TRUE) { + rst = _TRUE; + break; + } + } + #endif + } + } + + return rst; +} + +static int rtw_ro_ch_handler(_adapter *adapter, u8 *buf) +{ + int ret = H2C_SUCCESS; + struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf; + struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter); + struct roch_info *prochinfo = &adapter->rochinfo; +#ifdef CONFIG_CONCURRENT_MODE + struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; +#endif + u8 ready_on_channel = _FALSE; + u8 remain_ch; + unsigned int duration; + + _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); + + if (rtw_cfg80211_get_is_roch(adapter) != _TRUE) + goto exit; + + remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq); + duration = roch_parm->duration; + + RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n" + , FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie); + + if (roch_parm->wdev && roch_parm->cookie) { + if (prochinfo->ro_ch_wdev != roch_parm->wdev) { + RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n" + , FUNC_ADPT_ARG(adapter), prochinfo->ro_ch_wdev, roch_parm->wdev); + rtw_warn_on(1); + } + + if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) { + RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n" + , FUNC_ADPT_ARG(adapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie); + rtw_warn_on(1); + } + } + + if (rtw_roch_stay_in_cur_chan(adapter) == _TRUE) { + remain_ch = rtw_mi_get_union_chan(adapter); + RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch); + } + + #ifdef CONFIG_CONCURRENT_MODE + if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) { + if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) { + if (remain_ch != pmlmeext->cur_channel + #ifdef RTW_ROCH_BACK_OP + || ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1 + #endif + ) { + rtw_leave_opch(adapter); + + #ifdef RTW_ROCH_BACK_OP + RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, prochinfo->max_away_dur); + ATOMIC_SET(&pwdev_priv->switch_ch_to, 0); + /* remain_ch is not same as union channel. duration is max_away_dur to + * back to AP's channel. + */ + _set_timer(&prochinfo->ap_roch_ch_switch_timer, prochinfo->max_away_dur); + #endif + } + } + ready_on_channel = _TRUE; + } else + #endif /* CONFIG_CONCURRENT_MODE */ + { + if (remain_ch != rtw_get_oper_ch(adapter)) + ready_on_channel = _TRUE; + } + + if (ready_on_channel == _TRUE) { + #ifndef RTW_SINGLE_WIPHY + if (!check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) + #endif + { + #ifdef CONFIG_CONCURRENT_MODE + if (rtw_get_oper_ch(adapter) != remain_ch) + #endif + { + /* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */ + set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + } + } + } + + #ifdef CONFIG_BT_COEXIST + rtw_btcoex_ScanNotify(adapter, _TRUE); + #endif + + RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration); + _set_timer(&prochinfo->remain_on_ch_timer, duration); + +exit: + _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); + + return ret; +} + +static int rtw_cancel_ro_ch_handler(_adapter *padapter, u8 *buf) +{ + int ret = H2C_SUCCESS; + struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf; + struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); + struct roch_info *prochinfo = &padapter->rochinfo; + struct wireless_dev *wdev; +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; +#endif + u8 ch, bw, offset; + + _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); + + if (rtw_cfg80211_get_is_roch(padapter) != _TRUE) + goto exit; + + if (roch_parm->wdev && roch_parm->cookie) { + if (prochinfo->ro_ch_wdev != roch_parm->wdev) { + RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n" + , FUNC_ADPT_ARG(padapter), prochinfo->ro_ch_wdev, roch_parm->wdev); + rtw_warn_on(1); + } + + if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) { + RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n" + , FUNC_ADPT_ARG(padapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie); + rtw_warn_on(1); + } + } + +#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) + _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer); + ATOMIC_SET(&pwdev_priv->switch_ch_to, 1); +#endif + + if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) { + if (0) + RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); +#ifdef CONFIG_P2P + } else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) { + ch = pwdinfo->listen_channel; + bw = CHANNEL_WIDTH_20; + offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + if (0) + RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); +#endif + } else { + ch = prochinfo->restore_channel; + bw = CHANNEL_WIDTH_20; + offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + if (0) + RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); + } + + set_channel_bwmode(padapter, ch, offset, bw); + rtw_back_opch(padapter); +#ifdef CONFIG_P2P + rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); +#ifdef CONFIG_DEBUG_CFG80211 + RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo)); +#endif +#endif + + wdev = prochinfo->ro_ch_wdev; + + rtw_cfg80211_set_is_roch(padapter, _FALSE); + prochinfo->ro_ch_wdev = NULL; + rtw_cfg80211_set_last_ro_ch_time(padapter); + + rtw_cfg80211_remain_on_channel_expired(wdev + , prochinfo->remain_on_ch_cookie + , &prochinfo->remain_on_ch_channel + , prochinfo->remain_on_ch_type, GFP_KERNEL); + + RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n" + , prochinfo->remain_on_ch_cookie); + +#ifdef CONFIG_BT_COEXIST + rtw_btcoex_ScanNotify(padapter, _FALSE); +#endif + +exit: + _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); + + return ret; +} + +static void rtw_ro_ch_timer_process(void *FunctionContext) +{ + _adapter *adapter = (_adapter *)FunctionContext; + + rtw_cancel_roch_cmd(adapter, 0, NULL, 0); +} +#endif /* CONFIG_IOCTL_CFG80211 */ + +#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) +s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf) +{ + int ret = H2C_SUCCESS; + + switch (intCmdType) { + +#ifdef CONFIG_IOCTL_CFG80211 + case ROCH_RO_CH_WK: + ret = rtw_ro_ch_handler(padapter, buf); + break; + case ROCH_CANCEL_RO_CH_WK: + ret = rtw_cancel_ro_ch_handler(padapter, buf); + break; +#endif + +#ifdef CONFIG_CONCURRENT_MODE + case ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK: + rtw_concurrent_handler(padapter); + break; +#endif + + default: + rtw_warn_on(1); + break; + } + + return ret; +} + +static int get_roch_parm_size(struct rtw_roch_parm *roch_parm) +{ +#ifdef CONFIG_IOCTL_CFG80211 + return (roch_parm ? sizeof(*roch_parm) : 0); +#else + rtw_warn_on(roch_parm); + return 0; +#endif +} + +u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags) +{ + struct cmd_obj *ph2c = NULL; + struct drvextra_cmd_parm *pdrvextra_cmd_parm = NULL; + struct cmd_priv *pcmdpriv = &padapter->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 != rtw_roch_wk_hdl(padapter, intCmdType, (u8 *)roch_parm)) + res = _FAIL; + goto free_parm; + } else { + ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); + if (!ph2c) { + res = _FAIL; + goto free_parm; + } + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if (!pdrvextra_cmd_parm) { + res = _FAIL; + goto free_parm; + } + + pdrvextra_cmd_parm->ec_id = ROCH_WK_CID; + pdrvextra_cmd_parm->type = intCmdType; + pdrvextra_cmd_parm->size = get_roch_parm_size(roch_parm); + pdrvextra_cmd_parm->pbuf = (u8 *)roch_parm; + + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA); + + if (flags & RTW_CMDF_WAIT_ACK) { + ph2c->sctx = &sctx; + rtw_sctx_init(&sctx, 10 * 1000); + } + + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + + if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) { + rtw_sctx_wait(&sctx, __func__); + _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL); + if (sctx.status == RTW_SCTX_SUBMITTED) + ph2c->sctx = NULL; + _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL); + if (sctx.status != RTW_SCTX_DONE_SUCCESS) + res = _FAIL; + } + } + + return res; + +free_parm: + if (roch_parm) + rtw_mfree((u8 *)roch_parm, get_roch_parm_size(roch_parm)); + if (ph2c) + rtw_mfree((u8 *)ph2c, sizeof(*ph2c)); + + return res; +} + +#ifdef CONFIG_CONCURRENT_MODE +void rtw_ap_roch_ch_switch_timer_process(void *ctx) +{ + _adapter *adapter = (_adapter *)ctx; +#ifdef CONFIG_IOCTL_CFG80211 + struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter); +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + ATOMIC_SET(&pwdev_priv->switch_ch_to, 1); +#endif + + rtw_roch_wk_cmd(adapter, ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK, NULL, 0); +} + +static bool chk_need_stay_in_cur_chan(_adapter *padapter) +{ +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; + + /* When CONFIG_FULL_CH_IN_P2P_HANDSHAKE is defined and the + * interface is in the P2P_STATE_GONEGO_OK state, do not let the + * interface switch to the listen channel, because the interface will + * switch to the OP channel after the GO negotiation is successful. + */ + if (padapter->registrypriv.full_ch_in_p2p_handshake == 1 && rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK)) { + RTW_INFO("%s, No linked interface now, but go nego ok, do not back to listen channel\n", __func__); + return _TRUE; + } +#endif + + return _FALSE; +} + +static bool chk_driver_interface(_adapter *padapter, u8 driver_interface) +{ +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; + + if (pwdinfo->driver_interface == driver_interface) + return _TRUE; +#elif defined(CONFIG_IOCTL_CFG80211) + if (driver_interface == DRIVER_CFG80211) + return _TRUE; +#endif + + return _FALSE; +} + +static u8 get_remain_ch(_adapter *padapter) +{ + struct roch_info *prochinfo = &padapter->rochinfo; +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; +#endif + u8 remain_ch; + +#ifdef CONFIG_P2P + remain_ch = pwdinfo->listen_channel; +#elif defined(CONFIG_IOCTL_CFG80211) + if (chk_driver_interface(padapter, DRIVER_CFG80211)) + remain_ch = ieee80211_frequency_to_channel(prochinfo->remain_on_ch_channel.center_freq); + else + rtw_warn_on(1); +#endif + + return remain_ch; +} + +void rtw_concurrent_handler(_adapter *padapter) +{ +#ifdef CONFIG_IOCTL_CFG80211 + struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); +#endif + struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); + struct roch_info *prochinfo = &padapter->rochinfo; +#ifdef CONFIG_P2P + struct wifidirect_info *pwdinfo = &padapter->wdinfo; + u8 val8; +#endif + u8 remain_ch = get_remain_ch(padapter); + +#ifdef CONFIG_IOCTL_CFG80211 + if (chk_driver_interface(padapter, DRIVER_CFG80211) + && !rtw_cfg80211_get_is_roch(padapter)) + return; +#endif + + if (rtw_mi_check_status(padapter, MI_LINKED)) { + u8 union_ch = rtw_mi_get_union_chan(padapter); + u8 union_bw = rtw_mi_get_union_bw(padapter); + u8 union_offset = rtw_mi_get_union_offset(padapter); + unsigned int duration; + + #ifdef CONFIG_P2P + pwdinfo->operating_channel = union_ch; + #endif + + if (chk_driver_interface(padapter, DRIVER_CFG80211)) { + #ifdef CONFIG_IOCTL_CFG80211 + _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL); + + if (rtw_get_oper_ch(padapter) != union_ch) { + /* Current channel is not AP's channel - switching to AP's channel */ + RTW_INFO("%s, switch ch back to union=%u,%u, %u\n" + , __func__, union_ch, union_bw, union_offset); + set_channel_bwmode(padapter, union_ch, union_offset, union_bw); + rtw_back_opch(padapter); + + /* Now, the driver stays on AP's channel. We should stay on AP's + * channel for min_home_dur (duration) and next switch channel is + * listen channel. + */ + duration = prochinfo->min_home_dur; + } else { + /* Current channel is AP's channel - switching to listen channel */ + RTW_INFO("%s, switch ch to roch=%u\n" + , __func__, remain_ch); + rtw_leave_opch(padapter); + set_channel_bwmode(padapter, + remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + + /* Now, the driver stays on listen channel. We should stay on listen + * channel for max_away_dur (duration) and next switch channel is AP's + * channel. + */ + duration = prochinfo->max_away_dur; + } + + /* set channel switch timer */ + ATOMIC_SET(&pwdev_priv->switch_ch_to, 0); + _set_timer(&prochinfo->ap_roch_ch_switch_timer, duration); + RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration); + + _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL); + #endif + } + #ifdef CONFIG_P2P + else if (chk_driver_interface(padapter, DRIVER_WEXT)) { + if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) { + /* Now, the driver stays on the AP's channel. */ + /* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */ + if (pwdinfo->ext_listen_period > 0) { + RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period); + + if (union_ch != pwdinfo->listen_channel) { + rtw_leave_opch(padapter); + set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + } + + rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); + + if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) { + val8 = 1; + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + } + /* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */ + _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_period); + } + + } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) || + rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) || + (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) || + rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) { + /* Now, the driver is in the listen state of P2P mode. */ + RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval); + + /* Commented by Albert 2012/11/01 */ + /* If the AP's channel is the same as the listen channel, we should still be in the listen state */ + /* Other P2P device is still able to find this device out even this device is in the AP's channel. */ + /* So, configure this device to be able to receive the probe request frame and set it to listen state. */ + if (union_ch != pwdinfo->listen_channel) { + + set_channel_bwmode(padapter, union_ch, union_offset, union_bw); + if (!rtw_mi_check_status(padapter, MI_AP_MODE)) { + val8 = 0; + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + } + rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE); + rtw_back_opch(padapter); + } + + /* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */ + _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_interval); + + } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) { + /* The driver had finished the P2P handshake successfully. */ + val8 = 0; + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + set_channel_bwmode(padapter, union_ch, union_offset, union_bw); + rtw_back_opch(padapter); + + } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) { + val8 = 1; + set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); + } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) { + val8 = 1; + set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); + } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) { + /* + val8 = 1; + set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); + */ + } + } + #endif /* CONFIG_P2P */ + } else if (!chk_need_stay_in_cur_chan(padapter)) { + set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); + } +} +#endif /* CONFIG_CONCURRENT_MODE */ + +void rtw_init_roch_info(_adapter *padapter) +{ + struct roch_info *prochinfo = &padapter->rochinfo; + + _rtw_memset(prochinfo, 0x00, sizeof(struct roch_info)); + +#ifdef CONFIG_CONCURRENT_MODE + rtw_init_timer(&prochinfo->ap_roch_ch_switch_timer, padapter, rtw_ap_roch_ch_switch_timer_process, padapter); +#ifdef CONFIG_IOCTL_CFG80211 + prochinfo->min_home_dur = 1500; /* min duration for traffic, home_time */ + prochinfo->max_away_dur = 250; /* max acceptable away duration, home_away_time */ +#endif +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + rtw_init_timer(&prochinfo->remain_on_ch_timer, padapter, rtw_ro_ch_timer_process, padapter); +#endif +} +#endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */ diff --git a/include/hal_sdio_coex.h b/include/hal_sdio_coex.h index d95813a..ce41b99 100644 --- a/include/hal_sdio_coex.h +++ b/include/hal_sdio_coex.h @@ -1,41 +1,41 @@ -/****************************************************************************** - * - * Copyright(c) 2013 Realtek Corporation. All rights reserved. - * - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * - ******************************************************************************/ -#ifndef __HAL_SDIO_COEX_H__ -#define __HAL_SDIO_COEX_H__ - -#include - -#ifdef CONFIG_SDIO_MULTI_FUNCTION_COEX - -enum { /* for sdio multi-func. coex */ - SDIO_MULTI_WIFI = 0, - SDIO_MULTI_BT, - SDIO_MULTI_NUM -}; - -bool ex_hal_sdio_multi_if_bus_available(PADAPTER adapter); - -#else - -#define ex_hal_sdio_multi_if_bus_available(adapter) TRUE - -#endif /* CONFIG_SDIO_MULTI_FUNCTION_COEX */ -#endif /* !__HAL_SDIO_COEX_H__ */ - +/****************************************************************************** + * + * Copyright(c) 2013 Realtek Corporation. All rights reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __HAL_SDIO_COEX_H__ +#define __HAL_SDIO_COEX_H__ + +#include + +#ifdef CONFIG_SDIO_MULTI_FUNCTION_COEX + +enum { /* for sdio multi-func. coex */ + SDIO_MULTI_WIFI = 0, + SDIO_MULTI_BT, + SDIO_MULTI_NUM +}; + +bool ex_hal_sdio_multi_if_bus_available(PADAPTER adapter); + +#else + +#define ex_hal_sdio_multi_if_bus_available(adapter) TRUE + +#endif /* CONFIG_SDIO_MULTI_FUNCTION_COEX */ +#endif /* !__HAL_SDIO_COEX_H__ */ + diff --git a/include/rtw_ap.h b/include/rtw_ap.h index 64cb1a8..5ccb551 100644 --- a/include/rtw_ap.h +++ b/include/rtw_ap.h @@ -1,143 +1,143 @@ -/****************************************************************************** - * - * 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_AP_H_ -#define __RTW_AP_H_ - - -#ifdef CONFIG_AP_MODE - -/* external function */ -extern void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta); -extern void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta); - - -void init_mlme_ap_info(_adapter *padapter); -void free_mlme_ap_info(_adapter *padapter); -u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period - , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie); -/* void update_BCNTIM(_adapter *padapter); */ -void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len); -void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index); -void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, u8 flags, const char *tag); -#define update_beacon(adapter, ie_id, oui, tx, flags) _update_beacon((adapter), (ie_id), (oui), (tx), (flags), __func__) -/*update_beacon - (flags) can set to normal enqueue (0) and RTW_CMDF_WAIT_ACK enqueue. - (flags) = RTW_CMDF_DIRECTLY is not currently implemented, it will do normal enqueue.*/ - -void rtw_ap_update_sta_ra_info(_adapter *padapter, struct sta_info *psta); - -void expire_timeout_chk(_adapter *padapter); -void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta); -void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter); -void start_bss_network(_adapter *padapter, struct createbss_parm *parm); -int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len); -void rtw_ap_restore_network(_adapter *padapter); - -#if CONFIG_RTW_MACADDR_ACL -void rtw_macaddr_acl_init(_adapter *adapter, u8 period); -void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period); -void rtw_macaddr_acl_clear(_adapter *adapter, u8 period); -void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode); -int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr); -int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr); -#endif /* CONFIG_RTW_MACADDR_ACL */ - -u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk); -u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta); -int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid); -int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx); - -#ifdef CONFIG_NATIVEAP_MLME -void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type); -void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta); -u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta); -void sta_info_update(_adapter *padapter, struct sta_info *psta); -void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta); -u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue); -int rtw_sta_flush(_adapter *padapter, bool enqueue); -int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset); -void start_ap_mode(_adapter *padapter); -void stop_ap_mode(_adapter *padapter); -#endif - -void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset); -u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp - , s16 req_ch, s8 req_bw, s8 req_offset, u8 *ch, u8 *bw, u8 *offset, u8 *chbw_allow, bool *set_u_ch); - -#ifdef CONFIG_AUTO_AP_MODE -void rtw_auto_ap_rx_msg_dump(_adapter *padapter, union recv_frame *precv_frame, u8 *ehdr_pos); -extern void rtw_start_auto_ap(_adapter *adapter); -#endif /* CONFIG_AUTO_AP_MODE */ - -void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap); -u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len); -u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); -void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len); -void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); -void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); -void rtw_ap_parse_sta_multi_ap_ie(_adapter *adapter, struct sta_info *sta, u8 *ies, int ies_len); - -/* b2u flags */ -#define RTW_AP_B2U_ALL BIT0 -#define RTW_AP_B2U_GA_UCAST BIT1 /* WDS group addressed unicast frame, forward only */ -#define RTW_AP_B2U_BCAST BIT2 -#define RTW_AP_B2U_IP_MCAST BIT3 - -#define rtw_ap_src_b2u_policy_chk(flags, da) ( \ - (flags & RTW_AP_B2U_ALL) \ - || ((flags & RTW_AP_B2U_BCAST) && is_broadcast_mac_addr(da)) \ - || ((flags & RTW_AP_B2U_IP_MCAST) && (IP_MCAST_MAC(da) || ICMPV6_MCAST_MAC(da))) \ - ) - -#define rtw_ap_fwd_b2u_policy_chk(flags, da, gaucst) ( \ - (flags & RTW_AP_B2U_ALL) \ - || ((flags & RTW_AP_B2U_GA_UCAST) && gaucst) \ - || ((flags & RTW_AP_B2U_BCAST) && is_broadcast_mac_addr(da)) \ - || ((flags & RTW_AP_B2U_IP_MCAST) && (IP_MCAST_MAC(da) || ICMPV6_MCAST_MAC(da))) \ - ) - -void dump_ap_b2u_flags(void *sel, _adapter *adapter); - -int rtw_ap_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list); -int rtw_ap_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta); -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 *b2u_list); - -void update_bmc_sta(_adapter *padapter); - -#ifdef CONFIG_BMC_TX_RATE_SELECT -void rtw_update_bmc_sta_tx_rate(_adapter *adapter); -#endif - -void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field); -void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len); -#ifdef CONFIG_80211N_HT -int rtw_ht_operation_update(_adapter *padapter); -#endif /* CONFIG_80211N_HT */ -u8 rtw_ap_sta_states_check(_adapter *adapter); - -#ifdef CONFIG_FW_HANDLE_TXBCN -#define rtw_ap_get_nums(adapter) (adapter_to_dvobj(adapter)->nr_ap_if) -bool rtw_ap_nums_check(_adapter *adapter); -#endif - -#ifdef CONFIG_SWTIMER_BASED_TXBCN -void tx_beacon_handlder(struct dvobj_priv *pdvobj); -void tx_beacon_timer_handlder(void *ctx); -#endif /*CONFIG_SWTIMER_BASED_TXBCN*/ - -#endif /* end of CONFIG_AP_MODE */ -#endif /*__RTW_AP_H_*/ +/****************************************************************************** + * + * 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_AP_H_ +#define __RTW_AP_H_ + + +#ifdef CONFIG_AP_MODE + +/* external function */ +extern void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta); +extern void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta); + + +void init_mlme_ap_info(_adapter *padapter); +void free_mlme_ap_info(_adapter *padapter); +u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period + , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie); +/* void update_BCNTIM(_adapter *padapter); */ +void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len); +void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index); +void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, u8 flags, const char *tag); +#define update_beacon(adapter, ie_id, oui, tx, flags) _update_beacon((adapter), (ie_id), (oui), (tx), (flags), __func__) +/*update_beacon - (flags) can set to normal enqueue (0) and RTW_CMDF_WAIT_ACK enqueue. + (flags) = RTW_CMDF_DIRECTLY is not currently implemented, it will do normal enqueue.*/ + +void rtw_ap_update_sta_ra_info(_adapter *padapter, struct sta_info *psta); + +void expire_timeout_chk(_adapter *padapter); +void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta); +void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter); +void start_bss_network(_adapter *padapter, struct createbss_parm *parm); +int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len); +void rtw_ap_restore_network(_adapter *padapter); + +#if CONFIG_RTW_MACADDR_ACL +void rtw_macaddr_acl_init(_adapter *adapter, u8 period); +void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period); +void rtw_macaddr_acl_clear(_adapter *adapter, u8 period); +void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode); +int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr); +int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr); +#endif /* CONFIG_RTW_MACADDR_ACL */ + +u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk); +u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta); +int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid); +int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx); + +#ifdef CONFIG_NATIVEAP_MLME +void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type); +void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta); +u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta); +void sta_info_update(_adapter *padapter, struct sta_info *psta); +void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta); +u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue); +int rtw_sta_flush(_adapter *padapter, bool enqueue); +int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset); +void start_ap_mode(_adapter *padapter); +void stop_ap_mode(_adapter *padapter); +#endif + +void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset); +u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp + , s16 req_ch, s8 req_bw, s8 req_offset, u8 *ch, u8 *bw, u8 *offset, u8 *chbw_allow, bool *set_u_ch); + +#ifdef CONFIG_AUTO_AP_MODE +void rtw_auto_ap_rx_msg_dump(_adapter *padapter, union recv_frame *precv_frame, u8 *ehdr_pos); +extern void rtw_start_auto_ap(_adapter *adapter); +#endif /* CONFIG_AUTO_AP_MODE */ + +void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap); +u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len); +u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); +void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len); +void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); +void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems); +void rtw_ap_parse_sta_multi_ap_ie(_adapter *adapter, struct sta_info *sta, u8 *ies, int ies_len); + +/* b2u flags */ +#define RTW_AP_B2U_ALL BIT0 +#define RTW_AP_B2U_GA_UCAST BIT1 /* WDS group addressed unicast frame, forward only */ +#define RTW_AP_B2U_BCAST BIT2 +#define RTW_AP_B2U_IP_MCAST BIT3 + +#define rtw_ap_src_b2u_policy_chk(flags, da) ( \ + (flags & RTW_AP_B2U_ALL) \ + || ((flags & RTW_AP_B2U_BCAST) && is_broadcast_mac_addr(da)) \ + || ((flags & RTW_AP_B2U_IP_MCAST) && (IP_MCAST_MAC(da) || ICMPV6_MCAST_MAC(da))) \ + ) + +#define rtw_ap_fwd_b2u_policy_chk(flags, da, gaucst) ( \ + (flags & RTW_AP_B2U_ALL) \ + || ((flags & RTW_AP_B2U_GA_UCAST) && gaucst) \ + || ((flags & RTW_AP_B2U_BCAST) && is_broadcast_mac_addr(da)) \ + || ((flags & RTW_AP_B2U_IP_MCAST) && (IP_MCAST_MAC(da) || ICMPV6_MCAST_MAC(da))) \ + ) + +void dump_ap_b2u_flags(void *sel, _adapter *adapter); + +int rtw_ap_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list); +int rtw_ap_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta); +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 *b2u_list); + +void update_bmc_sta(_adapter *padapter); + +#ifdef CONFIG_BMC_TX_RATE_SELECT +void rtw_update_bmc_sta_tx_rate(_adapter *adapter); +#endif + +void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field); +void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len); +#ifdef CONFIG_80211N_HT +int rtw_ht_operation_update(_adapter *padapter); +#endif /* CONFIG_80211N_HT */ +u8 rtw_ap_sta_states_check(_adapter *adapter); + +#ifdef CONFIG_FW_HANDLE_TXBCN +#define rtw_ap_get_nums(adapter) (adapter_to_dvobj(adapter)->nr_ap_if) +bool rtw_ap_nums_check(_adapter *adapter); +#endif + +#ifdef CONFIG_SWTIMER_BASED_TXBCN +void tx_beacon_handlder(struct dvobj_priv *pdvobj); +void tx_beacon_timer_handlder(void *ctx); +#endif /*CONFIG_SWTIMER_BASED_TXBCN*/ + +#endif /* end of CONFIG_AP_MODE */ +#endif /*__RTW_AP_H_*/ diff --git a/include/rtw_roch.h b/include/rtw_roch.h index 2744f48..d3de7e2 100644 --- a/include/rtw_roch.h +++ b/include/rtw_roch.h @@ -1,61 +1,61 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 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. - * - *****************************************************************************/ -#ifndef __RTW_ROCH_H__ -#define __RTW_ROCH_H__ - -#include - -struct rtw_roch_parm; - -#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) -struct roch_info { -#ifdef CONFIG_CONCURRENT_MODE - _timer ap_roch_ch_switch_timer; /* Used to switch the channel between legacy AP and listen state. */ -#ifdef CONFIG_IOCTL_CFG80211 - u32 min_home_dur; /* min duration for traffic, home_time */ - u32 max_away_dur; /* max acceptable away duration, home_away_time */ -#endif -#endif - -#ifdef CONFIG_IOCTL_CFG80211 - _timer remain_on_ch_timer; - u8 restore_channel; - struct ieee80211_channel remain_on_ch_channel; - enum nl80211_channel_type remain_on_ch_type; - ATOMIC_T ro_ch_cookie_gen; - u64 remain_on_ch_cookie; - bool is_ro_ch; - struct wireless_dev *ro_ch_wdev; - systime last_ro_ch_time; /* this will be updated at the beginning and end of ro_ch */ -#endif -}; -#endif - -#ifdef CONFIG_IOCTL_CFG80211 -u8 rtw_roch_stay_in_cur_chan(_adapter *padapter); -#endif - -#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) -s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf); -u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags); - -#ifdef CONFIG_CONCURRENT_MODE -void rtw_concurrent_handler(_adapter *padapter); -#endif - -void rtw_init_roch_info(_adapter *padapter); -#endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */ - -#endif +/****************************************************************************** + * + * Copyright(c) 2007 - 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. + * + *****************************************************************************/ +#ifndef __RTW_ROCH_H__ +#define __RTW_ROCH_H__ + +#include + +struct rtw_roch_parm; + +#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) +struct roch_info { +#ifdef CONFIG_CONCURRENT_MODE + _timer ap_roch_ch_switch_timer; /* Used to switch the channel between legacy AP and listen state. */ +#ifdef CONFIG_IOCTL_CFG80211 + u32 min_home_dur; /* min duration for traffic, home_time */ + u32 max_away_dur; /* max acceptable away duration, home_away_time */ +#endif +#endif + +#ifdef CONFIG_IOCTL_CFG80211 + _timer remain_on_ch_timer; + u8 restore_channel; + struct ieee80211_channel remain_on_ch_channel; + enum nl80211_channel_type remain_on_ch_type; + ATOMIC_T ro_ch_cookie_gen; + u64 remain_on_ch_cookie; + bool is_ro_ch; + struct wireless_dev *ro_ch_wdev; + systime last_ro_ch_time; /* this will be updated at the beginning and end of ro_ch */ +#endif +}; +#endif + +#ifdef CONFIG_IOCTL_CFG80211 +u8 rtw_roch_stay_in_cur_chan(_adapter *padapter); +#endif + +#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) +s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf); +u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags); + +#ifdef CONFIG_CONCURRENT_MODE +void rtw_concurrent_handler(_adapter *padapter); +#endif + +void rtw_init_roch_info(_adapter *padapter); +#endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */ + +#endif diff --git a/os_dep/linux/rhashtable.c b/os_dep/linux/rhashtable.c index af9c9ae..0163a4b 100644 --- a/os_dep/linux/rhashtable.c +++ b/os_dep/linux/rhashtable.c @@ -1,844 +1,844 @@ -/* - * Resizable, Scalable, Concurrent Hash Table - * - * Copyright (c) 2015 Herbert Xu - * Copyright (c) 2014-2015 Thomas Graf - * Copyright (c) 2008-2014 Patrick McHardy - * - * Code partially derived from nft_hash - * Rewritten with rehash code from br_multicast plus single list - * pointer as suggested by Josh Triplett - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define HASH_DEFAULT_SIZE 64UL -#define HASH_MIN_SIZE 4U -#define BUCKET_LOCKS_PER_CPU 128UL - -static u32 head_hashfn(struct rhashtable *ht, - const struct bucket_table *tbl, - const struct rhash_head *he) -{ - return rht_head_hashfn(ht, tbl, he, ht->p); -} - -#ifdef CONFIG_PROVE_LOCKING -#define ASSERT_RHT_MUTEX(HT) BUG_ON(!lockdep_rht_mutex_is_held(HT)) - -int lockdep_rht_mutex_is_held(struct rhashtable *ht) -{ - return (debug_locks) ? lockdep_is_held(&ht->mutex) : 1; -} - -int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash) -{ - spinlock_t *lock = rht_bucket_lock(tbl, hash); - - return (debug_locks) ? lockdep_is_held(lock) : 1; -} -#else -#define ASSERT_RHT_MUTEX(HT) -#endif - - -static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl, - gfp_t gfp) -{ - unsigned int i, size; -#if defined(CONFIG_PROVE_LOCKING) - unsigned int nr_pcpus = 2; -#else - unsigned int nr_pcpus = num_possible_cpus(); -#endif - - nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL); - size = roundup_pow_of_two(nr_pcpus * ht->p.locks_mul); - - /* Never allocate more than 0.5 locks per bucket */ - size = min_t(unsigned int, size, tbl->size >> 1); - - if (sizeof(spinlock_t) != 0) { -#ifdef CONFIG_NUMA - if (size * sizeof(spinlock_t) > PAGE_SIZE && - gfp == GFP_KERNEL) - tbl->locks = vmalloc(size * sizeof(spinlock_t)); - else -#endif - tbl->locks = kmalloc_array(size, sizeof(spinlock_t), - gfp); - if (!tbl->locks) - return -ENOMEM; - for (i = 0; i < size; i++) - spin_lock_init(&tbl->locks[i]); - } - tbl->locks_mask = size - 1; - - return 0; -} - -static void bucket_table_free(const struct bucket_table *tbl) -{ - if (tbl) - kvfree(tbl->locks); - - kvfree(tbl); -} - -static void bucket_table_free_rcu(struct rcu_head *head) -{ - bucket_table_free(container_of(head, struct bucket_table, rcu)); -} - -static struct bucket_table *bucket_table_alloc(struct rhashtable *ht, - size_t nbuckets, - gfp_t gfp) -{ - struct bucket_table *tbl = NULL; - size_t size; - int i; - - size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]); - if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER) || - gfp != GFP_KERNEL) - tbl = kzalloc(size, gfp | __GFP_NOWARN | __GFP_NORETRY); - if (tbl == NULL && gfp == GFP_KERNEL) - tbl = vzalloc(size); - if (tbl == NULL) - return NULL; - - tbl->size = nbuckets; - - if (alloc_bucket_locks(ht, tbl, gfp) < 0) { - bucket_table_free(tbl); - return NULL; - } - - INIT_LIST_HEAD(&tbl->walkers); - - get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); - - for (i = 0; i < nbuckets; i++) - INIT_RHT_NULLS_HEAD(tbl->buckets[i], ht, i); - - return tbl; -} - -static struct bucket_table *rhashtable_last_table(struct rhashtable *ht, - struct bucket_table *tbl) -{ - struct bucket_table *new_tbl; - - do { - new_tbl = tbl; - tbl = rht_dereference_rcu(tbl->future_tbl, ht); - } while (tbl); - - return new_tbl; -} - -static int rhashtable_rehash_one(struct rhashtable *ht, unsigned int old_hash) -{ - struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); - struct bucket_table *new_tbl = rhashtable_last_table(ht, - rht_dereference_rcu(old_tbl->future_tbl, ht)); - struct rhash_head __rcu **pprev = &old_tbl->buckets[old_hash]; - int err = -ENOENT; - struct rhash_head *head, *next, *entry; - spinlock_t *new_bucket_lock; - unsigned int new_hash; - - rht_for_each(entry, old_tbl, old_hash) { - err = 0; - next = rht_dereference_bucket(entry->next, old_tbl, old_hash); - - if (rht_is_a_nulls(next)) - break; - - pprev = &entry->next; - } - - if (err) - goto out; - - new_hash = head_hashfn(ht, new_tbl, entry); - - new_bucket_lock = rht_bucket_lock(new_tbl, new_hash); - - spin_lock_nested(new_bucket_lock, SINGLE_DEPTH_NESTING); - head = rht_dereference_bucket(new_tbl->buckets[new_hash], - new_tbl, new_hash); - - RCU_INIT_POINTER(entry->next, head); - - rcu_assign_pointer(new_tbl->buckets[new_hash], entry); - spin_unlock(new_bucket_lock); - - rcu_assign_pointer(*pprev, next); - -out: - return err; -} - -static void rhashtable_rehash_chain(struct rhashtable *ht, - unsigned int old_hash) -{ - struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); - spinlock_t *old_bucket_lock; - - old_bucket_lock = rht_bucket_lock(old_tbl, old_hash); - - spin_lock_bh(old_bucket_lock); - while (!rhashtable_rehash_one(ht, old_hash)) - ; - old_tbl->rehash++; - spin_unlock_bh(old_bucket_lock); -} - -static int rhashtable_rehash_attach(struct rhashtable *ht, - struct bucket_table *old_tbl, - struct bucket_table *new_tbl) -{ - /* Protect future_tbl using the first bucket lock. */ - spin_lock_bh(old_tbl->locks); - - /* Did somebody beat us to it? */ - if (rcu_access_pointer(old_tbl->future_tbl)) { - spin_unlock_bh(old_tbl->locks); - return -EEXIST; - } - - /* Make insertions go into the new, empty table right away. Deletions - * and lookups will be attempted in both tables until we synchronize. - */ - rcu_assign_pointer(old_tbl->future_tbl, new_tbl); - - /* Ensure the new table is visible to readers. */ - smp_wmb(); - - spin_unlock_bh(old_tbl->locks); - - return 0; -} - -static int rhashtable_rehash_table(struct rhashtable *ht) -{ - struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); - struct bucket_table *new_tbl; - struct rhashtable_walker *walker; - unsigned int old_hash; - - new_tbl = rht_dereference(old_tbl->future_tbl, ht); - if (!new_tbl) - return 0; - - for (old_hash = 0; old_hash < old_tbl->size; old_hash++) - rhashtable_rehash_chain(ht, old_hash); - - /* Publish the new table pointer. */ - rcu_assign_pointer(ht->tbl, new_tbl); - - spin_lock(&ht->lock); - list_for_each_entry(walker, &old_tbl->walkers, list) - walker->tbl = NULL; - spin_unlock(&ht->lock); - - /* Wait for readers. All new readers will see the new - * table, and thus no references to the old table will - * remain. - */ - call_rcu(&old_tbl->rcu, bucket_table_free_rcu); - - return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0; -} - -/** - * rhashtable_expand - Expand hash table while allowing concurrent lookups - * @ht: the hash table to expand - * - * A secondary bucket array is allocated and the hash entries are migrated. - * - * This function may only be called in a context where it is safe to call - * synchronize_rcu(), e.g. not within a rcu_read_lock() section. - * - * The caller must ensure that no concurrent resizing occurs by holding - * ht->mutex. - * - * It is valid to have concurrent insertions and deletions protected by per - * bucket locks or concurrent RCU protected lookups and traversals. - */ -static int rhashtable_expand(struct rhashtable *ht) -{ - struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht); - int err; - - ASSERT_RHT_MUTEX(ht); - - old_tbl = rhashtable_last_table(ht, old_tbl); - - new_tbl = bucket_table_alloc(ht, old_tbl->size * 2, GFP_KERNEL); - if (new_tbl == NULL) - return -ENOMEM; - - err = rhashtable_rehash_attach(ht, old_tbl, new_tbl); - if (err) - bucket_table_free(new_tbl); - - return err; -} - -/** - * rhashtable_shrink - Shrink hash table while allowing concurrent lookups - * @ht: the hash table to shrink - * - * This function shrinks the hash table to fit, i.e., the smallest - * size would not cause it to expand right away automatically. - * - * The caller must ensure that no concurrent resizing occurs by holding - * ht->mutex. - * - * The caller must ensure that no concurrent table mutations take place. - * It is however valid to have concurrent lookups if they are RCU protected. - * - * It is valid to have concurrent insertions and deletions protected by per - * bucket locks or concurrent RCU protected lookups and traversals. - */ -static int rhashtable_shrink(struct rhashtable *ht) -{ - struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht); - unsigned int size; - int err; - - ASSERT_RHT_MUTEX(ht); - - size = roundup_pow_of_two(atomic_read(&ht->nelems) * 3 / 2); - if (size < ht->p.min_size) - size = ht->p.min_size; - - if (old_tbl->size <= size) - return 0; - - if (rht_dereference(old_tbl->future_tbl, ht)) - return -EEXIST; - - new_tbl = bucket_table_alloc(ht, size, GFP_KERNEL); - if (new_tbl == NULL) - return -ENOMEM; - - err = rhashtable_rehash_attach(ht, old_tbl, new_tbl); - if (err) - bucket_table_free(new_tbl); - - return err; -} - -static void rht_deferred_worker(struct work_struct *work) -{ - struct rhashtable *ht; - struct bucket_table *tbl; - int err = 0; - - ht = container_of(work, struct rhashtable, run_work); - mutex_lock(&ht->mutex); - - tbl = rht_dereference(ht->tbl, ht); - tbl = rhashtable_last_table(ht, tbl); - - if (rht_grow_above_75(ht, tbl)) - rhashtable_expand(ht); - else if (ht->p.automatic_shrinking && rht_shrink_below_30(ht, tbl)) - rhashtable_shrink(ht); - - err = rhashtable_rehash_table(ht); - - mutex_unlock(&ht->mutex); - - if (err) - schedule_work(&ht->run_work); -} - -static bool rhashtable_check_elasticity(struct rhashtable *ht, - struct bucket_table *tbl, - unsigned int hash) -{ - unsigned int elasticity = ht->elasticity; - struct rhash_head *head; - - rht_for_each(head, tbl, hash) - if (!--elasticity) - return true; - - return false; -} - -int rhashtable_insert_rehash(struct rhashtable *ht, - struct bucket_table *tbl) -{ - struct bucket_table *old_tbl; - struct bucket_table *new_tbl; - unsigned int size; - int err; - - old_tbl = rht_dereference_rcu(ht->tbl, ht); - - size = tbl->size; - - err = -EBUSY; - - if (rht_grow_above_75(ht, tbl)) - size *= 2; - /* Do not schedule more than one rehash */ - else if (old_tbl != tbl) - goto fail; - - err = -ENOMEM; - - new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC); - if (new_tbl == NULL) - goto fail; - - err = rhashtable_rehash_attach(ht, tbl, new_tbl); - if (err) { - bucket_table_free(new_tbl); - if (err == -EEXIST) - err = 0; - } else - schedule_work(&ht->run_work); - - return err; - -fail: - /* Do not fail the insert if someone else did a rehash. */ - if (likely(rcu_dereference_raw(tbl->future_tbl))) - return 0; - - /* Schedule async rehash to retry allocation in process context. */ - if (err == -ENOMEM) - schedule_work(&ht->run_work); - - return err; -} - -struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, - const void *key, - struct rhash_head *obj, - struct bucket_table *tbl) -{ - struct rhash_head *head; - unsigned int hash; - int err; - - tbl = rhashtable_last_table(ht, tbl); - hash = head_hashfn(ht, tbl, obj); - spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING); - - err = -EEXIST; - if (key && rhashtable_lookup_fast(ht, key, ht->p)) - goto exit; - - err = -E2BIG; - if (unlikely(rht_grow_above_max(ht, tbl))) - goto exit; - - err = -EAGAIN; - if (rhashtable_check_elasticity(ht, tbl, hash) || - rht_grow_above_100(ht, tbl)) - goto exit; - - err = 0; - - head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); - - RCU_INIT_POINTER(obj->next, head); - - rcu_assign_pointer(tbl->buckets[hash], obj); - - atomic_inc(&ht->nelems); - -exit: - spin_unlock(rht_bucket_lock(tbl, hash)); - - if (err == 0) - return NULL; - else if (err == -EAGAIN) - return tbl; - else - return ERR_PTR(err); -} - -/** - * rhashtable_walk_init - Initialise an iterator - * @ht: Table to walk over - * @iter: Hash table Iterator - * - * This function prepares a hash table walk. - * - * Note that if you restart a walk after rhashtable_walk_stop you - * may see the same object twice. Also, you may miss objects if - * there are removals in between rhashtable_walk_stop and the next - * call to rhashtable_walk_start. - * - * For a completely stable walk you should construct your own data - * structure outside the hash table. - * - * This function may sleep so you must not call it from interrupt - * context or with spin locks held. - * - * You must call rhashtable_walk_exit if this function returns - * successfully. - */ -int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter) -{ - iter->ht = ht; - iter->p = NULL; - iter->slot = 0; - iter->skip = 0; - - iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL); - if (!iter->walker) - return -ENOMEM; - - spin_lock(&ht->lock); - iter->walker->tbl = - rcu_dereference_protected(ht->tbl, lockdep_is_held(&ht->lock)); - list_add(&iter->walker->list, &iter->walker->tbl->walkers); - spin_unlock(&ht->lock); - - return 0; -} - -/** - * rhashtable_walk_exit - Free an iterator - * @iter: Hash table Iterator - * - * This function frees resources allocated by rhashtable_walk_init. - */ -void rhashtable_walk_exit(struct rhashtable_iter *iter) -{ - spin_lock(&iter->ht->lock); - if (iter->walker->tbl) - list_del(&iter->walker->list); - spin_unlock(&iter->ht->lock); - kfree(iter->walker); -} - -/** - * rhashtable_walk_start - Start a hash table walk - * @iter: Hash table iterator - * - * Start a hash table walk. Note that we take the RCU lock in all - * cases including when we return an error. So you must always call - * rhashtable_walk_stop to clean up. - * - * Returns zero if successful. - * - * Returns -EAGAIN if resize event occured. Note that the iterator - * will rewind back to the beginning and you may use it immediately - * by calling rhashtable_walk_next. - */ -int rhashtable_walk_start(struct rhashtable_iter *iter) - __acquires(RCU) -{ - struct rhashtable *ht = iter->ht; - - rcu_read_lock(); - - spin_lock(&ht->lock); - if (iter->walker->tbl) - list_del(&iter->walker->list); - spin_unlock(&ht->lock); - - if (!iter->walker->tbl) { - iter->walker->tbl = rht_dereference_rcu(ht->tbl, ht); - return -EAGAIN; - } - - return 0; -} - -/** - * rhashtable_walk_next - Return the next object and advance the iterator - * @iter: Hash table iterator - * - * Note that you must call rhashtable_walk_stop when you are finished - * with the walk. - * - * Returns the next object or NULL when the end of the table is reached. - * - * Returns -EAGAIN if resize event occured. Note that the iterator - * will rewind back to the beginning and you may continue to use it. - */ -void *rhashtable_walk_next(struct rhashtable_iter *iter) -{ - struct bucket_table *tbl = iter->walker->tbl; - struct rhashtable *ht = iter->ht; - struct rhash_head *p = iter->p; - - if (p) { - p = rht_dereference_bucket_rcu(p->next, tbl, iter->slot); - goto next; - } - - for (; iter->slot < tbl->size; iter->slot++) { - int skip = iter->skip; - - rht_for_each_rcu(p, tbl, iter->slot) { - if (!skip) - break; - skip--; - } - -next: - if (!rht_is_a_nulls(p)) { - iter->skip++; - iter->p = p; - return rht_obj(ht, p); - } - - iter->skip = 0; - } - - iter->p = NULL; - - /* Ensure we see any new tables. */ - smp_rmb(); - - iter->walker->tbl = rht_dereference_rcu(tbl->future_tbl, ht); - if (iter->walker->tbl) { - iter->slot = 0; - iter->skip = 0; - return ERR_PTR(-EAGAIN); - } - - return NULL; -} - -/** - * rhashtable_walk_stop - Finish a hash table walk - * @iter: Hash table iterator - * - * Finish a hash table walk. - */ -void rhashtable_walk_stop(struct rhashtable_iter *iter) - __releases(RCU) -{ - struct rhashtable *ht; - struct bucket_table *tbl = iter->walker->tbl; - - if (!tbl) - goto out; - - ht = iter->ht; - - spin_lock(&ht->lock); - if (tbl->rehash < tbl->size) - list_add(&iter->walker->list, &tbl->walkers); - else - iter->walker->tbl = NULL; - spin_unlock(&ht->lock); - - iter->p = NULL; - -out: - rcu_read_unlock(); -} - -static size_t rounded_hashtable_size(const struct rhashtable_params *params) -{ - return max(roundup_pow_of_two(params->nelem_hint * 4 / 3), - (unsigned long)params->min_size); -} - -static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed) -{ - return jhash2(key, length, seed); -} - -/** - * rhashtable_init - initialize a new hash table - * @ht: hash table to be initialized - * @params: configuration parameters - * - * Initializes a new hash table based on the provided configuration - * parameters. A table can be configured either with a variable or - * fixed length key: - * - * Configuration Example 1: Fixed length keys - * struct test_obj { - * int key; - * void * my_member; - * struct rhash_head node; - * }; - * - * struct rhashtable_params params = { - * .head_offset = offsetof(struct test_obj, node), - * .key_offset = offsetof(struct test_obj, key), - * .key_len = sizeof(int), - * .hashfn = jhash, - * .nulls_base = (1U << RHT_BASE_SHIFT), - * }; - * - * Configuration Example 2: Variable length keys - * struct test_obj { - * [...] - * struct rhash_head node; - * }; - * - * u32 my_hash_fn(const void *data, u32 len, u32 seed) - * { - * struct test_obj *obj = data; - * - * return [... hash ...]; - * } - * - * struct rhashtable_params params = { - * .head_offset = offsetof(struct test_obj, node), - * .hashfn = jhash, - * .obj_hashfn = my_hash_fn, - * }; - */ -int rhashtable_init(struct rhashtable *ht, - const struct rhashtable_params *params) -{ - struct bucket_table *tbl; - size_t size; - - size = HASH_DEFAULT_SIZE; - - if ((!params->key_len && !params->obj_hashfn) || - (params->obj_hashfn && !params->obj_cmpfn)) - return -EINVAL; - - if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT)) - return -EINVAL; - - memset(ht, 0, sizeof(*ht)); - mutex_init(&ht->mutex); - spin_lock_init(&ht->lock); - memcpy(&ht->p, params, sizeof(*params)); - - if (params->min_size) - ht->p.min_size = roundup_pow_of_two(params->min_size); - - if (params->max_size) - ht->p.max_size = rounddown_pow_of_two(params->max_size); - - if (params->insecure_max_entries) - ht->p.insecure_max_entries = - rounddown_pow_of_two(params->insecure_max_entries); - else - ht->p.insecure_max_entries = ht->p.max_size * 2; - - ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE); - - if (params->nelem_hint) - size = rounded_hashtable_size(&ht->p); - - /* The maximum (not average) chain length grows with the - * size of the hash table, at a rate of (log N)/(log log N). - * The value of 16 is selected so that even if the hash - * table grew to 2^32 you would not expect the maximum - * chain length to exceed it unless we are under attack - * (or extremely unlucky). - * - * As this limit is only to detect attacks, we don't need - * to set it to a lower value as you'd need the chain - * length to vastly exceed 16 to have any real effect - * on the system. - */ - if (!params->insecure_elasticity) - ht->elasticity = 16; - - if (params->locks_mul) - ht->p.locks_mul = roundup_pow_of_two(params->locks_mul); - else - ht->p.locks_mul = BUCKET_LOCKS_PER_CPU; - - ht->key_len = ht->p.key_len; - if (!params->hashfn) { - ht->p.hashfn = jhash; - - if (!(ht->key_len & (sizeof(u32) - 1))) { - ht->key_len /= sizeof(u32); - ht->p.hashfn = rhashtable_jhash2; - } - } - - tbl = bucket_table_alloc(ht, size, GFP_KERNEL); - if (tbl == NULL) - return -ENOMEM; - - atomic_set(&ht->nelems, 0); - - RCU_INIT_POINTER(ht->tbl, tbl); - - INIT_WORK(&ht->run_work, rht_deferred_worker); - - return 0; -} - -/** - * rhashtable_free_and_destroy - free elements and destroy hash table - * @ht: the hash table to destroy - * @free_fn: callback to release resources of element - * @arg: pointer passed to free_fn - * - * Stops an eventual async resize. If defined, invokes free_fn for each - * element to releasal resources. Please note that RCU protected - * readers may still be accessing the elements. Releasing of resources - * must occur in a compatible manner. Then frees the bucket array. - * - * This function will eventually sleep to wait for an async resize - * to complete. The caller is responsible that no further write operations - * occurs in parallel. - */ -void rhashtable_free_and_destroy(struct rhashtable *ht, - void (*free_fn)(void *ptr, void *arg), - void *arg) -{ - const struct bucket_table *tbl; - unsigned int i; - - cancel_work_sync(&ht->run_work); - - mutex_lock(&ht->mutex); - tbl = rht_dereference(ht->tbl, ht); - if (free_fn) { - for (i = 0; i < tbl->size; i++) { - struct rhash_head *pos, *next; - - for (pos = rht_dereference(tbl->buckets[i], ht), - next = !rht_is_a_nulls(pos) ? - rht_dereference(pos->next, ht) : NULL; - !rht_is_a_nulls(pos); - pos = next, - next = !rht_is_a_nulls(pos) ? - rht_dereference(pos->next, ht) : NULL) - free_fn(rht_obj(ht, pos), arg); - } - } - - bucket_table_free(tbl); - mutex_unlock(&ht->mutex); -} - -void rhashtable_destroy(struct rhashtable *ht) -{ - return rhashtable_free_and_destroy(ht, NULL, NULL); -} - +/* + * Resizable, Scalable, Concurrent Hash Table + * + * Copyright (c) 2015 Herbert Xu + * Copyright (c) 2014-2015 Thomas Graf + * Copyright (c) 2008-2014 Patrick McHardy + * + * Code partially derived from nft_hash + * Rewritten with rehash code from br_multicast plus single list + * pointer as suggested by Josh Triplett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HASH_DEFAULT_SIZE 64UL +#define HASH_MIN_SIZE 4U +#define BUCKET_LOCKS_PER_CPU 128UL + +static u32 head_hashfn(struct rhashtable *ht, + const struct bucket_table *tbl, + const struct rhash_head *he) +{ + return rht_head_hashfn(ht, tbl, he, ht->p); +} + +#ifdef CONFIG_PROVE_LOCKING +#define ASSERT_RHT_MUTEX(HT) BUG_ON(!lockdep_rht_mutex_is_held(HT)) + +int lockdep_rht_mutex_is_held(struct rhashtable *ht) +{ + return (debug_locks) ? lockdep_is_held(&ht->mutex) : 1; +} + +int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash) +{ + spinlock_t *lock = rht_bucket_lock(tbl, hash); + + return (debug_locks) ? lockdep_is_held(lock) : 1; +} +#else +#define ASSERT_RHT_MUTEX(HT) +#endif + + +static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl, + gfp_t gfp) +{ + unsigned int i, size; +#if defined(CONFIG_PROVE_LOCKING) + unsigned int nr_pcpus = 2; +#else + unsigned int nr_pcpus = num_possible_cpus(); +#endif + + nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL); + size = roundup_pow_of_two(nr_pcpus * ht->p.locks_mul); + + /* Never allocate more than 0.5 locks per bucket */ + size = min_t(unsigned int, size, tbl->size >> 1); + + if (sizeof(spinlock_t) != 0) { +#ifdef CONFIG_NUMA + if (size * sizeof(spinlock_t) > PAGE_SIZE && + gfp == GFP_KERNEL) + tbl->locks = vmalloc(size * sizeof(spinlock_t)); + else +#endif + tbl->locks = kmalloc_array(size, sizeof(spinlock_t), + gfp); + if (!tbl->locks) + return -ENOMEM; + for (i = 0; i < size; i++) + spin_lock_init(&tbl->locks[i]); + } + tbl->locks_mask = size - 1; + + return 0; +} + +static void bucket_table_free(const struct bucket_table *tbl) +{ + if (tbl) + kvfree(tbl->locks); + + kvfree(tbl); +} + +static void bucket_table_free_rcu(struct rcu_head *head) +{ + bucket_table_free(container_of(head, struct bucket_table, rcu)); +} + +static struct bucket_table *bucket_table_alloc(struct rhashtable *ht, + size_t nbuckets, + gfp_t gfp) +{ + struct bucket_table *tbl = NULL; + size_t size; + int i; + + size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]); + if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER) || + gfp != GFP_KERNEL) + tbl = kzalloc(size, gfp | __GFP_NOWARN | __GFP_NORETRY); + if (tbl == NULL && gfp == GFP_KERNEL) + tbl = vzalloc(size); + if (tbl == NULL) + return NULL; + + tbl->size = nbuckets; + + if (alloc_bucket_locks(ht, tbl, gfp) < 0) { + bucket_table_free(tbl); + return NULL; + } + + INIT_LIST_HEAD(&tbl->walkers); + + get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); + + for (i = 0; i < nbuckets; i++) + INIT_RHT_NULLS_HEAD(tbl->buckets[i], ht, i); + + return tbl; +} + +static struct bucket_table *rhashtable_last_table(struct rhashtable *ht, + struct bucket_table *tbl) +{ + struct bucket_table *new_tbl; + + do { + new_tbl = tbl; + tbl = rht_dereference_rcu(tbl->future_tbl, ht); + } while (tbl); + + return new_tbl; +} + +static int rhashtable_rehash_one(struct rhashtable *ht, unsigned int old_hash) +{ + struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); + struct bucket_table *new_tbl = rhashtable_last_table(ht, + rht_dereference_rcu(old_tbl->future_tbl, ht)); + struct rhash_head __rcu **pprev = &old_tbl->buckets[old_hash]; + int err = -ENOENT; + struct rhash_head *head, *next, *entry; + spinlock_t *new_bucket_lock; + unsigned int new_hash; + + rht_for_each(entry, old_tbl, old_hash) { + err = 0; + next = rht_dereference_bucket(entry->next, old_tbl, old_hash); + + if (rht_is_a_nulls(next)) + break; + + pprev = &entry->next; + } + + if (err) + goto out; + + new_hash = head_hashfn(ht, new_tbl, entry); + + new_bucket_lock = rht_bucket_lock(new_tbl, new_hash); + + spin_lock_nested(new_bucket_lock, SINGLE_DEPTH_NESTING); + head = rht_dereference_bucket(new_tbl->buckets[new_hash], + new_tbl, new_hash); + + RCU_INIT_POINTER(entry->next, head); + + rcu_assign_pointer(new_tbl->buckets[new_hash], entry); + spin_unlock(new_bucket_lock); + + rcu_assign_pointer(*pprev, next); + +out: + return err; +} + +static void rhashtable_rehash_chain(struct rhashtable *ht, + unsigned int old_hash) +{ + struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); + spinlock_t *old_bucket_lock; + + old_bucket_lock = rht_bucket_lock(old_tbl, old_hash); + + spin_lock_bh(old_bucket_lock); + while (!rhashtable_rehash_one(ht, old_hash)) + ; + old_tbl->rehash++; + spin_unlock_bh(old_bucket_lock); +} + +static int rhashtable_rehash_attach(struct rhashtable *ht, + struct bucket_table *old_tbl, + struct bucket_table *new_tbl) +{ + /* Protect future_tbl using the first bucket lock. */ + spin_lock_bh(old_tbl->locks); + + /* Did somebody beat us to it? */ + if (rcu_access_pointer(old_tbl->future_tbl)) { + spin_unlock_bh(old_tbl->locks); + return -EEXIST; + } + + /* Make insertions go into the new, empty table right away. Deletions + * and lookups will be attempted in both tables until we synchronize. + */ + rcu_assign_pointer(old_tbl->future_tbl, new_tbl); + + /* Ensure the new table is visible to readers. */ + smp_wmb(); + + spin_unlock_bh(old_tbl->locks); + + return 0; +} + +static int rhashtable_rehash_table(struct rhashtable *ht) +{ + struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht); + struct bucket_table *new_tbl; + struct rhashtable_walker *walker; + unsigned int old_hash; + + new_tbl = rht_dereference(old_tbl->future_tbl, ht); + if (!new_tbl) + return 0; + + for (old_hash = 0; old_hash < old_tbl->size; old_hash++) + rhashtable_rehash_chain(ht, old_hash); + + /* Publish the new table pointer. */ + rcu_assign_pointer(ht->tbl, new_tbl); + + spin_lock(&ht->lock); + list_for_each_entry(walker, &old_tbl->walkers, list) + walker->tbl = NULL; + spin_unlock(&ht->lock); + + /* Wait for readers. All new readers will see the new + * table, and thus no references to the old table will + * remain. + */ + call_rcu(&old_tbl->rcu, bucket_table_free_rcu); + + return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0; +} + +/** + * rhashtable_expand - Expand hash table while allowing concurrent lookups + * @ht: the hash table to expand + * + * A secondary bucket array is allocated and the hash entries are migrated. + * + * This function may only be called in a context where it is safe to call + * synchronize_rcu(), e.g. not within a rcu_read_lock() section. + * + * The caller must ensure that no concurrent resizing occurs by holding + * ht->mutex. + * + * It is valid to have concurrent insertions and deletions protected by per + * bucket locks or concurrent RCU protected lookups and traversals. + */ +static int rhashtable_expand(struct rhashtable *ht) +{ + struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht); + int err; + + ASSERT_RHT_MUTEX(ht); + + old_tbl = rhashtable_last_table(ht, old_tbl); + + new_tbl = bucket_table_alloc(ht, old_tbl->size * 2, GFP_KERNEL); + if (new_tbl == NULL) + return -ENOMEM; + + err = rhashtable_rehash_attach(ht, old_tbl, new_tbl); + if (err) + bucket_table_free(new_tbl); + + return err; +} + +/** + * rhashtable_shrink - Shrink hash table while allowing concurrent lookups + * @ht: the hash table to shrink + * + * This function shrinks the hash table to fit, i.e., the smallest + * size would not cause it to expand right away automatically. + * + * The caller must ensure that no concurrent resizing occurs by holding + * ht->mutex. + * + * The caller must ensure that no concurrent table mutations take place. + * It is however valid to have concurrent lookups if they are RCU protected. + * + * It is valid to have concurrent insertions and deletions protected by per + * bucket locks or concurrent RCU protected lookups and traversals. + */ +static int rhashtable_shrink(struct rhashtable *ht) +{ + struct bucket_table *new_tbl, *old_tbl = rht_dereference(ht->tbl, ht); + unsigned int size; + int err; + + ASSERT_RHT_MUTEX(ht); + + size = roundup_pow_of_two(atomic_read(&ht->nelems) * 3 / 2); + if (size < ht->p.min_size) + size = ht->p.min_size; + + if (old_tbl->size <= size) + return 0; + + if (rht_dereference(old_tbl->future_tbl, ht)) + return -EEXIST; + + new_tbl = bucket_table_alloc(ht, size, GFP_KERNEL); + if (new_tbl == NULL) + return -ENOMEM; + + err = rhashtable_rehash_attach(ht, old_tbl, new_tbl); + if (err) + bucket_table_free(new_tbl); + + return err; +} + +static void rht_deferred_worker(struct work_struct *work) +{ + struct rhashtable *ht; + struct bucket_table *tbl; + int err = 0; + + ht = container_of(work, struct rhashtable, run_work); + mutex_lock(&ht->mutex); + + tbl = rht_dereference(ht->tbl, ht); + tbl = rhashtable_last_table(ht, tbl); + + if (rht_grow_above_75(ht, tbl)) + rhashtable_expand(ht); + else if (ht->p.automatic_shrinking && rht_shrink_below_30(ht, tbl)) + rhashtable_shrink(ht); + + err = rhashtable_rehash_table(ht); + + mutex_unlock(&ht->mutex); + + if (err) + schedule_work(&ht->run_work); +} + +static bool rhashtable_check_elasticity(struct rhashtable *ht, + struct bucket_table *tbl, + unsigned int hash) +{ + unsigned int elasticity = ht->elasticity; + struct rhash_head *head; + + rht_for_each(head, tbl, hash) + if (!--elasticity) + return true; + + return false; +} + +int rhashtable_insert_rehash(struct rhashtable *ht, + struct bucket_table *tbl) +{ + struct bucket_table *old_tbl; + struct bucket_table *new_tbl; + unsigned int size; + int err; + + old_tbl = rht_dereference_rcu(ht->tbl, ht); + + size = tbl->size; + + err = -EBUSY; + + if (rht_grow_above_75(ht, tbl)) + size *= 2; + /* Do not schedule more than one rehash */ + else if (old_tbl != tbl) + goto fail; + + err = -ENOMEM; + + new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC); + if (new_tbl == NULL) + goto fail; + + err = rhashtable_rehash_attach(ht, tbl, new_tbl); + if (err) { + bucket_table_free(new_tbl); + if (err == -EEXIST) + err = 0; + } else + schedule_work(&ht->run_work); + + return err; + +fail: + /* Do not fail the insert if someone else did a rehash. */ + if (likely(rcu_dereference_raw(tbl->future_tbl))) + return 0; + + /* Schedule async rehash to retry allocation in process context. */ + if (err == -ENOMEM) + schedule_work(&ht->run_work); + + return err; +} + +struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, + const void *key, + struct rhash_head *obj, + struct bucket_table *tbl) +{ + struct rhash_head *head; + unsigned int hash; + int err; + + tbl = rhashtable_last_table(ht, tbl); + hash = head_hashfn(ht, tbl, obj); + spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING); + + err = -EEXIST; + if (key && rhashtable_lookup_fast(ht, key, ht->p)) + goto exit; + + err = -E2BIG; + if (unlikely(rht_grow_above_max(ht, tbl))) + goto exit; + + err = -EAGAIN; + if (rhashtable_check_elasticity(ht, tbl, hash) || + rht_grow_above_100(ht, tbl)) + goto exit; + + err = 0; + + head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); + + RCU_INIT_POINTER(obj->next, head); + + rcu_assign_pointer(tbl->buckets[hash], obj); + + atomic_inc(&ht->nelems); + +exit: + spin_unlock(rht_bucket_lock(tbl, hash)); + + if (err == 0) + return NULL; + else if (err == -EAGAIN) + return tbl; + else + return ERR_PTR(err); +} + +/** + * rhashtable_walk_init - Initialise an iterator + * @ht: Table to walk over + * @iter: Hash table Iterator + * + * This function prepares a hash table walk. + * + * Note that if you restart a walk after rhashtable_walk_stop you + * may see the same object twice. Also, you may miss objects if + * there are removals in between rhashtable_walk_stop and the next + * call to rhashtable_walk_start. + * + * For a completely stable walk you should construct your own data + * structure outside the hash table. + * + * This function may sleep so you must not call it from interrupt + * context or with spin locks held. + * + * You must call rhashtable_walk_exit if this function returns + * successfully. + */ +int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter) +{ + iter->ht = ht; + iter->p = NULL; + iter->slot = 0; + iter->skip = 0; + + iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL); + if (!iter->walker) + return -ENOMEM; + + spin_lock(&ht->lock); + iter->walker->tbl = + rcu_dereference_protected(ht->tbl, lockdep_is_held(&ht->lock)); + list_add(&iter->walker->list, &iter->walker->tbl->walkers); + spin_unlock(&ht->lock); + + return 0; +} + +/** + * rhashtable_walk_exit - Free an iterator + * @iter: Hash table Iterator + * + * This function frees resources allocated by rhashtable_walk_init. + */ +void rhashtable_walk_exit(struct rhashtable_iter *iter) +{ + spin_lock(&iter->ht->lock); + if (iter->walker->tbl) + list_del(&iter->walker->list); + spin_unlock(&iter->ht->lock); + kfree(iter->walker); +} + +/** + * rhashtable_walk_start - Start a hash table walk + * @iter: Hash table iterator + * + * Start a hash table walk. Note that we take the RCU lock in all + * cases including when we return an error. So you must always call + * rhashtable_walk_stop to clean up. + * + * Returns zero if successful. + * + * Returns -EAGAIN if resize event occured. Note that the iterator + * will rewind back to the beginning and you may use it immediately + * by calling rhashtable_walk_next. + */ +int rhashtable_walk_start(struct rhashtable_iter *iter) + __acquires(RCU) +{ + struct rhashtable *ht = iter->ht; + + rcu_read_lock(); + + spin_lock(&ht->lock); + if (iter->walker->tbl) + list_del(&iter->walker->list); + spin_unlock(&ht->lock); + + if (!iter->walker->tbl) { + iter->walker->tbl = rht_dereference_rcu(ht->tbl, ht); + return -EAGAIN; + } + + return 0; +} + +/** + * rhashtable_walk_next - Return the next object and advance the iterator + * @iter: Hash table iterator + * + * Note that you must call rhashtable_walk_stop when you are finished + * with the walk. + * + * Returns the next object or NULL when the end of the table is reached. + * + * Returns -EAGAIN if resize event occured. Note that the iterator + * will rewind back to the beginning and you may continue to use it. + */ +void *rhashtable_walk_next(struct rhashtable_iter *iter) +{ + struct bucket_table *tbl = iter->walker->tbl; + struct rhashtable *ht = iter->ht; + struct rhash_head *p = iter->p; + + if (p) { + p = rht_dereference_bucket_rcu(p->next, tbl, iter->slot); + goto next; + } + + for (; iter->slot < tbl->size; iter->slot++) { + int skip = iter->skip; + + rht_for_each_rcu(p, tbl, iter->slot) { + if (!skip) + break; + skip--; + } + +next: + if (!rht_is_a_nulls(p)) { + iter->skip++; + iter->p = p; + return rht_obj(ht, p); + } + + iter->skip = 0; + } + + iter->p = NULL; + + /* Ensure we see any new tables. */ + smp_rmb(); + + iter->walker->tbl = rht_dereference_rcu(tbl->future_tbl, ht); + if (iter->walker->tbl) { + iter->slot = 0; + iter->skip = 0; + return ERR_PTR(-EAGAIN); + } + + return NULL; +} + +/** + * rhashtable_walk_stop - Finish a hash table walk + * @iter: Hash table iterator + * + * Finish a hash table walk. + */ +void rhashtable_walk_stop(struct rhashtable_iter *iter) + __releases(RCU) +{ + struct rhashtable *ht; + struct bucket_table *tbl = iter->walker->tbl; + + if (!tbl) + goto out; + + ht = iter->ht; + + spin_lock(&ht->lock); + if (tbl->rehash < tbl->size) + list_add(&iter->walker->list, &tbl->walkers); + else + iter->walker->tbl = NULL; + spin_unlock(&ht->lock); + + iter->p = NULL; + +out: + rcu_read_unlock(); +} + +static size_t rounded_hashtable_size(const struct rhashtable_params *params) +{ + return max(roundup_pow_of_two(params->nelem_hint * 4 / 3), + (unsigned long)params->min_size); +} + +static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed) +{ + return jhash2(key, length, seed); +} + +/** + * rhashtable_init - initialize a new hash table + * @ht: hash table to be initialized + * @params: configuration parameters + * + * Initializes a new hash table based on the provided configuration + * parameters. A table can be configured either with a variable or + * fixed length key: + * + * Configuration Example 1: Fixed length keys + * struct test_obj { + * int key; + * void * my_member; + * struct rhash_head node; + * }; + * + * struct rhashtable_params params = { + * .head_offset = offsetof(struct test_obj, node), + * .key_offset = offsetof(struct test_obj, key), + * .key_len = sizeof(int), + * .hashfn = jhash, + * .nulls_base = (1U << RHT_BASE_SHIFT), + * }; + * + * Configuration Example 2: Variable length keys + * struct test_obj { + * [...] + * struct rhash_head node; + * }; + * + * u32 my_hash_fn(const void *data, u32 len, u32 seed) + * { + * struct test_obj *obj = data; + * + * return [... hash ...]; + * } + * + * struct rhashtable_params params = { + * .head_offset = offsetof(struct test_obj, node), + * .hashfn = jhash, + * .obj_hashfn = my_hash_fn, + * }; + */ +int rhashtable_init(struct rhashtable *ht, + const struct rhashtable_params *params) +{ + struct bucket_table *tbl; + size_t size; + + size = HASH_DEFAULT_SIZE; + + if ((!params->key_len && !params->obj_hashfn) || + (params->obj_hashfn && !params->obj_cmpfn)) + return -EINVAL; + + if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT)) + return -EINVAL; + + memset(ht, 0, sizeof(*ht)); + mutex_init(&ht->mutex); + spin_lock_init(&ht->lock); + memcpy(&ht->p, params, sizeof(*params)); + + if (params->min_size) + ht->p.min_size = roundup_pow_of_two(params->min_size); + + if (params->max_size) + ht->p.max_size = rounddown_pow_of_two(params->max_size); + + if (params->insecure_max_entries) + ht->p.insecure_max_entries = + rounddown_pow_of_two(params->insecure_max_entries); + else + ht->p.insecure_max_entries = ht->p.max_size * 2; + + ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE); + + if (params->nelem_hint) + size = rounded_hashtable_size(&ht->p); + + /* The maximum (not average) chain length grows with the + * size of the hash table, at a rate of (log N)/(log log N). + * The value of 16 is selected so that even if the hash + * table grew to 2^32 you would not expect the maximum + * chain length to exceed it unless we are under attack + * (or extremely unlucky). + * + * As this limit is only to detect attacks, we don't need + * to set it to a lower value as you'd need the chain + * length to vastly exceed 16 to have any real effect + * on the system. + */ + if (!params->insecure_elasticity) + ht->elasticity = 16; + + if (params->locks_mul) + ht->p.locks_mul = roundup_pow_of_two(params->locks_mul); + else + ht->p.locks_mul = BUCKET_LOCKS_PER_CPU; + + ht->key_len = ht->p.key_len; + if (!params->hashfn) { + ht->p.hashfn = jhash; + + if (!(ht->key_len & (sizeof(u32) - 1))) { + ht->key_len /= sizeof(u32); + ht->p.hashfn = rhashtable_jhash2; + } + } + + tbl = bucket_table_alloc(ht, size, GFP_KERNEL); + if (tbl == NULL) + return -ENOMEM; + + atomic_set(&ht->nelems, 0); + + RCU_INIT_POINTER(ht->tbl, tbl); + + INIT_WORK(&ht->run_work, rht_deferred_worker); + + return 0; +} + +/** + * rhashtable_free_and_destroy - free elements and destroy hash table + * @ht: the hash table to destroy + * @free_fn: callback to release resources of element + * @arg: pointer passed to free_fn + * + * Stops an eventual async resize. If defined, invokes free_fn for each + * element to releasal resources. Please note that RCU protected + * readers may still be accessing the elements. Releasing of resources + * must occur in a compatible manner. Then frees the bucket array. + * + * This function will eventually sleep to wait for an async resize + * to complete. The caller is responsible that no further write operations + * occurs in parallel. + */ +void rhashtable_free_and_destroy(struct rhashtable *ht, + void (*free_fn)(void *ptr, void *arg), + void *arg) +{ + const struct bucket_table *tbl; + unsigned int i; + + cancel_work_sync(&ht->run_work); + + mutex_lock(&ht->mutex); + tbl = rht_dereference(ht->tbl, ht); + if (free_fn) { + for (i = 0; i < tbl->size; i++) { + struct rhash_head *pos, *next; + + for (pos = rht_dereference(tbl->buckets[i], ht), + next = !rht_is_a_nulls(pos) ? + rht_dereference(pos->next, ht) : NULL; + !rht_is_a_nulls(pos); + pos = next, + next = !rht_is_a_nulls(pos) ? + rht_dereference(pos->next, ht) : NULL) + free_fn(rht_obj(ht, pos), arg); + } + } + + bucket_table_free(tbl); + mutex_unlock(&ht->mutex); +} + +void rhashtable_destroy(struct rhashtable *ht) +{ + return rhashtable_free_and_destroy(ht, NULL, NULL); +} + diff --git a/os_dep/linux/rhashtable.h b/os_dep/linux/rhashtable.h index a6db325..b47107f 100644 --- a/os_dep/linux/rhashtable.h +++ b/os_dep/linux/rhashtable.h @@ -1,827 +1,827 @@ -/* - * Resizable, Scalable, Concurrent Hash Table - * - * Copyright (c) 2015 Herbert Xu - * Copyright (c) 2014-2015 Thomas Graf - * Copyright (c) 2008-2014 Patrick McHardy - * - * Code partially derived from nft_hash - * Rewritten with rehash code from br_multicast plus single list - * pointer as suggested by Josh Triplett - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _LINUX_RHASHTABLE_H -#define _LINUX_RHASHTABLE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The end of the chain is marked with a special nulls marks which has - * the following format: - * - * +-------+-----------------------------------------------------+-+ - * | Base | Hash |1| - * +-------+-----------------------------------------------------+-+ - * - * Base (4 bits) : Reserved to distinguish between multiple tables. - * Specified via &struct rhashtable_params.nulls_base. - * Hash (27 bits): Full hash (unmasked) of first element added to bucket - * 1 (1 bit) : Nulls marker (always set) - * - * The remaining bits of the next pointer remain unused for now. - */ -#define RHT_BASE_BITS 4 -#define RHT_HASH_BITS 27 -#define RHT_BASE_SHIFT RHT_HASH_BITS - -/* Base bits plus 1 bit for nulls marker */ -#define RHT_HASH_RESERVED_SPACE (RHT_BASE_BITS + 1) - -struct rhash_head { - struct rhash_head __rcu *next; -}; - -/** - * struct bucket_table - Table of hash buckets - * @size: Number of hash buckets - * @rehash: Current bucket being rehashed - * @hash_rnd: Random seed to fold into hash - * @locks_mask: Mask to apply before accessing locks[] - * @locks: Array of spinlocks protecting individual buckets - * @walkers: List of active walkers - * @rcu: RCU structure for freeing the table - * @future_tbl: Table under construction during rehashing - * @buckets: size * hash buckets - */ -struct bucket_table { - unsigned int size; - unsigned int rehash; - u32 hash_rnd; - unsigned int locks_mask; - spinlock_t *locks; - struct list_head walkers; - struct rcu_head rcu; - - struct bucket_table __rcu *future_tbl; - - struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp; -}; - -/** - * struct rhashtable_compare_arg - Key for the function rhashtable_compare - * @ht: Hash table - * @key: Key to compare against - */ -struct rhashtable_compare_arg { - struct rhashtable *ht; - const void *key; -}; - -typedef u32 (*rht_hashfn_t)(const void *data, u32 len, u32 seed); -typedef u32 (*rht_obj_hashfn_t)(const void *data, u32 len, u32 seed); -typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg, - const void *obj); - -struct rhashtable; - -/** - * struct rhashtable_params - Hash table construction parameters - * @nelem_hint: Hint on number of elements, should be 75% of desired size - * @key_len: Length of key - * @key_offset: Offset of key in struct to be hashed - * @head_offset: Offset of rhash_head in struct to be hashed - * @insecure_max_entries: Maximum number of entries (may be exceeded) - * @max_size: Maximum size while expanding - * @min_size: Minimum size while shrinking - * @nulls_base: Base value to generate nulls marker - * @insecure_elasticity: Set to true to disable chain length checks - * @automatic_shrinking: Enable automatic shrinking of tables - * @locks_mul: Number of bucket locks to allocate per cpu (default: 128) - * @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash) - * @obj_hashfn: Function to hash object - * @obj_cmpfn: Function to compare key with object - */ -struct rhashtable_params { - size_t nelem_hint; - size_t key_len; - size_t key_offset; - size_t head_offset; - unsigned int insecure_max_entries; - unsigned int max_size; - unsigned int min_size; - u32 nulls_base; - bool insecure_elasticity; - bool automatic_shrinking; - size_t locks_mul; - rht_hashfn_t hashfn; - rht_obj_hashfn_t obj_hashfn; - rht_obj_cmpfn_t obj_cmpfn; -}; - -/** - * struct rhashtable - Hash table handle - * @tbl: Bucket table - * @nelems: Number of elements in table - * @key_len: Key length for hashfn - * @elasticity: Maximum chain length before rehash - * @p: Configuration parameters - * @run_work: Deferred worker to expand/shrink asynchronously - * @mutex: Mutex to protect current/future table swapping - * @lock: Spin lock to protect walker list - */ -struct rhashtable { - struct bucket_table __rcu *tbl; - atomic_t nelems; - unsigned int key_len; - unsigned int elasticity; - struct rhashtable_params p; - struct work_struct run_work; - struct mutex mutex; - spinlock_t lock; -}; - -/** - * struct rhashtable_walker - Hash table walker - * @list: List entry on list of walkers - * @tbl: The table that we were walking over - */ -struct rhashtable_walker { - struct list_head list; - struct bucket_table *tbl; -}; - -/** - * struct rhashtable_iter - Hash table iterator, fits into netlink cb - * @ht: Table to iterate through - * @p: Current pointer - * @walker: Associated rhashtable walker - * @slot: Current slot - * @skip: Number of entries to skip in slot - */ -struct rhashtable_iter { - struct rhashtable *ht; - struct rhash_head *p; - struct rhashtable_walker *walker; - unsigned int slot; - unsigned int skip; -}; - -static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash) -{ - return NULLS_MARKER(ht->p.nulls_base + hash); -} - -#define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \ - ((ptr) = (typeof(ptr)) rht_marker(ht, hash)) - -static inline bool rht_is_a_nulls(const struct rhash_head *ptr) -{ - return ((unsigned long) ptr & 1); -} - -static inline unsigned long rht_get_nulls_value(const struct rhash_head *ptr) -{ - return ((unsigned long) ptr) >> 1; -} - -static inline void *rht_obj(const struct rhashtable *ht, - const struct rhash_head *he) -{ - return (char *)he - ht->p.head_offset; -} - -static inline unsigned int rht_bucket_index(const struct bucket_table *tbl, - unsigned int hash) -{ - return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1); -} - -static inline unsigned int rht_key_hashfn( - struct rhashtable *ht, const struct bucket_table *tbl, - const void *key, const struct rhashtable_params params) -{ - unsigned int hash; - - /* params must be equal to ht->p if it isn't constant. */ - if (!__builtin_constant_p(params.key_len)) - hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd); - else if (params.key_len) { - unsigned int key_len = params.key_len; - - if (params.hashfn) - hash = params.hashfn(key, key_len, tbl->hash_rnd); - else if (key_len & (sizeof(u32) - 1)) - hash = jhash(key, key_len, tbl->hash_rnd); - else - hash = jhash2(key, key_len / sizeof(u32), - tbl->hash_rnd); - } else { - unsigned int key_len = ht->p.key_len; - - if (params.hashfn) - hash = params.hashfn(key, key_len, tbl->hash_rnd); - else - hash = jhash(key, key_len, tbl->hash_rnd); - } - - return rht_bucket_index(tbl, hash); -} - -static inline unsigned int rht_head_hashfn( - struct rhashtable *ht, const struct bucket_table *tbl, - const struct rhash_head *he, const struct rhashtable_params params) -{ - const char *ptr = rht_obj(ht, he); - - return likely(params.obj_hashfn) ? - rht_bucket_index(tbl, params.obj_hashfn(ptr, params.key_len ?: - ht->p.key_len, - tbl->hash_rnd)) : - rht_key_hashfn(ht, tbl, ptr + params.key_offset, params); -} - -/** - * rht_grow_above_75 - returns true if nelems > 0.75 * table-size - * @ht: hash table - * @tbl: current table - */ -static inline bool rht_grow_above_75(const struct rhashtable *ht, - const struct bucket_table *tbl) -{ - /* Expand table when exceeding 75% load */ - return atomic_read(&ht->nelems) > (tbl->size / 4 * 3) && - (!ht->p.max_size || tbl->size < ht->p.max_size); -} - -/** - * rht_shrink_below_30 - returns true if nelems < 0.3 * table-size - * @ht: hash table - * @tbl: current table - */ -static inline bool rht_shrink_below_30(const struct rhashtable *ht, - const struct bucket_table *tbl) -{ - /* Shrink table beneath 30% load */ - return atomic_read(&ht->nelems) < (tbl->size * 3 / 10) && - tbl->size > ht->p.min_size; -} - -/** - * rht_grow_above_100 - returns true if nelems > table-size - * @ht: hash table - * @tbl: current table - */ -static inline bool rht_grow_above_100(const struct rhashtable *ht, - const struct bucket_table *tbl) -{ - return atomic_read(&ht->nelems) > tbl->size && - (!ht->p.max_size || tbl->size < ht->p.max_size); -} - -/** - * rht_grow_above_max - returns true if table is above maximum - * @ht: hash table - * @tbl: current table - */ -static inline bool rht_grow_above_max(const struct rhashtable *ht, - const struct bucket_table *tbl) -{ - return ht->p.insecure_max_entries && - atomic_read(&ht->nelems) >= ht->p.insecure_max_entries; -} - -/* The bucket lock is selected based on the hash and protects mutations - * on a group of hash buckets. - * - * A maximum of tbl->size/2 bucket locks is allocated. This ensures that - * a single lock always covers both buckets which may both contains - * entries which link to the same bucket of the old table during resizing. - * This allows to simplify the locking as locking the bucket in both - * tables during resize always guarantee protection. - * - * IMPORTANT: When holding the bucket lock of both the old and new table - * during expansions and shrinking, the old bucket lock must always be - * acquired first. - */ -static inline spinlock_t *rht_bucket_lock(const struct bucket_table *tbl, - unsigned int hash) -{ - return &tbl->locks[hash & tbl->locks_mask]; -} - -#ifdef CONFIG_PROVE_LOCKING -int lockdep_rht_mutex_is_held(struct rhashtable *ht); -int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash); -#else -static inline int lockdep_rht_mutex_is_held(struct rhashtable *ht) -{ - return 1; -} - -static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, - u32 hash) -{ - return 1; -} -#endif /* CONFIG_PROVE_LOCKING */ - -int rhashtable_init(struct rhashtable *ht, - const struct rhashtable_params *params); - -struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, - const void *key, - struct rhash_head *obj, - struct bucket_table *old_tbl); -int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl); - -int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter); -void rhashtable_walk_exit(struct rhashtable_iter *iter); -int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU); -void *rhashtable_walk_next(struct rhashtable_iter *iter); -void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU); - -void rhashtable_free_and_destroy(struct rhashtable *ht, - void (*free_fn)(void *ptr, void *arg), - void *arg); -void rhashtable_destroy(struct rhashtable *ht); - -#define rht_dereference(p, ht) \ - rcu_dereference_protected(p, lockdep_rht_mutex_is_held(ht)) - -#define rht_dereference_rcu(p, ht) \ - rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) - -#define rht_dereference_bucket(p, tbl, hash) \ - rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash)) - -#define rht_dereference_bucket_rcu(p, tbl, hash) \ - rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash)) - -#define rht_entry(tpos, pos, member) \ - ({ tpos = container_of(pos, typeof(*tpos), member); 1; }) - -/** - * rht_for_each_continue - continue iterating over hash chain - * @pos: the &struct rhash_head to use as a loop cursor. - * @head: the previous &struct rhash_head to continue from - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - */ -#define rht_for_each_continue(pos, head, tbl, hash) \ - for (pos = rht_dereference_bucket(head, tbl, hash); \ - !rht_is_a_nulls(pos); \ - pos = rht_dereference_bucket((pos)->next, tbl, hash)) - -/** - * rht_for_each - iterate over hash chain - * @pos: the &struct rhash_head to use as a loop cursor. - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - */ -#define rht_for_each(pos, tbl, hash) \ - rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash) - -/** - * rht_for_each_entry_continue - continue iterating over hash chain - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct rhash_head to use as a loop cursor. - * @head: the previous &struct rhash_head to continue from - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * @member: name of the &struct rhash_head within the hashable struct. - */ -#define rht_for_each_entry_continue(tpos, pos, head, tbl, hash, member) \ - for (pos = rht_dereference_bucket(head, tbl, hash); \ - (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ - pos = rht_dereference_bucket((pos)->next, tbl, hash)) - -/** - * rht_for_each_entry - iterate over hash chain of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct rhash_head to use as a loop cursor. - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * @member: name of the &struct rhash_head within the hashable struct. - */ -#define rht_for_each_entry(tpos, pos, tbl, hash, member) \ - rht_for_each_entry_continue(tpos, pos, (tbl)->buckets[hash], \ - tbl, hash, member) - -/** - * rht_for_each_entry_safe - safely iterate over hash chain of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct rhash_head to use as a loop cursor. - * @next: the &struct rhash_head to use as next in loop cursor. - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * @member: name of the &struct rhash_head within the hashable struct. - * - * This hash chain list-traversal primitive allows for the looped code to - * remove the loop cursor from the list. - */ -#define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member) \ - for (pos = rht_dereference_bucket((tbl)->buckets[hash], tbl, hash), \ - next = !rht_is_a_nulls(pos) ? \ - rht_dereference_bucket(pos->next, tbl, hash) : NULL; \ - (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ - pos = next, \ - next = !rht_is_a_nulls(pos) ? \ - rht_dereference_bucket(pos->next, tbl, hash) : NULL) - -/** - * rht_for_each_rcu_continue - continue iterating over rcu hash chain - * @pos: the &struct rhash_head to use as a loop cursor. - * @head: the previous &struct rhash_head to continue from - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * - * This hash chain list-traversal primitive may safely run concurrently with - * the _rcu mutation primitives such as rhashtable_insert() as long as the - * traversal is guarded by rcu_read_lock(). - */ -#define rht_for_each_rcu_continue(pos, head, tbl, hash) \ - for (({barrier(); }), \ - pos = rht_dereference_bucket_rcu(head, tbl, hash); \ - !rht_is_a_nulls(pos); \ - pos = rcu_dereference_raw(pos->next)) - -/** - * rht_for_each_rcu - iterate over rcu hash chain - * @pos: the &struct rhash_head to use as a loop cursor. - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * - * This hash chain list-traversal primitive may safely run concurrently with - * the _rcu mutation primitives such as rhashtable_insert() as long as the - * traversal is guarded by rcu_read_lock(). - */ -#define rht_for_each_rcu(pos, tbl, hash) \ - rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash) - -/** - * rht_for_each_entry_rcu_continue - continue iterating over rcu hash chain - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct rhash_head to use as a loop cursor. - * @head: the previous &struct rhash_head to continue from - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * @member: name of the &struct rhash_head within the hashable struct. - * - * This hash chain list-traversal primitive may safely run concurrently with - * the _rcu mutation primitives such as rhashtable_insert() as long as the - * traversal is guarded by rcu_read_lock(). - */ -#define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \ - for (({barrier(); }), \ - pos = rht_dereference_bucket_rcu(head, tbl, hash); \ - (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ - pos = rht_dereference_bucket_rcu(pos->next, tbl, hash)) - -/** - * rht_for_each_entry_rcu - iterate over rcu hash chain of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct rhash_head to use as a loop cursor. - * @tbl: the &struct bucket_table - * @hash: the hash value / bucket index - * @member: name of the &struct rhash_head within the hashable struct. - * - * This hash chain list-traversal primitive may safely run concurrently with - * the _rcu mutation primitives such as rhashtable_insert() as long as the - * traversal is guarded by rcu_read_lock(). - */ -#define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \ - rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\ - tbl, hash, member) - -static inline int rhashtable_compare(struct rhashtable_compare_arg *arg, - const void *obj) -{ - struct rhashtable *ht = arg->ht; - const char *ptr = obj; - - return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len); -} - -/** - * rhashtable_lookup_fast - search hash table, inlined version - * @ht: hash table - * @key: the pointer to the key - * @params: hash table parameters - * - * Computes the hash value for the key and traverses the bucket chain looking - * for a entry with an identical key. The first matching entry is returned. - * - * Returns the first entry on which the compare function returned true. - */ -static inline void *rhashtable_lookup_fast( - struct rhashtable *ht, const void *key, - const struct rhashtable_params params) -{ - struct rhashtable_compare_arg arg = { - .ht = ht, - .key = key, - }; - const struct bucket_table *tbl; - struct rhash_head *he; - unsigned int hash; - - rcu_read_lock(); - - tbl = rht_dereference_rcu(ht->tbl, ht); -restart: - hash = rht_key_hashfn(ht, tbl, key, params); - rht_for_each_rcu(he, tbl, hash) { - if (params.obj_cmpfn ? - params.obj_cmpfn(&arg, rht_obj(ht, he)) : - rhashtable_compare(&arg, rht_obj(ht, he))) - continue; - rcu_read_unlock(); - return rht_obj(ht, he); - } - - /* Ensure we see any new tables. */ - smp_rmb(); - - tbl = rht_dereference_rcu(tbl->future_tbl, ht); - if (unlikely(tbl)) - goto restart; - rcu_read_unlock(); - - return NULL; -} - -/* Internal function, please use rhashtable_insert_fast() instead */ -static inline int __rhashtable_insert_fast( - struct rhashtable *ht, const void *key, struct rhash_head *obj, - const struct rhashtable_params params) -{ - struct rhashtable_compare_arg arg = { - .ht = ht, - .key = key, - }; - struct bucket_table *tbl, *new_tbl; - struct rhash_head *head; - spinlock_t *lock; - unsigned int elasticity; - unsigned int hash; - int err; - -restart: - rcu_read_lock(); - - tbl = rht_dereference_rcu(ht->tbl, ht); - - /* All insertions must grab the oldest table containing - * the hashed bucket that is yet to be rehashed. - */ - for (;;) { - hash = rht_head_hashfn(ht, tbl, obj, params); - lock = rht_bucket_lock(tbl, hash); - spin_lock_bh(lock); - - if (tbl->rehash <= hash) - break; - - spin_unlock_bh(lock); - tbl = rht_dereference_rcu(tbl->future_tbl, ht); - } - - new_tbl = rht_dereference_rcu(tbl->future_tbl, ht); - if (unlikely(new_tbl)) { - tbl = rhashtable_insert_slow(ht, key, obj, new_tbl); - if (!IS_ERR_OR_NULL(tbl)) - goto slow_path; - - err = PTR_ERR(tbl); - goto out; - } - - err = -E2BIG; - if (unlikely(rht_grow_above_max(ht, tbl))) - goto out; - - if (unlikely(rht_grow_above_100(ht, tbl))) { -slow_path: - spin_unlock_bh(lock); - err = rhashtable_insert_rehash(ht, tbl); - rcu_read_unlock(); - if (err) - return err; - - goto restart; - } - - err = -EEXIST; - elasticity = ht->elasticity; - rht_for_each(head, tbl, hash) { - if (key && - unlikely(!(params.obj_cmpfn ? - params.obj_cmpfn(&arg, rht_obj(ht, head)) : - rhashtable_compare(&arg, rht_obj(ht, head))))) - goto out; - if (!--elasticity) - goto slow_path; - } - - err = 0; - - head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); - - RCU_INIT_POINTER(obj->next, head); - - rcu_assign_pointer(tbl->buckets[hash], obj); - - atomic_inc(&ht->nelems); - if (rht_grow_above_75(ht, tbl)) - schedule_work(&ht->run_work); - -out: - spin_unlock_bh(lock); - rcu_read_unlock(); - - return err; -} - -/** - * rhashtable_insert_fast - insert object into hash table - * @ht: hash table - * @obj: pointer to hash head inside object - * @params: hash table parameters - * - * Will take a per bucket spinlock to protect against mutual mutations - * on the same bucket. Multiple insertions may occur in parallel unless - * they map to the same bucket lock. - * - * It is safe to call this function from atomic context. - * - * Will trigger an automatic deferred table resizing if the size grows - * beyond the watermark indicated by grow_decision() which can be passed - * to rhashtable_init(). - */ -static inline int rhashtable_insert_fast( - struct rhashtable *ht, struct rhash_head *obj, - const struct rhashtable_params params) -{ - return __rhashtable_insert_fast(ht, NULL, obj, params); -} - -/** - * rhashtable_lookup_insert_fast - lookup and insert object into hash table - * @ht: hash table - * @obj: pointer to hash head inside object - * @params: hash table parameters - * - * Locks down the bucket chain in both the old and new table if a resize - * is in progress to ensure that writers can't remove from the old table - * and can't insert to the new table during the atomic operation of search - * and insertion. Searches for duplicates in both the old and new table if - * a resize is in progress. - * - * This lookup function may only be used for fixed key hash table (key_len - * parameter set). It will BUG() if used inappropriately. - * - * It is safe to call this function from atomic context. - * - * Will trigger an automatic deferred table resizing if the size grows - * beyond the watermark indicated by grow_decision() which can be passed - * to rhashtable_init(). - */ -static inline int rhashtable_lookup_insert_fast( - struct rhashtable *ht, struct rhash_head *obj, - const struct rhashtable_params params) -{ - const char *key = rht_obj(ht, obj); - - BUG_ON(ht->p.obj_hashfn); - - return __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj, - params); -} - -/** - * rhashtable_lookup_insert_key - search and insert object to hash table - * with explicit key - * @ht: hash table - * @key: key - * @obj: pointer to hash head inside object - * @params: hash table parameters - * - * Locks down the bucket chain in both the old and new table if a resize - * is in progress to ensure that writers can't remove from the old table - * and can't insert to the new table during the atomic operation of search - * and insertion. Searches for duplicates in both the old and new table if - * a resize is in progress. - * - * Lookups may occur in parallel with hashtable mutations and resizing. - * - * Will trigger an automatic deferred table resizing if the size grows - * beyond the watermark indicated by grow_decision() which can be passed - * to rhashtable_init(). - * - * Returns zero on success. - */ -static inline int rhashtable_lookup_insert_key( - struct rhashtable *ht, const void *key, struct rhash_head *obj, - const struct rhashtable_params params) -{ - BUG_ON(!ht->p.obj_hashfn || !key); - - return __rhashtable_insert_fast(ht, key, obj, params); -} - -/* Internal function, please use rhashtable_remove_fast() instead */ -static inline int __rhashtable_remove_fast( - struct rhashtable *ht, struct bucket_table *tbl, - struct rhash_head *obj, const struct rhashtable_params params) -{ - struct rhash_head __rcu **pprev; - struct rhash_head *he; - spinlock_t * lock; - unsigned int hash; - int err = -ENOENT; - - hash = rht_head_hashfn(ht, tbl, obj, params); - lock = rht_bucket_lock(tbl, hash); - - spin_lock_bh(lock); - - pprev = &tbl->buckets[hash]; - rht_for_each(he, tbl, hash) { - if (he != obj) { - pprev = &he->next; - continue; - } - - rcu_assign_pointer(*pprev, obj->next); - err = 0; - break; - } - - spin_unlock_bh(lock); - - return err; -} - -/** - * rhashtable_remove_fast - remove object from hash table - * @ht: hash table - * @obj: pointer to hash head inside object - * @params: hash table parameters - * - * Since the hash chain is single linked, the removal operation needs to - * walk the bucket chain upon removal. The removal operation is thus - * considerable slow if the hash table is not correctly sized. - * - * Will automatically shrink the table via rhashtable_expand() if the - * shrink_decision function specified at rhashtable_init() returns true. - * - * Returns zero on success, -ENOENT if the entry could not be found. - */ -static inline int rhashtable_remove_fast( - struct rhashtable *ht, struct rhash_head *obj, - const struct rhashtable_params params) -{ - struct bucket_table *tbl; - int err; - - rcu_read_lock(); - - tbl = rht_dereference_rcu(ht->tbl, ht); - - /* Because we have already taken (and released) the bucket - * lock in old_tbl, if we find that future_tbl is not yet - * visible then that guarantees the entry to still be in - * the old tbl if it exists. - */ - while ((err = __rhashtable_remove_fast(ht, tbl, obj, params)) && - (tbl = rht_dereference_rcu(tbl->future_tbl, ht))) - ; - - if (err) - goto out; - - atomic_dec(&ht->nelems); - if (unlikely(ht->p.automatic_shrinking && - rht_shrink_below_30(ht, tbl))) - schedule_work(&ht->run_work); - -out: - rcu_read_unlock(); - - return err; -} - -#endif /* _LINUX_RHASHTABLE_H */ - +/* + * Resizable, Scalable, Concurrent Hash Table + * + * Copyright (c) 2015 Herbert Xu + * Copyright (c) 2014-2015 Thomas Graf + * Copyright (c) 2008-2014 Patrick McHardy + * + * Code partially derived from nft_hash + * Rewritten with rehash code from br_multicast plus single list + * pointer as suggested by Josh Triplett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _LINUX_RHASHTABLE_H +#define _LINUX_RHASHTABLE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The end of the chain is marked with a special nulls marks which has + * the following format: + * + * +-------+-----------------------------------------------------+-+ + * | Base | Hash |1| + * +-------+-----------------------------------------------------+-+ + * + * Base (4 bits) : Reserved to distinguish between multiple tables. + * Specified via &struct rhashtable_params.nulls_base. + * Hash (27 bits): Full hash (unmasked) of first element added to bucket + * 1 (1 bit) : Nulls marker (always set) + * + * The remaining bits of the next pointer remain unused for now. + */ +#define RHT_BASE_BITS 4 +#define RHT_HASH_BITS 27 +#define RHT_BASE_SHIFT RHT_HASH_BITS + +/* Base bits plus 1 bit for nulls marker */ +#define RHT_HASH_RESERVED_SPACE (RHT_BASE_BITS + 1) + +struct rhash_head { + struct rhash_head __rcu *next; +}; + +/** + * struct bucket_table - Table of hash buckets + * @size: Number of hash buckets + * @rehash: Current bucket being rehashed + * @hash_rnd: Random seed to fold into hash + * @locks_mask: Mask to apply before accessing locks[] + * @locks: Array of spinlocks protecting individual buckets + * @walkers: List of active walkers + * @rcu: RCU structure for freeing the table + * @future_tbl: Table under construction during rehashing + * @buckets: size * hash buckets + */ +struct bucket_table { + unsigned int size; + unsigned int rehash; + u32 hash_rnd; + unsigned int locks_mask; + spinlock_t *locks; + struct list_head walkers; + struct rcu_head rcu; + + struct bucket_table __rcu *future_tbl; + + struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp; +}; + +/** + * struct rhashtable_compare_arg - Key for the function rhashtable_compare + * @ht: Hash table + * @key: Key to compare against + */ +struct rhashtable_compare_arg { + struct rhashtable *ht; + const void *key; +}; + +typedef u32 (*rht_hashfn_t)(const void *data, u32 len, u32 seed); +typedef u32 (*rht_obj_hashfn_t)(const void *data, u32 len, u32 seed); +typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg, + const void *obj); + +struct rhashtable; + +/** + * struct rhashtable_params - Hash table construction parameters + * @nelem_hint: Hint on number of elements, should be 75% of desired size + * @key_len: Length of key + * @key_offset: Offset of key in struct to be hashed + * @head_offset: Offset of rhash_head in struct to be hashed + * @insecure_max_entries: Maximum number of entries (may be exceeded) + * @max_size: Maximum size while expanding + * @min_size: Minimum size while shrinking + * @nulls_base: Base value to generate nulls marker + * @insecure_elasticity: Set to true to disable chain length checks + * @automatic_shrinking: Enable automatic shrinking of tables + * @locks_mul: Number of bucket locks to allocate per cpu (default: 128) + * @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash) + * @obj_hashfn: Function to hash object + * @obj_cmpfn: Function to compare key with object + */ +struct rhashtable_params { + size_t nelem_hint; + size_t key_len; + size_t key_offset; + size_t head_offset; + unsigned int insecure_max_entries; + unsigned int max_size; + unsigned int min_size; + u32 nulls_base; + bool insecure_elasticity; + bool automatic_shrinking; + size_t locks_mul; + rht_hashfn_t hashfn; + rht_obj_hashfn_t obj_hashfn; + rht_obj_cmpfn_t obj_cmpfn; +}; + +/** + * struct rhashtable - Hash table handle + * @tbl: Bucket table + * @nelems: Number of elements in table + * @key_len: Key length for hashfn + * @elasticity: Maximum chain length before rehash + * @p: Configuration parameters + * @run_work: Deferred worker to expand/shrink asynchronously + * @mutex: Mutex to protect current/future table swapping + * @lock: Spin lock to protect walker list + */ +struct rhashtable { + struct bucket_table __rcu *tbl; + atomic_t nelems; + unsigned int key_len; + unsigned int elasticity; + struct rhashtable_params p; + struct work_struct run_work; + struct mutex mutex; + spinlock_t lock; +}; + +/** + * struct rhashtable_walker - Hash table walker + * @list: List entry on list of walkers + * @tbl: The table that we were walking over + */ +struct rhashtable_walker { + struct list_head list; + struct bucket_table *tbl; +}; + +/** + * struct rhashtable_iter - Hash table iterator, fits into netlink cb + * @ht: Table to iterate through + * @p: Current pointer + * @walker: Associated rhashtable walker + * @slot: Current slot + * @skip: Number of entries to skip in slot + */ +struct rhashtable_iter { + struct rhashtable *ht; + struct rhash_head *p; + struct rhashtable_walker *walker; + unsigned int slot; + unsigned int skip; +}; + +static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash) +{ + return NULLS_MARKER(ht->p.nulls_base + hash); +} + +#define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \ + ((ptr) = (typeof(ptr)) rht_marker(ht, hash)) + +static inline bool rht_is_a_nulls(const struct rhash_head *ptr) +{ + return ((unsigned long) ptr & 1); +} + +static inline unsigned long rht_get_nulls_value(const struct rhash_head *ptr) +{ + return ((unsigned long) ptr) >> 1; +} + +static inline void *rht_obj(const struct rhashtable *ht, + const struct rhash_head *he) +{ + return (char *)he - ht->p.head_offset; +} + +static inline unsigned int rht_bucket_index(const struct bucket_table *tbl, + unsigned int hash) +{ + return (hash >> RHT_HASH_RESERVED_SPACE) & (tbl->size - 1); +} + +static inline unsigned int rht_key_hashfn( + struct rhashtable *ht, const struct bucket_table *tbl, + const void *key, const struct rhashtable_params params) +{ + unsigned int hash; + + /* params must be equal to ht->p if it isn't constant. */ + if (!__builtin_constant_p(params.key_len)) + hash = ht->p.hashfn(key, ht->key_len, tbl->hash_rnd); + else if (params.key_len) { + unsigned int key_len = params.key_len; + + if (params.hashfn) + hash = params.hashfn(key, key_len, tbl->hash_rnd); + else if (key_len & (sizeof(u32) - 1)) + hash = jhash(key, key_len, tbl->hash_rnd); + else + hash = jhash2(key, key_len / sizeof(u32), + tbl->hash_rnd); + } else { + unsigned int key_len = ht->p.key_len; + + if (params.hashfn) + hash = params.hashfn(key, key_len, tbl->hash_rnd); + else + hash = jhash(key, key_len, tbl->hash_rnd); + } + + return rht_bucket_index(tbl, hash); +} + +static inline unsigned int rht_head_hashfn( + struct rhashtable *ht, const struct bucket_table *tbl, + const struct rhash_head *he, const struct rhashtable_params params) +{ + const char *ptr = rht_obj(ht, he); + + return likely(params.obj_hashfn) ? + rht_bucket_index(tbl, params.obj_hashfn(ptr, params.key_len ?: + ht->p.key_len, + tbl->hash_rnd)) : + rht_key_hashfn(ht, tbl, ptr + params.key_offset, params); +} + +/** + * rht_grow_above_75 - returns true if nelems > 0.75 * table-size + * @ht: hash table + * @tbl: current table + */ +static inline bool rht_grow_above_75(const struct rhashtable *ht, + const struct bucket_table *tbl) +{ + /* Expand table when exceeding 75% load */ + return atomic_read(&ht->nelems) > (tbl->size / 4 * 3) && + (!ht->p.max_size || tbl->size < ht->p.max_size); +} + +/** + * rht_shrink_below_30 - returns true if nelems < 0.3 * table-size + * @ht: hash table + * @tbl: current table + */ +static inline bool rht_shrink_below_30(const struct rhashtable *ht, + const struct bucket_table *tbl) +{ + /* Shrink table beneath 30% load */ + return atomic_read(&ht->nelems) < (tbl->size * 3 / 10) && + tbl->size > ht->p.min_size; +} + +/** + * rht_grow_above_100 - returns true if nelems > table-size + * @ht: hash table + * @tbl: current table + */ +static inline bool rht_grow_above_100(const struct rhashtable *ht, + const struct bucket_table *tbl) +{ + return atomic_read(&ht->nelems) > tbl->size && + (!ht->p.max_size || tbl->size < ht->p.max_size); +} + +/** + * rht_grow_above_max - returns true if table is above maximum + * @ht: hash table + * @tbl: current table + */ +static inline bool rht_grow_above_max(const struct rhashtable *ht, + const struct bucket_table *tbl) +{ + return ht->p.insecure_max_entries && + atomic_read(&ht->nelems) >= ht->p.insecure_max_entries; +} + +/* The bucket lock is selected based on the hash and protects mutations + * on a group of hash buckets. + * + * A maximum of tbl->size/2 bucket locks is allocated. This ensures that + * a single lock always covers both buckets which may both contains + * entries which link to the same bucket of the old table during resizing. + * This allows to simplify the locking as locking the bucket in both + * tables during resize always guarantee protection. + * + * IMPORTANT: When holding the bucket lock of both the old and new table + * during expansions and shrinking, the old bucket lock must always be + * acquired first. + */ +static inline spinlock_t *rht_bucket_lock(const struct bucket_table *tbl, + unsigned int hash) +{ + return &tbl->locks[hash & tbl->locks_mask]; +} + +#ifdef CONFIG_PROVE_LOCKING +int lockdep_rht_mutex_is_held(struct rhashtable *ht); +int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash); +#else +static inline int lockdep_rht_mutex_is_held(struct rhashtable *ht) +{ + return 1; +} + +static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, + u32 hash) +{ + return 1; +} +#endif /* CONFIG_PROVE_LOCKING */ + +int rhashtable_init(struct rhashtable *ht, + const struct rhashtable_params *params); + +struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, + const void *key, + struct rhash_head *obj, + struct bucket_table *old_tbl); +int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl); + +int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter); +void rhashtable_walk_exit(struct rhashtable_iter *iter); +int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU); +void *rhashtable_walk_next(struct rhashtable_iter *iter); +void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU); + +void rhashtable_free_and_destroy(struct rhashtable *ht, + void (*free_fn)(void *ptr, void *arg), + void *arg); +void rhashtable_destroy(struct rhashtable *ht); + +#define rht_dereference(p, ht) \ + rcu_dereference_protected(p, lockdep_rht_mutex_is_held(ht)) + +#define rht_dereference_rcu(p, ht) \ + rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) + +#define rht_dereference_bucket(p, tbl, hash) \ + rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash)) + +#define rht_dereference_bucket_rcu(p, tbl, hash) \ + rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash)) + +#define rht_entry(tpos, pos, member) \ + ({ tpos = container_of(pos, typeof(*tpos), member); 1; }) + +/** + * rht_for_each_continue - continue iterating over hash chain + * @pos: the &struct rhash_head to use as a loop cursor. + * @head: the previous &struct rhash_head to continue from + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + */ +#define rht_for_each_continue(pos, head, tbl, hash) \ + for (pos = rht_dereference_bucket(head, tbl, hash); \ + !rht_is_a_nulls(pos); \ + pos = rht_dereference_bucket((pos)->next, tbl, hash)) + +/** + * rht_for_each - iterate over hash chain + * @pos: the &struct rhash_head to use as a loop cursor. + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + */ +#define rht_for_each(pos, tbl, hash) \ + rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash) + +/** + * rht_for_each_entry_continue - continue iterating over hash chain + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct rhash_head to use as a loop cursor. + * @head: the previous &struct rhash_head to continue from + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * @member: name of the &struct rhash_head within the hashable struct. + */ +#define rht_for_each_entry_continue(tpos, pos, head, tbl, hash, member) \ + for (pos = rht_dereference_bucket(head, tbl, hash); \ + (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ + pos = rht_dereference_bucket((pos)->next, tbl, hash)) + +/** + * rht_for_each_entry - iterate over hash chain of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct rhash_head to use as a loop cursor. + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * @member: name of the &struct rhash_head within the hashable struct. + */ +#define rht_for_each_entry(tpos, pos, tbl, hash, member) \ + rht_for_each_entry_continue(tpos, pos, (tbl)->buckets[hash], \ + tbl, hash, member) + +/** + * rht_for_each_entry_safe - safely iterate over hash chain of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct rhash_head to use as a loop cursor. + * @next: the &struct rhash_head to use as next in loop cursor. + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * @member: name of the &struct rhash_head within the hashable struct. + * + * This hash chain list-traversal primitive allows for the looped code to + * remove the loop cursor from the list. + */ +#define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member) \ + for (pos = rht_dereference_bucket((tbl)->buckets[hash], tbl, hash), \ + next = !rht_is_a_nulls(pos) ? \ + rht_dereference_bucket(pos->next, tbl, hash) : NULL; \ + (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ + pos = next, \ + next = !rht_is_a_nulls(pos) ? \ + rht_dereference_bucket(pos->next, tbl, hash) : NULL) + +/** + * rht_for_each_rcu_continue - continue iterating over rcu hash chain + * @pos: the &struct rhash_head to use as a loop cursor. + * @head: the previous &struct rhash_head to continue from + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * + * This hash chain list-traversal primitive may safely run concurrently with + * the _rcu mutation primitives such as rhashtable_insert() as long as the + * traversal is guarded by rcu_read_lock(). + */ +#define rht_for_each_rcu_continue(pos, head, tbl, hash) \ + for (({barrier(); }), \ + pos = rht_dereference_bucket_rcu(head, tbl, hash); \ + !rht_is_a_nulls(pos); \ + pos = rcu_dereference_raw(pos->next)) + +/** + * rht_for_each_rcu - iterate over rcu hash chain + * @pos: the &struct rhash_head to use as a loop cursor. + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * + * This hash chain list-traversal primitive may safely run concurrently with + * the _rcu mutation primitives such as rhashtable_insert() as long as the + * traversal is guarded by rcu_read_lock(). + */ +#define rht_for_each_rcu(pos, tbl, hash) \ + rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash) + +/** + * rht_for_each_entry_rcu_continue - continue iterating over rcu hash chain + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct rhash_head to use as a loop cursor. + * @head: the previous &struct rhash_head to continue from + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * @member: name of the &struct rhash_head within the hashable struct. + * + * This hash chain list-traversal primitive may safely run concurrently with + * the _rcu mutation primitives such as rhashtable_insert() as long as the + * traversal is guarded by rcu_read_lock(). + */ +#define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \ + for (({barrier(); }), \ + pos = rht_dereference_bucket_rcu(head, tbl, hash); \ + (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \ + pos = rht_dereference_bucket_rcu(pos->next, tbl, hash)) + +/** + * rht_for_each_entry_rcu - iterate over rcu hash chain of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct rhash_head to use as a loop cursor. + * @tbl: the &struct bucket_table + * @hash: the hash value / bucket index + * @member: name of the &struct rhash_head within the hashable struct. + * + * This hash chain list-traversal primitive may safely run concurrently with + * the _rcu mutation primitives such as rhashtable_insert() as long as the + * traversal is guarded by rcu_read_lock(). + */ +#define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \ + rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\ + tbl, hash, member) + +static inline int rhashtable_compare(struct rhashtable_compare_arg *arg, + const void *obj) +{ + struct rhashtable *ht = arg->ht; + const char *ptr = obj; + + return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len); +} + +/** + * rhashtable_lookup_fast - search hash table, inlined version + * @ht: hash table + * @key: the pointer to the key + * @params: hash table parameters + * + * Computes the hash value for the key and traverses the bucket chain looking + * for a entry with an identical key. The first matching entry is returned. + * + * Returns the first entry on which the compare function returned true. + */ +static inline void *rhashtable_lookup_fast( + struct rhashtable *ht, const void *key, + const struct rhashtable_params params) +{ + struct rhashtable_compare_arg arg = { + .ht = ht, + .key = key, + }; + const struct bucket_table *tbl; + struct rhash_head *he; + unsigned int hash; + + rcu_read_lock(); + + tbl = rht_dereference_rcu(ht->tbl, ht); +restart: + hash = rht_key_hashfn(ht, tbl, key, params); + rht_for_each_rcu(he, tbl, hash) { + if (params.obj_cmpfn ? + params.obj_cmpfn(&arg, rht_obj(ht, he)) : + rhashtable_compare(&arg, rht_obj(ht, he))) + continue; + rcu_read_unlock(); + return rht_obj(ht, he); + } + + /* Ensure we see any new tables. */ + smp_rmb(); + + tbl = rht_dereference_rcu(tbl->future_tbl, ht); + if (unlikely(tbl)) + goto restart; + rcu_read_unlock(); + + return NULL; +} + +/* Internal function, please use rhashtable_insert_fast() instead */ +static inline int __rhashtable_insert_fast( + struct rhashtable *ht, const void *key, struct rhash_head *obj, + const struct rhashtable_params params) +{ + struct rhashtable_compare_arg arg = { + .ht = ht, + .key = key, + }; + struct bucket_table *tbl, *new_tbl; + struct rhash_head *head; + spinlock_t *lock; + unsigned int elasticity; + unsigned int hash; + int err; + +restart: + rcu_read_lock(); + + tbl = rht_dereference_rcu(ht->tbl, ht); + + /* All insertions must grab the oldest table containing + * the hashed bucket that is yet to be rehashed. + */ + for (;;) { + hash = rht_head_hashfn(ht, tbl, obj, params); + lock = rht_bucket_lock(tbl, hash); + spin_lock_bh(lock); + + if (tbl->rehash <= hash) + break; + + spin_unlock_bh(lock); + tbl = rht_dereference_rcu(tbl->future_tbl, ht); + } + + new_tbl = rht_dereference_rcu(tbl->future_tbl, ht); + if (unlikely(new_tbl)) { + tbl = rhashtable_insert_slow(ht, key, obj, new_tbl); + if (!IS_ERR_OR_NULL(tbl)) + goto slow_path; + + err = PTR_ERR(tbl); + goto out; + } + + err = -E2BIG; + if (unlikely(rht_grow_above_max(ht, tbl))) + goto out; + + if (unlikely(rht_grow_above_100(ht, tbl))) { +slow_path: + spin_unlock_bh(lock); + err = rhashtable_insert_rehash(ht, tbl); + rcu_read_unlock(); + if (err) + return err; + + goto restart; + } + + err = -EEXIST; + elasticity = ht->elasticity; + rht_for_each(head, tbl, hash) { + if (key && + unlikely(!(params.obj_cmpfn ? + params.obj_cmpfn(&arg, rht_obj(ht, head)) : + rhashtable_compare(&arg, rht_obj(ht, head))))) + goto out; + if (!--elasticity) + goto slow_path; + } + + err = 0; + + head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash); + + RCU_INIT_POINTER(obj->next, head); + + rcu_assign_pointer(tbl->buckets[hash], obj); + + atomic_inc(&ht->nelems); + if (rht_grow_above_75(ht, tbl)) + schedule_work(&ht->run_work); + +out: + spin_unlock_bh(lock); + rcu_read_unlock(); + + return err; +} + +/** + * rhashtable_insert_fast - insert object into hash table + * @ht: hash table + * @obj: pointer to hash head inside object + * @params: hash table parameters + * + * Will take a per bucket spinlock to protect against mutual mutations + * on the same bucket. Multiple insertions may occur in parallel unless + * they map to the same bucket lock. + * + * It is safe to call this function from atomic context. + * + * Will trigger an automatic deferred table resizing if the size grows + * beyond the watermark indicated by grow_decision() which can be passed + * to rhashtable_init(). + */ +static inline int rhashtable_insert_fast( + struct rhashtable *ht, struct rhash_head *obj, + const struct rhashtable_params params) +{ + return __rhashtable_insert_fast(ht, NULL, obj, params); +} + +/** + * rhashtable_lookup_insert_fast - lookup and insert object into hash table + * @ht: hash table + * @obj: pointer to hash head inside object + * @params: hash table parameters + * + * Locks down the bucket chain in both the old and new table if a resize + * is in progress to ensure that writers can't remove from the old table + * and can't insert to the new table during the atomic operation of search + * and insertion. Searches for duplicates in both the old and new table if + * a resize is in progress. + * + * This lookup function may only be used for fixed key hash table (key_len + * parameter set). It will BUG() if used inappropriately. + * + * It is safe to call this function from atomic context. + * + * Will trigger an automatic deferred table resizing if the size grows + * beyond the watermark indicated by grow_decision() which can be passed + * to rhashtable_init(). + */ +static inline int rhashtable_lookup_insert_fast( + struct rhashtable *ht, struct rhash_head *obj, + const struct rhashtable_params params) +{ + const char *key = rht_obj(ht, obj); + + BUG_ON(ht->p.obj_hashfn); + + return __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj, + params); +} + +/** + * rhashtable_lookup_insert_key - search and insert object to hash table + * with explicit key + * @ht: hash table + * @key: key + * @obj: pointer to hash head inside object + * @params: hash table parameters + * + * Locks down the bucket chain in both the old and new table if a resize + * is in progress to ensure that writers can't remove from the old table + * and can't insert to the new table during the atomic operation of search + * and insertion. Searches for duplicates in both the old and new table if + * a resize is in progress. + * + * Lookups may occur in parallel with hashtable mutations and resizing. + * + * Will trigger an automatic deferred table resizing if the size grows + * beyond the watermark indicated by grow_decision() which can be passed + * to rhashtable_init(). + * + * Returns zero on success. + */ +static inline int rhashtable_lookup_insert_key( + struct rhashtable *ht, const void *key, struct rhash_head *obj, + const struct rhashtable_params params) +{ + BUG_ON(!ht->p.obj_hashfn || !key); + + return __rhashtable_insert_fast(ht, key, obj, params); +} + +/* Internal function, please use rhashtable_remove_fast() instead */ +static inline int __rhashtable_remove_fast( + struct rhashtable *ht, struct bucket_table *tbl, + struct rhash_head *obj, const struct rhashtable_params params) +{ + struct rhash_head __rcu **pprev; + struct rhash_head *he; + spinlock_t * lock; + unsigned int hash; + int err = -ENOENT; + + hash = rht_head_hashfn(ht, tbl, obj, params); + lock = rht_bucket_lock(tbl, hash); + + spin_lock_bh(lock); + + pprev = &tbl->buckets[hash]; + rht_for_each(he, tbl, hash) { + if (he != obj) { + pprev = &he->next; + continue; + } + + rcu_assign_pointer(*pprev, obj->next); + err = 0; + break; + } + + spin_unlock_bh(lock); + + return err; +} + +/** + * rhashtable_remove_fast - remove object from hash table + * @ht: hash table + * @obj: pointer to hash head inside object + * @params: hash table parameters + * + * Since the hash chain is single linked, the removal operation needs to + * walk the bucket chain upon removal. The removal operation is thus + * considerable slow if the hash table is not correctly sized. + * + * Will automatically shrink the table via rhashtable_expand() if the + * shrink_decision function specified at rhashtable_init() returns true. + * + * Returns zero on success, -ENOENT if the entry could not be found. + */ +static inline int rhashtable_remove_fast( + struct rhashtable *ht, struct rhash_head *obj, + const struct rhashtable_params params) +{ + struct bucket_table *tbl; + int err; + + rcu_read_lock(); + + tbl = rht_dereference_rcu(ht->tbl, ht); + + /* Because we have already taken (and released) the bucket + * lock in old_tbl, if we find that future_tbl is not yet + * visible then that guarantees the entry to still be in + * the old tbl if it exists. + */ + while ((err = __rhashtable_remove_fast(ht, tbl, obj, params)) && + (tbl = rht_dereference_rcu(tbl->future_tbl, ht))) + ; + + if (err) + goto out; + + atomic_dec(&ht->nelems); + if (unlikely(ht->p.automatic_shrinking && + rht_shrink_below_30(ht, tbl))) + schedule_work(&ht->run_work); + +out: + rcu_read_unlock(); + + return err; +} + +#endif /* _LINUX_RHASHTABLE_H */ +