1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * Copyright(c) 2020 Realtek Corporation.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
6*4882a593Smuzhiyun * under the terms of version 2 of the GNU General Public License as
7*4882a593Smuzhiyun * published by the Free Software Foundation.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but WITHOUT
10*4882a593Smuzhiyun * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12*4882a593Smuzhiyun * more details.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun *****************************************************************************/
15*4882a593Smuzhiyun #include "phl_headers.h"
16*4882a593Smuzhiyun #include "phl_chnlplan.h"
17*4882a593Smuzhiyun #include "phl_country.h"
18*4882a593Smuzhiyun #include "phl_regulation_6g.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun extern const struct regulatory_domain_mapping rdmap[MAX_RD_MAP_NUM];
21*4882a593Smuzhiyun extern const struct chdef_2ghz chdef2g[MAX_CHDEF_2GHZ];
22*4882a593Smuzhiyun extern const struct chdef_5ghz chdef5g[MAX_CHDEF_5GHZ];
23*4882a593Smuzhiyun extern const struct country_domain_mapping cdmap[MAX_COUNTRY_NUM];
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun * @ Function description
27*4882a593Smuzhiyun * Convert 2 ghz channels from bit definition and then fill to
28*4882a593Smuzhiyun * struct rtw_regulation_channel *ch array[] and
29*4882a593Smuzhiyun * *ch_cnt will also be calculated.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * @ parameter
32*4882a593Smuzhiyun * *rg : internal regulatory information
33*4882a593Smuzhiyun * *ch_cnt : final converted 2ghz channel numbers.
34*4882a593Smuzhiyun * *rch : converted channels will be filled here.
35*4882a593Smuzhiyun * ch : 2 ghz bit difinitions
36*4882a593Smuzhiyun * passive : 2 ghz passive bit difinitions
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun */
_convert_ch2g(struct rtw_regulation * rg,u32 * ch_cnt,struct rtw_regulation_channel * rch,u16 ch,u16 passive)39*4882a593Smuzhiyun static void _convert_ch2g(struct rtw_regulation *rg, u32 *ch_cnt,
40*4882a593Smuzhiyun struct rtw_regulation_channel *rch, u16 ch, u16 passive)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun u8 i = 0, property = 0;
43*4882a593Smuzhiyun u32 shift = 0, cnt = 0;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun PHL_INFO("[REGU], convert 2 ghz channels\n");
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun for (i = 0; i < MAX_CH_NUM_2GHZ; i++) {
48*4882a593Smuzhiyun property = 0;
49*4882a593Smuzhiyun shift = (1 << i);
50*4882a593Smuzhiyun if (ch & shift) {
51*4882a593Smuzhiyun rch[*ch_cnt].band = BAND_ON_24G;
52*4882a593Smuzhiyun rch[*ch_cnt].channel = (u8)(i + 1);
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun if (passive & shift)
55*4882a593Smuzhiyun property |= CH_PASSIVE;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun rch[*ch_cnt].property = property;
58*4882a593Smuzhiyun (*ch_cnt)++;
59*4882a593Smuzhiyun PHL_INFO("[REGU], ch: %d%s\n", (i + 1),
60*4882a593Smuzhiyun ((property & CH_PASSIVE) ? ", passive" : " " ));
61*4882a593Smuzhiyun cnt++;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun PHL_INFO("[REGU], converted channels : %d\n", cnt);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
_chnlplan_update_2g(struct rtw_regulation * rg,const struct freq_plan * f)68*4882a593Smuzhiyun static enum rtw_regulation_status _chnlplan_update_2g(
69*4882a593Smuzhiyun struct rtw_regulation *rg, const struct freq_plan *f)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun const struct chdef_2ghz *chdef = NULL;
72*4882a593Smuzhiyun struct rtw_regulation_chplan_group *plan = NULL;
73*4882a593Smuzhiyun u16 i = 0, ch = 0, passive = 0;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun if (!f)
76*4882a593Smuzhiyun return REGULATION_FAILURE;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if (f->regulation >= REGULATION_MAX)
79*4882a593Smuzhiyun return REGULATION_FAILURE;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun for (i = 0; i < MAX_CHDEF_2GHZ; i++) {
82*4882a593Smuzhiyun if (f->ch_idx == chdef2g[i].idx) {
83*4882a593Smuzhiyun chdef = &chdef2g[i];
84*4882a593Smuzhiyun break;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (!chdef)
89*4882a593Smuzhiyun return REGULATION_FAILURE;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun rg->ch_idx2g = f->ch_idx;
92*4882a593Smuzhiyun rg->regulation_2g = f->regulation;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun plan = &rg->chplan[FREQ_GROUP_2GHZ];
95*4882a593Smuzhiyun plan->cnt = 0;
96*4882a593Smuzhiyun ch = ((chdef->support_ch[1] << 8) | (chdef->support_ch[0]));
97*4882a593Smuzhiyun passive = ((chdef->passive[1] << 8) | (chdef->passive[0]));
98*4882a593Smuzhiyun _convert_ch2g(rg, &plan->cnt, plan->ch, ch, passive);
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun PHL_INFO("[REGU], 2 GHz, total channel = %d\n", plan->cnt);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return REGULATION_SUCCESS;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
_get_5ghz_ch_info(const struct chdef_5ghz * chdef,u8 group,u16 * ch,u16 * passive,u16 * dfs,u8 * max_num,u8 * ch_start)105*4882a593Smuzhiyun static void _get_5ghz_ch_info(const struct chdef_5ghz *chdef,
106*4882a593Smuzhiyun u8 group, u16 *ch, u16 *passive, u16 *dfs, u8 *max_num, u8 *ch_start)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun switch (group) {
109*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND1:
110*4882a593Smuzhiyun *ch = chdef->support_ch_b1;
111*4882a593Smuzhiyun *passive = chdef->passive_b1;
112*4882a593Smuzhiyun *dfs = chdef->dfs_b1;
113*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND1;
114*4882a593Smuzhiyun *ch_start = 36;
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND2:
117*4882a593Smuzhiyun *ch = chdef->support_ch_b2;
118*4882a593Smuzhiyun *passive = chdef->passive_b2;
119*4882a593Smuzhiyun *dfs = chdef->dfs_b2;
120*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND2;
121*4882a593Smuzhiyun *ch_start = 52;
122*4882a593Smuzhiyun break;
123*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND3:
124*4882a593Smuzhiyun *ch = ((chdef->support_ch_b3[1] << 8) |
125*4882a593Smuzhiyun (chdef->support_ch_b3[0]));
126*4882a593Smuzhiyun *passive = ((chdef->passive_b3[1] << 8) |
127*4882a593Smuzhiyun (chdef->passive_b3[0]));
128*4882a593Smuzhiyun *dfs = ((chdef->dfs_b3[1] << 8) |
129*4882a593Smuzhiyun (chdef->dfs_b3[0])) ;
130*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND3;
131*4882a593Smuzhiyun *ch_start = 100;
132*4882a593Smuzhiyun break;
133*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND4:
134*4882a593Smuzhiyun *ch = chdef->support_ch_b4;
135*4882a593Smuzhiyun *passive = chdef->passive_b4;
136*4882a593Smuzhiyun *dfs = chdef->dfs_b4;
137*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND4;
138*4882a593Smuzhiyun *ch_start = 149;
139*4882a593Smuzhiyun break;
140*4882a593Smuzhiyun default:
141*4882a593Smuzhiyun *ch = 0;
142*4882a593Smuzhiyun *passive = 0;
143*4882a593Smuzhiyun *dfs = 0;
144*4882a593Smuzhiyun *max_num = 0;
145*4882a593Smuzhiyun *ch_start = 0;
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun * @ Function description
152*4882a593Smuzhiyun * Convert 5 ghz channels from bit definition and then fill to
153*4882a593Smuzhiyun * struct rtw_regulation_channel *ch array[] and
154*4882a593Smuzhiyun * *ch_cnt will also be calculated.
155*4882a593Smuzhiyun *
156*4882a593Smuzhiyun * @ parameter
157*4882a593Smuzhiyun * band_5g : 1~4 (5g band-1 ~ 5g band-4)
158*4882a593Smuzhiyun * *rg : internal regulatory information
159*4882a593Smuzhiyun * *ch_cnt : final converted 2ghz channel numbers.
160*4882a593Smuzhiyun * *rch : converted channels will be filled here.
161*4882a593Smuzhiyun * ch : 5 ghz bnad channel bit difinitions
162*4882a593Smuzhiyun * passive : 5 ghz band passive bit difinitions
163*4882a593Smuzhiyun * dfs : 5 ghz band dfs bit difinitions
164*4882a593Smuzhiyun * max_num : maximum channel numbers of the 5 ghz band.
165*4882a593Smuzhiyun * ch_start : start channel index of the 5 ghz band.
166*4882a593Smuzhiyun */
_convert_ch5g(u8 band_5g,struct rtw_regulation * rg,u32 * ch_cnt,struct rtw_regulation_channel * rch,u16 ch,u16 passive,u16 dfs,u8 max_num,u8 ch_start)167*4882a593Smuzhiyun static void _convert_ch5g(u8 band_5g, struct rtw_regulation *rg,
168*4882a593Smuzhiyun u32 *ch_cnt, struct rtw_regulation_channel *rch,
169*4882a593Smuzhiyun u16 ch, u16 passive, u16 dfs, u8 max_num, u8 ch_start)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun u16 i = 0;
172*4882a593Smuzhiyun u32 shift = 0;
173*4882a593Smuzhiyun u8 property = 0;
174*4882a593Smuzhiyun u32 cnt = 0;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun PHL_INFO("[REGU], convert 5ghz band-%d channels, from %d, ch=0x%x, passive = 0x%x, dfs=0x%x \n",
177*4882a593Smuzhiyun band_5g, ch_start, ch, passive, dfs);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun for (i = 0; i < max_num; i++) {
180*4882a593Smuzhiyun shift = (1 << i);
181*4882a593Smuzhiyun if (ch & shift) {
182*4882a593Smuzhiyun property = 0;
183*4882a593Smuzhiyun rch[*ch_cnt].band = BAND_ON_5G;
184*4882a593Smuzhiyun rch[*ch_cnt].channel = (u8)(ch_start + (i * 4));
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (passive & shift)
187*4882a593Smuzhiyun property |= CH_PASSIVE;
188*4882a593Smuzhiyun if (dfs & shift)
189*4882a593Smuzhiyun property |= CH_DFS;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun rch[*ch_cnt].property = property;
192*4882a593Smuzhiyun PHL_INFO("[REGU], ch: %d%s%s \n",
193*4882a593Smuzhiyun rch[*ch_cnt].channel,
194*4882a593Smuzhiyun ((property & CH_PASSIVE) ? ", passive" : ""),
195*4882a593Smuzhiyun ((property & CH_DFS) ? ", dfs" : ""));
196*4882a593Smuzhiyun (*ch_cnt)++;
197*4882a593Smuzhiyun cnt++;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun PHL_INFO("[REGU], converted channels : %d\n", cnt);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
_chnlplan_update_5g(struct rtw_regulation * rg,const struct freq_plan * f)204*4882a593Smuzhiyun static enum rtw_regulation_status _chnlplan_update_5g(
205*4882a593Smuzhiyun struct rtw_regulation *rg, const struct freq_plan *f)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun const struct chdef_5ghz *chdef = NULL;
208*4882a593Smuzhiyun struct rtw_regulation_chplan_group *plan = NULL;
209*4882a593Smuzhiyun u8 group = FREQ_GROUP_5GHZ_BAND1;
210*4882a593Smuzhiyun u8 max_num = 0, ch_start = 0;
211*4882a593Smuzhiyun u16 i = 0, ch = 0, passive = 0, dfs = 0;
212*4882a593Smuzhiyun u32 total = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun if (!f)
215*4882a593Smuzhiyun return REGULATION_FAILURE;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (f->regulation >= REGULATION_MAX)
218*4882a593Smuzhiyun return REGULATION_FAILURE;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun for (i = 0; i < MAX_CHDEF_5GHZ; i++) {
221*4882a593Smuzhiyun if (f->ch_idx == chdef5g[i].idx) {
222*4882a593Smuzhiyun chdef = &chdef5g[i];
223*4882a593Smuzhiyun break;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (!chdef)
228*4882a593Smuzhiyun return REGULATION_FAILURE;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun rg->ch_idx5g = f->ch_idx;
231*4882a593Smuzhiyun rg->regulation_5g = f->regulation;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
234*4882a593Smuzhiyun group = (u8)(i + FREQ_GROUP_5GHZ_BAND1);
235*4882a593Smuzhiyun plan = &rg->chplan[group];
236*4882a593Smuzhiyun plan->cnt = 0;
237*4882a593Smuzhiyun _get_5ghz_ch_info(chdef, group,
238*4882a593Smuzhiyun &ch, &passive, &dfs, &max_num, &ch_start);
239*4882a593Smuzhiyun _convert_ch5g((u8)(i + 1), rg, &plan->cnt, plan->ch,
240*4882a593Smuzhiyun ch, passive, dfs, max_num, ch_start);
241*4882a593Smuzhiyun total += plan->cnt;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun PHL_INFO("[REGU], 5 GHz, total channel = %d\n", total);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return REGULATION_SUCCESS;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
_regulatory_domain_update(struct rtw_regulation * rg,u8 did,enum regulation_rsn reason)249*4882a593Smuzhiyun static enum rtw_regulation_status _regulatory_domain_update(
250*4882a593Smuzhiyun struct rtw_regulation *rg, u8 did, enum regulation_rsn reason)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun enum rtw_regulation_status status = REGULATION_SUCCESS;
253*4882a593Smuzhiyun const struct freq_plan *plan_2g = NULL;
254*4882a593Smuzhiyun const struct freq_plan *plan_5g = NULL;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun plan_2g = &rdmap[did].freq_2g;
257*4882a593Smuzhiyun plan_5g = &rdmap[did].freq_5g;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun rg->domain.code = rdmap[did].domain_code;
260*4882a593Smuzhiyun rg->domain.reason = reason;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun status = _chnlplan_update_2g(rg, plan_2g);
263*4882a593Smuzhiyun if (status != REGULATION_SUCCESS)
264*4882a593Smuzhiyun return status;
265*4882a593Smuzhiyun status = _chnlplan_update_5g(rg, plan_5g);
266*4882a593Smuzhiyun if (status != REGULATION_SUCCESS)
267*4882a593Smuzhiyun return status;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return status;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
_get_group_chplan(struct rtw_regulation * rg,struct rtw_regulation_chplan_group * group,struct rtw_regulation_chplan * plan)272*4882a593Smuzhiyun static void _get_group_chplan(struct rtw_regulation *rg,
273*4882a593Smuzhiyun struct rtw_regulation_chplan_group *group,
274*4882a593Smuzhiyun struct rtw_regulation_chplan *plan)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun u32 i = 0;
277*4882a593Smuzhiyun u8 dfs = 0;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun for (i = 0; i < group->cnt; i++) {
280*4882a593Smuzhiyun dfs = ((group->ch[i].property & CH_DFS) ? 1 : 0);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if ((group->ch[i].channel) &&
283*4882a593Smuzhiyun (!dfs || ((rg->capability & CAPABILITY_DFS) && dfs))) {
284*4882a593Smuzhiyun plan->ch[plan->cnt].band =
285*4882a593Smuzhiyun group->ch[i].band;
286*4882a593Smuzhiyun plan->ch[plan->cnt].channel =
287*4882a593Smuzhiyun group->ch[i].channel;
288*4882a593Smuzhiyun plan->ch[plan->cnt].property =
289*4882a593Smuzhiyun group->ch[i].property;
290*4882a593Smuzhiyun plan->cnt++;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
_domain_index(u8 domain)295*4882a593Smuzhiyun static u8 _domain_index(u8 domain)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun u8 i = 0;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun for (i = 0; i < MAX_RD_MAP_NUM; i++) {
300*4882a593Smuzhiyun if (domain == rdmap[i].domain_code) {
301*4882a593Smuzhiyun return i;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun return MAX_RD_MAP_NUM;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
_get_chnlplan(struct rtw_regulation * rg,enum rtw_regulation_query type,struct rtw_regulation_chplan * plan)308*4882a593Smuzhiyun static enum rtw_regulation_status _get_chnlplan(struct rtw_regulation *rg,
309*4882a593Smuzhiyun enum rtw_regulation_query type,
310*4882a593Smuzhiyun struct rtw_regulation_chplan *plan)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct rtw_regulation_chplan_group *group = NULL;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (rg->domain.code == INVALID_DOMAIN_CODE)
315*4882a593Smuzhiyun return REGULATION_INVALID_DOMAIN;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun plan->cnt = 0;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /* 2ghz */
320*4882a593Smuzhiyun if (rg->capability & CAPABILITY_2GHZ) {
321*4882a593Smuzhiyun if (type == REGULQ_CHPLAN_FULL ||
322*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ_5GHZ ||
323*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ) {
324*4882a593Smuzhiyun group = &rg->chplan[FREQ_GROUP_2GHZ];
325*4882a593Smuzhiyun _get_group_chplan(rg, group, plan);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* 5ghz */
330*4882a593Smuzhiyun if (rg->capability & CAPABILITY_5GHZ) {
331*4882a593Smuzhiyun /* band1 */
332*4882a593Smuzhiyun if (type == REGULQ_CHPLAN_FULL ||
333*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ_5GHZ ||
334*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_ALL ||
335*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_BAND1) {
336*4882a593Smuzhiyun group = &rg->chplan[FREQ_GROUP_5GHZ_BAND1];
337*4882a593Smuzhiyun _get_group_chplan(rg, group, plan);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun /* band2 */
340*4882a593Smuzhiyun if (type == REGULQ_CHPLAN_FULL ||
341*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ_5GHZ ||
342*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_ALL ||
343*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_BAND2) {
344*4882a593Smuzhiyun group = &rg->chplan[FREQ_GROUP_5GHZ_BAND2];
345*4882a593Smuzhiyun _get_group_chplan(rg, group, plan);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun /* band3 */
348*4882a593Smuzhiyun if (type == REGULQ_CHPLAN_FULL ||
349*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ_5GHZ ||
350*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_ALL ||
351*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_BAND3) {
352*4882a593Smuzhiyun group = &rg->chplan[FREQ_GROUP_5GHZ_BAND3];
353*4882a593Smuzhiyun _get_group_chplan(rg, group, plan);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun /* band4 */
356*4882a593Smuzhiyun if (type == REGULQ_CHPLAN_FULL ||
357*4882a593Smuzhiyun type == REGULQ_CHPLAN_2GHZ_5GHZ ||
358*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_ALL ||
359*4882a593Smuzhiyun type == REGULQ_CHPLAN_5GHZ_BAND4) {
360*4882a593Smuzhiyun group = &rg->chplan[FREQ_GROUP_5GHZ_BAND4];
361*4882a593Smuzhiyun _get_group_chplan(rg, group, plan);
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun #ifdef CONFIG_6GHZ
366*4882a593Smuzhiyun regu_get_chnlplan_6g(rg, type, plan);
367*4882a593Smuzhiyun #endif
368*4882a593Smuzhiyun return REGULATION_SUCCESS;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
_valid_property(u8 property,u8 reject)371*4882a593Smuzhiyun static bool _valid_property(u8 property, u8 reject)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun u8 i = 0;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /* accept all property */
376*4882a593Smuzhiyun if (!reject)
377*4882a593Smuzhiyun return true;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun /* check if ch property rejected */
380*4882a593Smuzhiyun for (i = 0; i < 8; i++) {
381*4882a593Smuzhiyun if ((BIT(i) & property) & reject)
382*4882a593Smuzhiyun return false;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun return true;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
_filter_chnlplan(void * d,struct rtw_regulation_chplan * plan,struct rtw_chlist * filter)388*4882a593Smuzhiyun static void _filter_chnlplan(void *d,
389*4882a593Smuzhiyun struct rtw_regulation_chplan *plan,
390*4882a593Smuzhiyun struct rtw_chlist *filter)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun struct rtw_regulation_chplan inplan = {0};
393*4882a593Smuzhiyun u32 i = 0, j = 0, k = 0;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (!d || !plan || !filter)
396*4882a593Smuzhiyun return;
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun if (plan->cnt < filter->cnt)
399*4882a593Smuzhiyun return;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun _os_mem_cpy(d, &inplan, plan, sizeof(struct rtw_regulation_chplan));
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /*
404*4882a593Smuzhiyun * generate output chplan
405*4882a593Smuzhiyun * ex: filter : {1, 6}, inplan : {1, 6, 6, 11}, ouput => {1, 6, 6}
406*4882a593Smuzhiyun */
407*4882a593Smuzhiyun plan->cnt = 0;
408*4882a593Smuzhiyun for (i = 0; i < filter->cnt; i++) {
409*4882a593Smuzhiyun for (j = 0; j < inplan.cnt; j++) {
410*4882a593Smuzhiyun if ((filter->ch[i].band == inplan.ch[j].band) &&
411*4882a593Smuzhiyun (filter->ch[i].ch == inplan.ch[j].channel)) {
412*4882a593Smuzhiyun plan->ch[k].band = inplan.ch[j].band;
413*4882a593Smuzhiyun plan->ch[k].channel = inplan.ch[j].channel;
414*4882a593Smuzhiyun plan->ch[k].property = inplan.ch[j].property;
415*4882a593Smuzhiyun k++;
416*4882a593Smuzhiyun plan->cnt++;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
_regulation_valid(void * phl)422*4882a593Smuzhiyun static bool _regulation_valid(void *phl)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
425*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
426*4882a593Smuzhiyun void *d = NULL;
427*4882a593Smuzhiyun bool valid = false;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun if (!phl)
430*4882a593Smuzhiyun return false;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun rg = &phl_info->regulation;
433*4882a593Smuzhiyun if (!rg->init)
434*4882a593Smuzhiyun return false;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
437*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
438*4882a593Smuzhiyun valid = rg->valid;
439*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return valid;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
_query_channel(struct rtw_regulation * rg,enum band_type band,u16 channel,struct rtw_regulation_channel * ch)444*4882a593Smuzhiyun static bool _query_channel(struct rtw_regulation *rg,
445*4882a593Smuzhiyun enum band_type band, u16 channel,
446*4882a593Smuzhiyun struct rtw_regulation_channel *ch)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun struct rtw_regulation_chplan_group *plan = NULL;
449*4882a593Smuzhiyun u32 i = 0, j = 0;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if ((BAND_2GHZ(band) && !(rg->capability & CAPABILITY_2GHZ)) ||
452*4882a593Smuzhiyun (BAND_5GHZ(band) && !(rg->capability & CAPABILITY_5GHZ)) ||
453*4882a593Smuzhiyun (BAND_6GHZ(band) && !(rg->capability & CAPABILITY_6GHZ)))
454*4882a593Smuzhiyun return false;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun for (i = FREQ_GROUP_2GHZ; i < FREQ_GROUP_MAX; i++) {
457*4882a593Smuzhiyun plan = &rg->chplan[i];
458*4882a593Smuzhiyun for (j = 0; j < plan->cnt; j++) {
459*4882a593Smuzhiyun if (channel == plan->ch[j].channel) {
460*4882a593Smuzhiyun ch->band = plan->ch[j].band;
461*4882a593Smuzhiyun ch->channel = plan->ch[j].channel;
462*4882a593Smuzhiyun ch->property = plan->ch[j].property;
463*4882a593Smuzhiyun return true;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun return false;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
_display_chplan(struct rtw_regulation_chplan * plan)471*4882a593Smuzhiyun static void _display_chplan(struct rtw_regulation_chplan *plan)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun u32 i = 0;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun for (i = 0; i < plan->cnt; i++) {
476*4882a593Smuzhiyun PHL_INFO("[REGU], %d, %shz: ch %d%s%s%s\n", (i + 1),
477*4882a593Smuzhiyun ((plan->ch[i].band == BAND_ON_24G) ? "2g" :
478*4882a593Smuzhiyun ((plan->ch[i].band == BAND_ON_5G) ? "5g" :
479*4882a593Smuzhiyun ((plan->ch[i].band == BAND_ON_6G) ? "6g" : ""))),
480*4882a593Smuzhiyun (plan->ch[i].channel),
481*4882a593Smuzhiyun ((plan->ch[i].property & CH_PASSIVE) ?
482*4882a593Smuzhiyun ", passive" : ""),
483*4882a593Smuzhiyun ((plan->ch[i].property & CH_DFS) ? ", dfs" : ""),
484*4882a593Smuzhiyun ((plan->ch[i].property & CH_PSC) ? ", psc" : ""));
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
_phl_regulation_send_msg(struct phl_info_t * phl_info,u8 evt_id)488*4882a593Smuzhiyun static void _phl_regulation_send_msg(struct phl_info_t *phl_info, u8 evt_id)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun struct phl_msg msg = {0};
491*4882a593Smuzhiyun msg.inbuf = NULL;
492*4882a593Smuzhiyun msg.inlen = 0;
493*4882a593Smuzhiyun msg.band_idx = HW_BAND_0;
494*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_REGU);
495*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(msg.msg_id, evt_id);
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun if (RTW_PHL_STATUS_SUCCESS != phl_msg_hub_send(phl_info, NULL, &msg))
498*4882a593Smuzhiyun PHL_ERR("[REGULATION] sending message failed (evt_id: %u) \n", evt_id);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
_history_log(struct rtw_regulation * rg,u8 domain,u8 reason)501*4882a593Smuzhiyun static void _history_log(struct rtw_regulation *rg, u8 domain, u8 reason)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun rg->history[rg->history_cnt].code = domain;
504*4882a593Smuzhiyun rg->history[rg->history_cnt].reason = reason;
505*4882a593Smuzhiyun rg->history_cnt++;
506*4882a593Smuzhiyun if (rg->history_cnt >= MAX_HISTORY_NUM)
507*4882a593Smuzhiyun rg->history_cnt = 0;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun
_get_5ghz_udef_ch_info(struct rtw_user_def_chplan * udef,u8 group,u16 * ch,u16 * passive,u16 * dfs,u8 * max_num,u8 * ch_start)511*4882a593Smuzhiyun static void _get_5ghz_udef_ch_info(struct rtw_user_def_chplan *udef,
512*4882a593Smuzhiyun u8 group, u16 *ch, u16 *passive, u16 *dfs, u8 *max_num, u8 *ch_start)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun switch (group) {
515*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND1:
516*4882a593Smuzhiyun *ch = (u16)udef->ch5g & 0xf;
517*4882a593Smuzhiyun *passive = (u16)udef->passive5g & 0xf;
518*4882a593Smuzhiyun *dfs = (u16)udef->dfs5g & 0xf;
519*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND1;
520*4882a593Smuzhiyun *ch_start = 36;
521*4882a593Smuzhiyun break;
522*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND2:
523*4882a593Smuzhiyun *ch = (u16)((udef->ch5g & 0xf0) >> 4);
524*4882a593Smuzhiyun *passive = (u16)((udef->passive5g & 0xf0) >> 4);
525*4882a593Smuzhiyun *dfs = (u16)((udef->dfs5g & 0xf0) >> 4);
526*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND2;
527*4882a593Smuzhiyun *ch_start = 52;
528*4882a593Smuzhiyun break;
529*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND3:
530*4882a593Smuzhiyun *ch = (u16)((udef->ch5g & 0xfff00) >> 8);
531*4882a593Smuzhiyun *passive = (u16)((udef->passive5g & 0xfff00) >> 8);
532*4882a593Smuzhiyun *dfs = (u16)((udef->dfs5g & 0xfff00) >> 8);
533*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND3;
534*4882a593Smuzhiyun *ch_start = 100;
535*4882a593Smuzhiyun break;
536*4882a593Smuzhiyun case FREQ_GROUP_5GHZ_BAND4:
537*4882a593Smuzhiyun *ch = (u16)((udef->ch5g & 0xff00000) >> 20);
538*4882a593Smuzhiyun *passive = (u16)((udef->passive5g & 0xff00000) >> 20);
539*4882a593Smuzhiyun *dfs = (u16)((udef->dfs5g & 0xff00000) >> 20);
540*4882a593Smuzhiyun *max_num = MAX_CH_NUM_BAND4;
541*4882a593Smuzhiyun *ch_start = 149;
542*4882a593Smuzhiyun break;
543*4882a593Smuzhiyun default:
544*4882a593Smuzhiyun *ch = 0;
545*4882a593Smuzhiyun *passive = 0;
546*4882a593Smuzhiyun *dfs = 0;
547*4882a593Smuzhiyun *max_num = 0;
548*4882a593Smuzhiyun *ch_start = 0;
549*4882a593Smuzhiyun break;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /*
554*4882a593Smuzhiyun * @ Function description
555*4882a593Smuzhiyun * Reset regulatory info for non-specific country
556*4882a593Smuzhiyun */
_reset_for_non_specific_country(struct rtw_regulation * rg)557*4882a593Smuzhiyun static void _reset_for_non_specific_country(struct rtw_regulation *rg)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun /* reset country */
560*4882a593Smuzhiyun rg->country[0] = 0;
561*4882a593Smuzhiyun rg->country[1] = 0;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun /* reset TPO */
564*4882a593Smuzhiyun rg->tpo = TPO_NA;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /* default support all */
567*4882a593Smuzhiyun rg->support_mode |= (SUPPORT_11B | SUPPORT_11G | SUPPORT_11N |
568*4882a593Smuzhiyun SUPPORT_11A | SUPPORT_11AC | SUPPORT_11AX);
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /*
572*4882a593Smuzhiyun * @ Function description
573*4882a593Smuzhiyun * Set user defined channel plans
574*4882a593Smuzhiyun *
575*4882a593Smuzhiyun * @ parameter
576*4882a593Smuzhiyun * struct rtw_user_def_chplan *udef : user defined channels, bit definition
577*4882a593Smuzhiyun *
578*4882a593Smuzhiyun * @ return :
579*4882a593Smuzhiyun * true : if set successfully
580*4882a593Smuzhiyun * false : failed to set
581*4882a593Smuzhiyun *
582*4882a593Smuzhiyun */
rtw_phl_set_user_def_chplan(void * phl,struct rtw_user_def_chplan * udef)583*4882a593Smuzhiyun bool rtw_phl_set_user_def_chplan(void *phl, struct rtw_user_def_chplan *udef)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
586*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
587*4882a593Smuzhiyun struct rtw_regulation_chplan_group *plan = NULL;
588*4882a593Smuzhiyun u8 max_num = 0, ch_start = 0;
589*4882a593Smuzhiyun u16 ch = 0, passive = 0, dfs = 0;
590*4882a593Smuzhiyun u8 group = FREQ_GROUP_5GHZ_BAND1;
591*4882a593Smuzhiyun void *d = NULL;
592*4882a593Smuzhiyun u32 i = 0;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun if (!phl || !udef)
595*4882a593Smuzhiyun return false;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun rg = &phl_info->regulation;
598*4882a593Smuzhiyun if (!rg->init)
599*4882a593Smuzhiyun return false;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if (rg->domain.code != RSVD_DOMAIN) {
602*4882a593Smuzhiyun PHL_INFO("[REGU], Only reserved domain can set udef channel plan \n");
603*4882a593Smuzhiyun return false;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun PHL_INFO("[REGU], set udef channel plan, ch2g:0x%x, ch5g:0x%x\n",
607*4882a593Smuzhiyun udef->ch2g, udef->ch5g);
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
610*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun rg->regulation_2g = (u8)udef->regulatory_idx;
613*4882a593Smuzhiyun rg->regulation_5g = (u8)udef->regulatory_idx;
614*4882a593Smuzhiyun rg->tpo = udef->tpo;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /* 2 ghz */
617*4882a593Smuzhiyun plan = &rg->chplan[FREQ_GROUP_2GHZ];
618*4882a593Smuzhiyun plan->cnt = 0;
619*4882a593Smuzhiyun ch = udef->ch2g;
620*4882a593Smuzhiyun passive = udef->passive2g;
621*4882a593Smuzhiyun _convert_ch2g(rg, &plan->cnt, plan->ch, ch, passive);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun PHL_INFO("[REGU], 2 GHz, total channel = %d\n", plan->cnt);
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun /* 5 ghz */
626*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
627*4882a593Smuzhiyun group = (u8)(i + FREQ_GROUP_5GHZ_BAND1);
628*4882a593Smuzhiyun plan = &rg->chplan[group];
629*4882a593Smuzhiyun plan->cnt = 0;
630*4882a593Smuzhiyun _get_5ghz_udef_ch_info(udef, group,
631*4882a593Smuzhiyun &ch, &passive, &dfs, &max_num, &ch_start);
632*4882a593Smuzhiyun _convert_ch5g((u8)(i + 1), rg, &plan->cnt, plan->ch,
633*4882a593Smuzhiyun ch, passive, dfs, max_num, ch_start);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun return true;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /*
643*4882a593Smuzhiyun * @ Function description
644*4882a593Smuzhiyun * Check if domain is valid or not
645*4882a593Smuzhiyun *
646*4882a593Smuzhiyun * @ parameter
647*4882a593Smuzhiyun * domain : domain code to query
648*4882a593Smuzhiyun *
649*4882a593Smuzhiyun * @ return :
650*4882a593Smuzhiyun * true : if domain code exists in data base
651*4882a593Smuzhiyun * false : invalid domain code
652*4882a593Smuzhiyun *
653*4882a593Smuzhiyun */
rtw_phl_valid_regulation_domain(u8 domain)654*4882a593Smuzhiyun bool rtw_phl_valid_regulation_domain(u8 domain)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun if (domain == RSVD_DOMAIN)
657*4882a593Smuzhiyun return true;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (_domain_index(domain) >= MAX_RD_MAP_NUM)
660*4882a593Smuzhiyun return false;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun return true;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun /*
666*4882a593Smuzhiyun * @ Function description
667*4882a593Smuzhiyun * Set regulatory domain code
668*4882a593Smuzhiyun *
669*4882a593Smuzhiyun * @ parameter
670*4882a593Smuzhiyun * phl : struct phl_info_t *
671*4882a593Smuzhiyun * domain : domain code
672*4882a593Smuzhiyun * reason : why
673*4882a593Smuzhiyun *
674*4882a593Smuzhiyun * @ return :
675*4882a593Smuzhiyun * true : set domain successfully
676*4882a593Smuzhiyun * false : set fail
677*4882a593Smuzhiyun *
678*4882a593Smuzhiyun */
rtw_phl_regulation_set_domain(void * phl,u8 domain,enum regulation_rsn reason)679*4882a593Smuzhiyun bool rtw_phl_regulation_set_domain(void *phl, u8 domain,
680*4882a593Smuzhiyun enum regulation_rsn reason)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun enum rtw_regulation_status status = REGULATION_SUCCESS;
683*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
684*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
685*4882a593Smuzhiyun void *d = NULL;
686*4882a593Smuzhiyun u8 did = MAX_RD_MAP_NUM;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun PHL_INFO("[REGU], set domain code = 0x%x, reason = 0x%x\n",
689*4882a593Smuzhiyun domain, reason);
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (!phl_info)
692*4882a593Smuzhiyun return false;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun rg = &phl_info->regulation;
695*4882a593Smuzhiyun if (!rg->init)
696*4882a593Smuzhiyun return false;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (!rtw_phl_valid_regulation_domain(domain))
699*4882a593Smuzhiyun return false;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun did = _domain_index(domain);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun _history_log(rg, domain, reason);
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (domain == RSVD_DOMAIN) {
710*4882a593Smuzhiyun rg->domain.code = RSVD_DOMAIN;
711*4882a593Smuzhiyun rg->domain.reason = reason;
712*4882a593Smuzhiyun status = REGULATION_SUCCESS;
713*4882a593Smuzhiyun } else
714*4882a593Smuzhiyun status = _regulatory_domain_update(rg, did, reason);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun if (status == REGULATION_SUCCESS) {
717*4882a593Smuzhiyun _reset_for_non_specific_country(rg);
718*4882a593Smuzhiyun rg->valid = true;
719*4882a593Smuzhiyun } else {
720*4882a593Smuzhiyun rg->valid = false;
721*4882a593Smuzhiyun rg->invalid_cnt++;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun PHL_INFO("[REGU], domain code update status = 0x%x\n", status);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (status == REGULATION_SUCCESS) {
728*4882a593Smuzhiyun _phl_regulation_send_msg(phl_info, MSG_EVT_REGU_SET_DOMAIN);
729*4882a593Smuzhiyun #ifdef CONFIG_6GHZ
730*4882a593Smuzhiyun regu_set_domain_6g(phl, 0x7f, reason);
731*4882a593Smuzhiyun #endif
732*4882a593Smuzhiyun return true;
733*4882a593Smuzhiyun } else {
734*4882a593Smuzhiyun return false;
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun /*
739*4882a593Smuzhiyun * @ Function description
740*4882a593Smuzhiyun * Set regulation by 2bytes country code
741*4882a593Smuzhiyun *
742*4882a593Smuzhiyun * @ parameter
743*4882a593Smuzhiyun * phl : struct phl_info_t *
744*4882a593Smuzhiyun * country : 2 bytes char
745*4882a593Smuzhiyun * reason : why
746*4882a593Smuzhiyun *
747*4882a593Smuzhiyun * @ return :
748*4882a593Smuzhiyun * true : set country/domain successfully
749*4882a593Smuzhiyun * false : set fail
750*4882a593Smuzhiyun *
751*4882a593Smuzhiyun */
rtw_phl_regulation_set_country(void * phl,char * country,enum regulation_rsn reason)752*4882a593Smuzhiyun bool rtw_phl_regulation_set_country(void *phl, char *country,
753*4882a593Smuzhiyun enum regulation_rsn reason)
754*4882a593Smuzhiyun {
755*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
756*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
757*4882a593Smuzhiyun void *d = NULL;
758*4882a593Smuzhiyun u32 i = 0;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun PHL_INFO("[REGU], set country code = \"%c%c\", reason = 0x%x\n",
761*4882a593Smuzhiyun country[0], country[1], reason);
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun if (!phl_info)
764*4882a593Smuzhiyun return false;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
767*4882a593Smuzhiyun rg = &phl_info->regulation;
768*4882a593Smuzhiyun if (!rg->init)
769*4882a593Smuzhiyun return false;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun if (rg->domain.code == RSVD_DOMAIN)
772*4882a593Smuzhiyun return false;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun for (i = 0; i < MAX_COUNTRY_NUM; i++) {
775*4882a593Smuzhiyun if (cdmap[i].char2[0] == country[0] &&
776*4882a593Smuzhiyun cdmap[i].char2[1] == country[1] ) {
777*4882a593Smuzhiyun if (!rtw_phl_regulation_set_domain(phl,
778*4882a593Smuzhiyun cdmap[i].domain_code, reason))
779*4882a593Smuzhiyun return false;
780*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
781*4882a593Smuzhiyun rg->country[0] = country[0];
782*4882a593Smuzhiyun rg->country[1] = country[1];
783*4882a593Smuzhiyun rg->tpo = cdmap[i].tpo;
784*4882a593Smuzhiyun rg->support_mode = 0;
785*4882a593Smuzhiyun if(cdmap[i].support & BIT(0))
786*4882a593Smuzhiyun rg->support_mode |= (SUPPORT_11B | SUPPORT_11G | SUPPORT_11N);
787*4882a593Smuzhiyun if(cdmap[i].support & BIT(1))
788*4882a593Smuzhiyun rg->support_mode |= (SUPPORT_11A);
789*4882a593Smuzhiyun if(cdmap[i].support & BIT(2))
790*4882a593Smuzhiyun rg->support_mode |= (SUPPORT_11AC);
791*4882a593Smuzhiyun if(cdmap[i].support & BIT(3))
792*4882a593Smuzhiyun rg->support_mode |= (SUPPORT_11AX);
793*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
794*4882a593Smuzhiyun return true;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun PHL_INFO("[REGU], country mismatch !!\n");
799*4882a593Smuzhiyun return false;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun /*
803*4882a593Smuzhiyun * @ Function description
804*4882a593Smuzhiyun * Query current regulation channel plan
805*4882a593Smuzhiyun *
806*4882a593Smuzhiyun * @ parameter
807*4882a593Smuzhiyun * phl : struct phl_info_t *
808*4882a593Smuzhiyun * capability : enum rtw_regulation_capability
809*4882a593Smuzhiyun *
810*4882a593Smuzhiyun * @ return :
811*4882a593Smuzhiyun * true : set capability successfully
812*4882a593Smuzhiyun * false : set capability fail
813*4882a593Smuzhiyun *
814*4882a593Smuzhiyun */
rtw_phl_regulation_set_capability(void * phl,enum rtw_regulation_capability capability)815*4882a593Smuzhiyun bool rtw_phl_regulation_set_capability(void *phl,
816*4882a593Smuzhiyun enum rtw_regulation_capability capability)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
819*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
820*4882a593Smuzhiyun void *d = NULL;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun PHL_INFO("[REGU], set capability = 0x%x \n", capability);
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (!phl_info)
825*4882a593Smuzhiyun return false;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun rg = &phl_info->regulation;
828*4882a593Smuzhiyun if (!rg->init)
829*4882a593Smuzhiyun return false;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
832*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
833*4882a593Smuzhiyun rg->capability = capability;
834*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun PHL_INFO("[REGU], set capability = 0x%x successfully !!\n",
837*4882a593Smuzhiyun rg->capability);
838*4882a593Smuzhiyun return true;
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun /*
842*4882a593Smuzhiyun * @ Function description
843*4882a593Smuzhiyun * Query current regulation channel plan
844*4882a593Smuzhiyun *
845*4882a593Smuzhiyun * @ parameter
846*4882a593Smuzhiyun * phl : struct phl_info_t *
847*4882a593Smuzhiyun * type : enum rtw_regulation_query, different query type
848*4882a593Smuzhiyun * filter : struct rtw_chlist *, used to filter regulation channels
849*4882a593Smuzhiyun * plan : struct rtw_regulation_chplan *, query result will be filled here
850*4882a593Smuzhiyun * - result will be the intersection of regulation channel plan and
851*4882a593Smuzhiyun * the filter channels.
852*4882a593Smuzhiyun *
853*4882a593Smuzhiyun * @ return :
854*4882a593Smuzhiyun * true : regulation query successfully, caller can check result
855*4882a593Smuzhiyun * by input parameter *plan.
856*4882a593Smuzhiyun * false : regulation query fail
857*4882a593Smuzhiyun *
858*4882a593Smuzhiyun */
rtw_phl_regulation_query_chplan(void * phl,enum rtw_regulation_query type,struct rtw_chlist * filter,struct rtw_regulation_chplan * plan)859*4882a593Smuzhiyun bool rtw_phl_regulation_query_chplan(
860*4882a593Smuzhiyun void *phl, enum rtw_regulation_query type,
861*4882a593Smuzhiyun struct rtw_chlist *filter,
862*4882a593Smuzhiyun struct rtw_regulation_chplan *plan)
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
865*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
866*4882a593Smuzhiyun enum rtw_regulation_status status = REGULATION_FAILURE;
867*4882a593Smuzhiyun void *d = NULL;
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun if (!phl || !plan)
870*4882a593Smuzhiyun return false;
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun if (!_regulation_valid(phl))
873*4882a593Smuzhiyun return false;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun rg = &phl_info->regulation;
876*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
879*4882a593Smuzhiyun switch (type) {
880*4882a593Smuzhiyun case REGULQ_CHPLAN_FULL:
881*4882a593Smuzhiyun case REGULQ_CHPLAN_2GHZ:
882*4882a593Smuzhiyun case REGULQ_CHPLAN_5GHZ_ALL:
883*4882a593Smuzhiyun case REGULQ_CHPLAN_5GHZ_BAND1:
884*4882a593Smuzhiyun case REGULQ_CHPLAN_5GHZ_BAND2:
885*4882a593Smuzhiyun case REGULQ_CHPLAN_5GHZ_BAND3:
886*4882a593Smuzhiyun case REGULQ_CHPLAN_5GHZ_BAND4:
887*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ_UNII5:
888*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ_UNII6:
889*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ_UNII7:
890*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ_UNII8:
891*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ:
892*4882a593Smuzhiyun case REGULQ_CHPLAN_6GHZ_PSC:
893*4882a593Smuzhiyun case REGULQ_CHPLAN_2GHZ_5GHZ:
894*4882a593Smuzhiyun status = _get_chnlplan(rg, type, plan);
895*4882a593Smuzhiyun if (filter)
896*4882a593Smuzhiyun _filter_chnlplan(d, plan, filter);
897*4882a593Smuzhiyun break;
898*4882a593Smuzhiyun default:
899*4882a593Smuzhiyun break;
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (status == REGULATION_SUCCESS) {
904*4882a593Smuzhiyun /* _display_chplan(plan); */
905*4882a593Smuzhiyun return true;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun else
908*4882a593Smuzhiyun return false;
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun /*
912*4882a593Smuzhiyun * @ Function description
913*4882a593Smuzhiyun * Query specific regulation channel plan by domain code
914*4882a593Smuzhiyun *
915*4882a593Smuzhiyun * @ parameter
916*4882a593Smuzhiyun * domain : domain code
917*4882a593Smuzhiyun * plan : struct rtw_regulation_chplan *, query result will be filled here
918*4882a593Smuzhiyun *
919*4882a593Smuzhiyun * @ return :
920*4882a593Smuzhiyun * true : regulation query successfully, caller can check result
921*4882a593Smuzhiyun * by input parameter *plan.
922*4882a593Smuzhiyun * false : regulation query fail
923*4882a593Smuzhiyun *
924*4882a593Smuzhiyun */
rtw_phl_query_specific_chplan(void * phl,u8 domain,struct rtw_regulation_chplan * plan)925*4882a593Smuzhiyun bool rtw_phl_query_specific_chplan(void *phl, u8 domain,
926*4882a593Smuzhiyun struct rtw_regulation_chplan *plan)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
929*4882a593Smuzhiyun const struct chdef_2ghz *chdef2 = NULL;
930*4882a593Smuzhiyun const struct chdef_5ghz *chdef5 = NULL;
931*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
932*4882a593Smuzhiyun u8 did = MAX_RD_MAP_NUM;
933*4882a593Smuzhiyun u8 idx2g = INVALID_CHDEF;
934*4882a593Smuzhiyun u8 idx5g = INVALID_CHDEF;
935*4882a593Smuzhiyun u16 i = 0, ch = 0, passive = 0, dfs = 0;
936*4882a593Smuzhiyun u8 group = FREQ_GROUP_5GHZ_BAND1;
937*4882a593Smuzhiyun u8 max_num = 0, ch_start = 0;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun if (!plan)
940*4882a593Smuzhiyun return false;
941*4882a593Smuzhiyun plan->cnt = 0;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun PHL_INFO("[REGU], query specific channel plan for domain : 0x%x!!\n",
944*4882a593Smuzhiyun domain);
945*4882a593Smuzhiyun
946*4882a593Smuzhiyun if (!rtw_phl_valid_regulation_domain(domain))
947*4882a593Smuzhiyun return false;
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun /* find channel definition for 2 ghz & 5 ghz */
950*4882a593Smuzhiyun did = _domain_index(domain);
951*4882a593Smuzhiyun idx2g = rdmap[did].freq_2g.ch_idx;
952*4882a593Smuzhiyun for (i = 0; i < MAX_CHDEF_2GHZ; i++) {
953*4882a593Smuzhiyun if (idx2g == chdef2g[i].idx) {
954*4882a593Smuzhiyun chdef2 = &chdef2g[i];
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun idx5g = rdmap[did].freq_5g.ch_idx;
958*4882a593Smuzhiyun for (i = 0; i < MAX_CHDEF_5GHZ; i++) {
959*4882a593Smuzhiyun if (idx5g == chdef5g[i].idx) {
960*4882a593Smuzhiyun chdef5 = &chdef5g[i];
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun /* when regulatory domain & capability is set, check regulatory capability setting first */
965*4882a593Smuzhiyun if (_regulation_valid(phl)) {
966*4882a593Smuzhiyun rg = &phl_info->regulation;
967*4882a593Smuzhiyun if (!(rg->capability & CAPABILITY_2GHZ))
968*4882a593Smuzhiyun chdef2 = NULL;
969*4882a593Smuzhiyun if (!(rg->capability & CAPABILITY_5GHZ))
970*4882a593Smuzhiyun chdef5 = NULL;
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun /* 2ghz */
974*4882a593Smuzhiyun if (chdef2) {
975*4882a593Smuzhiyun ch = ((chdef2->support_ch[1] << 8) |
976*4882a593Smuzhiyun (chdef2->support_ch[0]));
977*4882a593Smuzhiyun passive = ((chdef2->passive[1] << 8) |
978*4882a593Smuzhiyun (chdef2->passive[0]));
979*4882a593Smuzhiyun _convert_ch2g(rg, &plan->cnt, plan->ch, ch, passive);
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun /* 5ghz */
983*4882a593Smuzhiyun if (chdef5) {
984*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
985*4882a593Smuzhiyun group = (u8)(i + FREQ_GROUP_5GHZ_BAND1);
986*4882a593Smuzhiyun _get_5ghz_ch_info(chdef5, group, &ch, &passive, &dfs,
987*4882a593Smuzhiyun &max_num, &ch_start);
988*4882a593Smuzhiyun _convert_ch5g((u8)(i + 1), rg, &plan->cnt, plan->ch,
989*4882a593Smuzhiyun ch, passive, dfs, max_num, ch_start);
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun PHL_INFO("[REGU], query specific channel plan for domain : 0x%x, total channels : %d !!\n",
994*4882a593Smuzhiyun domain, plan->cnt);
995*4882a593Smuzhiyun _display_chplan(plan);
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun return true;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun /*
1001*4882a593Smuzhiyun * @ Function description
1002*4882a593Smuzhiyun * Query basic regulation info
1003*4882a593Smuzhiyun *
1004*4882a593Smuzhiyun * @ parameter
1005*4882a593Smuzhiyun * phl : struct phl_info_t *
1006*4882a593Smuzhiyun * info : struct rtw_regulation_info *, query result will be filled here
1007*4882a593Smuzhiyun *
1008*4882a593Smuzhiyun * @ return :
1009*4882a593Smuzhiyun * true : regulation query successfully, caller can check result
1010*4882a593Smuzhiyun * by input parameter *info.
1011*4882a593Smuzhiyun * false : regulation query fail
1012*4882a593Smuzhiyun *
1013*4882a593Smuzhiyun */
rtw_phl_query_regulation_info(void * phl,struct rtw_regulation_info * info)1014*4882a593Smuzhiyun bool rtw_phl_query_regulation_info(void *phl, struct rtw_regulation_info *info)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1017*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
1018*4882a593Smuzhiyun void *d = NULL;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun if (!phl || !info)
1021*4882a593Smuzhiyun return false;
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun if (!_regulation_valid(phl))
1024*4882a593Smuzhiyun return false;
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun rg = &phl_info->regulation;
1027*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun info->domain_code = (u8)rg->domain.code;
1032*4882a593Smuzhiyun info->domain_reason = rg->domain.reason;
1033*4882a593Smuzhiyun info->country[0] = rg->country[0];
1034*4882a593Smuzhiyun info->country[1] = rg->country[1];
1035*4882a593Smuzhiyun info->tpo = rg->tpo;
1036*4882a593Smuzhiyun info->support_mode = rg->support_mode;
1037*4882a593Smuzhiyun info->regulation_2g = rg->regulation_2g;
1038*4882a593Smuzhiyun info->regulation_5g = rg->regulation_5g;
1039*4882a593Smuzhiyun info->chplan_ver = REGULATION_CHPLAN_VERSION;
1040*4882a593Smuzhiyun info->country_ver = REGULATION_COUNTRY_VERSION;
1041*4882a593Smuzhiyun info->capability = rg->capability;
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun return true;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun /*
1049*4882a593Smuzhiyun * @ Function description
1050*4882a593Smuzhiyun * Use the coutry code to query the corresponding
1051*4882a593Smuzhiyun * domain code and properties
1052*4882a593Smuzhiyun *
1053*4882a593Smuzhiyun * @ parameter
1054*4882a593Smuzhiyun * country : 2 bytes char
1055*4882a593Smuzhiyun * country_chplan : pointer to structre of chplan's info
1056*4882a593Smuzhiyun *
1057*4882a593Smuzhiyun * @ return :
1058*4882a593Smuzhiyun * true : successfully search the entry form cdmap
1059*4882a593Smuzhiyun * false : country chplan query fail
1060*4882a593Smuzhiyun */
rtw_phl_query_country_chplan(char * country,struct rtw_regulation_country_chplan * country_chplan)1061*4882a593Smuzhiyun bool rtw_phl_query_country_chplan(char *country,
1062*4882a593Smuzhiyun struct rtw_regulation_country_chplan* country_chplan)
1063*4882a593Smuzhiyun {
1064*4882a593Smuzhiyun u32 i = 0;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun PHL_INFO("[REGU], query country code = \"%c%c\"\n",
1067*4882a593Smuzhiyun country[0], country[1]);
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun for (i = 0; i < MAX_COUNTRY_NUM; i++) {
1070*4882a593Smuzhiyun if (cdmap[i].char2[0] == country[0] &&
1071*4882a593Smuzhiyun cdmap[i].char2[1] == country[1] ) {
1072*4882a593Smuzhiyun country_chplan->domain_code = cdmap[i].domain_code;
1073*4882a593Smuzhiyun if(cdmap[i].support & BIT(0))
1074*4882a593Smuzhiyun country_chplan->support_mode |= (SUPPORT_11B | SUPPORT_11G | SUPPORT_11N);
1075*4882a593Smuzhiyun if(cdmap[i].support & BIT(1))
1076*4882a593Smuzhiyun country_chplan->support_mode |= (SUPPORT_11A);
1077*4882a593Smuzhiyun if(cdmap[i].support & BIT(2))
1078*4882a593Smuzhiyun country_chplan->support_mode |= (SUPPORT_11AC);
1079*4882a593Smuzhiyun if(cdmap[i].support & BIT(3))
1080*4882a593Smuzhiyun country_chplan->support_mode |= (SUPPORT_11AX);
1081*4882a593Smuzhiyun country_chplan->tpo = cdmap[i].tpo;
1082*4882a593Smuzhiyun return true;
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun return false;
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
rtw_phl_regulation_valid(void * phl)1088*4882a593Smuzhiyun bool rtw_phl_regulation_valid(void *phl)
1089*4882a593Smuzhiyun {
1090*4882a593Smuzhiyun return _regulation_valid(phl);
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun /*
1094*4882a593Smuzhiyun * @ Function description
1095*4882a593Smuzhiyun * Used to check if channel is in regulation channel list
1096*4882a593Smuzhiyun *
1097*4882a593Smuzhiyun * @ parameter
1098*4882a593Smuzhiyun * phl : struct phl_info_t *
1099*4882a593Smuzhiyun * channel : channel to be checked
1100*4882a593Smuzhiyun * reject : enum ch_property, ex: (CH_PASSIVE | CH_DFS)
1101*4882a593Smuzhiyun *
1102*4882a593Smuzhiyun * @ return :
1103*4882a593Smuzhiyun * true : channel is in regulation list and not rejected
1104*4882a593Smuzhiyun * false : query regulation failed or channel is not in regulation
1105*4882a593Smuzhiyun * channel list
1106*4882a593Smuzhiyun */
rtw_phl_regulation_valid_channel(void * phl,enum band_type band,u16 channel,u8 reject)1107*4882a593Smuzhiyun bool rtw_phl_regulation_valid_channel(void *phl, enum band_type band,
1108*4882a593Smuzhiyun u16 channel, u8 reject)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1111*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
1112*4882a593Smuzhiyun struct rtw_regulation_channel ch = {0};
1113*4882a593Smuzhiyun bool valid = false;
1114*4882a593Smuzhiyun void *d = NULL;
1115*4882a593Smuzhiyun u8 rej_property = reject;
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun if (!_regulation_valid(phl))
1118*4882a593Smuzhiyun return false;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun rg = &phl_info->regulation;
1121*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
1124*4882a593Smuzhiyun if (_query_channel(rg, band, channel, &ch)) {
1125*4882a593Smuzhiyun if (!(rg->capability & CAPABILITY_DFS))
1126*4882a593Smuzhiyun rej_property |= CAPABILITY_DFS;
1127*4882a593Smuzhiyun if (_valid_property(ch.property, rej_property))
1128*4882a593Smuzhiyun valid = true;
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun return valid;
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun /*
1136*4882a593Smuzhiyun * @ Function description
1137*4882a593Smuzhiyun * Used to check if channel is a regulation DFS channel
1138*4882a593Smuzhiyun *
1139*4882a593Smuzhiyun * @ parameter
1140*4882a593Smuzhiyun * phl : struct phl_info_t *
1141*4882a593Smuzhiyun * channel : channel to be checked
1142*4882a593Smuzhiyun * dfs : result will be filled here
1143*4882a593Smuzhiyun *
1144*4882a593Smuzhiyun * @ return :
1145*4882a593Smuzhiyun * true : regulation query successfully, caller can check result
1146*4882a593Smuzhiyun * by input parameter *dfs.
1147*4882a593Smuzhiyun * false : regulation fail
1148*4882a593Smuzhiyun *
1149*4882a593Smuzhiyun */
rtw_phl_regulation_dfs_channel(void * phl,enum band_type band,u16 channel,bool * dfs)1150*4882a593Smuzhiyun bool rtw_phl_regulation_dfs_channel(void *phl, enum band_type band,
1151*4882a593Smuzhiyun u16 channel, bool *dfs)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1154*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
1155*4882a593Smuzhiyun struct rtw_regulation_channel ch = {0};
1156*4882a593Smuzhiyun void *d = NULL;
1157*4882a593Smuzhiyun bool query = false;
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun if (!_regulation_valid(phl) || !dfs)
1160*4882a593Smuzhiyun return false;
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun rg = &phl_info->regulation;
1163*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
1166*4882a593Smuzhiyun if (_query_channel(rg, band, channel, &ch)) {
1167*4882a593Smuzhiyun query = true;
1168*4882a593Smuzhiyun if (ch.property & CH_DFS)
1169*4882a593Smuzhiyun *dfs = true;
1170*4882a593Smuzhiyun else
1171*4882a593Smuzhiyun *dfs = false;
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun return query;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun /*
1179*4882a593Smuzhiyun * @ Function description
1180*4882a593Smuzhiyun * Query regulation channel
1181*4882a593Smuzhiyun *
1182*4882a593Smuzhiyun * @ parameter
1183*4882a593Smuzhiyun * phl : struct phl_info_t *
1184*4882a593Smuzhiyun * channel : channel for query
1185*4882a593Smuzhiyun * ch : query result will be filled here
1186*4882a593Smuzhiyun *
1187*4882a593Smuzhiyun * @ return :
1188*4882a593Smuzhiyun * true : regulation query successfully, caller can check result
1189*4882a593Smuzhiyun * by input parameter *ch.
1190*4882a593Smuzhiyun * false : regulation query fail
1191*4882a593Smuzhiyun *
1192*4882a593Smuzhiyun */
rtw_phl_regulation_query_ch(void * phl,enum band_type band,u8 channel,struct rtw_regulation_channel * ch)1193*4882a593Smuzhiyun bool rtw_phl_regulation_query_ch(void *phl, enum band_type band, u8 channel,
1194*4882a593Smuzhiyun struct rtw_regulation_channel *ch)
1195*4882a593Smuzhiyun {
1196*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1197*4882a593Smuzhiyun struct rtw_regulation *rg = NULL;
1198*4882a593Smuzhiyun void *d = NULL;
1199*4882a593Smuzhiyun bool query = false;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (!_regulation_valid(phl) || !ch)
1202*4882a593Smuzhiyun return false;
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun rg = &phl_info->regulation;
1205*4882a593Smuzhiyun d = phl_to_drvpriv(phl_info);
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun _os_spinlock(d, &rg->lock, _bh, NULL);
1208*4882a593Smuzhiyun if (_query_channel(rg, band, channel, ch))
1209*4882a593Smuzhiyun query = true;
1210*4882a593Smuzhiyun _os_spinunlock(d, &rg->lock, _bh, NULL);
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun return query;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun
rtw_phl_get_domain_regulation_2g(u8 domain)1215*4882a593Smuzhiyun u8 rtw_phl_get_domain_regulation_2g(u8 domain)
1216*4882a593Smuzhiyun {
1217*4882a593Smuzhiyun u8 did = MAX_RD_MAP_NUM;
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun if (!rtw_phl_valid_regulation_domain(domain))
1220*4882a593Smuzhiyun return REGULATION_MAX;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun did = _domain_index(domain);
1223*4882a593Smuzhiyun if (did >= MAX_RD_MAP_NUM)
1224*4882a593Smuzhiyun return REGULATION_MAX;
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun return rdmap[did].freq_2g.regulation;
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
rtw_phl_get_domain_regulation_5g(u8 domain)1229*4882a593Smuzhiyun u8 rtw_phl_get_domain_regulation_5g(u8 domain)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun u8 did = MAX_RD_MAP_NUM;
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun if (!rtw_phl_valid_regulation_domain(domain))
1234*4882a593Smuzhiyun return REGULATION_MAX;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun did = _domain_index(domain);
1237*4882a593Smuzhiyun if (did >= MAX_RD_MAP_NUM)
1238*4882a593Smuzhiyun return REGULATION_MAX;
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun return rdmap[did].freq_5g.regulation;
1241*4882a593Smuzhiyun }
1242*4882a593Smuzhiyun
1243