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