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