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