1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: This file contains definition for mandatory legacy API
20 */
21
22 #include "qdf_str.h"
23 #include "wlan_utility.h"
24 #include <wlan_cmn.h>
25 #include "wlan_osif_priv.h"
26 #include <net/cfg80211.h>
27 #include <qdf_module.h>
28 #include <wlan_vdev_mlme_api.h>
29 #include "cfg_ucfg_api.h"
30 #include <wlan_serialization_api.h>
31 #include "wlan_cm_api.h"
32 #include "host_diag_core_event.h"
33
34 /* CRC polynomial 0xedb88320 */
35 static unsigned long const wlan_shortssid_table[] = {
36 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
37 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
38 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
39 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
40 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
41 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
42 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
43 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
44 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
45 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
46 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
47 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
48 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
49 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
50 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
51 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
52 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
53 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
54 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
55 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
56 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
57 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
58 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
59 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
60 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
61 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
62 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
63 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
64 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
65 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
66 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
67 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
68 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
69 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
70 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
71 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
72 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
73 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
74 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
75 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
76 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
77 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
78 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
79 };
80
wlan_construct_shortssid(uint8_t * ssid,uint8_t ssid_len)81 uint32_t wlan_construct_shortssid(uint8_t *ssid, uint8_t ssid_len)
82 {
83 uint32_t shortssid = 0xffffffff;
84 uint8_t i;
85
86 if (!ssid || ssid_len > WLAN_SSID_MAX_LEN)
87 return shortssid;
88
89 for (i = 0; i < ssid_len; i++)
90 shortssid = wlan_shortssid_table[(shortssid ^ ssid[i]) & 0xff] ^
91 (shortssid >> 8);
92 return (shortssid ^ 0xffffffff);
93 }
94
wlan_chan_to_freq(uint8_t chan)95 uint32_t wlan_chan_to_freq(uint8_t chan)
96 {
97 if (chan == 0 )
98 return 0;
99
100 if (chan < WLAN_24_GHZ_CHANNEL_14)
101 return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
102 else if (chan == WLAN_24_GHZ_CHANNEL_14)
103 return WLAN_CHAN_14_FREQ;
104 else if (chan < WLAN_24_GHZ_CHANNEL_27)
105 /* ch 15 - ch 26 */
106 return WLAN_CHAN_15_FREQ +
107 (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ;
108 else if (chan == WLAN_5_GHZ_CHANNEL_170)
109 return WLAN_CHAN_170_FREQ;
110 else
111 return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
112 }
113
wlan_freq_to_chan(uint32_t freq)114 uint8_t wlan_freq_to_chan(uint32_t freq)
115 {
116 uint8_t chan;
117
118 if (freq == 0)
119 return 0;
120
121 if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ)
122 chan = ((freq - WLAN_24_GHZ_BASE_FREQ) /
123 WLAN_CHAN_SPACING_5MHZ);
124 else if (freq == WLAN_CHAN_14_FREQ)
125 chan = WLAN_24_GHZ_CHANNEL_14;
126 else if ((freq > WLAN_24_GHZ_BASE_FREQ) &&
127 (freq < WLAN_5_GHZ_BASE_FREQ))
128 chan = (((freq - WLAN_CHAN_15_FREQ) /
129 WLAN_CHAN_SPACING_20MHZ) +
130 WLAN_24_GHZ_CHANNEL_15);
131 else
132 chan = (freq - WLAN_5_GHZ_BASE_FREQ) /
133 WLAN_CHAN_SPACING_5MHZ;
134
135 return chan;
136 }
137
138 void
wlan_get_320_center_freq(qdf_freq_t freq,qdf_freq_t * center_freq1,qdf_freq_t * center_freq2)139 wlan_get_320_center_freq(qdf_freq_t freq,
140 qdf_freq_t *center_freq1,
141 qdf_freq_t *center_freq2)
142 {
143 *center_freq1 = 0;
144 *center_freq2 = 0;
145
146 if ((freq >= 5500) && (freq <= 5800)) {
147 *center_freq1 = 5650;
148 } else if ((freq >= 5955) && (freq <= 6095)) {
149 *center_freq1 = 6105;
150 } else if ((freq >= 6115) && (freq <= 6255)) {
151 *center_freq1 = 6105;
152 *center_freq2 = 6265;
153 } else if ((freq >= 6275) && (freq <= 6415)) {
154 *center_freq1 = 6265;
155 *center_freq2 = 6425;
156 } else if ((freq >= 6435) && (freq <= 6575)) {
157 *center_freq1 = 6425;
158 *center_freq2 = 6585;
159 } else if ((freq >= 6595) && (freq <= 6735)) {
160 *center_freq1 = 6585;
161 *center_freq2 = 6745;
162 } else if ((freq >= 6755) && (freq <= 6895)) {
163 *center_freq1 = 6745;
164 *center_freq2 = 6905;
165 } else if ((freq >= 6915) && (freq <= 7055)) {
166 *center_freq1 = 6905;
167 }
168 }
169
wlan_is_ie_valid(const uint8_t * ie,size_t ie_len)170 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len)
171 {
172 uint8_t elen;
173
174 while (ie_len) {
175 if (ie_len < 2)
176 return false;
177
178 elen = ie[1];
179 ie_len -= 2;
180 ie += 2;
181 if (elen > ie_len)
182 return false;
183
184 ie_len -= elen;
185 ie += elen;
186 }
187
188 return true;
189 }
190
wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,const uint8_t * oui,uint8_t oui_size,const uint8_t * ie,uint16_t ie_len)191 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,
192 const uint8_t *oui,
193 uint8_t oui_size,
194 const uint8_t *ie,
195 uint16_t ie_len)
196 {
197 int32_t left = ie_len;
198 const uint8_t *ptr = ie;
199 uint8_t elem_id, elem_len;
200
201 while (left >= 2) {
202 elem_id = ptr[0];
203 elem_len = ptr[1];
204 left -= 2;
205
206 if (elem_len > left)
207 return NULL;
208
209 if (eid == elem_id) {
210 /* if oui is not provide eid match is enough */
211 if (!oui)
212 return ptr;
213
214 /*
215 * if oui is provided and oui_size is more than left
216 * bytes, then we cannot have match
217 */
218 if (oui_size > left)
219 return NULL;
220
221 if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0)
222 return ptr;
223 }
224
225 left -= elem_len;
226 ptr += (elem_len + 2);
227 }
228
229 return NULL;
230 }
231
wlan_iecap_set(uint8_t * iecap,uint8_t bit_pos,uint8_t tot_bits,uint32_t value)232 void wlan_iecap_set(uint8_t *iecap,
233 uint8_t bit_pos,
234 uint8_t tot_bits,
235 uint32_t value)
236 {
237 uint8_t fit_bits;
238 uint8_t byte_cnt;
239 uint8_t prev_fit_bits = 0;
240 uint32_t shift_value;
241
242 /* calculate byte position of the field in IE capability */
243 byte_cnt = bit_pos / 8;
244 /* calculate the bit position in the start byte that needs to be set */
245 bit_pos = bit_pos % 8;
246 fit_bits = 8 - bit_pos;
247 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
248
249 while ((bit_pos + tot_bits) > 8) {
250 /* clear the target bit */
251 QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, value);
252 tot_bits = tot_bits - fit_bits;
253 bit_pos = bit_pos + fit_bits;
254 if (bit_pos == 8) {
255 bit_pos = 0;
256 byte_cnt++;
257 }
258 prev_fit_bits = prev_fit_bits + fit_bits;
259 fit_bits = 8 - bit_pos;
260 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
261 }
262
263 if ((bit_pos + tot_bits) <= 8) {
264 /* clear the target bit */
265 shift_value = value >> prev_fit_bits;
266 QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, shift_value);
267 }
268 }
269
wlan_iecap_get(uint8_t * iecap,uint8_t bit_pos,uint32_t tot_bits)270 uint32_t wlan_iecap_get(uint8_t *iecap,
271 uint8_t bit_pos,
272 uint32_t tot_bits)
273 {
274 uint8_t fit_bits;
275 uint8_t byte_cnt;
276 uint8_t temp_val;
277 uint8_t cur_bit_pos = 0;
278 uint32_t val = 0;
279
280 /* calculate byte position of the field in IE capability */
281 byte_cnt = bit_pos / 8;
282 temp_val = *(iecap + byte_cnt);
283 /* calculate the bit position in the start byte */
284 bit_pos = bit_pos % 8;
285 fit_bits = 8 - bit_pos;
286 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
287
288 while ((tot_bits + bit_pos) > 8) {
289 val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos;
290 tot_bits = tot_bits - fit_bits;
291 bit_pos = bit_pos + fit_bits;
292 if (bit_pos == 8) {
293 bit_pos = 0;
294 byte_cnt++;
295 temp_val = *(iecap + byte_cnt);
296 }
297 cur_bit_pos = cur_bit_pos + fit_bits;
298
299 fit_bits = 8 - bit_pos;
300 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
301 }
302
303 if ((bit_pos + tot_bits) <= 8)
304 val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos;
305
306 return val;
307 }
308
wlan_get_ie_ptr_from_eid(uint8_t eid,const uint8_t * ie,int ie_len)309 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid,
310 const uint8_t *ie,
311 int ie_len)
312 {
313 return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len);
314 }
315
wlan_get_vendor_ie_ptr_from_oui(const uint8_t * oui,uint8_t oui_size,const uint8_t * ie,uint16_t ie_len)316 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui,
317 uint8_t oui_size,
318 const uint8_t *ie,
319 uint16_t ie_len)
320 {
321 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR,
322 oui, oui_size, ie, ie_len);
323 }
324
wlan_get_ext_ie_ptr_from_ext_id(const uint8_t * oui,uint8_t oui_size,const uint8_t * ie,uint16_t ie_len)325 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui,
326 uint8_t oui_size,
327 const uint8_t *ie,
328 uint16_t ie_len)
329 {
330 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT,
331 oui, oui_size, ie, ie_len);
332 }
333
334 static inline
wlan_get_elemunit_info(bool is_subelem,uint8_t subelemfragid,uint8_t * elemunit_fragid,qdf_size_t * elemunit_hdrlen,qdf_size_t * elemunit_maxpayloadlen,int * elemunit_id_pos,int * elemunit_len_pos,int * elemunit_idext_pos)335 QDF_STATUS wlan_get_elemunit_info(bool is_subelem,
336 uint8_t subelemfragid,
337 uint8_t *elemunit_fragid,
338 qdf_size_t *elemunit_hdrlen,
339 qdf_size_t *elemunit_maxpayloadlen,
340 int *elemunit_id_pos,
341 int *elemunit_len_pos,
342 int *elemunit_idext_pos)
343 {
344 /* Helper function to populate information about the given element unit.
345 * Here, an 'element unit' refers to either an 802.11 element or a
346 * 802.11 subelement.
347 *
348 * Populating this information in a central helper here allows for
349 * better control over handling of future variances, and also for common
350 * code for handling different types of element units.
351 */
352
353 if (is_subelem) {
354 /* Populate the subelement header length */
355 if (elemunit_hdrlen)
356 *elemunit_hdrlen = sizeof(struct subelem_header);
357
358 /* Populate the subelement's max payload length */
359 if (elemunit_maxpayloadlen)
360 *elemunit_maxpayloadlen = WLAN_MAX_SUBELEM_LEN;
361
362 /* Populate the index position for the subelement ID */
363 if (elemunit_id_pos)
364 *elemunit_id_pos = qdf_offsetof(struct subelem_header,
365 subelem_id);
366
367 /* Populate the index position for the subelement length */
368 if (elemunit_len_pos)
369 *elemunit_len_pos = qdf_offsetof(struct subelem_header,
370 subelem_len);
371
372 /* Mark that there is (currently) no valid value for subelement
373 * ID extension.
374 */
375 if (elemunit_idext_pos)
376 *elemunit_idext_pos = -1;
377
378 /* Populate the subelement fragment ID (which can vary by
379 * protocol area). This could also have been directly populated
380 * by the caller, but we populate it here for uniformity and
381 * future control of variability.
382 */
383 if (elemunit_fragid)
384 *elemunit_fragid = subelemfragid;
385 } else {
386 /* Populate the element header length */
387 if (elemunit_hdrlen)
388 *elemunit_hdrlen = sizeof(struct ie_header);
389
390 /* Populate the element's max payload length */
391 if (elemunit_maxpayloadlen)
392 *elemunit_maxpayloadlen = WLAN_MAX_IE_LEN;
393
394 /* Populate the index position for the element ID */
395 if (elemunit_id_pos)
396 *elemunit_id_pos = qdf_offsetof(struct ie_header,
397 ie_id);
398
399 /* Populate the index position for the element length */
400 if (elemunit_len_pos)
401 *elemunit_len_pos = qdf_offsetof(struct ie_header,
402 ie_len);
403
404 /* Populate the index position for the element ID extension
405 */
406 if (elemunit_idext_pos)
407 *elemunit_idext_pos =
408 qdf_offsetof(struct extn_ie_header, ie_extn_id);
409
410 /* Populate the element fragment ID. */
411 if (elemunit_fragid)
412 *elemunit_fragid = WLAN_ELEMID_FRAGMENT;
413 }
414
415 return QDF_STATUS_SUCCESS;
416 }
417
418 static QDF_STATUS
wlan_get_elemsubelem_fragseq_creationparams(bool is_subelem,uint8_t id,qdf_size_t payloadlen,bool * is_frag_required,qdf_size_t * expected_fragseqlen,qdf_size_t * prepayload_leadbytes,uint32_t * num_maxsizefrags,qdf_size_t * smallerfrag_size,qdf_size_t * extrahdrbytes)419 wlan_get_elemsubelem_fragseq_creationparams(bool is_subelem,
420 uint8_t id,
421 qdf_size_t payloadlen,
422 bool *is_frag_required,
423 qdf_size_t *expected_fragseqlen,
424 qdf_size_t *prepayload_leadbytes,
425 uint32_t *num_maxsizefrags,
426 qdf_size_t *smallerfrag_size,
427 qdf_size_t *extrahdrbytes)
428 {
429 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
430 * or a 802.11 subelement.
431 */
432 qdf_size_t elemunit_hdrlen;
433 qdf_size_t elemunit_maxpayloadlen;
434
435 qdf_size_t tmp_expected_fragseqlen;
436 qdf_size_t tmp_prepayload_leadbytes;
437 uint32_t tmp_num_maxsizefrags;
438 qdf_size_t tmp_smallerfrag_size;
439 qdf_size_t tmp_extrahdrbytes;
440
441 QDF_STATUS ret;
442
443 /* Helper function to determine element or subelement fragment sequence
444 * creation parameters. Currently, this helper determines the following
445 * parameters (it is mandatory for the caller to provide the pointer
446 * for the first parameter, those for the remaining are optional):
447 *
448 * - Whether fragmentation is required
449 * If fragmentation is required then the following are determined, else
450 * they should be ignored by the caller:
451 * - Expected fragment sequence length (inclusive of payload and all
452 * headers)
453 * - The lead bytes that occur before the payload (i.e. the lead
454 * element/subelement's header, and if applicable, the element's
455 * element ID extension)
456 * - The number of max sized fragments (inclusive of the lead element)
457 * - The size of the smaller sized fragment at the end (non-zero if such
458 * a fragment would be present, zero if it would be absent)
459 * - The number of extra header bytes that would be introduced (not
460 * inclusive of the header of the lead fragment).
461 */
462
463 if (!is_frag_required) {
464 qdf_nofl_err("Pointer to indication of whether fragmentation is required or not is NULL");
465 return QDF_STATUS_E_NULL_VALUE;
466 }
467
468 ret = wlan_get_elemunit_info(is_subelem,
469 0,
470 NULL,
471 &elemunit_hdrlen,
472 &elemunit_maxpayloadlen,
473 NULL,
474 NULL,
475 NULL);
476 if (QDF_IS_STATUS_ERROR(ret)) {
477 qdf_rl_nofl_err("Get elem unit info: Error %d",
478 ret);
479 return QDF_STATUS_E_FAILURE;
480 }
481
482 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) {
483 if (payloadlen <= (elemunit_maxpayloadlen - 1)) {
484 *is_frag_required = false;
485 return QDF_STATUS_SUCCESS;
486 }
487 } else {
488 if (payloadlen <= elemunit_maxpayloadlen) {
489 *is_frag_required = false;
490 return QDF_STATUS_SUCCESS;
491 }
492 }
493
494 *is_frag_required = true;
495
496 if (!expected_fragseqlen &&
497 !prepayload_leadbytes && !num_maxsizefrags &&
498 !smallerfrag_size && !extrahdrbytes)
499 return QDF_STATUS_SUCCESS;
500
501 tmp_expected_fragseqlen = 0;
502 tmp_prepayload_leadbytes = 0;
503 tmp_num_maxsizefrags = 0;
504 tmp_smallerfrag_size = 0;
505 tmp_extrahdrbytes = 0;
506
507 /* As per the standard, the information to be fragmented is divided into
508 * M + N portions, where the following define each variable:
509 *
510 * I)For an element without an Element ID Extension field, or for a
511 * subelement:
512 * L is the size of the information in octets (this does not include the
513 * element/subelement header)
514 * M is L/255 floored
515 * N is equal to 1 if L mod 255 > 0 and equal to 0 otherwise.
516 * The size of each of the M fragments is 255 octets
517 * If N is 1, then the size of this single fragment is L mod 255 octets
518 *
519 * II) For an element with an Element ID Extension field:
520 * L is the size of the information in octets (this does not include the
521 * element header and the element ID extension field)
522 * M is (L + 1)/255 floored
523 * N is equal to 1 if (L - 254) mod 255 > 0 and equal to 0 otherwise.
524 * The size of each of the M fragments is 255 octets
525 * If N is 1, then the size of this single fragment is (L - 254) mod 255
526 * octets.
527 *
528 * For both I and II above, the mapping of code variables is as follows:
529 * payloadlen = L
530 * tmp_num_maxsizefrags = M
531 * tmp_smallerfrag_size = Size of N if N is 1, else 0
532 * Additionally, elemunit_maxpayloadlen is used to denote the value
533 * 255 for future extensibility if and when required.
534 */
535
536 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) {
537 tmp_num_maxsizefrags = (payloadlen + 1) /
538 elemunit_maxpayloadlen;
539 tmp_smallerfrag_size =
540 (payloadlen - (elemunit_maxpayloadlen - 1)) %
541 elemunit_maxpayloadlen;
542 } else {
543 tmp_num_maxsizefrags = payloadlen / elemunit_maxpayloadlen;
544 tmp_smallerfrag_size = payloadlen %
545 elemunit_maxpayloadlen;
546 }
547
548 /* Determine the number of extra bytes introduced due to the headers of
549 * non-leading fragments.
550 */
551 tmp_extrahdrbytes = (tmp_num_maxsizefrags - 1) * elemunit_hdrlen;
552 if (tmp_smallerfrag_size)
553 tmp_extrahdrbytes += elemunit_hdrlen;
554
555 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
556 tmp_prepayload_leadbytes = elemunit_hdrlen + 1;
557 else
558 tmp_prepayload_leadbytes = elemunit_hdrlen;
559
560 tmp_expected_fragseqlen = tmp_prepayload_leadbytes +
561 payloadlen + tmp_extrahdrbytes;
562
563 if (expected_fragseqlen)
564 *expected_fragseqlen = tmp_expected_fragseqlen;
565
566 if (prepayload_leadbytes)
567 *prepayload_leadbytes = tmp_prepayload_leadbytes;
568
569 if (num_maxsizefrags)
570 *num_maxsizefrags = tmp_num_maxsizefrags;
571
572 if (smallerfrag_size)
573 *smallerfrag_size = tmp_smallerfrag_size;
574
575 if (extrahdrbytes)
576 *extrahdrbytes = tmp_extrahdrbytes;
577
578 return QDF_STATUS_SUCCESS;
579 }
580
581 static QDF_STATUS
wlan_create_elemsubelem_fragseq(bool inline_frag,bool is_subelem,uint8_t id,uint8_t idext,uint8_t subelemfragid,uint8_t * payloadbuff,qdf_size_t payloadbuff_maxsize,qdf_size_t payloadlen,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,qdf_size_t * fragseqlen)582 wlan_create_elemsubelem_fragseq(bool inline_frag,
583 bool is_subelem,
584 uint8_t id,
585 uint8_t idext,
586 uint8_t subelemfragid,
587 uint8_t *payloadbuff,
588 qdf_size_t payloadbuff_maxsize,
589 qdf_size_t payloadlen,
590 uint8_t *fragbuff,
591 qdf_size_t fragbuff_maxsize,
592 qdf_size_t *fragseqlen)
593 {
594 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
595 * or a 802.11 subelement.
596 */
597 uint8_t elemunit_fragid;
598 qdf_size_t elemunit_hdrlen;
599 qdf_size_t elemunit_maxpayloadlen;
600 int elemunit_id_pos;
601 int elemunit_len_pos;
602 int elemunit_idext_pos;
603 uint8_t *curr_elemunit_ptr;
604
605 /* Whether fragmentation is required */
606 bool is_frag_required;
607
608 /*Fragment sequence length (inclusive of payload and all headers) */
609 qdf_size_t expected_fragseqlen;
610
611 /* Number of fragments with the maximum size */
612 uint32_t num_maxsizefrags;
613 /* Size of the last fragment which is smaller than the maximum (if
614 * present). If such a fragment is not present, this size will be zero.
615 */
616 qdf_size_t smallerfrag_size;
617
618 /* The number of extra header bytes that would be introduced (not
619 * inclusive of the header of the lead fragment).
620 */
621 qdf_size_t extrahdrbytes;
622 /* The number of extra header bytes remaining to be introduced */
623 qdf_size_t extrahdrbytes_remaining;
624
625 /* The lead bytes that occur before the payload */
626 qdf_size_t prepayload_leadbytes;
627
628 /* used for inline copy, the extra bytes needed in the payload buffer
629 * due to difference in destination and source.
630 * Note that the caller should ensure there is enough bytes beyond
631 * valid data until payloadbuff_maxsize*/
632 qdf_size_t payloadbuff_shiftsize;
633
634 /* Miscellaneous variables */
635 uint8_t *src;
636 uint8_t *dst;
637 uint16_t i;
638 qdf_size_t bytes_to_transfer;
639
640 QDF_STATUS ret;
641
642 /* Helper function to create an element or subelement fragment sequence.
643 * Refer to the documentation of the public APIs which call this helper,
644 * for more information. These APIs are mainly wrappers over this
645 * helper.
646 */
647
648 ret = wlan_get_elemunit_info(is_subelem,
649 subelemfragid,
650 &elemunit_fragid,
651 &elemunit_hdrlen,
652 &elemunit_maxpayloadlen,
653 &elemunit_id_pos,
654 &elemunit_len_pos,
655 &elemunit_idext_pos);
656 if (QDF_IS_STATUS_ERROR(ret)) {
657 qdf_rl_nofl_err("Get elem unit info: Error %d",
658 ret);
659 return QDF_STATUS_E_FAILURE;
660 }
661
662 ret = wlan_get_elemsubelem_fragseq_creationparams(is_subelem,
663 id,
664 payloadlen,
665 &is_frag_required,
666 &expected_fragseqlen,
667 &prepayload_leadbytes,
668 &num_maxsizefrags,
669 &smallerfrag_size,
670 &extrahdrbytes);
671 if (QDF_IS_STATUS_ERROR(ret))
672 return ret;
673
674 if (!is_frag_required) {
675 /* We treat this as an error since the caller is expected to
676 * have first determined requirements related to fragmentation,
677 * including whether fragmentation is required or not.
678 */
679 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
680 qdf_nofl_err("Fragmentation inapplicable for elem with elem ID ext and post elem ID ext payload len %zu",
681 payloadlen);
682 else
683 qdf_nofl_err("Fragmentation inapplicable for subelem/elem without elem ID ext and with payload len %zu",
684 payloadlen);
685
686 return QDF_STATUS_E_INVAL;
687 }
688
689 if (!payloadbuff) {
690 qdf_nofl_err("Payload buff is NULL");
691 return QDF_STATUS_E_NULL_VALUE;
692 }
693
694 if (payloadbuff_maxsize == 0) {
695 qdf_nofl_err("Payload buff max size is 0");
696 return QDF_STATUS_E_INVAL;
697 }
698
699 if (payloadbuff_maxsize < payloadlen) {
700 qdf_nofl_err("Payload buff max size %zu < payload len %zu",
701 payloadbuff_maxsize,
702 payloadlen);
703 return QDF_STATUS_E_INVAL;
704 }
705
706 if (inline_frag) {
707 if (payloadbuff_maxsize < expected_fragseqlen) {
708 qdf_nofl_err("Inline frag buff max size %zu < frag sequence expected len %zu",
709 payloadbuff_maxsize,
710 expected_fragseqlen);
711 return QDF_STATUS_E_INVAL;
712 }
713 } else {
714 if (!fragbuff) {
715 qdf_nofl_err("Frag sequence buff is NULL");
716 return QDF_STATUS_E_NULL_VALUE;
717 }
718
719 if (fragbuff_maxsize == 0) {
720 qdf_nofl_err("Frag sequence buff max size is 0");
721 return QDF_STATUS_E_INVAL;
722 }
723
724 if (fragbuff_maxsize < expected_fragseqlen) {
725 qdf_nofl_err("Frag sequence buff max size %zu < frag sequence expected len %zu",
726 fragbuff_maxsize,
727 expected_fragseqlen);
728 return QDF_STATUS_E_INVAL;
729 }
730 }
731
732 if (!fragseqlen) {
733 qdf_nofl_err("Pointer to location of frag sequence len is NULL");
734 return QDF_STATUS_E_NULL_VALUE;
735 }
736
737 /* Preferably, ensure that error checks (if any) for future changes are
738 * executed before this point. We wouldn't want to touch the destination
739 * buffer unless we are sure we can successfully execute (especially for
740 * the inline mode).
741 */
742
743 /* We rely on wlan_get_elemsubelem_fragseq_creationparams() to give us
744 * sane values for extrahdrbytes and other parameters.
745 */
746
747 extrahdrbytes_remaining = extrahdrbytes;
748
749 /* We need to accommodate elemunit_hdrlen bytes for each non-leading
750 * fragment by moving the non-leading fragment to a higher location.
751 * Shift bytes and form fragment elements/subelements starting with the
752 * last fragment and going backwards from there.
753 */
754
755 /* First move/copy the smaller sized fragment if present */
756 if (smallerfrag_size) {
757 /* The source for the copy/move is just after the end of all the
758 * max sized fragments (including the lead fragment). The
759 * element unit header is present for the lead fragment alone.
760 */
761 src = payloadbuff + elemunit_hdrlen +
762 (num_maxsizefrags * elemunit_maxpayloadlen);
763
764 /* The destination for the copy/move is computed to reflect a
765 * shift by extrahdrbytes_remaining to accommodate the headers
766 * for the smaller fragment and all the non-lead max sized
767 * fragments.
768 */
769 if (inline_frag)
770 dst = src + extrahdrbytes_remaining;
771 else
772 dst = fragbuff + elemunit_hdrlen +
773 (num_maxsizefrags * elemunit_maxpayloadlen) +
774 extrahdrbytes_remaining;
775
776 bytes_to_transfer = smallerfrag_size;
777
778 /* Account for increased size due to shift in data */
779 if (inline_frag && (dst > src))
780 payloadbuff_shiftsize = (dst - src);
781 else
782 payloadbuff_shiftsize = 0;
783
784 /* In the case of inline fragmentation, if the payload buffer
785 * has additional contents beyond the payload, include those
786 * contents in the move/copy.
787 */
788 if (inline_frag &&
789 (payloadbuff_maxsize > (prepayload_leadbytes + payloadlen)))
790 bytes_to_transfer += (payloadbuff_maxsize -
791 prepayload_leadbytes -
792 payloadlen -
793 payloadbuff_shiftsize);
794
795 if (inline_frag)
796 qdf_mem_move(dst, src, bytes_to_transfer);
797 else
798 qdf_mem_copy(dst, src, bytes_to_transfer);
799
800 /* Copy/move of payload done. Set fragment ID and length in
801 * element unit header.
802 */
803 curr_elemunit_ptr = dst - elemunit_hdrlen;
804 curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid;
805 curr_elemunit_ptr[elemunit_len_pos] = smallerfrag_size;
806
807 extrahdrbytes_remaining -= elemunit_hdrlen;
808 }
809
810 /* Next, move/copy the non-lead max-sized fragments, if present.
811 * Fragments at higher memory locations are processed first.
812 */
813 for (i = num_maxsizefrags; i > 1; i--) {
814 /* Process the 'i'th max-sized fragment. The lead max-sized
815 * fragment has i=1 and is not processed in this 'for' loop.
816 * Also note that 'previous .* fragments' in comments for this
817 * 'for' loop refers to fragments in lower memory locations as
818 * compared to the current, i.e. 'i'th max-sized fragment.
819 */
820
821 /* The source for the copy/move is just after the end of all the
822 * previous max-sized fragments (including the lead fragment).
823 * The element unit header is present for the lead fragment
824 * alone.
825 */
826 src = payloadbuff + elemunit_hdrlen +
827 ((i - 1) * elemunit_maxpayloadlen);
828
829 /* The destination for the copy/move is computed to reflect a
830 * shift by extrahdrbytes_remaining to accommodate the headers
831 * for the current non-lead max-sized fragment and all the
832 * previous max-sized non-lead fragments.
833 */
834 if (inline_frag)
835 dst = src + extrahdrbytes_remaining;
836 else
837 dst = fragbuff + elemunit_hdrlen +
838 ((i - 1) * elemunit_maxpayloadlen) +
839 extrahdrbytes_remaining;
840
841 bytes_to_transfer = elemunit_maxpayloadlen;
842
843 /* Account for increased size due to shift in data */
844 if (inline_frag && (dst > src))
845 payloadbuff_shiftsize = (dst - src);
846 else
847 payloadbuff_shiftsize = 0;
848
849 /* In the case of inline fragmentation, if this is the last
850 * non-lead max-sized fragment (i.e. at the highest memory
851 * location), if the payload buffer has additional contents
852 * beyond the payload, and these additional contents have not
853 * already been taken care of by the presence (and processing)
854 * of a smaller fragment, include the additional contents in the
855 * move/copy.
856 */
857 if (inline_frag &&
858 (i == num_maxsizefrags) &&
859 (payloadbuff_maxsize > (prepayload_leadbytes +
860 payloadlen)) &&
861 !smallerfrag_size)
862 bytes_to_transfer += (payloadbuff_maxsize -
863 prepayload_leadbytes -
864 payloadlen -
865 payloadbuff_shiftsize);
866
867 if (inline_frag)
868 qdf_mem_move(dst, src, bytes_to_transfer);
869 else
870 qdf_mem_copy(dst, src, bytes_to_transfer);
871
872 /* Copy/move of payload done. Set fragment ID and length in
873 * element unit header.
874 */
875 curr_elemunit_ptr = dst - elemunit_hdrlen;
876 curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid;
877 curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen;
878
879 extrahdrbytes_remaining -= elemunit_hdrlen;
880 }
881
882 /* Update the element unit pointer for the lead max-sized fragment.
883 *
884 * Copy the payload of the lead max-sized fragment if inline
885 * fragmentation is not being used.
886 */
887 if (inline_frag) {
888 curr_elemunit_ptr = payloadbuff;
889 } else {
890 qdf_mem_copy(fragbuff + elemunit_hdrlen,
891 payloadbuff + elemunit_hdrlen,
892 elemunit_maxpayloadlen);
893 curr_elemunit_ptr = fragbuff;
894 }
895
896 /* Set IDs and length in the header for the leading fragment */
897 curr_elemunit_ptr[elemunit_id_pos] = id;
898 curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen;
899 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
900 curr_elemunit_ptr[elemunit_idext_pos] = idext;
901
902 *fragseqlen = expected_fragseqlen;
903
904 return QDF_STATUS_SUCCESS;
905 }
906
907 static inline QDF_STATUS
wlan_get_elemsubelem_successorfrag(bool is_subelem,uint8_t subelemfragid,uint8_t * curr_elemunit_ptr,uint8_t * buff,qdf_size_t buff_maxsize,uint8_t ** successorfrag,qdf_size_t * successorfrag_totallen,qdf_size_t * successorfrag_payloadlen)908 wlan_get_elemsubelem_successorfrag(bool is_subelem,
909 uint8_t subelemfragid,
910 uint8_t *curr_elemunit_ptr,
911 uint8_t *buff,
912 qdf_size_t buff_maxsize,
913 uint8_t **successorfrag,
914 qdf_size_t *successorfrag_totallen,
915 qdf_size_t *successorfrag_payloadlen)
916 {
917 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
918 * or a 802.11 subelement.
919 */
920 uint8_t elemunit_fragid;
921 qdf_size_t elemunit_hdrlen;
922 qdf_size_t elemunit_maxpayloadlen;
923 int elemunit_id_pos;
924 int elemunit_len_pos;
925
926 qdf_size_t curr_elemunit_totallen;
927
928 uint8_t *next_elemunit_ptr;
929 qdf_size_t next_elemunit_totallen;
930
931 QDF_STATUS ret;
932
933 /* This helper checks if the very next element unit after the current
934 * one is a valid fragment element unit and that there is sufficient
935 * space in the buffer for this next element, and if so, it returns a
936 * pointer to this fragment element unit as well as the total length of
937 * this fragment element unit and the length of the payload of this
938 * fragment element unit.
939 */
940
941 ret = wlan_get_elemunit_info(is_subelem,
942 subelemfragid,
943 &elemunit_fragid,
944 &elemunit_hdrlen,
945 &elemunit_maxpayloadlen,
946 &elemunit_id_pos,
947 &elemunit_len_pos,
948 NULL);
949 if (QDF_IS_STATUS_ERROR(ret)) {
950 qdf_rl_nofl_err("Get elem unit info: Error %d",
951 ret);
952 return QDF_STATUS_E_FAILURE;
953 }
954
955 if (!curr_elemunit_ptr) {
956 qdf_nofl_err("Ptr to curr elem unit is NULL");
957 return QDF_STATUS_E_NULL_VALUE;
958 }
959
960 if (!buff) {
961 qdf_nofl_err("Elem unit buff is NULL");
962 return QDF_STATUS_E_NULL_VALUE;
963 }
964
965 if (buff_maxsize == 0) {
966 qdf_nofl_err("Max size of elem unit buff is 0");
967 return QDF_STATUS_E_INVAL;
968 }
969
970 if (!successorfrag) {
971 qdf_nofl_err("Double ptr to successor frag is NULL");
972 return QDF_STATUS_E_NULL_VALUE;
973 }
974
975 if (!successorfrag_totallen) {
976 qdf_nofl_err("Ptr to successor frag total len is NULL");
977 return QDF_STATUS_E_NULL_VALUE;
978 }
979
980 if (!successorfrag_payloadlen) {
981 qdf_nofl_err("Ptr to successor frag payload len is NULL");
982 return QDF_STATUS_E_NULL_VALUE;
983 }
984
985 if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) {
986 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
987 buff_maxsize - (curr_elemunit_ptr - buff),
988 curr_elemunit_ptr - buff,
989 elemunit_hdrlen);
990 return QDF_STATUS_E_PROTO;
991 }
992
993 curr_elemunit_totallen =
994 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
995
996 if ((buff + buff_maxsize) <
997 (curr_elemunit_ptr + curr_elemunit_totallen)) {
998 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
999 buff_maxsize - (curr_elemunit_ptr - buff),
1000 curr_elemunit_ptr - buff,
1001 curr_elemunit_totallen);
1002 return QDF_STATUS_E_PROTO;
1003 }
1004
1005 if ((buff + buff_maxsize) ==
1006 (curr_elemunit_ptr + curr_elemunit_totallen)) {
1007 /* We have reached the end of the buffer. There is no successor
1008 * fragment.
1009 */
1010 *successorfrag = NULL;
1011 return QDF_STATUS_SUCCESS;
1012 }
1013
1014 next_elemunit_ptr = curr_elemunit_ptr + curr_elemunit_totallen;
1015
1016 if ((buff + buff_maxsize) < (next_elemunit_ptr + elemunit_hdrlen)) {
1017 qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
1018 buff_maxsize - (next_elemunit_ptr - buff),
1019 next_elemunit_ptr - buff,
1020 elemunit_hdrlen);
1021 return QDF_STATUS_E_PROTO;
1022 }
1023
1024 next_elemunit_totallen =
1025 elemunit_hdrlen + next_elemunit_ptr[elemunit_len_pos];
1026
1027 if ((buff + buff_maxsize) <
1028 (next_elemunit_ptr + next_elemunit_totallen)) {
1029 qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
1030 buff_maxsize - (next_elemunit_ptr - buff),
1031 next_elemunit_ptr - buff,
1032 next_elemunit_totallen);
1033 return QDF_STATUS_E_PROTO;
1034 }
1035
1036 if (next_elemunit_ptr[elemunit_id_pos] != elemunit_fragid) {
1037 *successorfrag = NULL;
1038 return QDF_STATUS_SUCCESS;
1039 }
1040
1041 /* We should not be seeing a successor fragment if the length of the
1042 * current element unit is lesser than the max.
1043 */
1044 if (curr_elemunit_ptr[elemunit_len_pos] != elemunit_maxpayloadlen) {
1045 qdf_rl_nofl_err("Potential successor frag found though (len %u of payload of curr elem unit) != (max payload len %zu)",
1046 curr_elemunit_ptr[elemunit_len_pos],
1047 elemunit_maxpayloadlen);
1048 return QDF_STATUS_E_PROTO;
1049 }
1050
1051 if (next_elemunit_ptr[elemunit_len_pos] == 0) {
1052 qdf_rl_nofl_err("Potential successor frag len is 0");
1053 return QDF_STATUS_E_PROTO;
1054 }
1055
1056 *successorfrag = next_elemunit_ptr;
1057 *successorfrag_totallen = next_elemunit_totallen;
1058 *successorfrag_payloadlen = next_elemunit_ptr[elemunit_len_pos];
1059
1060 return QDF_STATUS_SUCCESS;
1061 }
1062
1063 static QDF_STATUS
wlan_get_elemsubelem_fragseq_info(bool is_subelem,uint8_t subelemfragid,uint8_t * buff,qdf_size_t buff_maxsize,bool * is_fragseq,qdf_size_t * fragseq_totallen,qdf_size_t * fragseq_payloadlen)1064 wlan_get_elemsubelem_fragseq_info(bool is_subelem,
1065 uint8_t subelemfragid,
1066 uint8_t *buff,
1067 qdf_size_t buff_maxsize,
1068 bool *is_fragseq,
1069 qdf_size_t *fragseq_totallen,
1070 qdf_size_t *fragseq_payloadlen)
1071 {
1072 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
1073 * or a 802.11 subelement.
1074 */
1075 qdf_size_t elemunit_hdrlen;
1076 int elemunit_id_pos;
1077 int elemunit_len_pos;
1078
1079 uint8_t *curr_elemunit_ptr;
1080 qdf_size_t curr_elemunit_totallen;
1081
1082 qdf_size_t fragseq_currtotallen;
1083 qdf_size_t fragseq_currpayloadlen;
1084
1085 uint8_t *successorfrag;
1086 qdf_size_t successorfrag_totallen;
1087 qdf_size_t successorfrag_payloadlen;
1088
1089 QDF_STATUS ret;
1090
1091 /* Helper function to get element or subelement fragment sequence
1092 * information. Refer to the documentation of the public APIs which
1093 * call this helper, for more information. These APIs are mainly
1094 * wrappers over this helper.
1095 *
1096 * If this helper reports that an element fragment sequence is present,
1097 * it also serves to check for the sanity of various lengths and
1098 * protocol requirements related to the fragment sequence (either by
1099 * itself or though other helpers).
1100 */
1101
1102 ret = wlan_get_elemunit_info(is_subelem,
1103 0,
1104 NULL,
1105 &elemunit_hdrlen,
1106 NULL,
1107 &elemunit_id_pos,
1108 &elemunit_len_pos,
1109 NULL);
1110 if (QDF_IS_STATUS_ERROR(ret)) {
1111 qdf_rl_nofl_err("Get elem unit info: Error %d",
1112 ret);
1113 return QDF_STATUS_E_FAILURE;
1114 }
1115
1116 if (!buff) {
1117 qdf_nofl_err("Elem unit buff is NULL");
1118 return QDF_STATUS_E_NULL_VALUE;
1119 }
1120
1121 if (buff_maxsize == 0) {
1122 qdf_nofl_err("Max size of elem unit buff is 0");
1123 return QDF_STATUS_E_INVAL;
1124 }
1125
1126 if (!is_fragseq) {
1127 qdf_nofl_err("Ptr to status of frag seq presence is NULL");
1128 return QDF_STATUS_E_NULL_VALUE;
1129 }
1130
1131 if (!fragseq_totallen) {
1132 qdf_nofl_err("Ptr to total len of frag seq is NULL");
1133 return QDF_STATUS_E_NULL_VALUE;
1134 }
1135
1136 if (!fragseq_payloadlen) {
1137 qdf_nofl_err("Ptr to payload len of frag seq is NULL");
1138 return QDF_STATUS_E_NULL_VALUE;
1139 }
1140
1141 curr_elemunit_ptr = buff;
1142 fragseq_currtotallen = 0;
1143 fragseq_currpayloadlen = 0;
1144
1145 if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) {
1146 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
1147 buff_maxsize - (curr_elemunit_ptr - buff),
1148 curr_elemunit_ptr - buff,
1149 elemunit_hdrlen);
1150 return QDF_STATUS_E_PROTO;
1151 }
1152
1153 curr_elemunit_totallen =
1154 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
1155
1156 if ((buff + buff_maxsize) <
1157 (curr_elemunit_ptr + curr_elemunit_totallen)) {
1158 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
1159 buff_maxsize - (curr_elemunit_ptr - buff),
1160 curr_elemunit_ptr - buff,
1161 curr_elemunit_totallen);
1162 return QDF_STATUS_E_PROTO;
1163 }
1164
1165 successorfrag = NULL;
1166
1167 ret = wlan_get_elemsubelem_successorfrag(is_subelem,
1168 subelemfragid,
1169 curr_elemunit_ptr,
1170 buff,
1171 buff_maxsize,
1172 &successorfrag,
1173 &successorfrag_totallen,
1174 &successorfrag_payloadlen);
1175 if (QDF_IS_STATUS_ERROR(ret))
1176 return ret;
1177
1178 if (!successorfrag) {
1179 *is_fragseq = false;
1180 *fragseq_totallen = 0;
1181 *fragseq_payloadlen = 0;
1182 return QDF_STATUS_SUCCESS;
1183 }
1184
1185 fragseq_currtotallen += curr_elemunit_totallen;
1186
1187 if (!is_subelem &&
1188 (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) {
1189 fragseq_currpayloadlen +=
1190 (curr_elemunit_ptr[elemunit_len_pos] - 1);
1191 } else {
1192 fragseq_currpayloadlen +=
1193 curr_elemunit_ptr[elemunit_len_pos];
1194 }
1195
1196 while (successorfrag) {
1197 /* wlan_get_elemsubelem_successorfrag() has already validated
1198 * the length values for the successor fragment.
1199 */
1200 fragseq_currtotallen += successorfrag_totallen;
1201 fragseq_currpayloadlen += successorfrag_payloadlen;
1202
1203 curr_elemunit_ptr = successorfrag;
1204 successorfrag = NULL;
1205
1206 ret = wlan_get_elemsubelem_successorfrag(is_subelem,
1207 subelemfragid,
1208 curr_elemunit_ptr,
1209 buff,
1210 buff_maxsize,
1211 &successorfrag,
1212 &successorfrag_totallen,
1213 &successorfrag_payloadlen);
1214 if (QDF_IS_STATUS_ERROR(ret))
1215 return ret;
1216 }
1217
1218 *is_fragseq = true;
1219 *fragseq_totallen = fragseq_currtotallen;
1220 *fragseq_payloadlen = fragseq_currpayloadlen;
1221
1222 return QDF_STATUS_SUCCESS;
1223 }
1224
wlan_defrag_elemsubelem_fragseq(bool inline_defrag,bool is_subelem,uint8_t subelemfragid,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,uint8_t * defragbuff,qdf_size_t defragbuff_maxsize,qdf_size_t * defragpayload_len)1225 static QDF_STATUS wlan_defrag_elemsubelem_fragseq(bool inline_defrag,
1226 bool is_subelem,
1227 uint8_t subelemfragid,
1228 uint8_t *fragbuff,
1229 qdf_size_t fragbuff_maxsize,
1230 uint8_t *defragbuff,
1231 qdf_size_t defragbuff_maxsize,
1232 qdf_size_t *defragpayload_len)
1233 {
1234 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
1235 * or a 802.11 subelement.
1236 */
1237 uint8_t elemunit_fragid;
1238 qdf_size_t elemunit_hdrlen;
1239 int elemunit_id_pos;
1240 int elemunit_len_pos;
1241 int elemunit_idext_pos;
1242
1243 bool is_fragseq;
1244 qdf_size_t fragseq_totallen;
1245 qdf_size_t fragseq_payloadlen;
1246
1247 uint8_t *curr_elemunit_ptr;
1248 qdf_size_t curr_elemunit_payloadlen;
1249 qdf_size_t curr_elemunit_totallen;
1250
1251 uint8_t *src;
1252 uint8_t *dst;
1253
1254 /* Current length of the defragmented payload */
1255 qdf_size_t defragpayload_currlen;
1256
1257 /* Remaining length available in the source buffer containing the
1258 * fragment sequence, after element units processed so far.
1259 */
1260 qdf_size_t fragbuff_remlen;
1261
1262 QDF_STATUS ret;
1263
1264 /* Helper function to de-fragment element or subelement fragment
1265 * sequence. Refer to the documentation of the public APIs which call
1266 * this helper, for more information. Those APIs are mainly wrappers
1267 * over this helper.
1268 */
1269
1270 ret = wlan_get_elemunit_info(is_subelem,
1271 subelemfragid,
1272 &elemunit_fragid,
1273 &elemunit_hdrlen,
1274 NULL,
1275 &elemunit_id_pos,
1276 &elemunit_len_pos,
1277 &elemunit_idext_pos);
1278 if (QDF_IS_STATUS_ERROR(ret)) {
1279 qdf_rl_nofl_err("Get elem unit info: Error %d",
1280 ret);
1281 return QDF_STATUS_E_FAILURE;
1282 }
1283
1284 if (!fragbuff) {
1285 qdf_nofl_err("Src buff for frag seq is NULL");
1286 return QDF_STATUS_E_NULL_VALUE;
1287 }
1288
1289 if (fragbuff_maxsize == 0) {
1290 qdf_nofl_err("Size of src buff for frag seq is 0");
1291 return QDF_STATUS_E_INVAL;
1292 }
1293
1294 if (!inline_defrag) {
1295 if (!defragbuff) {
1296 qdf_nofl_err("Dest buff for defragged payload is NULL");
1297 return QDF_STATUS_E_NULL_VALUE;
1298 }
1299
1300 if (defragbuff_maxsize == 0) {
1301 qdf_nofl_err("Size of dest buff for defragged payload is 0");
1302 return QDF_STATUS_E_INVAL;
1303 }
1304 }
1305
1306 if (!defragpayload_len) {
1307 qdf_nofl_err("Ptr to len of defragged payload is NULL");
1308 return QDF_STATUS_E_NULL_VALUE;
1309 }
1310
1311 ret = wlan_get_elemsubelem_fragseq_info(is_subelem,
1312 subelemfragid,
1313 fragbuff,
1314 fragbuff_maxsize,
1315 &is_fragseq,
1316 &fragseq_totallen,
1317 &fragseq_payloadlen);
1318 if (QDF_IS_STATUS_ERROR(ret))
1319 return ret;
1320
1321 if (!is_fragseq) {
1322 /* We treat this as an error since the caller is supposed to
1323 * check this.
1324 */
1325 qdf_rl_nofl_err("Frag seq not found at start of src buff for frag seq");
1326 return QDF_STATUS_E_INVAL;
1327 }
1328
1329 /* fragseq_totallen is known to be smaller than or equal to
1330 * fragbuff_maxsize since wlan_get_elemsubelem_fragseq_info() is bound
1331 * by fragbuff_maxsize in the search for a fragment sequence and it's
1332 * total length.
1333 */
1334
1335 if (!inline_defrag && (defragbuff_maxsize < fragseq_payloadlen)) {
1336 qdf_rl_nofl_err("(Size of dest buff for defragged payload %zu) < (size of frag seq payload %zu)",
1337 defragbuff_maxsize, fragseq_payloadlen);
1338 return QDF_STATUS_E_INVAL;
1339 }
1340
1341 defragpayload_currlen = 0;
1342 fragbuff_remlen = fragbuff_maxsize;
1343
1344 /* We have already validated through wlan_get_elemsubelem_fragseq_info()
1345 * that the elements we are about to access below are within the bounds
1346 * of fragbuff.
1347 */
1348
1349 curr_elemunit_ptr = fragbuff;
1350
1351 if (!is_subelem &&
1352 (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) {
1353 curr_elemunit_payloadlen =
1354 curr_elemunit_ptr[elemunit_len_pos] - 1;
1355 src = curr_elemunit_ptr + elemunit_hdrlen + 1;
1356 } else {
1357 curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos];
1358 src = curr_elemunit_ptr + elemunit_hdrlen;
1359 }
1360
1361 curr_elemunit_totallen =
1362 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
1363
1364 if (inline_defrag) {
1365 /* There is no need to move any bytes in the lead element. Set
1366 * dst=src so that the next update for dst can happen in a
1367 * manner uniform with the non-inlined defrag case.
1368 */
1369 dst = src;
1370 } else {
1371 dst = defragbuff;
1372 qdf_mem_copy(dst, src, curr_elemunit_payloadlen);
1373 }
1374
1375 defragpayload_currlen += curr_elemunit_payloadlen;
1376
1377 fragbuff_remlen -= curr_elemunit_totallen;
1378
1379 dst += curr_elemunit_payloadlen;
1380
1381 curr_elemunit_ptr += curr_elemunit_totallen;
1382
1383 /* We have already validated through wlan_get_elemsubelem_fragseq_info()
1384 * that at least one non-lead fragment element is present as required in
1385 * the standard.
1386 */
1387 while (curr_elemunit_ptr[elemunit_id_pos] == elemunit_fragid) {
1388 curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos];
1389 curr_elemunit_totallen =
1390 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
1391 src = curr_elemunit_ptr + elemunit_hdrlen;
1392
1393 if (inline_defrag)
1394 qdf_mem_move(dst, src, curr_elemunit_payloadlen);
1395 else
1396 qdf_mem_copy(dst, src, curr_elemunit_payloadlen);
1397
1398 defragpayload_currlen += curr_elemunit_payloadlen;
1399
1400 fragbuff_remlen -= curr_elemunit_totallen;
1401
1402 if (fragbuff_remlen == 0)
1403 break;
1404
1405 dst += curr_elemunit_payloadlen;
1406
1407 curr_elemunit_ptr += curr_elemunit_totallen;
1408 }
1409
1410 if (inline_defrag && (fragbuff_remlen != 0)) {
1411 /* Move the residual content after the fragments, in the source
1412 * buffer.
1413 */
1414 src = curr_elemunit_ptr;
1415 qdf_mem_move(dst, src, fragbuff_remlen);
1416 }
1417
1418 *defragpayload_len = defragpayload_currlen;
1419
1420 return QDF_STATUS_SUCCESS;
1421 }
1422
1423 QDF_STATUS
wlan_get_elem_fragseq_requirements(uint8_t elemid,qdf_size_t payloadlen,bool * is_frag_required,qdf_size_t * required_fragbuff_size)1424 wlan_get_elem_fragseq_requirements(uint8_t elemid,
1425 qdf_size_t payloadlen,
1426 bool *is_frag_required,
1427 qdf_size_t *required_fragbuff_size)
1428 {
1429 return wlan_get_elemsubelem_fragseq_creationparams(false,
1430 elemid,
1431 payloadlen,
1432 is_frag_required,
1433 required_fragbuff_size,
1434 NULL,
1435 NULL,
1436 NULL,
1437 NULL);
1438 }
1439
wlan_create_elem_fragseq(bool inline_frag,uint8_t elemid,uint8_t elemidext,uint8_t * payloadbuff,qdf_size_t payloadbuff_maxsize,qdf_size_t payloadlen,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,qdf_size_t * fragseqlen)1440 QDF_STATUS wlan_create_elem_fragseq(bool inline_frag,
1441 uint8_t elemid,
1442 uint8_t elemidext,
1443 uint8_t *payloadbuff,
1444 qdf_size_t payloadbuff_maxsize,
1445 qdf_size_t payloadlen,
1446 uint8_t *fragbuff,
1447 qdf_size_t fragbuff_maxsize,
1448 qdf_size_t *fragseqlen)
1449 {
1450 return wlan_create_elemsubelem_fragseq(inline_frag,
1451 false,
1452 elemid,
1453 elemidext,
1454 0,
1455 payloadbuff,
1456 payloadbuff_maxsize,
1457 payloadlen,
1458 fragbuff,
1459 fragbuff_maxsize,
1460 fragseqlen);
1461 }
1462
1463 QDF_STATUS
wlan_get_subelem_fragseq_requirements(uint8_t subelemid,qdf_size_t payloadlen,bool * is_frag_required,qdf_size_t * required_fragbuff_size)1464 wlan_get_subelem_fragseq_requirements(uint8_t subelemid,
1465 qdf_size_t payloadlen,
1466 bool *is_frag_required,
1467 qdf_size_t *required_fragbuff_size)
1468 {
1469 return wlan_get_elemsubelem_fragseq_creationparams(true,
1470 subelemid,
1471 payloadlen,
1472 is_frag_required,
1473 required_fragbuff_size,
1474 NULL,
1475 NULL,
1476 NULL,
1477 NULL);
1478 }
1479
wlan_create_subelem_fragseq(bool inline_frag,uint8_t subelemid,uint8_t subelemfragid,uint8_t * payloadbuff,qdf_size_t payloadbuff_maxsize,qdf_size_t payloadlen,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,qdf_size_t * fragseqlen)1480 QDF_STATUS wlan_create_subelem_fragseq(bool inline_frag,
1481 uint8_t subelemid,
1482 uint8_t subelemfragid,
1483 uint8_t *payloadbuff,
1484 qdf_size_t payloadbuff_maxsize,
1485 qdf_size_t payloadlen,
1486 uint8_t *fragbuff,
1487 qdf_size_t fragbuff_maxsize,
1488 qdf_size_t *fragseqlen)
1489 {
1490 return wlan_create_elemsubelem_fragseq(inline_frag,
1491 true,
1492 subelemid,
1493 0,
1494 subelemfragid,
1495 payloadbuff,
1496 payloadbuff_maxsize,
1497 payloadlen,
1498 fragbuff,
1499 fragbuff_maxsize,
1500 fragseqlen);
1501 }
1502
wlan_get_elem_fragseq_info(uint8_t * elembuff,qdf_size_t elembuff_maxsize,bool * is_fragseq,qdf_size_t * fragseq_totallen,qdf_size_t * fragseq_payloadlen)1503 QDF_STATUS wlan_get_elem_fragseq_info(uint8_t *elembuff,
1504 qdf_size_t elembuff_maxsize,
1505 bool *is_fragseq,
1506 qdf_size_t *fragseq_totallen,
1507 qdf_size_t *fragseq_payloadlen)
1508 {
1509 return wlan_get_elemsubelem_fragseq_info(false,
1510 0,
1511 elembuff,
1512 elembuff_maxsize,
1513 is_fragseq,
1514 fragseq_totallen,
1515 fragseq_payloadlen);
1516 }
1517
wlan_defrag_elem_fragseq(bool inline_defrag,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,uint8_t * defragbuff,qdf_size_t defragbuff_maxsize,qdf_size_t * defragpayload_len)1518 QDF_STATUS wlan_defrag_elem_fragseq(bool inline_defrag,
1519 uint8_t *fragbuff,
1520 qdf_size_t fragbuff_maxsize,
1521 uint8_t *defragbuff,
1522 qdf_size_t defragbuff_maxsize,
1523 qdf_size_t *defragpayload_len)
1524 {
1525 return wlan_defrag_elemsubelem_fragseq(inline_defrag,
1526 false,
1527 0,
1528 fragbuff,
1529 fragbuff_maxsize,
1530 defragbuff,
1531 defragbuff_maxsize,
1532 defragpayload_len);
1533 }
1534
wlan_get_subelem_fragseq_info(uint8_t subelemfragid,uint8_t * subelembuff,qdf_size_t subelembuff_maxsize,bool * is_fragseq,qdf_size_t * fragseq_totallen,qdf_size_t * fragseq_payloadlen)1535 QDF_STATUS wlan_get_subelem_fragseq_info(uint8_t subelemfragid,
1536 uint8_t *subelembuff,
1537 qdf_size_t subelembuff_maxsize,
1538 bool *is_fragseq,
1539 qdf_size_t *fragseq_totallen,
1540 qdf_size_t *fragseq_payloadlen)
1541 {
1542 return wlan_get_elemsubelem_fragseq_info(true,
1543 subelemfragid,
1544 subelembuff,
1545 subelembuff_maxsize,
1546 is_fragseq,
1547 fragseq_totallen,
1548 fragseq_payloadlen);
1549 }
1550
wlan_defrag_subelem_fragseq(bool inline_defrag,uint8_t subelemfragid,uint8_t * fragbuff,qdf_size_t fragbuff_maxsize,uint8_t * defragbuff,qdf_size_t defragbuff_maxsize,qdf_size_t * defragpayload_len)1551 QDF_STATUS wlan_defrag_subelem_fragseq(bool inline_defrag,
1552 uint8_t subelemfragid,
1553 uint8_t *fragbuff,
1554 qdf_size_t fragbuff_maxsize,
1555 uint8_t *defragbuff,
1556 qdf_size_t defragbuff_maxsize,
1557 qdf_size_t *defragpayload_len)
1558 {
1559 return wlan_defrag_elemsubelem_fragseq(inline_defrag,
1560 true,
1561 subelemfragid,
1562 fragbuff,
1563 fragbuff_maxsize,
1564 defragbuff,
1565 defragbuff_maxsize,
1566 defragpayload_len);
1567 }
1568
wlan_is_emulation_platform(uint32_t phy_version)1569 bool wlan_is_emulation_platform(uint32_t phy_version)
1570 {
1571 if ((phy_version == 0xABC0) || (phy_version == 0xABC1) ||
1572 (phy_version == 0xABC2) || (phy_version == 0xABC3) ||
1573 (phy_version == 0xFFFF) || (phy_version == 0xABCD))
1574 return true;
1575
1576 return false;
1577 }
1578
wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,wlan_objmgr_ref_dbgid dbg_id)1579 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc,
1580 uint8_t vdev_id,
1581 wlan_objmgr_ref_dbgid dbg_id)
1582 {
1583 struct wlan_objmgr_vdev *vdev;
1584 struct wlan_objmgr_pdev *pdev = NULL;
1585 uint32_t pdev_id = WLAN_INVALID_PDEV_ID;
1586
1587 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1588 vdev_id, dbg_id);
1589
1590 if (vdev) {
1591 pdev = wlan_vdev_get_pdev(vdev);
1592 if (pdev)
1593 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1594 wlan_objmgr_vdev_release_ref(vdev, dbg_id);
1595 }
1596
1597 return pdev_id;
1598 }
1599 qdf_export_symbol(wlan_get_pdev_id_from_vdev_id);
1600
wlan_vdev_active(struct wlan_objmgr_pdev * pdev,void * object,void * arg)1601 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object,
1602 void *arg)
1603 {
1604 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
1605 uint8_t *flag = (uint8_t *)arg;
1606
1607 wlan_vdev_obj_lock(vdev);
1608 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
1609 *flag = 1;
1610
1611 wlan_vdev_obj_unlock(vdev);
1612 }
1613
wlan_vdev_is_up(struct wlan_objmgr_vdev * vdev)1614 QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev)
1615 {
1616 return wlan_vdev_allow_connect_n_tx(vdev);
1617 }
1618 qdf_export_symbol(wlan_vdev_is_up);
1619
wlan_util_is_vdev_active(struct wlan_objmgr_pdev * pdev,wlan_objmgr_ref_dbgid dbg_id)1620 QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev,
1621 wlan_objmgr_ref_dbgid dbg_id)
1622 {
1623 uint8_t flag = 0;
1624
1625 if (!pdev)
1626 return QDF_STATUS_E_INVAL;
1627
1628 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active,
1629 &flag, 0, dbg_id);
1630
1631 if (flag == 1)
1632 return QDF_STATUS_SUCCESS;
1633
1634 return QDF_STATUS_E_INVAL;
1635 }
1636
1637 qdf_export_symbol(wlan_util_is_vdev_active);
1638
wlan_util_change_map_index(unsigned long * map,uint8_t id,uint8_t set)1639 void wlan_util_change_map_index(unsigned long *map, uint8_t id, uint8_t set)
1640 {
1641 if (set)
1642 qdf_set_bit(id, map);
1643 else
1644 qdf_clear_bit(id, map);
1645 }
1646
wlan_util_map_index_is_set(unsigned long * map,uint8_t id)1647 bool wlan_util_map_index_is_set(unsigned long *map, uint8_t id)
1648 {
1649 return qdf_test_bit(id, map);
1650 }
1651
wlan_util_map_is_any_index_set(unsigned long * map,unsigned long nbytes)1652 bool wlan_util_map_is_any_index_set(unsigned long *map, unsigned long nbytes)
1653 {
1654 return !qdf_bitmap_empty(map, QDF_CHAR_BIT * nbytes);
1655 }
1656
wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev * pdev,void * object,void * arg)1657 static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev,
1658 void *object, void *arg)
1659 {
1660 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
1661 unsigned long *vdev_id_map = (unsigned long *)arg;
1662 uint8_t id = 0;
1663 struct wlan_objmgr_psoc *psoc;
1664
1665 psoc = wlan_pdev_get_psoc(pdev);
1666 if (!psoc)
1667 return;
1668
1669 wlan_vdev_obj_lock(vdev);
1670 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
1671 id = wlan_vdev_get_id(vdev);
1672 /* Invalid vdev id */
1673 if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
1674 wlan_vdev_obj_unlock(vdev);
1675 return;
1676 }
1677
1678 wlan_util_change_map_index(vdev_id_map, id, 1);
1679 }
1680
1681 wlan_vdev_obj_unlock(vdev);
1682 }
1683
wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev * pdev,unsigned long * vdev_id_map,wlan_objmgr_ref_dbgid dbg_id)1684 QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev,
1685 unsigned long *vdev_id_map,
1686 wlan_objmgr_ref_dbgid dbg_id)
1687 {
1688 if (!pdev)
1689 return QDF_STATUS_E_INVAL;
1690
1691 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
1692 wlan_vdev_chan_change_pending,
1693 vdev_id_map, 0, dbg_id);
1694
1695 return QDF_STATUS_SUCCESS;
1696 }
1697
wlan_vdev_down_pending(struct wlan_objmgr_pdev * pdev,void * object,void * arg)1698 static void wlan_vdev_down_pending(struct wlan_objmgr_pdev *pdev,
1699 void *object, void *arg)
1700 {
1701 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
1702 unsigned long *vdev_id_map = (unsigned long *)arg;
1703 uint8_t id = 0;
1704 struct wlan_objmgr_psoc *psoc;
1705 enum wlan_serialization_cmd_type cmd_type;
1706
1707 psoc = wlan_pdev_get_psoc(pdev);
1708 if (!psoc)
1709 return;
1710
1711 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev))
1712 return;
1713
1714 cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev);
1715 wlan_vdev_obj_lock(vdev);
1716 if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) ||
1717 (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) {
1718 id = wlan_vdev_get_id(vdev);
1719 /* Invalid vdev id */
1720 if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
1721 wlan_vdev_obj_unlock(vdev);
1722 return;
1723 }
1724 wlan_util_change_map_index(vdev_id_map, id, 1);
1725 }
1726
1727 wlan_vdev_obj_unlock(vdev);
1728 }
1729
wlan_vdev_ap_down_pending(struct wlan_objmgr_pdev * pdev,void * object,void * arg)1730 static void wlan_vdev_ap_down_pending(struct wlan_objmgr_pdev *pdev,
1731 void *object, void *arg)
1732 {
1733 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
1734 unsigned long *vdev_id_map = (unsigned long *)arg;
1735 uint8_t id = 0;
1736 struct wlan_objmgr_psoc *psoc;
1737 enum wlan_serialization_cmd_type cmd_type;
1738
1739 psoc = wlan_pdev_get_psoc(pdev);
1740 if (!psoc)
1741 return;
1742
1743 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
1744 return;
1745
1746 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev))
1747 return;
1748
1749 cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev);
1750 wlan_vdev_obj_lock(vdev);
1751 if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) ||
1752 (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) {
1753 id = wlan_vdev_get_id(vdev);
1754 /* Invalid vdev id */
1755 if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
1756 wlan_vdev_obj_unlock(vdev);
1757 return;
1758 }
1759 wlan_util_change_map_index(vdev_id_map, id, 1);
1760 }
1761
1762 wlan_vdev_obj_unlock(vdev);
1763 }
1764
wlan_pdev_chan_change_pending_vdevs_down(struct wlan_objmgr_pdev * pdev,unsigned long * vdev_id_map,wlan_objmgr_ref_dbgid dbg_id)1765 QDF_STATUS wlan_pdev_chan_change_pending_vdevs_down(
1766 struct wlan_objmgr_pdev *pdev,
1767 unsigned long *vdev_id_map,
1768 wlan_objmgr_ref_dbgid dbg_id)
1769 {
1770 if (!pdev)
1771 return QDF_STATUS_E_INVAL;
1772
1773 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
1774 wlan_vdev_down_pending,
1775 vdev_id_map, 0, dbg_id);
1776
1777 return QDF_STATUS_SUCCESS;
1778 }
1779
wlan_pdev_chan_change_pending_ap_vdevs_down(struct wlan_objmgr_pdev * pdev,unsigned long * vdev_id_map,wlan_objmgr_ref_dbgid dbg_id)1780 QDF_STATUS wlan_pdev_chan_change_pending_ap_vdevs_down(
1781 struct wlan_objmgr_pdev *pdev,
1782 unsigned long *vdev_id_map,
1783 wlan_objmgr_ref_dbgid dbg_id)
1784 {
1785 if (!pdev)
1786 return QDF_STATUS_E_INVAL;
1787
1788 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
1789 wlan_vdev_ap_down_pending,
1790 vdev_id_map, 0, dbg_id);
1791
1792 return QDF_STATUS_SUCCESS;
1793 }
1794
1795 #ifdef WLAN_FEATURE_11BE
1796 static inline bool
wlan_chan_puncture_eq(struct wlan_channel * chan1,struct wlan_channel * chan2)1797 wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
1798 {
1799 if (chan1->puncture_bitmap == chan2->puncture_bitmap)
1800 return true;
1801
1802 return false;
1803 }
1804 #else
1805 static inline bool
wlan_chan_puncture_eq(struct wlan_channel * chan1,struct wlan_channel * chan2)1806 wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
1807 {
1808 return true;
1809 }
1810 #endif /* WLAN_FEATURE_11BE */
1811
wlan_chan_eq(struct wlan_channel * chan1,struct wlan_channel * chan2)1812 QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
1813 {
1814 if ((chan1->ch_ieee == chan2->ch_ieee) &&
1815 (chan1->ch_freq_seg2 == chan2->ch_freq_seg2) &&
1816 wlan_chan_puncture_eq(chan1, chan2))
1817 return QDF_STATUS_SUCCESS;
1818
1819 return QDF_STATUS_E_FAILURE;
1820 }
1821
wlan_chan_copy(struct wlan_channel * tgt,struct wlan_channel * src)1822 void wlan_chan_copy(struct wlan_channel *tgt, struct wlan_channel *src)
1823 {
1824 qdf_mem_copy(tgt, src, sizeof(struct wlan_channel));
1825 }
1826
wlan_vdev_get_active_channel(struct wlan_objmgr_vdev * vdev)1827 struct wlan_channel *wlan_vdev_get_active_channel(struct wlan_objmgr_vdev *vdev)
1828 {
1829 struct wlan_channel *comp_vdev_chan = NULL;
1830
1831 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
1832 /* compare with BSS channel, when vdev is active, since desired
1833 * channel gets update, if channel is triggered in another path
1834 */
1835 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
1836 comp_vdev_chan = wlan_vdev_mlme_get_bss_chan(vdev);
1837 else
1838 comp_vdev_chan = wlan_vdev_mlme_get_des_chan(vdev);
1839 }
1840
1841 return comp_vdev_chan;
1842 }
1843
1844 /**
1845 * struct wlan_check_bssid_context - bssid check context
1846 * @bssid: bssid to be checked
1847 * @connected: connected by vdev or not
1848 * @vdev_id: vdev id of connected vdev
1849 */
1850 struct wlan_check_bssid_context {
1851 struct qdf_mac_addr bssid;
1852 bool connected;
1853 uint8_t vdev_id;
1854 };
1855
1856 /**
1857 * wlan_get_connected_vdev_handler() - check vdev connected on bssid
1858 * @psoc: psoc object
1859 * @obj: vdev object
1860 * @args: handler context
1861 *
1862 * This function will check whether vdev is connected on bssid or not and
1863 * update the result to handler context accordingly.
1864 *
1865 * Return: void
1866 */
wlan_get_connected_vdev_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * args)1867 static void wlan_get_connected_vdev_handler(struct wlan_objmgr_psoc *psoc,
1868 void *obj, void *args)
1869 {
1870 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
1871 struct wlan_check_bssid_context *context =
1872 (struct wlan_check_bssid_context *)args;
1873 struct qdf_mac_addr bss_peer_mac;
1874 enum QDF_OPMODE op_mode;
1875
1876 if (context->connected)
1877 return;
1878
1879 op_mode = wlan_vdev_mlme_get_opmode(vdev);
1880 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
1881 return;
1882
1883 if (wlan_cm_is_vdev_disconnected(vdev))
1884 return;
1885
1886 if (wlan_vdev_get_bss_peer_mac(vdev, &bss_peer_mac) !=
1887 QDF_STATUS_SUCCESS)
1888 return;
1889 if (qdf_is_macaddr_equal(&bss_peer_mac, &context->bssid)) {
1890 context->connected = true;
1891 context->vdev_id = wlan_vdev_get_id(vdev);
1892 }
1893 }
1894
wlan_get_connected_vdev_from_psoc_by_bssid(struct wlan_objmgr_psoc * psoc,uint8_t * bssid,uint8_t * vdev_id)1895 bool wlan_get_connected_vdev_from_psoc_by_bssid(struct wlan_objmgr_psoc *psoc,
1896 uint8_t *bssid,
1897 uint8_t *vdev_id)
1898 {
1899 struct wlan_check_bssid_context context;
1900
1901 qdf_mem_zero(&context, sizeof(struct wlan_check_bssid_context));
1902 qdf_mem_copy(context.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
1903 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
1904 wlan_get_connected_vdev_handler,
1905 &context, true, WLAN_OSIF_SCAN_ID);
1906 if (context.connected)
1907 *vdev_id = context.vdev_id;
1908
1909 return context.connected;
1910 }
1911
1912 qdf_export_symbol(wlan_get_connected_vdev_from_psoc_by_bssid);
1913
wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev * pdev,uint8_t * bssid,uint8_t * vdev_id)1914 bool wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev *pdev,
1915 uint8_t *bssid, uint8_t *vdev_id)
1916 {
1917 return wlan_get_connected_vdev_from_psoc_by_bssid(
1918 wlan_pdev_get_psoc(pdev), bssid, vdev_id);
1919 }
1920
1921 qdf_export_symbol(wlan_get_connected_vdev_by_bssid);
1922
1923 #ifdef WLAN_FEATURE_11BE_MLO
1924 /**
1925 * struct wlan_check_mld_addr_context - mld mac addr check context
1926 * @mld_addr: mld_addrto be checked
1927 * @connected: connected by vdev or not
1928 * @vdev_id: vdev id of connected vdev
1929 */
1930 struct wlan_check_mld_addr_context {
1931 struct qdf_mac_addr mld_addr;
1932 bool connected;
1933 uint8_t vdev_id;
1934 };
1935
1936 /**
1937 * wlan_get_connected_mlo_dev_ctx_handler() - check vdev connected on mld mac
1938 * @psoc: psoc object
1939 * @obj: vdev object
1940 * @args: handler context
1941 *
1942 * This function will check whether vdev is connected on mld mac or not and
1943 * update the result to handler context accordingly.
1944 *
1945 * Return: void
1946 */
wlan_get_connected_mlo_dev_ctx_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * args)1947 static void wlan_get_connected_mlo_dev_ctx_handler(
1948 struct wlan_objmgr_psoc *psoc,
1949 void *obj, void *args)
1950 {
1951 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
1952 struct wlan_check_mld_addr_context *context =
1953 (struct wlan_check_mld_addr_context *)args;
1954 struct qdf_mac_addr bss_peer_mld_mac;
1955 enum QDF_OPMODE op_mode;
1956
1957 if (context->connected)
1958 return;
1959 op_mode = wlan_vdev_mlme_get_opmode(vdev);
1960 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
1961 return;
1962 if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS)
1963 return;
1964 if (QDF_IS_STATUS_ERROR(wlan_vdev_get_bss_peer_mld_mac(
1965 vdev, &bss_peer_mld_mac)))
1966 return;
1967 if (qdf_is_macaddr_equal(&bss_peer_mld_mac, &context->mld_addr)) {
1968 context->connected = true;
1969 context->vdev_id = wlan_vdev_get_id(vdev);
1970 }
1971 }
1972
wlan_get_connected_vdev_by_mld_addr(struct wlan_objmgr_psoc * psoc,uint8_t * mld_mac,uint8_t * vdev_id)1973 bool wlan_get_connected_vdev_by_mld_addr(struct wlan_objmgr_psoc *psoc,
1974 uint8_t *mld_mac, uint8_t *vdev_id)
1975 {
1976 struct wlan_check_mld_addr_context context;
1977
1978 qdf_mem_zero(&context, sizeof(struct wlan_check_mld_addr_context));
1979 qdf_copy_macaddr(&context.mld_addr, (struct qdf_mac_addr *)mld_mac);
1980 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
1981 wlan_get_connected_mlo_dev_ctx_handler,
1982 &context, true, WLAN_MLME_OBJMGR_ID);
1983
1984 if (context.connected)
1985 *vdev_id = context.vdev_id;
1986
1987 return context.connected;
1988 }
1989 #endif
1990
1991 #if defined(WLAN_FEATURE_11BE)
1992 enum wlan_phymode
wlan_eht_chan_phy_mode(uint32_t freq,uint16_t bw_val,enum phy_ch_width chan_width)1993 wlan_eht_chan_phy_mode(uint32_t freq,
1994 uint16_t bw_val,
1995 enum phy_ch_width chan_width)
1996 {
1997 if (wlan_reg_is_24ghz_ch_freq(freq)) {
1998 if (bw_val == 20)
1999 return WLAN_PHYMODE_11BEG_EHT20;
2000 else if (bw_val == 40)
2001 return WLAN_PHYMODE_11BEG_EHT40;
2002 } else {
2003 if (bw_val == 20)
2004 return WLAN_PHYMODE_11BEA_EHT20;
2005 else if (bw_val == 40)
2006 return WLAN_PHYMODE_11BEA_EHT40;
2007 else if (bw_val == 80)
2008 return WLAN_PHYMODE_11BEA_EHT80;
2009 else if (chan_width == CH_WIDTH_160MHZ)
2010 return WLAN_PHYMODE_11BEA_EHT160;
2011 else if (chan_width == CH_WIDTH_320MHZ)
2012 return WLAN_PHYMODE_11BEA_EHT320;
2013 }
2014 return WLAN_PHYMODE_AUTO;
2015 }
2016 #else
2017 enum wlan_phymode
wlan_eht_chan_phy_mode(uint32_t freq,uint16_t bw_val,enum phy_ch_width chan_width)2018 wlan_eht_chan_phy_mode(uint32_t freq,
2019 uint16_t bw_val,
2020 enum phy_ch_width chan_width)
2021 {
2022 return WLAN_PHYMODE_AUTO;
2023 }
2024
2025 #endif
2026
wlan_pdev_chan_match(struct wlan_objmgr_pdev * pdev,void * object,void * arg)2027 static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
2028 void *arg)
2029 {
2030 struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object;
2031 struct wlan_vdev_ch_check_filter *ch_filter = arg;
2032 struct wlan_channel vdev_chan, *chan;
2033 struct wlan_channel *iter_vdev_chan;
2034
2035 if (ch_filter->flag)
2036 return;
2037
2038 if (comp_vdev == ch_filter->vdev)
2039 return;
2040
2041 wlan_vdev_obj_lock(comp_vdev);
2042 chan = wlan_vdev_get_active_channel(comp_vdev);
2043 if (!chan) {
2044 wlan_vdev_obj_unlock(comp_vdev);
2045 return;
2046 }
2047 wlan_chan_copy(&vdev_chan, chan);
2048 wlan_vdev_obj_unlock(comp_vdev);
2049
2050 wlan_vdev_obj_lock(ch_filter->vdev);
2051 iter_vdev_chan = wlan_vdev_mlme_get_des_chan(ch_filter->vdev);
2052 if (wlan_chan_eq(&vdev_chan, iter_vdev_chan)
2053 != QDF_STATUS_SUCCESS) {
2054 ch_filter->flag = 1;
2055 qdf_debug("==> iter vdev id: %d: ieee %d, mode %d",
2056 wlan_vdev_get_id(comp_vdev),
2057 vdev_chan.ch_ieee,
2058 vdev_chan.ch_phymode);
2059 qdf_debug("fl %016llx, fl-ext %08x, s1 %d, s2 %d ",
2060 vdev_chan.ch_flags, vdev_chan.ch_flagext,
2061 vdev_chan.ch_freq_seg1,
2062 vdev_chan.ch_freq_seg2);
2063 qdf_debug("==> base vdev id: %d: ieee %d mode %d",
2064 wlan_vdev_get_id(ch_filter->vdev),
2065 iter_vdev_chan->ch_ieee,
2066 iter_vdev_chan->ch_phymode);
2067 qdf_debug("fl %016llx, fl-ext %08x s1 %d, s2 %d",
2068 iter_vdev_chan->ch_flags,
2069 iter_vdev_chan->ch_flagext,
2070 iter_vdev_chan->ch_freq_seg1,
2071 iter_vdev_chan->ch_freq_seg2);
2072 }
2073 wlan_vdev_obj_unlock(ch_filter->vdev);
2074 }
2075
wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,wlan_objmgr_ref_dbgid dbg_id)2076 QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev,
2077 struct wlan_objmgr_vdev *vdev,
2078 wlan_objmgr_ref_dbgid dbg_id)
2079 {
2080 struct wlan_vdev_ch_check_filter ch_filter;
2081
2082 if (!pdev)
2083 return QDF_STATUS_E_INVAL;
2084
2085 if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_CHAN_CONCURRENCY))
2086 return QDF_STATUS_SUCCESS;
2087
2088 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == QDF_STATUS_SUCCESS) {
2089 ch_filter.flag = 0;
2090 ch_filter.vdev = vdev;
2091
2092 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
2093 wlan_pdev_chan_match,
2094 &ch_filter, 0, dbg_id);
2095
2096 wlan_objmgr_vdev_release_ref(vdev, dbg_id);
2097
2098 if (ch_filter.flag == 0)
2099 return QDF_STATUS_SUCCESS;
2100 }
2101
2102 return QDF_STATUS_E_FAILURE;
2103 }
2104
wlan_vdev_restart_progress(struct wlan_objmgr_pdev * pdev,void * object,void * arg)2105 static void wlan_vdev_restart_progress(struct wlan_objmgr_pdev *pdev,
2106 void *object, void *arg)
2107 {
2108 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
2109 uint8_t *flag = (uint8_t *)arg;
2110
2111 wlan_vdev_obj_lock(vdev);
2112 if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS)
2113 *flag = 1;
2114
2115 wlan_vdev_obj_unlock(vdev);
2116 }
2117
wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev * pdev,wlan_objmgr_ref_dbgid dbg_id)2118 QDF_STATUS wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev *pdev,
2119 wlan_objmgr_ref_dbgid dbg_id)
2120 {
2121 uint8_t flag = 0;
2122
2123 if (!pdev)
2124 return QDF_STATUS_E_INVAL;
2125
2126 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
2127 wlan_vdev_restart_progress,
2128 &flag, 0, dbg_id);
2129
2130 if (flag == 1)
2131 return QDF_STATUS_SUCCESS;
2132
2133 return QDF_STATUS_E_INVAL;
2134 }
2135
wlan_vdev_scan_allowed(struct wlan_objmgr_pdev * pdev,void * object,void * arg)2136 static void wlan_vdev_scan_allowed(struct wlan_objmgr_pdev *pdev, void *object,
2137 void *arg)
2138 {
2139 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
2140 uint8_t *flag = (uint8_t *)arg;
2141
2142 wlan_vdev_obj_lock(vdev);
2143 if (wlan_vdev_mlme_is_scan_allowed(vdev) != QDF_STATUS_SUCCESS)
2144 *flag = 1;
2145
2146 wlan_vdev_obj_unlock(vdev);
2147 }
2148
wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev * pdev,wlan_objmgr_ref_dbgid dbg_id)2149 QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev,
2150 wlan_objmgr_ref_dbgid dbg_id)
2151 {
2152 uint8_t flag = 0;
2153
2154 if (!pdev)
2155 return QDF_STATUS_E_INVAL;
2156
2157 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
2158 wlan_vdev_scan_allowed,
2159 &flag, 0, dbg_id);
2160
2161 if (flag == 1)
2162 return QDF_STATUS_E_FAILURE;
2163
2164 return QDF_STATUS_SUCCESS;
2165 }
2166
2167 void
wlan_util_stats_get_rssi(bool db2dbm_enabled,int32_t bcn_snr,int32_t dat_snr,int8_t * rssi)2168 wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr,
2169 int8_t *rssi)
2170 {
2171 uint32_t snr;
2172
2173 if (db2dbm_enabled) {
2174 if (TGT_IS_VALID_RSSI(bcn_snr))
2175 *rssi = bcn_snr;
2176 else if (TGT_IS_VALID_RSSI(dat_snr))
2177 *rssi = dat_snr;
2178 else
2179 *rssi = TGT_NOISE_FLOOR_DBM;
2180 } else {
2181 if (TGT_IS_VALID_SNR(bcn_snr))
2182 snr = bcn_snr;
2183 else if (TGT_IS_VALID_SNR(dat_snr))
2184 snr = dat_snr;
2185 else
2186 snr = TGT_INVALID_SNR;
2187
2188 /* Get the absolute rssi value from the current rssi value */
2189 *rssi = snr + TGT_NOISE_FLOOR_DBM;
2190 }
2191 }
2192
2193 /**
2194 * wlan_util_get_mode_specific_peer_count - This api gives vdev mode specific
2195 * peer count`
2196 * @pdev: PDEV object
2197 * @object: vdev object
2198 * @arg: argument passed by caller
2199 *
2200 * Return: void
2201 */
2202 static void
wlan_util_get_mode_specific_peer_count(struct wlan_objmgr_pdev * pdev,void * object,void * arg)2203 wlan_util_get_mode_specific_peer_count(struct wlan_objmgr_pdev *pdev,
2204 void *object, void *arg)
2205 {
2206 struct wlan_objmgr_vdev *vdev = object;
2207 uint16_t temp_count = 0;
2208 struct wlan_op_mode_peer_count *count = arg;
2209
2210 wlan_vdev_obj_lock(vdev);
2211 if (wlan_vdev_mlme_get_opmode(vdev) == count->opmode) {
2212 temp_count = wlan_vdev_get_peer_count(vdev);
2213 /* Decrement the self peer count */
2214 if (temp_count > 1)
2215 count->peer_count += (temp_count - 1);
2216 }
2217 wlan_vdev_obj_unlock(vdev);
2218 }
2219
wlan_util_get_peer_count_for_mode(struct wlan_objmgr_pdev * pdev,enum QDF_OPMODE mode)2220 uint16_t wlan_util_get_peer_count_for_mode(struct wlan_objmgr_pdev *pdev,
2221 enum QDF_OPMODE mode)
2222 {
2223 struct wlan_op_mode_peer_count count;
2224
2225 count.opmode = mode;
2226 count.peer_count = 0;
2227 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
2228 wlan_util_get_mode_specific_peer_count, &count,
2229 0, WLAN_OBJMGR_ID);
2230
2231 return count.peer_count;
2232 }
2233
2234 #ifdef CONFIG_QCA_MINIDUMP
wlan_minidump_log_enabled(struct wlan_objmgr_psoc * psoc,enum wlan_minidump_host_data type)2235 static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc,
2236 enum wlan_minidump_host_data type)
2237 {
2238 bool setval = false;
2239
2240 switch (type) {
2241 case WLAN_MD_CP_EXT_PDEV:
2242 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PDEV))
2243 setval = true;
2244 break;
2245 case WLAN_MD_CP_EXT_PSOC:
2246 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PSOC))
2247 setval = true;
2248 break;
2249 case WLAN_MD_CP_EXT_VDEV:
2250 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_VDEV))
2251 setval = true;
2252 break;
2253 case WLAN_MD_CP_EXT_PEER:
2254 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PEER))
2255 setval = true;
2256 break;
2257 case WLAN_MD_DP_SOC:
2258 if (cfg_get(psoc, CFG_OL_MD_DP_SOC))
2259 setval = true;
2260 break;
2261 case WLAN_MD_DP_PDEV:
2262 if (cfg_get(psoc, CFG_OL_MD_DP_PDEV))
2263 setval = true;
2264 break;
2265 case WLAN_MD_DP_PEER:
2266 if (cfg_get(psoc, CFG_OL_MD_DP_PEER))
2267 setval = true;
2268 break;
2269 case WLAN_MD_DP_SRNG_REO_DEST:
2270 case WLAN_MD_DP_SRNG_REO_EXCEPTION:
2271 case WLAN_MD_DP_SRNG_RX_REL:
2272 case WLAN_MD_DP_SRNG_REO_REINJECT:
2273 case WLAN_MD_DP_SRNG_REO_CMD:
2274 case WLAN_MD_DP_SRNG_REO_STATUS:
2275 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_REO))
2276 setval = true;
2277 break;
2278 case WLAN_MD_DP_SRNG_TCL_DATA:
2279 case WLAN_MD_DP_SRNG_TCL_CMD:
2280 case WLAN_MD_DP_SRNG_TCL_STATUS:
2281 case WLAN_MD_DP_SRNG_TX_COMP:
2282 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_TCL))
2283 setval = true;
2284 break;
2285 case WLAN_MD_DP_SRNG_WBM_DESC_REL:
2286 case WLAN_MD_DP_SRNG_WBM_IDLE_LINK:
2287 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_WBM))
2288 setval = true;
2289 break;
2290 case WLAN_MD_DP_LINK_DESC_BANK:
2291 if (cfg_get(psoc, CFG_OL_MD_DP_LINK_DESC_BANK))
2292 setval = true;
2293 break;
2294 case WLAN_MD_DP_SRNG_RXDMA_MON_BUF:
2295 case WLAN_MD_DP_SRNG_RXDMA_MON_DST:
2296 case WLAN_MD_DP_SRNG_RXDMA_MON_DESC:
2297 case WLAN_MD_DP_SRNG_RXDMA_ERR_DST:
2298 case WLAN_MD_DP_SRNG_RXDMA_MON_STATUS:
2299 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_RXDMA))
2300 setval = true;
2301 break;
2302 case WLAN_MD_DP_HAL_SOC:
2303 if (cfg_get(psoc, CFG_OL_MD_DP_HAL_SOC))
2304 setval = true;
2305 break;
2306 case WLAN_MD_OBJMGR_PSOC:
2307 case WLAN_MD_OBJMGR_PSOC_TGT_INFO:
2308 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PSOC))
2309 setval = true;
2310 break;
2311 case WLAN_MD_OBJMGR_PDEV:
2312 case WLAN_MD_OBJMGR_PDEV_MLME:
2313 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PDEV))
2314 setval = true;
2315 break;
2316 case WLAN_MD_OBJMGR_VDEV_MLME:
2317 case WLAN_MD_OBJMGR_VDEV_SM:
2318 case WLAN_MD_OBJMGR_VDEV:
2319 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_VDEV))
2320 setval = true;
2321 break;
2322 default:
2323 qdf_debug("Minidump: Type not implemented");
2324 }
2325
2326 return setval;
2327 }
2328 #else /* CONFIG_QCA_MINIDUMP */
wlan_minidump_log_enabled(struct wlan_objmgr_psoc * psoc,enum wlan_minidump_host_data type)2329 static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc,
2330 enum wlan_minidump_host_data type)
2331 {
2332 return false;
2333 }
2334 #endif
2335
wlan_minidump_log(void * start_addr,const size_t size,void * psoc_obj,enum wlan_minidump_host_data type,const char * name)2336 void wlan_minidump_log(void *start_addr, const size_t size,
2337 void *psoc_obj,
2338 enum wlan_minidump_host_data type,
2339 const char *name)
2340 {
2341 struct wlan_objmgr_psoc *psoc;
2342
2343 if (!psoc_obj) {
2344 qdf_debug("Minidump: Psoc is NULL");
2345 return;
2346 }
2347
2348 psoc = (struct wlan_objmgr_psoc *)psoc_obj;
2349
2350 if (psoc && wlan_minidump_log_enabled(psoc, type))
2351 qdf_minidump_log(start_addr, size, name);
2352 }
2353 qdf_export_symbol(wlan_minidump_log);
2354
wlan_minidump_remove(void * start_addr,const size_t size,void * psoc_obj,enum wlan_minidump_host_data type,const char * name)2355 void wlan_minidump_remove(void *start_addr, const size_t size,
2356 void *psoc_obj,
2357 enum wlan_minidump_host_data type,
2358 const char *name)
2359 {
2360 struct wlan_objmgr_psoc *psoc;
2361
2362 if (!psoc_obj) {
2363 qdf_debug("Minidump: Psoc is NULL");
2364 return;
2365 }
2366
2367 psoc = (struct wlan_objmgr_psoc *)psoc_obj;
2368
2369 if (psoc && wlan_minidump_log_enabled(psoc, type))
2370 qdf_minidump_remove(start_addr, size, name);
2371 }
2372 qdf_export_symbol(wlan_minidump_remove);
2373
vdev_cac_in_progress(struct wlan_objmgr_pdev * pdev,void * object,void * arg)2374 static void vdev_cac_in_progress(struct wlan_objmgr_pdev *pdev,
2375 void *object, void *arg)
2376 {
2377 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
2378 bool *cac_is_in_progress = (bool *)arg;
2379
2380 if (*cac_is_in_progress)
2381 return;
2382
2383 if (wlan_vdev_is_dfs_cac_wait(vdev) == QDF_STATUS_SUCCESS)
2384 *cac_is_in_progress = true;
2385 }
2386
wlan_util_is_vdev_in_cac_wait(struct wlan_objmgr_pdev * pdev,wlan_objmgr_ref_dbgid dbg_id)2387 bool wlan_util_is_vdev_in_cac_wait(struct wlan_objmgr_pdev *pdev,
2388 wlan_objmgr_ref_dbgid dbg_id)
2389 {
2390 bool cac_is_in_progress = false;
2391
2392 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
2393 vdev_cac_in_progress,
2394 &cac_is_in_progress, 0,
2395 dbg_id);
2396
2397 return cac_is_in_progress;
2398 }
2399
2400 qdf_export_symbol(wlan_util_is_vdev_in_cac_wait);
2401