1 /** @file mlan_11h.c
2 *
3 * @brief This file provides functions for 802.11H
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 /*************************************************************
12 Change Log:
13 03/26/2009: initial version
14 ************************************************************/
15
16 #include <mlan_api.h>
17
18 /* Additional WMSDK header files */
19 #include <wmerrno.h>
20 #include <osa.h>
21
22 /* Always keep this include at the end of all include files */
23 #include <mlan_remap_mem_operations.h>
24
25 /********************************************************
26 Local Variables
27 ********************************************************/
28 /** Default IBSS DFS recovery interval (in TBTTs); used for adhoc start */
29 #define WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL 100
30
31 /** Default 11h power constraint used to offset the maximum transmit power */
32 #define WLAN_11H_TPC_POWERCONSTRAINT 0
33
34 /** 11h TPC Power capability minimum setting, sent in TPC_INFO command to fw */
35 #define WLAN_11H_TPC_POWERCAPABILITY_MIN 5
36
37 /** 11h TPC Power capability maximum setting, sent in TPC_INFO command to fw */
38 #define WLAN_11H_TPC_POWERCAPABILITY_MAX 20
39
40 /** Regulatory requirement for the duration of a channel availability check */
41 #define WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION 60000 /* in ms */
42
43 /** Starting Frequency for 11A band */
44 #define START_FREQ_11A_BAND 5000 /* in MHz */
45
46 /** Regulatory requirement for the duration of a non-occupancy period */
47 #define WLAN_11H_NON_OCCUPANCY_PERIOD 1800 /* in sec (30mins) */
48
49 /** Maximum allowable age (seconds) on DFS report data */
50 #define MAX_DFS_REPORT_USABLE_AGE_SEC (120) // 2 minutes
51
52 /** Minimum delay for CHAN_SW IE to broadcast by FW */
53 #define MIN_RDH_CHAN_SW_IE_PERIOD_MSEC (500) // 5 beacons @ 100ms
54
55 /** Maximum delay for CHAN_SW IE to broadcast by FW */
56 #define MAX_RDH_CHAN_SW_IE_PERIOD_MSEC (3000) // 5 beacons @ 600ms
57
58 /** Maximum retries on selecting new random channel */
59 #define MAX_RANDOM_CHANNEL_RETRIES (20)
60
61 /** Maximum retries on selecting new random non-dfs channel */
62 #define MAX_SWITCH_CHANNEL_RETRIES (30)
63
64 /** Value for undetermined priv_curr_idx on first entry to new RDH stage */
65 #define RDH_STAGE_FIRST_ENTRY_PRIV_IDX (0xff)
66
67 /** Internally passed structure used to send a CMD_802_11_TPC_INFO command */
68 typedef struct
69 {
70 t_u8 chan; /**< Channel to which the power constraint applies */
71 t_u8 power_constraint; /**< Local power constraint to send to firmware */
72 } wlan_11h_tpc_info_param_t;
73
74 /********************************************************
75 Global Variables
76 ********************************************************/
77
78 /********************************************************
79 Local Functions
80 ********************************************************/
81
82 /**
83 * @brief Initialize the 11h parameters and enable 11h when starting an IBSS
84 *
85 * @param adapter mlan_adapter structure
86 *
87 * @return N/A
88 */
wlan_11h_init(mlan_adapter * adapter)89 void wlan_11h_init(mlan_adapter *adapter)
90 {
91 wlan_11h_device_state_t *pstate_11h = &adapter->state_11h;
92 IEEEtypes_Quiet_t *pquiet = &adapter->state_11h.quiet_ie;
93 wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
94 wlan_radar_det_hndlg_state_t *pstate_rdh = &adapter->state_rdh;
95 #ifdef DFS_TESTING_SUPPORT
96 wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
97 #endif
98
99 ENTER();
100
101 /* Initialize 11H struct */
102 pstate_11h->usr_def_power_constraint = WLAN_11H_TPC_POWERCONSTRAINT;
103 pstate_11h->min_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MIN;
104 pstate_11h->max_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MAX;
105 pstate_11h->recvd_chanswann_event = MFALSE;
106 pstate_11h->master_radar_det_enable_pending = MFALSE;
107 pstate_11h->slave_radar_det_enable_pending = MFALSE;
108 pstate_11h->is_master_radar_det_active = MFALSE;
109 pstate_11h->is_slave_radar_det_active = MFALSE;
110
111 /* Initialize quiet_ie */
112 (void)__memset(adapter, pquiet, 0, sizeof(IEEEtypes_Quiet_t));
113 pquiet->element_id = QUIET;
114 pquiet->len = (sizeof(pquiet->quiet_count) + sizeof(pquiet->quiet_period) + sizeof(pquiet->quiet_duration) +
115 sizeof(pquiet->quiet_offset));
116
117 /* Initialize DFS struct */
118 pstate_dfs->dfs_check_pending = MFALSE;
119 pstate_dfs->dfs_radar_found = MFALSE;
120 pstate_dfs->dfs_check_channel = 0;
121 pstate_dfs->dfs_report_time_sec = 0;
122 util_init_list((pmlan_linked_list)(void *)&pstate_dfs->dfs_ts_head);
123
124 /* Initialize RDH struct */
125 pstate_rdh->stage = RDH_OFF;
126 pstate_rdh->priv_list_count = 0;
127 pstate_rdh->priv_curr_idx = 0;
128 pstate_rdh->curr_channel = 0;
129 pstate_rdh->new_channel = 0;
130 pstate_rdh->uap_band_cfg = 0;
131 pstate_rdh->max_bcn_dtim_ms = 0;
132 (void)__memset(adapter, pstate_rdh->priv_list, 0, sizeof(pstate_rdh->priv_list));
133
134 #ifdef DFS_TESTING_SUPPORT
135 /* Initialize DFS testing struct */
136 pdfs_test->user_cac_period_msec = 0;
137 pdfs_test->user_nop_period_sec = 0;
138 pdfs_test->no_channel_change_on_radar = MFALSE;
139 pdfs_test->fixed_new_channel_on_radar = 0;
140 #endif
141 LEAVE();
142 }
143
144 /**
145 * @brief Initialize the 11h parameters and enable 11h when starting an IBSS
146 *
147 * @param pmpriv Pointer to mlan_private structure
148 *
149 * @return N/A
150 */
wlan_11h_priv_init(mlan_private * pmpriv)151 void wlan_11h_priv_init(mlan_private *pmpriv)
152 {
153 wlan_11h_interface_state_t *pistate_11h = &pmpriv->intf_state_11h;
154
155 ENTER();
156
157 pistate_11h->is_11h_enabled = MTRUE;
158 pistate_11h->is_11h_active = MFALSE;
159 pistate_11h->adhoc_auto_sel_chan = MTRUE;
160 pistate_11h->tx_disabled = MFALSE;
161
162 LEAVE();
163 }
164
165 /**
166 * @brief Check if the current region's regulations require the input channel
167 * to be scanned for radar.
168 *
169 * Based on statically defined requirements for sub-bands per regulatory
170 * agency requirements.
171 *
172 * Used in adhoc start to determine if channel availability check is required
173 *
174 * @param priv Private driver information structure
175 * @param channel Channel to determine radar detection requirements
176 *
177 * @return
178 * - MTRUE if radar detection is required
179 * - MFALSE otherwise
180 */
181 /** @sa wlan_11h_issue_radar_detect
182 */
wlan_11h_radar_detect_required(mlan_private * priv,t_u8 channel)183 t_bool wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel)
184 {
185 t_bool required = MFALSE;
186
187 ENTER();
188
189 /*
190 * No checks for 11h or measurement code being enabled is placed here
191 * since regulatory requirements exist whether we support them or not.
192 */
193
194 required = wlan_get_cfp_radar_detect(priv, channel);
195
196 if (!priv->adapter->region_code)
197 {
198 PRINTM(MINFO,
199 "11h: Radar detection in CFP code[BG:%#x, A:%#x] "
200 "is %srequired for channel %d\n",
201 priv->adapter->cfp_code_bg, priv->adapter->cfp_code_a, (required ? "" : "not "), channel);
202 }
203 else
204 {
205 PRINTM(MINFO,
206 "11h: Radar detection in region %#02x "
207 "is %srequired for channel %d\n",
208 priv->adapter->region_code, (required ? "" : "not "), channel);
209 }
210
211 if (required == MTRUE && priv->media_connected == MTRUE && priv->curr_bss_params.bss_descriptor.channel == channel)
212 {
213 required = MFALSE;
214
215 PRINTM(MINFO,
216 "11h: Radar detection not required. "
217 "Already operating on the channel\n");
218 }
219
220 LEAVE();
221 return required;
222 }
223
224 #if CONFIG_ECSA
225 /**
226 * @brief try to get a non-dfs channel
227 *
228 * @param priv Void pointer to mlan_private
229 *
230 * @param chan pointer to channel
231 *
232 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
233 */
wlan_get_non_dfs_chan(mlan_private * priv,t_u8 * chan)234 mlan_status wlan_get_non_dfs_chan(mlan_private *priv, t_u8 *chan)
235 {
236 mlan_status ret = MLAN_STATUS_FAILURE;
237 t_u32 band = 0;
238 t_u32 entry;
239 t_u8 def_chan = 0;
240 region_chan_t *chn_tbl = MNULL;
241 pmlan_adapter pmadapter = priv->adapter;
242
243 ENTER();
244
245 if(!chan || *chan == 0)
246 {
247 PRINTM(MERROR, "11h: Invalid channel\n");
248 goto done;
249 }
250
251 if (*chan > 14)
252 band = BAND_5GHZ;
253 else
254 band = BAND_2GHZ;
255 /* get the channel table first */
256 chn_tbl = &pmadapter->region_channel[band];
257 if (!chn_tbl || !chn_tbl->pcfp)
258 {
259 goto done;
260 }
261
262 for (entry = 0; entry < chn_tbl->num_cfp; entry++)
263 {
264 if (chn_tbl->pcfp[entry].passive_scan_or_radar_detect == MFALSE)
265 {
266 def_chan = (t_u8)chn_tbl->pcfp[entry].channel;
267 break;
268 }
269 }
270
271 if (entry == chn_tbl->num_cfp)
272 {
273 goto done;
274 }
275
276 *chan = def_chan;
277 ret = MLAN_STATUS_SUCCESS;
278 done:
279 LEAVE();
280 return ret;
281 }
282 #endif
283