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