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