xref: /wlan-driver/qcacld-3.0/core/wma/src/wma_utils.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  *  DOC:    wma_utis.c
22*5113495bSYour Name  *  This file contains utilities and stats related functions.
23*5113495bSYour Name  */
24*5113495bSYour Name 
25*5113495bSYour Name /* Header files */
26*5113495bSYour Name 
27*5113495bSYour Name #include "wma.h"
28*5113495bSYour Name #include "wma_api.h"
29*5113495bSYour Name #include "cds_api.h"
30*5113495bSYour Name #include "wmi_unified_api.h"
31*5113495bSYour Name #include "wlan_qct_sys.h"
32*5113495bSYour Name #include "wni_api.h"
33*5113495bSYour Name #include "ani_global.h"
34*5113495bSYour Name #include "wmi_unified.h"
35*5113495bSYour Name #include "wni_cfg.h"
36*5113495bSYour Name 
37*5113495bSYour Name #include "qdf_nbuf.h"
38*5113495bSYour Name #include "qdf_types.h"
39*5113495bSYour Name #include "qdf_mem.h"
40*5113495bSYour Name 
41*5113495bSYour Name #include "wma_types.h"
42*5113495bSYour Name #include "lim_api.h"
43*5113495bSYour Name #include "lim_session_utils.h"
44*5113495bSYour Name 
45*5113495bSYour Name #include "cds_utils.h"
46*5113495bSYour Name 
47*5113495bSYour Name #if !defined(REMOVE_PKT_LOG)
48*5113495bSYour Name #include "pktlog_ac.h"
49*5113495bSYour Name #endif /* REMOVE_PKT_LOG */
50*5113495bSYour Name 
51*5113495bSYour Name #include "dbglog_host.h"
52*5113495bSYour Name #include "csr_api.h"
53*5113495bSYour Name #include "ol_fw.h"
54*5113495bSYour Name 
55*5113495bSYour Name #include "wma_internal.h"
56*5113495bSYour Name #include "wlan_policy_mgr_api.h"
57*5113495bSYour Name #include "wmi_unified_param.h"
58*5113495bSYour Name #include "linux/ieee80211.h"
59*5113495bSYour Name #include <cdp_txrx_handle.h>
60*5113495bSYour Name #include <cdp_txrx_peer_ops.h>
61*5113495bSYour Name #include "cds_reg_service.h"
62*5113495bSYour Name #include "target_if.h"
63*5113495bSYour Name #include <wlan_utility.h>
64*5113495bSYour Name #include <wlan_mlme_main.h>
65*5113495bSYour Name #include "host_diag_core_log.h"
66*5113495bSYour Name #include <wlan_mlme_api.h>
67*5113495bSYour Name #include <../../core/src/vdev_mgr_ops.h>
68*5113495bSYour Name #include "cdp_txrx_misc.h"
69*5113495bSYour Name #include <cdp_txrx_host_stats.h>
70*5113495bSYour Name #include "wlan_mlme_ucfg_api.h"
71*5113495bSYour Name #include <wlan_cp_stats_mc_tgt_api.h>
72*5113495bSYour Name #include "wma_eht.h"
73*5113495bSYour Name #include <target_if_spatial_reuse.h>
74*5113495bSYour Name #include "wlan_dp_ucfg_api.h"
75*5113495bSYour Name 
76*5113495bSYour Name /* MCS Based rate table */
77*5113495bSYour Name /* HT MCS parameters with Nss = 1 */
78*5113495bSYour Name static const struct index_data_rate_type mcs_nss1[] = {
79*5113495bSYour Name 	/* MCS L20  S20   L40   S40 */
80*5113495bSYour Name 	{0,  {65,  72},  {135,  150 } },
81*5113495bSYour Name 	{1,  {130, 144}, {270,  300 } },
82*5113495bSYour Name 	{2,  {195, 217}, {405,  450 } },
83*5113495bSYour Name 	{3,  {260, 289}, {540,  600 } },
84*5113495bSYour Name 	{4,  {390, 433}, {815,  900 } },
85*5113495bSYour Name 	{5,  {520, 578}, {1080, 1200} },
86*5113495bSYour Name 	{6,  {585, 650}, {1215, 1350} },
87*5113495bSYour Name 	{7,  {650, 722}, {1350, 1500} }
88*5113495bSYour Name };
89*5113495bSYour Name 
90*5113495bSYour Name /* HT MCS parameters with Nss = 2 */
91*5113495bSYour Name static const struct index_data_rate_type mcs_nss2[] = {
92*5113495bSYour Name 	/* MCS L20  S20    L40   S40 */
93*5113495bSYour Name 	{0,  {130,  144},  {270,  300 } },
94*5113495bSYour Name 	{1,  {260,  289},  {540,  600 } },
95*5113495bSYour Name 	{2,  {390,  433},  {810,  900 } },
96*5113495bSYour Name 	{3,  {520,  578},  {1080, 1200} },
97*5113495bSYour Name 	{4,  {780,  867},  {1620, 1800} },
98*5113495bSYour Name 	{5,  {1040, 1156}, {2160, 2400} },
99*5113495bSYour Name 	{6,  {1170, 1300}, {2430, 2700} },
100*5113495bSYour Name 	{7,  {1300, 1440}, {2700, 3000} }
101*5113495bSYour Name };
102*5113495bSYour Name 
103*5113495bSYour Name /* MCS Based VHT rate table */
104*5113495bSYour Name /* MCS parameters with Nss = 1*/
105*5113495bSYour Name static const struct index_vht_data_rate_type vht_mcs_nss1[] = {
106*5113495bSYour Name 	/* MCS L20  S20    L40   S40    L80   S80    L160  S160*/
107*5113495bSYour Name 	{0,  {65,   72 }, {135,  150},  {293,  325}, {585, 650} },
108*5113495bSYour Name 	{1,  {130,  144}, {270,  300},  {585,  650}, {1170, 1300} },
109*5113495bSYour Name 	{2,  {195,  217}, {405,  450},  {878,  975}, {1755, 1950} },
110*5113495bSYour Name 	{3,  {260,  289}, {540,  600},  {1170, 1300}, {2340, 2600} },
111*5113495bSYour Name 	{4,  {390,  433}, {810,  900},  {1755, 1950}, {3510, 3900} },
112*5113495bSYour Name 	{5,  {520,  578}, {1080, 1200}, {2340, 2600}, {4680, 5200} },
113*5113495bSYour Name 	{6,  {585,  650}, {1215, 1350}, {2633, 2925}, {5265, 5850} },
114*5113495bSYour Name 	{7,  {650,  722}, {1350, 1500}, {2925, 3250}, {5850, 6500} },
115*5113495bSYour Name 	{8,  {780,  867}, {1620, 1800}, {3510, 3900}, {7020, 7800} },
116*5113495bSYour Name 	{9,  {865,  960}, {1800, 2000}, {3900, 4333}, {7800, 8667} },
117*5113495bSYour Name 	{10, {975, 1083}, {2025, 2250}, {4388, 4875}, {8775, 9750} },
118*5113495bSYour Name 	{11, {1083, 1204}, {2250, 2500}, {4875, 5417}, {9750, 1083} }
119*5113495bSYour Name };
120*5113495bSYour Name 
121*5113495bSYour Name /*MCS parameters with Nss = 2*/
122*5113495bSYour Name static const struct index_vht_data_rate_type vht_mcs_nss2[] = {
123*5113495bSYour Name 	/* MCS L20  S20    L40    S40    L80    S80    L160   S160*/
124*5113495bSYour Name 	{0,  {130,  144},  {270,  300},  { 585,  650}, {1170, 1300} },
125*5113495bSYour Name 	{1,  {260,  289},  {540,  600},  {1170, 1300}, {2340, 2600} },
126*5113495bSYour Name 	{2,  {390,  433},  {810,  900},  {1755, 1950}, {3510, 3900} },
127*5113495bSYour Name 	{3,  {520,  578},  {1080, 1200}, {2340, 2600}, {4680, 5200} },
128*5113495bSYour Name 	{4,  {780,  867},  {1620, 1800}, {3510, 3900}, {7020, 7800} },
129*5113495bSYour Name 	{5,  {1040, 1156}, {2160, 2400}, {4680, 5200}, {9360, 10400} },
130*5113495bSYour Name 	{6,  {1170, 1300}, {2430, 2700}, {5265, 5850}, {10530, 11700} },
131*5113495bSYour Name 	{7,  {1300, 1444}, {2700, 3000}, {5850, 6500}, {11700, 13000} },
132*5113495bSYour Name 	{8,  {1560, 1733}, {3240, 3600}, {7020, 7800}, {14040, 15600} },
133*5113495bSYour Name 	{9,  {1730, 1920}, {3600, 4000}, {7800, 8667}, {15600, 17333} },
134*5113495bSYour Name 	{10, {1950, 2167}, {4050, 4500}, {8775, 9750}, {17550, 19500} },
135*5113495bSYour Name 	{11, {2167, 2407}, {4500, 5000}, {9750, 10833}, {19500, 21667} }
136*5113495bSYour Name };
137*5113495bSYour Name 
138*5113495bSYour Name #ifdef WLAN_FEATURE_11AX
139*5113495bSYour Name /* MCS Based HE rate table */
140*5113495bSYour Name /* MCS parameters with Nss = 1*/
141*5113495bSYour Name static const struct index_he_data_rate_type he_mcs_nss1[] = {
142*5113495bSYour Name /* MCS,  {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */
143*5113495bSYour Name 	{0,  {{86,   81,   73  }, {43,   40,  36 } }, /* HE20 */
144*5113495bSYour Name 	     {{172,  163,  146 }, {86,   81,  73 } }, /* HE40 */
145*5113495bSYour Name 	     {{360,  340,  306 }, {180,  170, 153} }, /* HE80 */
146*5113495bSYour Name 	     {{721,  681,  613 }, {360,  340, 306} } }, /* HE160/HE80+80 */
147*5113495bSYour Name 	{1,  {{172,  163,  146 }, {86,   81,  73 } },
148*5113495bSYour Name 	     {{344,  325,  293 }, {172,  163, 146} },
149*5113495bSYour Name 	     {{721,  681,  613 }, {360,  340, 306} },
150*5113495bSYour Name 	     {{1441, 1361, 1225}, {721,  681, 613} } },
151*5113495bSYour Name 	{2,  {{258,  244,  219 }, {0} },
152*5113495bSYour Name 	     {{516,  488,  439 }, {0} },
153*5113495bSYour Name 	     {{1081, 1021, 919 }, {0} },
154*5113495bSYour Name 	     {{2162, 2042, 1838}, {0} } },
155*5113495bSYour Name 	{3,  {{344,  325,  293 }, {172,  163, 146} },
156*5113495bSYour Name 	     {{688,  650,  585 }, {344,  325, 293} },
157*5113495bSYour Name 	     {{1441, 1361, 1225}, {721,  681, 613} },
158*5113495bSYour Name 	     {{2882, 2722, 2450}, {1441, 1361, 1225} } },
159*5113495bSYour Name 	{4,  {{516,  488,  439 }, {258,  244, 219} },
160*5113495bSYour Name 	     {{1032, 975,  878 }, {516,  488, 439} },
161*5113495bSYour Name 	     {{2162, 2042, 1838}, {1081, 1021, 919} },
162*5113495bSYour Name 	     {{4324, 4083, 3675}, {2162, 2042, 1838} } },
163*5113495bSYour Name 	{5,  {{688,  650,  585 }, {0} },
164*5113495bSYour Name 	     {{1376, 1300, 1170}, {0} },
165*5113495bSYour Name 	     {{2882, 2722, 2450}, {0} },
166*5113495bSYour Name 	     {{5765, 5444, 4900}, {0} } },
167*5113495bSYour Name 	{6,  {{774,  731,  658 }, {0} },
168*5113495bSYour Name 	     {{1549, 1463, 1316}, {0} },
169*5113495bSYour Name 	     {{3243, 3063, 2756}, {0} },
170*5113495bSYour Name 	     {{6485, 6125, 5513}, {0} } },
171*5113495bSYour Name 	{7,  {{860,  813,  731 }, {0} },
172*5113495bSYour Name 	     {{1721, 1625, 1463}, {0} },
173*5113495bSYour Name 	     {{3603, 3403, 3063}, {0} },
174*5113495bSYour Name 	     {{7206, 6806, 6125}, {0} } },
175*5113495bSYour Name 	{8,  {{1032, 975,  878 }, {0} },
176*5113495bSYour Name 	     {{2065, 1950, 1755}, {0} },
177*5113495bSYour Name 	     {{4324, 4083, 3675}, {0} },
178*5113495bSYour Name 	     {{8647, 8167, 7350}, {0} } },
179*5113495bSYour Name 	{9,  {{1147, 1083, 975 }, {0} },
180*5113495bSYour Name 	     {{2294, 2167, 1950}, {0} },
181*5113495bSYour Name 	     {{4804, 4537, 4083}, {0} },
182*5113495bSYour Name 	     {{9607, 9074, 8166}, {0} } },
183*5113495bSYour Name 	{10, {{1290, 1219, 1097}, {0} },
184*5113495bSYour Name 	     {{2581, 2438, 2194}, {0} },
185*5113495bSYour Name 	     {{5404, 5104, 4594}, {0} },
186*5113495bSYour Name 	     {{10809, 10208, 9188}, {0} } },
187*5113495bSYour Name 	{11, {{1434, 1354, 1219}, {0} },
188*5113495bSYour Name 	     {{2868, 2708, 2438}, {0} },
189*5113495bSYour Name 	     {{6004, 5671, 5104}, {0} },
190*5113495bSYour Name 	     {{12010, 11342, 10208}, {0} } },
191*5113495bSYour Name 	{12, {{1549, 1463, 1316}, {0} },
192*5113495bSYour Name 	     {{3097, 2925, 2633}, {0} },
193*5113495bSYour Name 	     {{6485, 6125, 5513}, {0} },
194*5113495bSYour Name 	     {{12971, 12250, 11025}, {0} } },
195*5113495bSYour Name 	{13, {{1721, 1625, 1463}, {0} },
196*5113495bSYour Name 	     {{3441, 3250, 2925}, {0} },
197*5113495bSYour Name 	     {{7206, 6806, 6125}, {0} },
198*5113495bSYour Name 	     {{14412, 13611, 12250}, {0} } }
199*5113495bSYour Name };
200*5113495bSYour Name 
201*5113495bSYour Name /*MCS parameters with Nss = 2*/
202*5113495bSYour Name static const struct index_he_data_rate_type he_mcs_nss2[] = {
203*5113495bSYour Name /* MCS,  {dcm0:0.8/1.6/3.2}, {dcm1:0.8/1.6/3.2} */
204*5113495bSYour Name 	{0,  {{172,   163,   146 }, {86,   81,   73 } }, /* HE20 */
205*5113495bSYour Name 	     {{344,   325,   293 }, {172,  163,  146} }, /* HE40 */
206*5113495bSYour Name 	     {{721,   681,   613 }, {360,  340,  306} }, /* HE80 */
207*5113495bSYour Name 	     {{1441, 1361, 1225},   {721, 681, 613} } }, /* HE160/HE80+80 */
208*5113495bSYour Name 	{1,  {{344,   325,   293 }, {172,  163,  146} },
209*5113495bSYour Name 	     {{688,   650,   585 }, {344,  325,  293} },
210*5113495bSYour Name 	     {{1441,  1361,  1225}, {721,  681,  613} },
211*5113495bSYour Name 	     {{2882, 2722, 2450},   {1441, 1361, 1225} } },
212*5113495bSYour Name 	{2,  {{516,   488,   439 }, {0} },
213*5113495bSYour Name 	     {{1032,  975,   878 }, {0} },
214*5113495bSYour Name 	     {{2162,  2042,  1838}, {0} },
215*5113495bSYour Name 	     {{4324, 4083, 3675}, {0} } },
216*5113495bSYour Name 	{3,  {{688,   650,   585 }, {344,  325,  293 } },
217*5113495bSYour Name 	     {{1376,  1300,  1170}, {688,  650,  585  } },
218*5113495bSYour Name 	     {{2882,  2722,  2450}, {1441, 1361, 1225} },
219*5113495bSYour Name 	     {{5765, 5444, 4900}, {2882, 2722, 2450} } },
220*5113495bSYour Name 	{4,  {{1032,  975,   878 }, {516,  488,  439 } },
221*5113495bSYour Name 	     {{2065,  1950,  1755}, {1032, 975,  878 } },
222*5113495bSYour Name 	     {{4324,  4083,  3675}, {2162, 2042, 1838} },
223*5113495bSYour Name 	     {{8647, 8167, 7350}, {4324, 4083, 3675} } },
224*5113495bSYour Name 	{5,  {{1376,  1300,  1170}, {0} },
225*5113495bSYour Name 	     {{2753,  2600,  2340}, {0} },
226*5113495bSYour Name 	     {{5765,  5444,  4900}, {0} },
227*5113495bSYour Name 	     {{11529, 10889, 9800}, {0} } },
228*5113495bSYour Name 	{6,  {{1549,  1463,  1316}, {0} },
229*5113495bSYour Name 	     {{3097,  2925,  2633}, {0} },
230*5113495bSYour Name 	     {{6485,  6125,  5513}, {0} },
231*5113495bSYour Name 	     {{12971, 12250, 11025}, {0} } },
232*5113495bSYour Name 	{7,  {{1721,  1625,  1463}, {0} },
233*5113495bSYour Name 	     {{3441,  3250,  2925}, {0} },
234*5113495bSYour Name 	     {{7206,  6806,  6125}, {0} },
235*5113495bSYour Name 	     {{14412, 13611, 12250}, {0} } },
236*5113495bSYour Name 	{8,  {{2065,  1950,  1755}, {0} },
237*5113495bSYour Name 	     {{4129,  3900,  3510}, {0} },
238*5113495bSYour Name 	     {{8647,  8167,  7350}, {0} },
239*5113495bSYour Name 	     {{17294, 16333, 14700}, {0} } },
240*5113495bSYour Name 	{9,  {{2294,  2167,  1950}, {0} },
241*5113495bSYour Name 	     {{4588,  4333,  3900}, {0} },
242*5113495bSYour Name 	     {{9607,  9074,  8166}, {0} },
243*5113495bSYour Name 	     {{19215, 18148, 16333}, {0} } },
244*5113495bSYour Name 	{10, {{2581,  2438,  2194}, {0} },
245*5113495bSYour Name 	     {{5162,  4875,  4388}, {0} },
246*5113495bSYour Name 	     {{10809, 10208, 9188}, {0} },
247*5113495bSYour Name 	     {{21618, 20417, 18375}, {0} } },
248*5113495bSYour Name 	{11, {{2868,  2708,  2438}, {0} },
249*5113495bSYour Name 	     {{5735,  5417,  4875}, {0} },
250*5113495bSYour Name 	     {{12010, 11343, 10208}, {0} },
251*5113495bSYour Name 	     {{24019, 22685, 20416}, {0} } },
252*5113495bSYour Name 	{12, {{3097,  2925,  2633}, {0} },
253*5113495bSYour Name 	     {{6194,  5850,  5265}, {0} },
254*5113495bSYour Name 	     {{12971, 12250, 11025}, {0} },
255*5113495bSYour Name 	     {{25941, 24500, 22050}, {0} } },
256*5113495bSYour Name 	{13, {{3441,  3250,  2925}, {0} },
257*5113495bSYour Name 	     {{6882,  6500,  5850}, {0} },
258*5113495bSYour Name 	     {{14412, 13611, 12250}, {0} },
259*5113495bSYour Name 	     {{28824, 27222, 24500}, {0} } }
260*5113495bSYour Name };
261*5113495bSYour Name #endif
262*5113495bSYour Name 
263*5113495bSYour Name #ifdef BIG_ENDIAN_HOST
264*5113495bSYour Name 
265*5113495bSYour Name /* ############# function definitions ############ */
266*5113495bSYour Name 
267*5113495bSYour Name /**
268*5113495bSYour Name  * wma_swap_bytes() - swap bytes
269*5113495bSYour Name  * @pv: buffer
270*5113495bSYour Name  * @n: swap bytes
271*5113495bSYour Name  *
272*5113495bSYour Name  * Return: none
273*5113495bSYour Name  */
wma_swap_bytes(void * pv,uint32_t n)274*5113495bSYour Name void wma_swap_bytes(void *pv, uint32_t n)
275*5113495bSYour Name {
276*5113495bSYour Name 	int32_t no_words;
277*5113495bSYour Name 	int32_t i;
278*5113495bSYour Name 	uint32_t *word_ptr;
279*5113495bSYour Name 
280*5113495bSYour Name 	no_words = n / sizeof(uint32_t);
281*5113495bSYour Name 	word_ptr = (uint32_t *) pv;
282*5113495bSYour Name 	for (i = 0; i < no_words; i++)
283*5113495bSYour Name 		*(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
284*5113495bSYour Name }
285*5113495bSYour Name 
286*5113495bSYour Name #define SWAPME(x, len) wma_swap_bytes(&x, len)
287*5113495bSYour Name #endif /* BIG_ENDIAN_HOST */
288*5113495bSYour Name 
wma_mcs_rate_match(uint16_t raw_rate,bool is_he,const uint16_t * nss1_rate,const uint16_t * nss2_rate,uint8_t * nss,enum txrate_gi * guard_interval)289*5113495bSYour Name uint16_t wma_mcs_rate_match(uint16_t raw_rate, bool is_he,
290*5113495bSYour Name 			    const uint16_t *nss1_rate,
291*5113495bSYour Name 			    const uint16_t *nss2_rate,
292*5113495bSYour Name 			    uint8_t *nss, enum txrate_gi *guard_interval)
293*5113495bSYour Name {
294*5113495bSYour Name 	uint8_t gi_index;
295*5113495bSYour Name 	uint8_t gi_index_max = 2;
296*5113495bSYour Name 	uint16_t ret_rate = 0;
297*5113495bSYour Name 
298*5113495bSYour Name 	if (is_he)
299*5113495bSYour Name 		gi_index_max = 3;
300*5113495bSYour Name 
301*5113495bSYour Name 	for (gi_index = 0; gi_index < gi_index_max; gi_index++) {
302*5113495bSYour Name 		if (raw_rate == nss1_rate[gi_index]) {
303*5113495bSYour Name 			*nss = 1;
304*5113495bSYour Name 			ret_rate = nss1_rate[gi_index];
305*5113495bSYour Name 			break;
306*5113495bSYour Name 		}
307*5113495bSYour Name 		if (*nss == 2 && raw_rate == nss2_rate[gi_index]) {
308*5113495bSYour Name 			ret_rate = nss2_rate[gi_index];
309*5113495bSYour Name 			break;
310*5113495bSYour Name 		}
311*5113495bSYour Name 	}
312*5113495bSYour Name 
313*5113495bSYour Name 	if (ret_rate) {
314*5113495bSYour Name 		if (gi_index == 1)
315*5113495bSYour Name 			*guard_interval =
316*5113495bSYour Name 				is_he ? TXRATE_GI_1_6_US : TXRATE_GI_0_4_US;
317*5113495bSYour Name 		else if (is_he && gi_index == 2)
318*5113495bSYour Name 			*guard_interval = TXRATE_GI_3_2_US;
319*5113495bSYour Name 		else
320*5113495bSYour Name 			*guard_interval = TXRATE_GI_0_8_US;
321*5113495bSYour Name 	}
322*5113495bSYour Name 
323*5113495bSYour Name 	return ret_rate;
324*5113495bSYour Name }
325*5113495bSYour Name 
326*5113495bSYour Name #ifdef WLAN_FEATURE_11AX
327*5113495bSYour Name /**
328*5113495bSYour Name  * wma_match_he_rate() - get matching rate for HE
329*5113495bSYour Name  * @raw_rate: raw rate from fw
330*5113495bSYour Name  * @rate_flags: rate flags
331*5113495bSYour Name  * @is_he_mcs_12_13_supported: is HE MCS12/MCS13 supported
332*5113495bSYour Name  * @nss: nss
333*5113495bSYour Name  * @dcm: dcm
334*5113495bSYour Name  * @guard_interval: guard interval
335*5113495bSYour Name  * @mcs_rate_flag: mcs rate flags
336*5113495bSYour Name  * @p_index: index for matched rate
337*5113495bSYour Name  *
338*5113495bSYour Name  *  Return: return match rate if found, else 0
339*5113495bSYour Name  */
wma_match_he_rate(uint16_t raw_rate,enum tx_rate_info rate_flags,bool is_he_mcs_12_13_supported,uint8_t * nss,uint8_t * dcm,enum txrate_gi * guard_interval,enum tx_rate_info * mcs_rate_flag,uint8_t * p_index)340*5113495bSYour Name static uint16_t wma_match_he_rate(uint16_t raw_rate,
341*5113495bSYour Name 				  enum tx_rate_info rate_flags,
342*5113495bSYour Name 				  bool is_he_mcs_12_13_supported,
343*5113495bSYour Name 				  uint8_t *nss, uint8_t *dcm,
344*5113495bSYour Name 				  enum txrate_gi *guard_interval,
345*5113495bSYour Name 				  enum tx_rate_info *mcs_rate_flag,
346*5113495bSYour Name 				  uint8_t *p_index)
347*5113495bSYour Name {
348*5113495bSYour Name 	uint8_t index = 0, max_he_mcs_idx;
349*5113495bSYour Name 	uint8_t dcm_index_max = 1;
350*5113495bSYour Name 	uint8_t dcm_index = 0;
351*5113495bSYour Name 	uint16_t match_rate = 0;
352*5113495bSYour Name 	const uint16_t *nss1_rate;
353*5113495bSYour Name 	const uint16_t *nss2_rate;
354*5113495bSYour Name 
355*5113495bSYour Name 	*p_index = 0;
356*5113495bSYour Name 	if (!(rate_flags & (TX_RATE_HE160 | TX_RATE_HE80 | TX_RATE_HE40 |
357*5113495bSYour Name 		TX_RATE_HE20)))
358*5113495bSYour Name 		return 0;
359*5113495bSYour Name 
360*5113495bSYour Name 	if (is_he_mcs_12_13_supported)
361*5113495bSYour Name 		max_he_mcs_idx = QDF_ARRAY_SIZE(he_mcs_nss1);
362*5113495bSYour Name 	else
363*5113495bSYour Name 		max_he_mcs_idx = QDF_ARRAY_SIZE(he_mcs_nss1) - 2;
364*5113495bSYour Name 
365*5113495bSYour Name 	for (index = 0; index < max_he_mcs_idx; index++) {
366*5113495bSYour Name 		dcm_index_max = IS_MCS_HAS_DCM_RATE(index) ? 2 : 1;
367*5113495bSYour Name 
368*5113495bSYour Name 		for (dcm_index = 0; dcm_index < dcm_index_max;
369*5113495bSYour Name 			 dcm_index++) {
370*5113495bSYour Name 			if (rate_flags & TX_RATE_HE160) {
371*5113495bSYour Name 				nss1_rate = &he_mcs_nss1[index].
372*5113495bSYour Name 					supported_he160_rate[dcm_index][0];
373*5113495bSYour Name 				nss2_rate = &he_mcs_nss2[index].
374*5113495bSYour Name 					supported_he160_rate[dcm_index][0];
375*5113495bSYour Name 				/* check for he160 nss1/2 rate set */
376*5113495bSYour Name 				match_rate = wma_mcs_rate_match(raw_rate, 1,
377*5113495bSYour Name 								nss1_rate,
378*5113495bSYour Name 								nss2_rate,
379*5113495bSYour Name 								nss,
380*5113495bSYour Name 								guard_interval);
381*5113495bSYour Name 				if (match_rate)
382*5113495bSYour Name 					goto rate_found;
383*5113495bSYour Name 			}
384*5113495bSYour Name 
385*5113495bSYour Name 			if (rate_flags & (TX_RATE_HE80 | TX_RATE_HE160)) {
386*5113495bSYour Name 				nss1_rate = &he_mcs_nss1[index].
387*5113495bSYour Name 					supported_he80_rate[dcm_index][0];
388*5113495bSYour Name 				nss2_rate = &he_mcs_nss2[index].
389*5113495bSYour Name 					supported_he80_rate[dcm_index][0];
390*5113495bSYour Name 				/* check for he80 nss1/2 rate set */
391*5113495bSYour Name 				match_rate = wma_mcs_rate_match(raw_rate, 1,
392*5113495bSYour Name 								nss1_rate,
393*5113495bSYour Name 								nss2_rate,
394*5113495bSYour Name 								nss,
395*5113495bSYour Name 								guard_interval);
396*5113495bSYour Name 				if (match_rate) {
397*5113495bSYour Name 					*mcs_rate_flag &= ~TX_RATE_HE160;
398*5113495bSYour Name 					goto rate_found;
399*5113495bSYour Name 				}
400*5113495bSYour Name 			}
401*5113495bSYour Name 
402*5113495bSYour Name 			if (rate_flags & (TX_RATE_HE40 | TX_RATE_HE80 |
403*5113495bSYour Name 					  TX_RATE_HE160)) {
404*5113495bSYour Name 				nss1_rate = &he_mcs_nss1[index].
405*5113495bSYour Name 					supported_he40_rate[dcm_index][0];
406*5113495bSYour Name 				nss2_rate = &he_mcs_nss2[index].
407*5113495bSYour Name 					supported_he40_rate[dcm_index][0];
408*5113495bSYour Name 				/* check for he40 nss1/2 rate set */
409*5113495bSYour Name 				match_rate = wma_mcs_rate_match(raw_rate, 1,
410*5113495bSYour Name 								nss1_rate,
411*5113495bSYour Name 								nss2_rate,
412*5113495bSYour Name 								nss,
413*5113495bSYour Name 								guard_interval);
414*5113495bSYour Name 
415*5113495bSYour Name 				if (match_rate) {
416*5113495bSYour Name 					*mcs_rate_flag &= ~(TX_RATE_HE80 |
417*5113495bSYour Name 							    TX_RATE_HE160);
418*5113495bSYour Name 					goto rate_found;
419*5113495bSYour Name 				}
420*5113495bSYour Name 			}
421*5113495bSYour Name 
422*5113495bSYour Name 			if (rate_flags & (TX_RATE_HE80 | TX_RATE_HE40 |
423*5113495bSYour Name 				TX_RATE_HE20 | TX_RATE_HE160)) {
424*5113495bSYour Name 				nss1_rate = &he_mcs_nss1[index].
425*5113495bSYour Name 					supported_he20_rate[dcm_index][0];
426*5113495bSYour Name 				nss2_rate = &he_mcs_nss2[index].
427*5113495bSYour Name 					supported_he20_rate[dcm_index][0];
428*5113495bSYour Name 				/* check for he20 nss1/2 rate set */
429*5113495bSYour Name 				match_rate = wma_mcs_rate_match(raw_rate, 1,
430*5113495bSYour Name 								nss1_rate,
431*5113495bSYour Name 								nss2_rate,
432*5113495bSYour Name 								nss,
433*5113495bSYour Name 								guard_interval);
434*5113495bSYour Name 
435*5113495bSYour Name 				if (match_rate) {
436*5113495bSYour Name 					*mcs_rate_flag &= TX_RATE_HE20;
437*5113495bSYour Name 					goto rate_found;
438*5113495bSYour Name 				}
439*5113495bSYour Name 			}
440*5113495bSYour Name 		}
441*5113495bSYour Name 	}
442*5113495bSYour Name 
443*5113495bSYour Name rate_found:
444*5113495bSYour Name 	if (match_rate) {
445*5113495bSYour Name 		if (dcm_index == 1)
446*5113495bSYour Name 			*dcm = 1;
447*5113495bSYour Name 		*p_index = index;
448*5113495bSYour Name 	}
449*5113495bSYour Name 	return match_rate;
450*5113495bSYour Name }
451*5113495bSYour Name #else
wma_match_he_rate(uint16_t raw_rate,enum tx_rate_info rate_flags,bool is_he_mcs_12_13_supported,uint8_t * nss,uint8_t * dcm,enum txrate_gi * guard_interval,enum tx_rate_info * mcs_rate_flag,uint8_t * p_index)452*5113495bSYour Name static uint16_t wma_match_he_rate(uint16_t raw_rate,
453*5113495bSYour Name 				  enum tx_rate_info rate_flags,
454*5113495bSYour Name 				  bool is_he_mcs_12_13_supported,
455*5113495bSYour Name 				  uint8_t *nss, uint8_t *dcm,
456*5113495bSYour Name 				  enum txrate_gi *guard_interval,
457*5113495bSYour Name 				  enum tx_rate_info *mcs_rate_flag,
458*5113495bSYour Name 				  uint8_t *p_index)
459*5113495bSYour Name {
460*5113495bSYour Name 		return 0;
461*5113495bSYour Name }
462*5113495bSYour Name #endif
463*5113495bSYour Name 
wma_get_mcs_idx(uint16_t raw_rate,enum tx_rate_info rate_flags,bool is_he_mcs_12_13_supported,uint8_t * nss,uint8_t * dcm,enum txrate_gi * guard_interval,enum tx_rate_info * mcs_rate_flag)464*5113495bSYour Name uint8_t wma_get_mcs_idx(uint16_t raw_rate, enum tx_rate_info rate_flags,
465*5113495bSYour Name 			bool is_he_mcs_12_13_supported,
466*5113495bSYour Name 			uint8_t *nss, uint8_t *dcm,
467*5113495bSYour Name 			enum txrate_gi *guard_interval,
468*5113495bSYour Name 			enum tx_rate_info *mcs_rate_flag)
469*5113495bSYour Name {
470*5113495bSYour Name 	uint8_t  index = 0;
471*5113495bSYour Name 	uint16_t match_rate = 0;
472*5113495bSYour Name 	uint8_t max_ht_mcs_idx;
473*5113495bSYour Name 	const uint16_t *nss1_rate;
474*5113495bSYour Name 	const uint16_t *nss2_rate;
475*5113495bSYour Name 
476*5113495bSYour Name 	wma_debug("Rates from FW:  raw_rate:%d rate_flgs: 0x%x is_he_mcs_12_13_supported: %d nss: %d",
477*5113495bSYour Name 		  raw_rate, rate_flags, is_he_mcs_12_13_supported, *nss);
478*5113495bSYour Name 
479*5113495bSYour Name 	*mcs_rate_flag = rate_flags;
480*5113495bSYour Name 
481*5113495bSYour Name 	match_rate = wma_match_eht_rate(raw_rate, rate_flags,
482*5113495bSYour Name 					nss, dcm, guard_interval,
483*5113495bSYour Name 					mcs_rate_flag, &index);
484*5113495bSYour Name 	if (match_rate)
485*5113495bSYour Name 		goto rate_found;
486*5113495bSYour Name 
487*5113495bSYour Name 	match_rate = wma_match_he_rate(raw_rate, rate_flags,
488*5113495bSYour Name 				       is_he_mcs_12_13_supported,
489*5113495bSYour Name 				       nss, dcm, guard_interval,
490*5113495bSYour Name 				       mcs_rate_flag, &index);
491*5113495bSYour Name 	if (match_rate)
492*5113495bSYour Name 		goto rate_found;
493*5113495bSYour Name 
494*5113495bSYour Name 	for (index = 0; index < QDF_ARRAY_SIZE(vht_mcs_nss1); index++) {
495*5113495bSYour Name 		if (rate_flags & TX_RATE_VHT160) {
496*5113495bSYour Name 			nss1_rate = &vht_mcs_nss1[index].ht160_rate[0];
497*5113495bSYour Name 			nss2_rate = &vht_mcs_nss2[index].ht160_rate[0];
498*5113495bSYour Name 			/* check for vht160 nss1/2 rate set */
499*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
500*5113495bSYour Name 							nss1_rate,
501*5113495bSYour Name 							nss2_rate,
502*5113495bSYour Name 							nss, guard_interval);
503*5113495bSYour Name 			if (match_rate)
504*5113495bSYour Name 				goto rate_found;
505*5113495bSYour Name 		}
506*5113495bSYour Name 		if (rate_flags & (TX_RATE_VHT80 | TX_RATE_VHT160)) {
507*5113495bSYour Name 			nss1_rate = &vht_mcs_nss1[index].ht80_rate[0];
508*5113495bSYour Name 			nss2_rate = &vht_mcs_nss2[index].ht80_rate[0];
509*5113495bSYour Name 			/* check for vht80 nss1/2 rate set */
510*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
511*5113495bSYour Name 							nss1_rate,
512*5113495bSYour Name 							nss2_rate,
513*5113495bSYour Name 							nss, guard_interval);
514*5113495bSYour Name 			if (match_rate) {
515*5113495bSYour Name 				*mcs_rate_flag &= ~TX_RATE_VHT160;
516*5113495bSYour Name 				goto rate_found;
517*5113495bSYour Name 			}
518*5113495bSYour Name 		}
519*5113495bSYour Name 		if (rate_flags & (TX_RATE_VHT40 | TX_RATE_VHT80 |
520*5113495bSYour Name 				TX_RATE_VHT160)) {
521*5113495bSYour Name 			nss1_rate = &vht_mcs_nss1[index].ht40_rate[0];
522*5113495bSYour Name 			nss2_rate = &vht_mcs_nss2[index].ht40_rate[0];
523*5113495bSYour Name 			/* check for vht40 nss1/2 rate set */
524*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
525*5113495bSYour Name 							nss1_rate,
526*5113495bSYour Name 							nss2_rate,
527*5113495bSYour Name 							nss, guard_interval);
528*5113495bSYour Name 			if (match_rate) {
529*5113495bSYour Name 				*mcs_rate_flag &= ~TX_RATE_VHT80;
530*5113495bSYour Name 				goto rate_found;
531*5113495bSYour Name 			}
532*5113495bSYour Name 		}
533*5113495bSYour Name 		if (rate_flags & (TX_RATE_VHT20 | TX_RATE_VHT40 |
534*5113495bSYour Name 			TX_RATE_VHT80 | TX_RATE_VHT160)) {
535*5113495bSYour Name 			nss1_rate = &vht_mcs_nss1[index].ht20_rate[0];
536*5113495bSYour Name 			nss2_rate = &vht_mcs_nss2[index].ht20_rate[0];
537*5113495bSYour Name 			/* check for vht20 nss1/2 rate set */
538*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
539*5113495bSYour Name 							nss1_rate,
540*5113495bSYour Name 							nss2_rate,
541*5113495bSYour Name 							nss, guard_interval);
542*5113495bSYour Name 			if (match_rate) {
543*5113495bSYour Name 				*mcs_rate_flag &= ~(TX_RATE_VHT80 |
544*5113495bSYour Name 						TX_RATE_VHT40);
545*5113495bSYour Name 				goto rate_found;
546*5113495bSYour Name 			}
547*5113495bSYour Name 		}
548*5113495bSYour Name 	}
549*5113495bSYour Name 	max_ht_mcs_idx = QDF_ARRAY_SIZE(mcs_nss1);
550*5113495bSYour Name 	for (index = 0; index < max_ht_mcs_idx; index++) {
551*5113495bSYour Name 		if (rate_flags & TX_RATE_HT40) {
552*5113495bSYour Name 			nss1_rate = &mcs_nss1[index].ht40_rate[0];
553*5113495bSYour Name 			nss2_rate = &mcs_nss2[index].ht40_rate[0];
554*5113495bSYour Name 			/* check for ht40 nss1/2 rate set */
555*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
556*5113495bSYour Name 							nss1_rate,
557*5113495bSYour Name 							nss2_rate,
558*5113495bSYour Name 							nss, guard_interval);
559*5113495bSYour Name 			if (match_rate) {
560*5113495bSYour Name 				*mcs_rate_flag = TX_RATE_HT40;
561*5113495bSYour Name 				if (*nss == 2)
562*5113495bSYour Name 					index += max_ht_mcs_idx;
563*5113495bSYour Name 				goto rate_found;
564*5113495bSYour Name 			}
565*5113495bSYour Name 		}
566*5113495bSYour Name 		if (rate_flags & (TX_RATE_HT20 | TX_RATE_HT40)) {
567*5113495bSYour Name 			nss1_rate = &mcs_nss1[index].ht20_rate[0];
568*5113495bSYour Name 			nss2_rate = &mcs_nss2[index].ht20_rate[0];
569*5113495bSYour Name 			/* check for ht20 nss1/2 rate set */
570*5113495bSYour Name 			match_rate = wma_mcs_rate_match(raw_rate, 0,
571*5113495bSYour Name 							nss1_rate,
572*5113495bSYour Name 							nss2_rate,
573*5113495bSYour Name 							nss, guard_interval);
574*5113495bSYour Name 			if (match_rate) {
575*5113495bSYour Name 				*mcs_rate_flag = TX_RATE_HT20;
576*5113495bSYour Name 				if (*nss == 2)
577*5113495bSYour Name 					index += max_ht_mcs_idx;
578*5113495bSYour Name 				goto rate_found;
579*5113495bSYour Name 			}
580*5113495bSYour Name 		}
581*5113495bSYour Name 	}
582*5113495bSYour Name 
583*5113495bSYour Name rate_found:
584*5113495bSYour Name 
585*5113495bSYour Name 	/* set SGI flag only if this is SGI rate */
586*5113495bSYour Name 	if (match_rate && *guard_interval == TXRATE_GI_0_4_US)
587*5113495bSYour Name 		*mcs_rate_flag |= TX_RATE_SGI;
588*5113495bSYour Name 	else
589*5113495bSYour Name 		*mcs_rate_flag &= ~TX_RATE_SGI;
590*5113495bSYour Name 
591*5113495bSYour Name 	wma_debug("Matched rate in table: %d index: %d"
592*5113495bSYour Name 		 " mcs_rate_flag: 0x%x nss %d guard interval %d",
593*5113495bSYour Name 		 match_rate, index, *mcs_rate_flag,
594*5113495bSYour Name 		 *nss, *guard_interval);
595*5113495bSYour Name 
596*5113495bSYour Name 	return match_rate ? index : INVALID_MCS_IDX;
597*5113495bSYour Name }
598*5113495bSYour Name 
wma_lost_link_info_handler(tp_wma_handle wma,uint32_t vdev_id,int32_t rssi)599*5113495bSYour Name void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
600*5113495bSYour Name 					int32_t rssi)
601*5113495bSYour Name {
602*5113495bSYour Name 	struct sir_lost_link_info *lost_link_info;
603*5113495bSYour Name 	QDF_STATUS qdf_status;
604*5113495bSYour Name 	struct scheduler_msg sme_msg = {0};
605*5113495bSYour Name 
606*5113495bSYour Name 	if (vdev_id >= wma->max_bssid) {
607*5113495bSYour Name 		wma_err("received invalid vdev_id %d", vdev_id);
608*5113495bSYour Name 		return;
609*5113495bSYour Name 	}
610*5113495bSYour Name 
611*5113495bSYour Name 	/* report lost link information only for STA mode */
612*5113495bSYour Name 	if (wma_is_vdev_up(vdev_id) &&
613*5113495bSYour Name 	    (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
614*5113495bSYour Name 	    (0 == wma->interfaces[vdev_id].sub_type)) {
615*5113495bSYour Name 		lim_update_lost_link_rssi(wma->mac_context, rssi);
616*5113495bSYour Name 		lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
617*5113495bSYour Name 		if (!lost_link_info)
618*5113495bSYour Name 			return;
619*5113495bSYour Name 
620*5113495bSYour Name 		lost_link_info->vdev_id = vdev_id;
621*5113495bSYour Name 		lost_link_info->rssi = rssi;
622*5113495bSYour Name 		sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
623*5113495bSYour Name 		sme_msg.bodyptr = lost_link_info;
624*5113495bSYour Name 		sme_msg.bodyval = 0;
625*5113495bSYour Name 		qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
626*5113495bSYour Name 						    QDF_MODULE_ID_SME,
627*5113495bSYour Name 						    QDF_MODULE_ID_SME,
628*5113495bSYour Name 						    &sme_msg);
629*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
630*5113495bSYour Name 			wma_err("fail to post msg to SME");
631*5113495bSYour Name 			qdf_mem_free(lost_link_info);
632*5113495bSYour Name 		}
633*5113495bSYour Name 	}
634*5113495bSYour Name }
635*5113495bSYour Name 
636*5113495bSYour Name /**
637*5113495bSYour Name  * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
638*5113495bSYour Name  * @fw_smps_mode: fw smps mode
639*5113495bSYour Name  *
640*5113495bSYour Name  * Return: return enum eSmpsModeValue
641*5113495bSYour Name  */
host_map_smps_mode(A_UINT32 fw_smps_mode)642*5113495bSYour Name enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
643*5113495bSYour Name {
644*5113495bSYour Name 	enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
645*5113495bSYour Name 
646*5113495bSYour Name 	switch (fw_smps_mode) {
647*5113495bSYour Name 	case WMI_SMPS_FORCED_MODE_STATIC:
648*5113495bSYour Name 		smps_mode = STATIC_SMPS_MODE;
649*5113495bSYour Name 		break;
650*5113495bSYour Name 	case WMI_SMPS_FORCED_MODE_DYNAMIC:
651*5113495bSYour Name 		smps_mode = DYNAMIC_SMPS_MODE;
652*5113495bSYour Name 		break;
653*5113495bSYour Name 	default:
654*5113495bSYour Name 		smps_mode = SMPS_MODE_DISABLED;
655*5113495bSYour Name 	}
656*5113495bSYour Name 
657*5113495bSYour Name 	return smps_mode;
658*5113495bSYour Name }
659*5113495bSYour Name 
660*5113495bSYour Name /**
661*5113495bSYour Name  * wma_smps_mode_to_force_mode_param() - Map smps mode to force
662*5113495bSYour Name  * mode command param
663*5113495bSYour Name  * @smps_mode: SMPS mode according to the protocol
664*5113495bSYour Name  *
665*5113495bSYour Name  * Return: int > 0 for success else failure
666*5113495bSYour Name  */
wma_smps_mode_to_force_mode_param(uint8_t smps_mode)667*5113495bSYour Name int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
668*5113495bSYour Name {
669*5113495bSYour Name 	int param = -EINVAL;
670*5113495bSYour Name 
671*5113495bSYour Name 	switch (smps_mode) {
672*5113495bSYour Name 	case STATIC_SMPS_MODE:
673*5113495bSYour Name 		param = WMI_SMPS_FORCED_MODE_STATIC;
674*5113495bSYour Name 		break;
675*5113495bSYour Name 	case DYNAMIC_SMPS_MODE:
676*5113495bSYour Name 		param = WMI_SMPS_FORCED_MODE_DYNAMIC;
677*5113495bSYour Name 		break;
678*5113495bSYour Name 	case SMPS_MODE_DISABLED:
679*5113495bSYour Name 		param = WMI_SMPS_FORCED_MODE_DISABLED;
680*5113495bSYour Name 		break;
681*5113495bSYour Name 	default:
682*5113495bSYour Name 		wma_err("smps mode cannot be mapped :%d", smps_mode);
683*5113495bSYour Name 	}
684*5113495bSYour Name 	return param;
685*5113495bSYour Name }
686*5113495bSYour Name 
687*5113495bSYour Name #ifdef WLAN_FEATURE_STATS_EXT
688*5113495bSYour Name #ifdef FEATURE_STATS_EXT_V2
wma_stats_ext_event_handler(void * handle,uint8_t * event_buf,uint32_t len)689*5113495bSYour Name int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
690*5113495bSYour Name 				uint32_t len)
691*5113495bSYour Name {
692*5113495bSYour Name 	WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
693*5113495bSYour Name 	tSirStatsExtEvent *stats_ext_event;
694*5113495bSYour Name 	wmi_stats_ext_event_fixed_param *stats_ext_info;
695*5113495bSYour Name 	QDF_STATUS status;
696*5113495bSYour Name 	struct scheduler_msg cds_msg = {0};
697*5113495bSYour Name 	uint8_t *buf_ptr;
698*5113495bSYour Name 	uint32_t alloc_len = 0, i, partner_links_data_len = 0;
699*5113495bSYour Name 	struct cdp_txrx_ext_stats ext_stats = {0};
700*5113495bSYour Name 	struct cdp_soc_t *soc_hdl = cds_get_context(QDF_MODULE_ID_SOC);
701*5113495bSYour Name 	wmi_partner_link_stats *link_stats;
702*5113495bSYour Name 
703*5113495bSYour Name 	wma_debug("Posting stats ext event to SME");
704*5113495bSYour Name 
705*5113495bSYour Name 	param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *)event_buf;
706*5113495bSYour Name 	if (!param_buf) {
707*5113495bSYour Name 		wma_err("Invalid stats ext event buf");
708*5113495bSYour Name 		return -EINVAL;
709*5113495bSYour Name 	}
710*5113495bSYour Name 
711*5113495bSYour Name 	if (param_buf->num_partner_link_stats)
712*5113495bSYour Name 		wma_debug("number of partner link stats:%d",
713*5113495bSYour Name 			  param_buf->num_partner_link_stats);
714*5113495bSYour Name 
715*5113495bSYour Name 	stats_ext_info = param_buf->fixed_param;
716*5113495bSYour Name 	buf_ptr = (uint8_t *)stats_ext_info;
717*5113495bSYour Name 
718*5113495bSYour Name 	alloc_len += sizeof(tSirStatsExtEvent);
719*5113495bSYour Name 	alloc_len += stats_ext_info->data_len;
720*5113495bSYour Name 	alloc_len += sizeof(struct cdp_txrx_ext_stats);
721*5113495bSYour Name 
722*5113495bSYour Name 	if (param_buf->num_partner_link_stats) {
723*5113495bSYour Name 		link_stats = param_buf->partner_link_stats;
724*5113495bSYour Name 		if (link_stats) {
725*5113495bSYour Name 			for (i = 0; i < param_buf->num_partner_link_stats; i++) {
726*5113495bSYour Name 				partner_links_data_len += link_stats->data_length;
727*5113495bSYour Name 				link_stats++;
728*5113495bSYour Name 			}
729*5113495bSYour Name 		alloc_len += partner_links_data_len;
730*5113495bSYour Name 		alloc_len += param_buf->num_partner_link_stats *
731*5113495bSYour Name 			     sizeof(struct cdp_txrx_ext_stats);
732*5113495bSYour Name 		}
733*5113495bSYour Name 	}
734*5113495bSYour Name 
735*5113495bSYour Name 	if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
736*5113495bSYour Name 	    WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) ||
737*5113495bSYour Name 	    stats_ext_info->data_len > param_buf->num_data) {
738*5113495bSYour Name 		wma_err("Excess data_len:%d, num_data:%d",
739*5113495bSYour Name 			stats_ext_info->data_len, param_buf->num_data);
740*5113495bSYour Name 		return -EINVAL;
741*5113495bSYour Name 	}
742*5113495bSYour Name 	stats_ext_event = qdf_mem_malloc(alloc_len);
743*5113495bSYour Name 	if (!stats_ext_event)
744*5113495bSYour Name 		return -ENOMEM;
745*5113495bSYour Name 
746*5113495bSYour Name 	buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
747*5113495bSYour Name 
748*5113495bSYour Name 	stats_ext_event->vdev_id = stats_ext_info->vdev_id;
749*5113495bSYour Name 	stats_ext_event->event_data_len = stats_ext_info->data_len;
750*5113495bSYour Name 	qdf_mem_copy(stats_ext_event->event_data,
751*5113495bSYour Name 		     buf_ptr, stats_ext_event->event_data_len);
752*5113495bSYour Name 
753*5113495bSYour Name 	cdp_txrx_ext_stats_request(soc_hdl, OL_TXRX_PDEV_ID, &ext_stats);
754*5113495bSYour Name 	qdf_mem_copy(stats_ext_event->event_data +
755*5113495bSYour Name 		     stats_ext_event->event_data_len,
756*5113495bSYour Name 		     &ext_stats, sizeof(struct cdp_txrx_ext_stats));
757*5113495bSYour Name 
758*5113495bSYour Name 	stats_ext_event->event_data_len += sizeof(struct cdp_txrx_ext_stats);
759*5113495bSYour Name 
760*5113495bSYour Name 	if (param_buf->num_partner_link_stats) {
761*5113495bSYour Name 		link_stats = param_buf->partner_link_stats;
762*5113495bSYour Name 		if (link_stats) {
763*5113495bSYour Name 			for (i = 0; i < param_buf->num_partner_link_stats; i++) {
764*5113495bSYour Name 				qdf_mem_copy(((uint8_t *)stats_ext_event->event_data) +
765*5113495bSYour Name 					     stats_ext_event->event_data_len,
766*5113495bSYour Name 					     param_buf->partner_link_data +
767*5113495bSYour Name 					     link_stats->offset,
768*5113495bSYour Name 					     link_stats->data_length);
769*5113495bSYour Name 
770*5113495bSYour Name 				stats_ext_event->event_data_len +=
771*5113495bSYour Name 							link_stats->data_length;
772*5113495bSYour Name 
773*5113495bSYour Name 				qdf_mem_copy(stats_ext_event->event_data +
774*5113495bSYour Name 						stats_ext_event->event_data_len,
775*5113495bSYour Name 						&ext_stats,
776*5113495bSYour Name 						sizeof(struct cdp_txrx_ext_stats));
777*5113495bSYour Name 				stats_ext_event->event_data_len +=
778*5113495bSYour Name 					sizeof(struct cdp_txrx_ext_stats);
779*5113495bSYour Name 				link_stats++;
780*5113495bSYour Name 			}
781*5113495bSYour Name 		}
782*5113495bSYour Name 	}
783*5113495bSYour Name 
784*5113495bSYour Name 	cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
785*5113495bSYour Name 	cds_msg.bodyptr = (void *)stats_ext_event;
786*5113495bSYour Name 	cds_msg.bodyval = 0;
787*5113495bSYour Name 
788*5113495bSYour Name 	status = scheduler_post_message(QDF_MODULE_ID_WMA,
789*5113495bSYour Name 					QDF_MODULE_ID_SME,
790*5113495bSYour Name 					QDF_MODULE_ID_SME, &cds_msg);
791*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
792*5113495bSYour Name 		qdf_mem_free(stats_ext_event);
793*5113495bSYour Name 		return -EFAULT;
794*5113495bSYour Name 	}
795*5113495bSYour Name 
796*5113495bSYour Name 	wma_debug("stats ext event Posted to SME");
797*5113495bSYour Name 	return 0;
798*5113495bSYour Name }
799*5113495bSYour Name #else
wma_stats_ext_event_handler(void * handle,uint8_t * event_buf,uint32_t len)800*5113495bSYour Name int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
801*5113495bSYour Name 				uint32_t len)
802*5113495bSYour Name {
803*5113495bSYour Name 	WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
804*5113495bSYour Name 	tSirStatsExtEvent *stats_ext_event;
805*5113495bSYour Name 	wmi_stats_ext_event_fixed_param *stats_ext_info;
806*5113495bSYour Name 	QDF_STATUS status;
807*5113495bSYour Name 	struct scheduler_msg cds_msg = {0};
808*5113495bSYour Name 	uint8_t *buf_ptr;
809*5113495bSYour Name 	uint32_t alloc_len;
810*5113495bSYour Name 
811*5113495bSYour Name 	wma_debug("Posting stats ext event to SME");
812*5113495bSYour Name 
813*5113495bSYour Name 	param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *)event_buf;
814*5113495bSYour Name 	if (!param_buf) {
815*5113495bSYour Name 		wma_err("Invalid stats ext event buf");
816*5113495bSYour Name 		return -EINVAL;
817*5113495bSYour Name 	}
818*5113495bSYour Name 
819*5113495bSYour Name 	stats_ext_info = param_buf->fixed_param;
820*5113495bSYour Name 	buf_ptr = (uint8_t *)stats_ext_info;
821*5113495bSYour Name 
822*5113495bSYour Name 	alloc_len = sizeof(tSirStatsExtEvent);
823*5113495bSYour Name 	alloc_len += stats_ext_info->data_len;
824*5113495bSYour Name 
825*5113495bSYour Name 	if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
826*5113495bSYour Name 	    WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) ||
827*5113495bSYour Name 	    stats_ext_info->data_len > param_buf->num_data) {
828*5113495bSYour Name 		wma_err("Excess data_len:%d, num_data:%d",
829*5113495bSYour Name 			stats_ext_info->data_len, param_buf->num_data);
830*5113495bSYour Name 		return -EINVAL;
831*5113495bSYour Name 	}
832*5113495bSYour Name 	stats_ext_event = qdf_mem_malloc(alloc_len);
833*5113495bSYour Name 	if (!stats_ext_event)
834*5113495bSYour Name 		return -ENOMEM;
835*5113495bSYour Name 
836*5113495bSYour Name 	buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
837*5113495bSYour Name 
838*5113495bSYour Name 	stats_ext_event->vdev_id = stats_ext_info->vdev_id;
839*5113495bSYour Name 	stats_ext_event->event_data_len = stats_ext_info->data_len;
840*5113495bSYour Name 	qdf_mem_copy(stats_ext_event->event_data,
841*5113495bSYour Name 		     buf_ptr, stats_ext_event->event_data_len);
842*5113495bSYour Name 
843*5113495bSYour Name 	cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
844*5113495bSYour Name 	cds_msg.bodyptr = (void *)stats_ext_event;
845*5113495bSYour Name 	cds_msg.bodyval = 0;
846*5113495bSYour Name 
847*5113495bSYour Name 	status = scheduler_post_message(QDF_MODULE_ID_WMA,
848*5113495bSYour Name 					QDF_MODULE_ID_SME,
849*5113495bSYour Name 					QDF_MODULE_ID_SME, &cds_msg);
850*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
851*5113495bSYour Name 		qdf_mem_free(stats_ext_event);
852*5113495bSYour Name 		return -EFAULT;
853*5113495bSYour Name 	}
854*5113495bSYour Name 
855*5113495bSYour Name 	wma_debug("stats ext event Posted to SME");
856*5113495bSYour Name 	return 0;
857*5113495bSYour Name }
858*5113495bSYour Name #endif
859*5113495bSYour Name #endif /* WLAN_FEATURE_STATS_EXT */
860*5113495bSYour Name 
861*5113495bSYour Name /**
862*5113495bSYour Name  * wma_profile_data_report_event_handler() - fw profiling handler
863*5113495bSYour Name  * @handle:     wma handle
864*5113495bSYour Name  * @event_buf:  event buffer received from fw
865*5113495bSYour Name  * @len:        length of data
866*5113495bSYour Name  *
867*5113495bSYour Name  * Return: 0 for success or error code
868*5113495bSYour Name  */
wma_profile_data_report_event_handler(void * handle,uint8_t * event_buf,uint32_t len)869*5113495bSYour Name int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
870*5113495bSYour Name 				uint32_t len)
871*5113495bSYour Name {
872*5113495bSYour Name 	WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
873*5113495bSYour Name 	wmi_wlan_profile_ctx_t *profile_ctx;
874*5113495bSYour Name 	wmi_wlan_profile_t *profile_data;
875*5113495bSYour Name 	uint32_t i = 0;
876*5113495bSYour Name 	uint32_t entries;
877*5113495bSYour Name 	char temp_str[150];
878*5113495bSYour Name 
879*5113495bSYour Name 	param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
880*5113495bSYour Name 	if (!param_buf) {
881*5113495bSYour Name 		wma_err("Invalid profile data event buf");
882*5113495bSYour Name 		return -EINVAL;
883*5113495bSYour Name 	}
884*5113495bSYour Name 
885*5113495bSYour Name 	profile_ctx = param_buf->profile_ctx;
886*5113495bSYour Name 	entries = profile_ctx->bin_count;
887*5113495bSYour Name 	if (entries > param_buf->num_profile_data) {
888*5113495bSYour Name 		wma_err("FW bin count %d more than data %d in TLV hdr",
889*5113495bSYour Name 			 entries,
890*5113495bSYour Name 			 param_buf->num_profile_data);
891*5113495bSYour Name 		return -EINVAL;
892*5113495bSYour Name 	}
893*5113495bSYour Name 
894*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
895*5113495bSYour Name 				"Profile data stats\n");
896*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
897*5113495bSYour Name 		"TOT: %d\n"
898*5113495bSYour Name 		"tx_msdu_cnt: %d\n"
899*5113495bSYour Name 		"tx_mpdu_cnt: %d\n"
900*5113495bSYour Name 		"tx_ppdu_cnt: %d\n"
901*5113495bSYour Name 		"rx_msdu_cnt: %d\n"
902*5113495bSYour Name 		"rx_mpdu_cnt: %d\n"
903*5113495bSYour Name 		"bin_count: %d\n",
904*5113495bSYour Name 		profile_ctx->tot,
905*5113495bSYour Name 		profile_ctx->tx_msdu_cnt,
906*5113495bSYour Name 		profile_ctx->tx_mpdu_cnt,
907*5113495bSYour Name 		profile_ctx->tx_ppdu_cnt,
908*5113495bSYour Name 		profile_ctx->rx_msdu_cnt,
909*5113495bSYour Name 		profile_ctx->rx_mpdu_cnt,
910*5113495bSYour Name 		profile_ctx->bin_count);
911*5113495bSYour Name 
912*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
913*5113495bSYour Name 		  "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
914*5113495bSYour Name 
915*5113495bSYour Name 	profile_data = param_buf->profile_data;
916*5113495bSYour Name 	for (i = 0; i < entries; i++) {
917*5113495bSYour Name 		if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
918*5113495bSYour Name 			break;
919*5113495bSYour Name 		snprintf(temp_str, sizeof(temp_str),
920*5113495bSYour Name 			 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
921*5113495bSYour Name 			profile_data[i].id,
922*5113495bSYour Name 			profile_data[i].cnt,
923*5113495bSYour Name 			profile_data[i].tot,
924*5113495bSYour Name 			profile_data[i].min,
925*5113495bSYour Name 			profile_data[i].max,
926*5113495bSYour Name 			profile_data[i].hist_intvl,
927*5113495bSYour Name 			profile_data[i].hist[0],
928*5113495bSYour Name 			profile_data[i].hist[1],
929*5113495bSYour Name 			profile_data[i].hist[2]);
930*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
931*5113495bSYour Name 			"%s", temp_str);
932*5113495bSYour Name 	}
933*5113495bSYour Name 
934*5113495bSYour Name 	return 0;
935*5113495bSYour Name }
936*5113495bSYour Name 
937*5113495bSYour Name #ifdef WLAN_FEATURE_LINK_LAYER_STATS
938*5113495bSYour Name 
939*5113495bSYour Name #define WMA_FILL_TX_STATS(eve, msg)   do {\
940*5113495bSYour Name 	(msg)->msdus = (eve)->tx_msdu_cnt;\
941*5113495bSYour Name 	(msg)->mpdus = (eve)->tx_mpdu_cnt;\
942*5113495bSYour Name 	(msg)->ppdus = (eve)->tx_ppdu_cnt;\
943*5113495bSYour Name 	(msg)->bytes = (eve)->tx_bytes;\
944*5113495bSYour Name 	(msg)->drops = (eve)->tx_msdu_drop_cnt;\
945*5113495bSYour Name 	(msg)->drop_bytes = (eve)->tx_drop_bytes;\
946*5113495bSYour Name 	(msg)->retries = (eve)->tx_mpdu_retry_cnt;\
947*5113495bSYour Name 	(msg)->failed = (eve)->tx_mpdu_fail_cnt;\
948*5113495bSYour Name } while (0)
949*5113495bSYour Name 
950*5113495bSYour Name #define WMA_FILL_RX_STATS(eve, msg)       do {\
951*5113495bSYour Name 	(msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
952*5113495bSYour Name 	(msg)->bytes = (eve)->mac_rx_bytes;\
953*5113495bSYour Name 	(msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
954*5113495bSYour Name 	(msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
955*5113495bSYour Name 	(msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
956*5113495bSYour Name 	(msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
957*5113495bSYour Name 	(msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
958*5113495bSYour Name } while (0)
959*5113495bSYour Name 
960*5113495bSYour Name /**
961*5113495bSYour Name  * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
962*5113495bSYour Name  * @len: buffer length output
963*5113495bSYour Name  * @peer_num: peer number
964*5113495bSYour Name  * @fixed_param: fixed parameters in WMI event
965*5113495bSYour Name  *
966*5113495bSYour Name  * Structure of the stats message
967*5113495bSYour Name  * LL_EXT_STATS
968*5113495bSYour Name  *  |
969*5113495bSYour Name  *  |--Channel stats[1~n]
970*5113495bSYour Name  *  |--Peer[1~n]
971*5113495bSYour Name  *      |
972*5113495bSYour Name  *      +---Signal
973*5113495bSYour Name  *      +---TX
974*5113495bSYour Name  *      |    +---BE
975*5113495bSYour Name  *      |    +---BK
976*5113495bSYour Name  *      |    +---VI
977*5113495bSYour Name  *      |    +---VO
978*5113495bSYour Name  *      |
979*5113495bSYour Name  *      +---RX
980*5113495bSYour Name  *           +---BE
981*5113495bSYour Name  *           +---BK
982*5113495bSYour Name  *           +---VI
983*5113495bSYour Name  *           +---VO
984*5113495bSYour Name  * For each Access Category, the arregation and mcs
985*5113495bSYour Name  * stats are as this:
986*5113495bSYour Name  *  TX
987*5113495bSYour Name  *   +-BE/BK/VI/VO
988*5113495bSYour Name  *         +----tx_mpdu_aggr_array
989*5113495bSYour Name  *         +----tx_succ_mcs_array
990*5113495bSYour Name  *         +----tx_fail_mcs_array
991*5113495bSYour Name  *         +----tx_delay_array
992*5113495bSYour Name  *  RX
993*5113495bSYour Name  *   +-BE/BK/VI/VO
994*5113495bSYour Name  *         +----rx_mpdu_aggr_array
995*5113495bSYour Name  *         +----rx_mcs_array
996*5113495bSYour Name  *
997*5113495bSYour Name  * return: Address for result buffer.
998*5113495bSYour Name  */
wma_get_ll_stats_ext_buf(uint32_t * len,uint32_t peer_num,wmi_report_stats_event_fixed_param * fixed_param)999*5113495bSYour Name static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
1000*5113495bSYour Name 						    uint32_t peer_num,
1001*5113495bSYour Name 			wmi_report_stats_event_fixed_param *fixed_param)
1002*5113495bSYour Name {
1003*5113495bSYour Name 	tSirLLStatsResults *buf;
1004*5113495bSYour Name 	uint32_t buf_len;
1005*5113495bSYour Name 	uint32_t total_array_len, total_peer_len;
1006*5113495bSYour Name 	bool excess_data = false;
1007*5113495bSYour Name 
1008*5113495bSYour Name 	if (!len || !fixed_param) {
1009*5113495bSYour Name 		wma_err("Invalid input parameters");
1010*5113495bSYour Name 		return NULL;
1011*5113495bSYour Name 	}
1012*5113495bSYour Name 
1013*5113495bSYour Name 	/*
1014*5113495bSYour Name 	 * Result buffer has a structure like this:
1015*5113495bSYour Name 	 *     ---------------------------------
1016*5113495bSYour Name 	 *     |      trigger_cond_i           |
1017*5113495bSYour Name 	 *     +-------------------------------+
1018*5113495bSYour Name 	 *     |      cca_chgd_bitmap          |
1019*5113495bSYour Name 	 *     +-------------------------------+
1020*5113495bSYour Name 	 *     |      sig_chgd_bitmap          |
1021*5113495bSYour Name 	 *     +-------------------------------+
1022*5113495bSYour Name 	 *     |      tx_chgd_bitmap           |
1023*5113495bSYour Name 	 *     +-------------------------------+
1024*5113495bSYour Name 	 *     |      rx_chgd_bitmap           |
1025*5113495bSYour Name 	 *     +-------------------------------+
1026*5113495bSYour Name 	 *     |      peer_num                 |
1027*5113495bSYour Name 	 *     +-------------------------------+
1028*5113495bSYour Name 	 *     |      channel_num              |
1029*5113495bSYour Name 	 *     +-------------------------------+
1030*5113495bSYour Name 	 *     |      tx_mpdu_aggr_array_len   |
1031*5113495bSYour Name 	 *     +-------------------------------+
1032*5113495bSYour Name 	 *     |      tx_succ_mcs_array_len    |
1033*5113495bSYour Name 	 *     +-------------------------------+
1034*5113495bSYour Name 	 *     |      tx_fail_mcs_array_len    |
1035*5113495bSYour Name 	 *     +-------------------------------+
1036*5113495bSYour Name 	 *     |      tx_delay_array_len       |
1037*5113495bSYour Name 	 *     +-------------------------------+
1038*5113495bSYour Name 	 *     |      rx_mpdu_aggr_array_len   |
1039*5113495bSYour Name 	 *     +-------------------------------+
1040*5113495bSYour Name 	 *     |      rx_mcs_array_len         |
1041*5113495bSYour Name 	 *     +-------------------------------+
1042*5113495bSYour Name 	 *     |      pointer to CCA stats     |
1043*5113495bSYour Name 	 *     +-------------------------------+
1044*5113495bSYour Name 	 *     |      CCA stats                |
1045*5113495bSYour Name 	 *     +-------------------------------+
1046*5113495bSYour Name 	 *     |      peer_stats               |----+
1047*5113495bSYour Name 	 *     +-------------------------------+    |
1048*5113495bSYour Name 	 *     | TX aggr/mcs parameters array  |    |
1049*5113495bSYour Name 	 *     | Length of this buffer is      |    |
1050*5113495bSYour Name 	 *     | not fixed.                    |<-+ |
1051*5113495bSYour Name 	 *     +-------------------------------+  | |
1052*5113495bSYour Name 	 *     |      per peer tx stats        |--+ |
1053*5113495bSYour Name 	 *     |         BE                    | <--+
1054*5113495bSYour Name 	 *     |         BK                    |    |
1055*5113495bSYour Name 	 *     |         VI                    |    |
1056*5113495bSYour Name 	 *     |         VO                    |    |
1057*5113495bSYour Name 	 *     +-------------------------------+    |
1058*5113495bSYour Name 	 *     | TX aggr/mcs parameters array  |    |
1059*5113495bSYour Name 	 *     | Length of this buffer is      |    |
1060*5113495bSYour Name 	 *     | not fixed.                    |<-+ |
1061*5113495bSYour Name 	 *     +-------------------------------+  | |
1062*5113495bSYour Name 	 *     |      peer peer rx stats       |--+ |
1063*5113495bSYour Name 	 *     |         BE                    | <--+
1064*5113495bSYour Name 	 *     |         BK                    |
1065*5113495bSYour Name 	 *     |         VI                    |
1066*5113495bSYour Name 	 *     |         VO                    |
1067*5113495bSYour Name 	 *     ---------------------------------
1068*5113495bSYour Name 	 */
1069*5113495bSYour Name 
1070*5113495bSYour Name 	buf_len = sizeof(tSirLLStatsResults) +
1071*5113495bSYour Name 		  sizeof(struct sir_wifi_ll_ext_stats);
1072*5113495bSYour Name 	do {
1073*5113495bSYour Name 		if (fixed_param->num_chan_cca_stats > (WMI_SVC_MSG_MAX_SIZE /
1074*5113495bSYour Name 		    sizeof(struct sir_wifi_chan_cca_stats))) {
1075*5113495bSYour Name 			excess_data = true;
1076*5113495bSYour Name 			break;
1077*5113495bSYour Name 		}
1078*5113495bSYour Name 		buf_len += (fixed_param->num_chan_cca_stats *
1079*5113495bSYour Name 				sizeof(struct sir_wifi_chan_cca_stats));
1080*5113495bSYour Name 		if (fixed_param->tx_mpdu_aggr_array_len >
1081*5113495bSYour Name 		    WMI_SVC_MSG_MAX_SIZE) {
1082*5113495bSYour Name 			excess_data = true;
1083*5113495bSYour Name 			break;
1084*5113495bSYour Name 		} else {
1085*5113495bSYour Name 			total_array_len = fixed_param->tx_mpdu_aggr_array_len;
1086*5113495bSYour Name 		}
1087*5113495bSYour Name 		if (fixed_param->tx_succ_mcs_array_len >
1088*5113495bSYour Name 		    (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
1089*5113495bSYour Name 			excess_data = true;
1090*5113495bSYour Name 			break;
1091*5113495bSYour Name 		} else {
1092*5113495bSYour Name 			total_array_len += fixed_param->tx_succ_mcs_array_len;
1093*5113495bSYour Name 		}
1094*5113495bSYour Name 		if (fixed_param->tx_fail_mcs_array_len >
1095*5113495bSYour Name 		    (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
1096*5113495bSYour Name 			excess_data = true;
1097*5113495bSYour Name 			break;
1098*5113495bSYour Name 		} else {
1099*5113495bSYour Name 			total_array_len += fixed_param->tx_fail_mcs_array_len;
1100*5113495bSYour Name 		}
1101*5113495bSYour Name 		if (fixed_param->tx_ppdu_delay_array_len >
1102*5113495bSYour Name 		    (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
1103*5113495bSYour Name 			excess_data = true;
1104*5113495bSYour Name 			break;
1105*5113495bSYour Name 		} else {
1106*5113495bSYour Name 			total_array_len += fixed_param->tx_ppdu_delay_array_len;
1107*5113495bSYour Name 		}
1108*5113495bSYour Name 		if (fixed_param->rx_mpdu_aggr_array_len >
1109*5113495bSYour Name 		    (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
1110*5113495bSYour Name 			excess_data = true;
1111*5113495bSYour Name 			break;
1112*5113495bSYour Name 		} else {
1113*5113495bSYour Name 			total_array_len += fixed_param->rx_mpdu_aggr_array_len;
1114*5113495bSYour Name 		}
1115*5113495bSYour Name 		if (fixed_param->rx_mcs_array_len >
1116*5113495bSYour Name 		    (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
1117*5113495bSYour Name 			excess_data = true;
1118*5113495bSYour Name 			break;
1119*5113495bSYour Name 		} else {
1120*5113495bSYour Name 			total_array_len += fixed_param->rx_mcs_array_len;
1121*5113495bSYour Name 		}
1122*5113495bSYour Name 
1123*5113495bSYour Name 		if (total_array_len > (WMI_SVC_MSG_MAX_SIZE /
1124*5113495bSYour Name 		    (sizeof(uint32_t) * WLAN_MAX_AC))) {
1125*5113495bSYour Name 			excess_data = true;
1126*5113495bSYour Name 			break;
1127*5113495bSYour Name 		} else {
1128*5113495bSYour Name 			total_peer_len = (sizeof(uint32_t) * WLAN_MAX_AC *
1129*5113495bSYour Name 					 total_array_len) +
1130*5113495bSYour Name 					 (WLAN_MAX_AC *
1131*5113495bSYour Name 					 (sizeof(struct sir_wifi_tx) +
1132*5113495bSYour Name 					 sizeof(struct sir_wifi_rx)));
1133*5113495bSYour Name 		}
1134*5113495bSYour Name 		if (total_peer_len > WMI_SVC_MSG_MAX_SIZE) {
1135*5113495bSYour Name 			excess_data = true;
1136*5113495bSYour Name 			break;
1137*5113495bSYour Name 		}
1138*5113495bSYour Name 		if (peer_num > WMI_SVC_MSG_MAX_SIZE / (total_peer_len +
1139*5113495bSYour Name 		    sizeof(struct sir_wifi_ll_ext_peer_stats))) {
1140*5113495bSYour Name 			excess_data = true;
1141*5113495bSYour Name 			break;
1142*5113495bSYour Name 		} else {
1143*5113495bSYour Name 			buf_len += peer_num *
1144*5113495bSYour Name 				   (sizeof(struct sir_wifi_ll_ext_peer_stats) +
1145*5113495bSYour Name 				    total_peer_len);
1146*5113495bSYour Name 		}
1147*5113495bSYour Name 	} while (0);
1148*5113495bSYour Name 
1149*5113495bSYour Name 	if (excess_data || (buf_len > WMI_SVC_MSG_MAX_SIZE)) {
1150*5113495bSYour Name 		wma_err("excess wmi buffer: peer %d cca %d tx_mpdu %d tx_succ%d tx_fail %d tx_ppdu %d rx_mpdu %d rx_mcs %d",
1151*5113495bSYour Name 			 peer_num, fixed_param->num_chan_cca_stats,
1152*5113495bSYour Name 			 fixed_param->tx_mpdu_aggr_array_len,
1153*5113495bSYour Name 			 fixed_param->tx_succ_mcs_array_len,
1154*5113495bSYour Name 			 fixed_param->tx_fail_mcs_array_len,
1155*5113495bSYour Name 			 fixed_param->tx_ppdu_delay_array_len,
1156*5113495bSYour Name 			 fixed_param->rx_mpdu_aggr_array_len,
1157*5113495bSYour Name 			 fixed_param->rx_mcs_array_len);
1158*5113495bSYour Name 		return NULL;
1159*5113495bSYour Name 	}
1160*5113495bSYour Name 
1161*5113495bSYour Name 	buf = qdf_mem_malloc(buf_len);
1162*5113495bSYour Name 	if (!buf)
1163*5113495bSYour Name 		*len = 0;
1164*5113495bSYour Name 	else
1165*5113495bSYour Name 		*len = buf_len;
1166*5113495bSYour Name 
1167*5113495bSYour Name 	return buf;
1168*5113495bSYour Name }
1169*5113495bSYour Name 
1170*5113495bSYour Name /**
1171*5113495bSYour Name  * wma_fill_tx_stats() - Fix TX stats into result buffer
1172*5113495bSYour Name  * @ll_stats: LL stats buffer
1173*5113495bSYour Name  * @fix_param: parameters with fixed length in WMI event
1174*5113495bSYour Name  * @param_buf: parameters without fixed length in WMI event
1175*5113495bSYour Name  * @buf: buffer for TLV parameters
1176*5113495bSYour Name  * @buf_length: length of @buf
1177*5113495bSYour Name  *
1178*5113495bSYour Name  * Return: QDF_STATUS
1179*5113495bSYour Name  */
1180*5113495bSYour Name static QDF_STATUS
wma_fill_tx_stats(struct sir_wifi_ll_ext_stats * ll_stats,wmi_report_stats_event_fixed_param * fix_param,WMI_REPORT_STATS_EVENTID_param_tlvs * param_buf,uint8_t ** buf,uint32_t * buf_length)1181*5113495bSYour Name wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
1182*5113495bSYour Name 		  wmi_report_stats_event_fixed_param *fix_param,
1183*5113495bSYour Name 		  WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
1184*5113495bSYour Name 		  uint8_t **buf, uint32_t *buf_length)
1185*5113495bSYour Name {
1186*5113495bSYour Name 	uint8_t *result;
1187*5113495bSYour Name 	uint32_t i, j, k;
1188*5113495bSYour Name 	wmi_peer_ac_tx_stats *wmi_peer_tx;
1189*5113495bSYour Name 	wmi_tx_stats *wmi_tx;
1190*5113495bSYour Name 	struct sir_wifi_tx *tx_stats;
1191*5113495bSYour Name 	struct sir_wifi_ll_ext_peer_stats *peer_stats;
1192*5113495bSYour Name 	uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
1193*5113495bSYour Name 	uint32_t len, dst_len, param_len, num_entries,
1194*5113495bSYour Name 		 tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
1195*5113495bSYour Name 		 tx_fail_mcs_array_len, tx_delay_array_len;
1196*5113495bSYour Name 
1197*5113495bSYour Name 	result = *buf;
1198*5113495bSYour Name 	dst_len = *buf_length;
1199*5113495bSYour Name 	tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
1200*5113495bSYour Name 	ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
1201*5113495bSYour Name 	tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
1202*5113495bSYour Name 	ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
1203*5113495bSYour Name 	tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
1204*5113495bSYour Name 	ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
1205*5113495bSYour Name 	tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
1206*5113495bSYour Name 	ll_stats->tx_delay_array_len = tx_delay_array_len;
1207*5113495bSYour Name 	wmi_peer_tx = param_buf->peer_ac_tx_stats;
1208*5113495bSYour Name 	wmi_tx = param_buf->tx_stats;
1209*5113495bSYour Name 
1210*5113495bSYour Name 	len = fix_param->num_peer_ac_tx_stats *
1211*5113495bSYour Name 		WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
1212*5113495bSYour Name 	param_len = param_buf->num_tx_mpdu_aggr * sizeof(uint32_t);
1213*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->tx_mpdu_aggr) {
1214*5113495bSYour Name 		tx_mpdu_aggr = (uint32_t *)result;
1215*5113495bSYour Name 		qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
1216*5113495bSYour Name 		result += len;
1217*5113495bSYour Name 		dst_len -= len;
1218*5113495bSYour Name 	} else {
1219*5113495bSYour Name 		wma_err("TX_MPDU_AGGR invalid arg, %d, %d, %d",
1220*5113495bSYour Name 			len, dst_len, param_len);
1221*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1222*5113495bSYour Name 	}
1223*5113495bSYour Name 
1224*5113495bSYour Name 	len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
1225*5113495bSYour Name 		tx_succ_mcs_array_len * sizeof(uint32_t);
1226*5113495bSYour Name 	param_len = param_buf->num_tx_succ_mcs * sizeof(uint32_t);
1227*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->tx_succ_mcs) {
1228*5113495bSYour Name 		tx_succ_mcs = (uint32_t *)result;
1229*5113495bSYour Name 		qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
1230*5113495bSYour Name 		result += len;
1231*5113495bSYour Name 		dst_len -= len;
1232*5113495bSYour Name 	} else {
1233*5113495bSYour Name 		wma_err("TX_SUCC_MCS invalid arg, %d, %d, %d",
1234*5113495bSYour Name 			 len, dst_len, param_len);
1235*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1236*5113495bSYour Name 	}
1237*5113495bSYour Name 
1238*5113495bSYour Name 	len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
1239*5113495bSYour Name 		tx_fail_mcs_array_len * sizeof(uint32_t);
1240*5113495bSYour Name 	param_len = param_buf->num_tx_fail_mcs * sizeof(uint32_t);
1241*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->tx_fail_mcs) {
1242*5113495bSYour Name 		tx_fail_mcs = (uint32_t *)result;
1243*5113495bSYour Name 		qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
1244*5113495bSYour Name 		result += len;
1245*5113495bSYour Name 		dst_len -= len;
1246*5113495bSYour Name 	} else {
1247*5113495bSYour Name 		wma_err("TX_FAIL_MCS invalid arg, %d, %d %d",
1248*5113495bSYour Name 			 len, dst_len, param_len);
1249*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1250*5113495bSYour Name 	}
1251*5113495bSYour Name 
1252*5113495bSYour Name 	len = fix_param->num_peer_ac_tx_stats *
1253*5113495bSYour Name 		WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
1254*5113495bSYour Name 	param_len = param_buf->num_tx_ppdu_delay * sizeof(uint32_t);
1255*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->tx_ppdu_delay) {
1256*5113495bSYour Name 		tx_delay = (uint32_t *)result;
1257*5113495bSYour Name 		qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
1258*5113495bSYour Name 		result += len;
1259*5113495bSYour Name 		dst_len -= len;
1260*5113495bSYour Name 	} else {
1261*5113495bSYour Name 		wma_err("TX_DELAY invalid arg, %d, %d, %d",
1262*5113495bSYour Name 			 len, dst_len, param_len);
1263*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1264*5113495bSYour Name 	}
1265*5113495bSYour Name 
1266*5113495bSYour Name 	/* per peer tx stats */
1267*5113495bSYour Name 	peer_stats = ll_stats->peer_stats;
1268*5113495bSYour Name 	if (!wmi_peer_tx || !wmi_tx || !peer_stats) {
1269*5113495bSYour Name 		wma_err("Invalid arg, peer_tx %pK, wmi_tx %pK stats %pK",
1270*5113495bSYour Name 			 wmi_peer_tx, wmi_tx, peer_stats);
1271*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1272*5113495bSYour Name 	}
1273*5113495bSYour Name 
1274*5113495bSYour Name 	num_entries = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC;
1275*5113495bSYour Name 	if (num_entries > param_buf->num_tx_stats) {
1276*5113495bSYour Name 		wma_err("tx stats invalid arg, %d", num_entries);
1277*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1278*5113495bSYour Name 	}
1279*5113495bSYour Name 
1280*5113495bSYour Name 	for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
1281*5113495bSYour Name 		uint32_t peer_id = wmi_peer_tx[i].peer_id;
1282*5113495bSYour Name 		struct sir_wifi_tx *ac;
1283*5113495bSYour Name 		wmi_tx_stats *wmi_tx_stats;
1284*5113495bSYour Name 
1285*5113495bSYour Name 		for (j = 0; j < ll_stats->peer_num; j++) {
1286*5113495bSYour Name 			peer_stats += j;
1287*5113495bSYour Name 			if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
1288*5113495bSYour Name 			    peer_stats->peer_id == peer_id)
1289*5113495bSYour Name 				break;
1290*5113495bSYour Name 		}
1291*5113495bSYour Name 
1292*5113495bSYour Name 		if (j < ll_stats->peer_num) {
1293*5113495bSYour Name 			peer_stats->peer_id = wmi_peer_tx[i].peer_id;
1294*5113495bSYour Name 			peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
1295*5113495bSYour Name 			tx_stats = (struct sir_wifi_tx *)result;
1296*5113495bSYour Name 			for (k = 0; k < WLAN_MAX_AC; k++) {
1297*5113495bSYour Name 				wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
1298*5113495bSYour Name 				ac = &tx_stats[k];
1299*5113495bSYour Name 				WMA_FILL_TX_STATS(wmi_tx_stats, ac);
1300*5113495bSYour Name 				ac->mpdu_aggr_size = tx_mpdu_aggr;
1301*5113495bSYour Name 				ac->aggr_len = tx_mpdu_aggr_array_len *
1302*5113495bSYour Name 							sizeof(uint32_t);
1303*5113495bSYour Name 				ac->success_mcs_len = tx_succ_mcs_array_len *
1304*5113495bSYour Name 							sizeof(uint32_t);
1305*5113495bSYour Name 				ac->success_mcs = tx_succ_mcs;
1306*5113495bSYour Name 				ac->fail_mcs = tx_fail_mcs;
1307*5113495bSYour Name 				ac->fail_mcs_len = tx_fail_mcs_array_len *
1308*5113495bSYour Name 							sizeof(uint32_t);
1309*5113495bSYour Name 				ac->delay = tx_delay;
1310*5113495bSYour Name 				ac->delay_len = tx_delay_array_len *
1311*5113495bSYour Name 							sizeof(uint32_t);
1312*5113495bSYour Name 				peer_stats->ac_stats[k].tx_stats = ac;
1313*5113495bSYour Name 				peer_stats->ac_stats[k].type = k;
1314*5113495bSYour Name 				tx_mpdu_aggr += tx_mpdu_aggr_array_len;
1315*5113495bSYour Name 				tx_succ_mcs += tx_succ_mcs_array_len;
1316*5113495bSYour Name 				tx_fail_mcs += tx_fail_mcs_array_len;
1317*5113495bSYour Name 				tx_delay += tx_delay_array_len;
1318*5113495bSYour Name 			}
1319*5113495bSYour Name 			result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
1320*5113495bSYour Name 		} else {
1321*5113495bSYour Name 			/*
1322*5113495bSYour Name 			 * Buffer for Peer TX counter overflow.
1323*5113495bSYour Name 			 * There is peer ID mismatch between TX, RX,
1324*5113495bSYour Name 			 * signal counters.
1325*5113495bSYour Name 			 */
1326*5113495bSYour Name 			wma_err("One peer TX info is dropped");
1327*5113495bSYour Name 
1328*5113495bSYour Name 			tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
1329*5113495bSYour Name 			tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
1330*5113495bSYour Name 			tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
1331*5113495bSYour Name 			tx_delay += tx_delay_array_len * WLAN_MAX_AC;
1332*5113495bSYour Name 		}
1333*5113495bSYour Name 	}
1334*5113495bSYour Name 	*buf = result;
1335*5113495bSYour Name 	*buf_length = dst_len;
1336*5113495bSYour Name 
1337*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1338*5113495bSYour Name }
1339*5113495bSYour Name 
1340*5113495bSYour Name /**
1341*5113495bSYour Name  * wma_fill_rx_stats() - Fix RX stats into result buffer
1342*5113495bSYour Name  * @ll_stats: LL stats buffer
1343*5113495bSYour Name  * @fix_param: parameters with fixed length in WMI event
1344*5113495bSYour Name  * @param_buf: parameters without fixed length in WMI event
1345*5113495bSYour Name  * @buf: buffer for TLV parameters
1346*5113495bSYour Name  * @buf_length: length of @buf
1347*5113495bSYour Name  *
1348*5113495bSYour Name  * Return: QDF_STATUS
1349*5113495bSYour Name  */
1350*5113495bSYour Name static QDF_STATUS
wma_fill_rx_stats(struct sir_wifi_ll_ext_stats * ll_stats,wmi_report_stats_event_fixed_param * fix_param,WMI_REPORT_STATS_EVENTID_param_tlvs * param_buf,uint8_t ** buf,uint32_t * buf_length)1351*5113495bSYour Name wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
1352*5113495bSYour Name 		  wmi_report_stats_event_fixed_param *fix_param,
1353*5113495bSYour Name 		  WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
1354*5113495bSYour Name 		  uint8_t **buf, uint32_t *buf_length)
1355*5113495bSYour Name {
1356*5113495bSYour Name 	uint8_t *result;
1357*5113495bSYour Name 	uint32_t i, j, k;
1358*5113495bSYour Name 	uint32_t *rx_mpdu_aggr, *rx_mcs;
1359*5113495bSYour Name 	wmi_rx_stats *wmi_rx;
1360*5113495bSYour Name 	wmi_peer_ac_rx_stats *wmi_peer_rx;
1361*5113495bSYour Name 	struct sir_wifi_rx *rx_stats;
1362*5113495bSYour Name 	struct sir_wifi_ll_ext_peer_stats *peer_stats;
1363*5113495bSYour Name 	uint32_t len, dst_len, param_len,
1364*5113495bSYour Name 		 rx_mpdu_aggr_array_len, rx_mcs_array_len;
1365*5113495bSYour Name 
1366*5113495bSYour Name 	rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
1367*5113495bSYour Name 	ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
1368*5113495bSYour Name 	rx_mcs_array_len = fix_param->rx_mcs_array_len;
1369*5113495bSYour Name 	ll_stats->rx_mcs_array_len = rx_mcs_array_len;
1370*5113495bSYour Name 	wmi_peer_rx = param_buf->peer_ac_rx_stats;
1371*5113495bSYour Name 	wmi_rx = param_buf->rx_stats;
1372*5113495bSYour Name 
1373*5113495bSYour Name 	result = *buf;
1374*5113495bSYour Name 	dst_len = *buf_length;
1375*5113495bSYour Name 	len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
1376*5113495bSYour Name 				  WLAN_MAX_AC * rx_mpdu_aggr_array_len);
1377*5113495bSYour Name 	param_len = param_buf->num_rx_mpdu_aggr * sizeof(uint32_t);
1378*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->rx_mpdu_aggr) {
1379*5113495bSYour Name 		rx_mpdu_aggr = (uint32_t *)result;
1380*5113495bSYour Name 		qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
1381*5113495bSYour Name 		result += len;
1382*5113495bSYour Name 		dst_len -= len;
1383*5113495bSYour Name 	} else {
1384*5113495bSYour Name 		wma_err("RX_MPDU_AGGR invalid arg %d, %d, %d",
1385*5113495bSYour Name 			 len, dst_len, param_len);
1386*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1387*5113495bSYour Name 	}
1388*5113495bSYour Name 
1389*5113495bSYour Name 	len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
1390*5113495bSYour Name 				  WLAN_MAX_AC * rx_mcs_array_len);
1391*5113495bSYour Name 	param_len = param_buf->num_rx_mcs * sizeof(uint32_t);
1392*5113495bSYour Name 	if (len <= dst_len && len <= param_len && param_buf->rx_mcs) {
1393*5113495bSYour Name 		rx_mcs = (uint32_t *)result;
1394*5113495bSYour Name 		qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
1395*5113495bSYour Name 		result += len;
1396*5113495bSYour Name 		dst_len -= len;
1397*5113495bSYour Name 	} else {
1398*5113495bSYour Name 		wma_err("RX_MCS invalid arg %d, %d, %d",
1399*5113495bSYour Name 			 len, dst_len, param_len);
1400*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1401*5113495bSYour Name 	}
1402*5113495bSYour Name 
1403*5113495bSYour Name 	/* per peer rx stats */
1404*5113495bSYour Name 	peer_stats = ll_stats->peer_stats;
1405*5113495bSYour Name 	if (!wmi_peer_rx || !wmi_rx || !peer_stats) {
1406*5113495bSYour Name 		wma_err("Invalid arg, peer_rx %pK, wmi_rx %pK stats %pK",
1407*5113495bSYour Name 			 wmi_peer_rx, wmi_rx, peer_stats);
1408*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1409*5113495bSYour Name 	}
1410*5113495bSYour Name 	for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
1411*5113495bSYour Name 		uint32_t peer_id = wmi_peer_rx[i].peer_id;
1412*5113495bSYour Name 		struct sir_wifi_rx *ac;
1413*5113495bSYour Name 		wmi_rx_stats *wmi_rx_stats;
1414*5113495bSYour Name 
1415*5113495bSYour Name 		for (j = 0; j < ll_stats->peer_num; j++) {
1416*5113495bSYour Name 			peer_stats += j;
1417*5113495bSYour Name 			if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
1418*5113495bSYour Name 			    (peer_stats->peer_id == peer_id))
1419*5113495bSYour Name 				break;
1420*5113495bSYour Name 		}
1421*5113495bSYour Name 
1422*5113495bSYour Name 		if (j < ll_stats->peer_num) {
1423*5113495bSYour Name 			peer_stats->peer_id = wmi_peer_rx[i].peer_id;
1424*5113495bSYour Name 			peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
1425*5113495bSYour Name 			peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
1426*5113495bSYour Name 			peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
1427*5113495bSYour Name 			peer_stats->rx_probe_reqs =
1428*5113495bSYour Name 						wmi_peer_rx[i].rx_probe_reqs;
1429*5113495bSYour Name 			peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
1430*5113495bSYour Name 			rx_stats = (struct sir_wifi_rx *)result;
1431*5113495bSYour Name 
1432*5113495bSYour Name 			for (k = 0; k < WLAN_MAX_AC; k++) {
1433*5113495bSYour Name 				wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
1434*5113495bSYour Name 				ac = &rx_stats[k];
1435*5113495bSYour Name 				WMA_FILL_RX_STATS(wmi_rx_stats, ac);
1436*5113495bSYour Name 				ac->mpdu_aggr = rx_mpdu_aggr;
1437*5113495bSYour Name 				ac->aggr_len = rx_mpdu_aggr_array_len *
1438*5113495bSYour Name 							sizeof(uint32_t);
1439*5113495bSYour Name 				ac->mcs = rx_mcs;
1440*5113495bSYour Name 				ac->mcs_len = rx_mcs_array_len *
1441*5113495bSYour Name 							sizeof(uint32_t);
1442*5113495bSYour Name 				peer_stats->ac_stats[k].rx_stats = ac;
1443*5113495bSYour Name 				peer_stats->ac_stats[k].type = k;
1444*5113495bSYour Name 				rx_mpdu_aggr += rx_mpdu_aggr_array_len;
1445*5113495bSYour Name 				rx_mcs += rx_mcs_array_len;
1446*5113495bSYour Name 			}
1447*5113495bSYour Name 			result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
1448*5113495bSYour Name 		} else {
1449*5113495bSYour Name 			/*
1450*5113495bSYour Name 			 * Buffer for Peer RX counter overflow.
1451*5113495bSYour Name 			 * There is peer ID mismatch between TX, RX,
1452*5113495bSYour Name 			 * signal counters.
1453*5113495bSYour Name 			 */
1454*5113495bSYour Name 			wma_err("One peer RX info is dropped");
1455*5113495bSYour Name 			rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
1456*5113495bSYour Name 			rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
1457*5113495bSYour Name 		}
1458*5113495bSYour Name 	}
1459*5113495bSYour Name 	*buf = result;
1460*5113495bSYour Name 	*buf_length = dst_len;
1461*5113495bSYour Name 
1462*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1463*5113495bSYour Name }
1464*5113495bSYour Name 
1465*5113495bSYour Name /**
1466*5113495bSYour Name  * wma_ll_stats_evt_handler() - handler for MAC layer counters.
1467*5113495bSYour Name  * @handle: wma handle
1468*5113495bSYour Name  * @event: FW event
1469*5113495bSYour Name  * @len: length of FW event
1470*5113495bSYour Name  *
1471*5113495bSYour Name  * return: 0 success.
1472*5113495bSYour Name  */
wma_ll_stats_evt_handler(void * handle,u_int8_t * event,u_int32_t len)1473*5113495bSYour Name static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
1474*5113495bSYour Name 				    u_int32_t len)
1475*5113495bSYour Name {
1476*5113495bSYour Name 	WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
1477*5113495bSYour Name 	wmi_report_stats_event_fixed_param *fixed_param;
1478*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
1479*5113495bSYour Name 	wmi_chan_cca_stats *wmi_cca_stats;
1480*5113495bSYour Name 	wmi_peer_signal_stats *wmi_peer_signal;
1481*5113495bSYour Name 	struct sir_wifi_ll_ext_stats *ll_stats;
1482*5113495bSYour Name 	struct sir_wifi_ll_ext_peer_stats *peer_stats;
1483*5113495bSYour Name 	struct sir_wifi_chan_cca_stats *cca_stats;
1484*5113495bSYour Name 	struct sir_wifi_peer_signal_stats *peer_signal;
1485*5113495bSYour Name 	uint8_t *result;
1486*5113495bSYour Name 	uint32_t i, peer_num, result_size, dst_len;
1487*5113495bSYour Name 	struct mac_context *mac;
1488*5113495bSYour Name 	struct scheduler_msg sme_msg = { 0 };
1489*5113495bSYour Name 	QDF_STATUS qdf_status;
1490*5113495bSYour Name 
1491*5113495bSYour Name 	mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
1492*5113495bSYour Name 	if (!mac) {
1493*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
1494*5113495bSYour Name 		return -EINVAL;
1495*5113495bSYour Name 	}
1496*5113495bSYour Name 
1497*5113495bSYour Name 	if (!mac->sme.link_layer_stats_ext_cb) {
1498*5113495bSYour Name 		wma_debug("HDD callback is null");
1499*5113495bSYour Name 		return -EINVAL;
1500*5113495bSYour Name 	}
1501*5113495bSYour Name 
1502*5113495bSYour Name 	wma_debug("Posting MAC counters event to HDD");
1503*5113495bSYour Name 
1504*5113495bSYour Name 	param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1505*5113495bSYour Name 	if (!param_buf) {
1506*5113495bSYour Name 		wma_debug("param_buf is null");
1507*5113495bSYour Name 		return -EINVAL;
1508*5113495bSYour Name 	}
1509*5113495bSYour Name 	fixed_param = param_buf->fixed_param;
1510*5113495bSYour Name 	if (!fixed_param) {
1511*5113495bSYour Name 		wma_debug("fixed_param is null");
1512*5113495bSYour Name 		return -EINVAL;
1513*5113495bSYour Name 	}
1514*5113495bSYour Name 	wmi_cca_stats = param_buf->chan_cca_stats;
1515*5113495bSYour Name 	wmi_peer_signal = param_buf->peer_signal_stats;
1516*5113495bSYour Name 	if (fixed_param->num_peer_signal_stats >
1517*5113495bSYour Name 		param_buf->num_peer_signal_stats ||
1518*5113495bSYour Name 		fixed_param->num_peer_ac_tx_stats >
1519*5113495bSYour Name 		param_buf->num_peer_ac_tx_stats ||
1520*5113495bSYour Name 		fixed_param->num_peer_ac_rx_stats >
1521*5113495bSYour Name 		param_buf->num_peer_ac_rx_stats) {
1522*5113495bSYour Name 		wma_err("excess num_peer_signal_stats:%d, num_peer_ac_tx_stats:%d, num_peer_ac_rx_stats:%d",
1523*5113495bSYour Name 			fixed_param->num_peer_signal_stats,
1524*5113495bSYour Name 			fixed_param->num_peer_ac_tx_stats,
1525*5113495bSYour Name 			fixed_param->num_peer_ac_rx_stats);
1526*5113495bSYour Name 		return -EINVAL;
1527*5113495bSYour Name 	}
1528*5113495bSYour Name 
1529*5113495bSYour Name 	/* Get the MAX of three peer numbers */
1530*5113495bSYour Name 	peer_num = fixed_param->num_peer_signal_stats >
1531*5113495bSYour Name 			fixed_param->num_peer_ac_tx_stats ?
1532*5113495bSYour Name 			fixed_param->num_peer_signal_stats :
1533*5113495bSYour Name 			fixed_param->num_peer_ac_tx_stats;
1534*5113495bSYour Name 	peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1535*5113495bSYour Name 			peer_num : fixed_param->num_peer_ac_rx_stats;
1536*5113495bSYour Name 
1537*5113495bSYour Name 	if (peer_num == 0)
1538*5113495bSYour Name 		return -EINVAL;
1539*5113495bSYour Name 
1540*5113495bSYour Name 	link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1541*5113495bSYour Name 						      peer_num,
1542*5113495bSYour Name 						      fixed_param);
1543*5113495bSYour Name 	if (!link_stats_results) {
1544*5113495bSYour Name 		wma_err("Fail to allocate stats buffer");
1545*5113495bSYour Name 		return -EINVAL;
1546*5113495bSYour Name 	}
1547*5113495bSYour Name 	link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1548*5113495bSYour Name 	link_stats_results->num_peers = peer_num;
1549*5113495bSYour Name 	link_stats_results->peer_event_number = 1;
1550*5113495bSYour Name 	link_stats_results->moreResultToFollow = 0;
1551*5113495bSYour Name 
1552*5113495bSYour Name 	ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1553*5113495bSYour Name 	ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1554*5113495bSYour Name 	ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1555*5113495bSYour Name 	ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1556*5113495bSYour Name 	ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1557*5113495bSYour Name 	ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1558*5113495bSYour Name 	ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1559*5113495bSYour Name 	ll_stats->peer_num = peer_num;
1560*5113495bSYour Name 
1561*5113495bSYour Name 	result = (uint8_t *)ll_stats->stats;
1562*5113495bSYour Name 	if (!result) {
1563*5113495bSYour Name 		wma_err("result is null");
1564*5113495bSYour Name 		qdf_mem_free(link_stats_results);
1565*5113495bSYour Name 		return -EINVAL;
1566*5113495bSYour Name 	}
1567*5113495bSYour Name 	peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1568*5113495bSYour Name 	ll_stats->peer_stats = peer_stats;
1569*5113495bSYour Name 
1570*5113495bSYour Name 	for (i = 0; i < peer_num && peer_stats; i++) {
1571*5113495bSYour Name 		peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1572*5113495bSYour Name 		peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1573*5113495bSYour Name 	}
1574*5113495bSYour Name 
1575*5113495bSYour Name 	/* Per peer signal */
1576*5113495bSYour Name 	result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1577*5113495bSYour Name 	dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1578*5113495bSYour Name 	for (i = 0;
1579*5113495bSYour Name 	     i < fixed_param->num_peer_signal_stats &&
1580*5113495bSYour Name 	     peer_stats && wmi_peer_signal;
1581*5113495bSYour Name 	     i++) {
1582*5113495bSYour Name 		peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1583*5113495bSYour Name 		peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1584*5113495bSYour Name 		peer_signal = &peer_stats[i].peer_signal_stats;
1585*5113495bSYour Name 
1586*5113495bSYour Name 		wma_debug("%d antennas for peer %d",
1587*5113495bSYour Name 			 wmi_peer_signal->num_chains_valid,
1588*5113495bSYour Name 			 wmi_peer_signal->peer_id);
1589*5113495bSYour Name 		if (dst_len <= result_size && peer_signal) {
1590*5113495bSYour Name 			peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1591*5113495bSYour Name 			peer_signal->peer_id = wmi_peer_signal->peer_id;
1592*5113495bSYour Name 			peer_signal->num_chain =
1593*5113495bSYour Name 					wmi_peer_signal->num_chains_valid;
1594*5113495bSYour Name 			qdf_mem_copy(peer_signal->per_ant_snr,
1595*5113495bSYour Name 				     wmi_peer_signal->per_chain_snr,
1596*5113495bSYour Name 				     sizeof(peer_signal->per_ant_snr));
1597*5113495bSYour Name 			qdf_mem_copy(peer_signal->nf,
1598*5113495bSYour Name 				     wmi_peer_signal->per_chain_nf,
1599*5113495bSYour Name 				     sizeof(peer_signal->nf));
1600*5113495bSYour Name 			qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1601*5113495bSYour Name 				     wmi_peer_signal->per_antenna_rx_mpdus,
1602*5113495bSYour Name 				     sizeof(peer_signal->per_ant_rx_mpdus));
1603*5113495bSYour Name 			qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1604*5113495bSYour Name 				     wmi_peer_signal->per_antenna_tx_mpdus,
1605*5113495bSYour Name 				     sizeof(peer_signal->per_ant_tx_mpdus));
1606*5113495bSYour Name 			result_size -= dst_len;
1607*5113495bSYour Name 		} else {
1608*5113495bSYour Name 			wma_err("Invalid length of PEER signal");
1609*5113495bSYour Name 		}
1610*5113495bSYour Name 		wmi_peer_signal++;
1611*5113495bSYour Name 	}
1612*5113495bSYour Name 
1613*5113495bSYour Name 	result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1614*5113495bSYour Name 	cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1615*5113495bSYour Name 	ll_stats->cca = cca_stats;
1616*5113495bSYour Name 	dst_len = sizeof(*cca_stats);
1617*5113495bSYour Name 	for (i = 0;
1618*5113495bSYour Name 	     i < ll_stats->channel_num && cca_stats && wmi_cca_stats;
1619*5113495bSYour Name 	     i++) {
1620*5113495bSYour Name 		if (dst_len <= result_size) {
1621*5113495bSYour Name 			cca_stats->vdev_id = wmi_cca_stats->vdev_id;
1622*5113495bSYour Name 			cca_stats->idle_time = wmi_cca_stats->idle_time;
1623*5113495bSYour Name 			cca_stats->tx_time = wmi_cca_stats->tx_time;
1624*5113495bSYour Name 			cca_stats->rx_in_bss_time =
1625*5113495bSYour Name 				wmi_cca_stats->rx_in_bss_time;
1626*5113495bSYour Name 			cca_stats->rx_out_bss_time =
1627*5113495bSYour Name 				wmi_cca_stats->rx_out_bss_time;
1628*5113495bSYour Name 			cca_stats->rx_busy_time = wmi_cca_stats->rx_busy_time;
1629*5113495bSYour Name 			cca_stats->rx_in_bad_cond_time =
1630*5113495bSYour Name 				wmi_cca_stats->rx_in_bad_cond_time;
1631*5113495bSYour Name 			cca_stats->tx_in_bad_cond_time =
1632*5113495bSYour Name 				wmi_cca_stats->tx_in_bad_cond_time;
1633*5113495bSYour Name 			cca_stats->wlan_not_avail_time =
1634*5113495bSYour Name 				wmi_cca_stats->wlan_not_avail_time;
1635*5113495bSYour Name 			result_size -= dst_len;
1636*5113495bSYour Name 		} else {
1637*5113495bSYour Name 			wma_err("Invalid length of CCA");
1638*5113495bSYour Name 		}
1639*5113495bSYour Name 		cca_stats++;
1640*5113495bSYour Name 	}
1641*5113495bSYour Name 
1642*5113495bSYour Name 	result += i * sizeof(struct sir_wifi_chan_cca_stats);
1643*5113495bSYour Name 	qdf_status = wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1644*5113495bSYour Name 				       &result, &result_size);
1645*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
1646*5113495bSYour Name 		qdf_status = wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1647*5113495bSYour Name 					       &result, &result_size);
1648*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
1649*5113495bSYour Name 		sme_msg.type = eWMI_SME_LL_STATS_IND;
1650*5113495bSYour Name 		sme_msg.bodyptr = (void *)link_stats_results;
1651*5113495bSYour Name 		sme_msg.bodyval = 0;
1652*5113495bSYour Name 		qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
1653*5113495bSYour Name 						    QDF_MODULE_ID_SME,
1654*5113495bSYour Name 						    QDF_MODULE_ID_SME,
1655*5113495bSYour Name 						    &sme_msg);
1656*5113495bSYour Name 	}
1657*5113495bSYour Name 
1658*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1659*5113495bSYour Name 		qdf_mem_free(link_stats_results);
1660*5113495bSYour Name 		return -EINVAL;
1661*5113495bSYour Name 	}
1662*5113495bSYour Name 
1663*5113495bSYour Name 	return 0;
1664*5113495bSYour Name }
1665*5113495bSYour Name 
1666*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO
wma_get_mlo_per_link_stats_cap(wmi_unified_t wmi_handle)1667*5113495bSYour Name static bool wma_get_mlo_per_link_stats_cap(wmi_unified_t wmi_handle)
1668*5113495bSYour Name {
1669*5113495bSYour Name 	return wmi_service_enabled(wmi_handle,
1670*5113495bSYour Name 				   wmi_service_per_link_stats_support);
1671*5113495bSYour Name }
1672*5113495bSYour Name #else
wma_get_mlo_per_link_stats_cap(wmi_unified_t wmi_handle)1673*5113495bSYour Name static inline bool wma_get_mlo_per_link_stats_cap(wmi_unified_t wmi_handle)
1674*5113495bSYour Name {
1675*5113495bSYour Name 	return false;
1676*5113495bSYour Name }
1677*5113495bSYour Name #endif
1678*5113495bSYour Name 
1679*5113495bSYour Name /**
1680*5113495bSYour Name  * wma_get_dp_peer_stats() - get host dp peer stats
1681*5113495bSYour Name  * @wmi_handle: wmi handle
1682*5113495bSYour Name  * @dp_stats: buffer to store stats
1683*5113495bSYour Name  * @peer_mac: peer mac address
1684*5113495bSYour Name  *
1685*5113495bSYour Name  * Return: 0 on success or error code
1686*5113495bSYour Name  */
wma_get_dp_peer_stats(wmi_unified_t wmi_handle,struct cdp_peer_stats * dp_stats,uint8_t * peer_mac)1687*5113495bSYour Name static QDF_STATUS wma_get_dp_peer_stats(wmi_unified_t wmi_handle,
1688*5113495bSYour Name 					struct cdp_peer_stats *dp_stats,
1689*5113495bSYour Name 					uint8_t *peer_mac)
1690*5113495bSYour Name {
1691*5113495bSYour Name 	void *dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
1692*5113495bSYour Name 	uint8_t vdev_id;
1693*5113495bSYour Name 	QDF_STATUS status;
1694*5113495bSYour Name 
1695*5113495bSYour Name 	status = cdp_peer_get_vdevid(dp_soc, peer_mac, &vdev_id);
1696*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1697*5113495bSYour Name 		wma_err("Unable to find peer ["QDF_MAC_ADDR_FMT"]",
1698*5113495bSYour Name 			QDF_MAC_ADDR_REF(peer_mac));
1699*5113495bSYour Name 		return status;
1700*5113495bSYour Name 	}
1701*5113495bSYour Name 
1702*5113495bSYour Name 	if (!wma_get_mlo_per_link_stats_cap(wmi_handle))
1703*5113495bSYour Name 		return cdp_host_get_peer_stats(dp_soc, vdev_id,
1704*5113495bSYour Name 					       peer_mac, dp_stats);
1705*5113495bSYour Name 
1706*5113495bSYour Name 	return ucfg_dp_get_per_link_peer_stats(dp_soc, vdev_id, peer_mac,
1707*5113495bSYour Name 					       dp_stats, CDP_WILD_PEER_TYPE,
1708*5113495bSYour Name 					       WLAN_MAX_MLD);
1709*5113495bSYour Name }
1710*5113495bSYour Name 
1711*5113495bSYour Name /**
1712*5113495bSYour Name  * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1713*5113495bSYour Name  * @handle:          wma handle
1714*5113495bSYour Name  * @cmd_param_info:  data received with event from fw
1715*5113495bSYour Name  * @len:             length of data
1716*5113495bSYour Name  *
1717*5113495bSYour Name  * Return: 0 for success or error code
1718*5113495bSYour Name  */
wma_unified_link_peer_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)1719*5113495bSYour Name static int wma_unified_link_peer_stats_event_handler(void *handle,
1720*5113495bSYour Name 						     uint8_t *cmd_param_info,
1721*5113495bSYour Name 						     uint32_t len)
1722*5113495bSYour Name {
1723*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
1724*5113495bSYour Name 	WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1725*5113495bSYour Name 	wmi_peer_stats_event_fixed_param *fixed_param;
1726*5113495bSYour Name 	wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1727*5113495bSYour Name 	wmi_rate_stats *rate_stats;
1728*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
1729*5113495bSYour Name 	uint8_t *results, *t_peer_stats, *t_rate_stats, *peer_mac;
1730*5113495bSYour Name 	uint32_t count, rate_cnt;
1731*5113495bSYour Name 	uint32_t total_num_rates = 0;
1732*5113495bSYour Name 	uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1733*5113495bSYour Name 	size_t peer_info_size, peer_stats_size, rate_stats_size;
1734*5113495bSYour Name 	size_t link_stats_results_size;
1735*5113495bSYour Name 	bool excess_data = false;
1736*5113495bSYour Name 	uint32_t buf_len = 0;
1737*5113495bSYour Name 	struct cdp_peer_stats *dp_stats;
1738*5113495bSYour Name 	QDF_STATUS status;
1739*5113495bSYour Name 	uint8_t mcs_index;
1740*5113495bSYour Name 
1741*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1742*5113495bSYour Name 
1743*5113495bSYour Name 	if (!mac) {
1744*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
1745*5113495bSYour Name 		return -EINVAL;
1746*5113495bSYour Name 	}
1747*5113495bSYour Name 
1748*5113495bSYour Name 	if (!mac->sme.link_layer_stats_cb) {
1749*5113495bSYour Name 		wma_debug("HDD callback is null");
1750*5113495bSYour Name 		return -EINVAL;
1751*5113495bSYour Name 	}
1752*5113495bSYour Name 
1753*5113495bSYour Name 	param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1754*5113495bSYour Name 	if (!param_tlvs) {
1755*5113495bSYour Name 		wma_err("Invalid stats event");
1756*5113495bSYour Name 		return -EINVAL;
1757*5113495bSYour Name 	}
1758*5113495bSYour Name 	/*
1759*5113495bSYour Name 	 * cmd_param_info contains
1760*5113495bSYour Name 	 * wmi_peer_stats_event_fixed_param fixed_param;
1761*5113495bSYour Name 	 * num_peers * size of(struct wmi_peer_link_stats)
1762*5113495bSYour Name 	 * total_num_rates * size of(struct wmi_rate_stats)
1763*5113495bSYour Name 	 * total_num_rates is the sum of the rates of all the peers.
1764*5113495bSYour Name 	 */
1765*5113495bSYour Name 	fixed_param = param_tlvs->fixed_param;
1766*5113495bSYour Name 	peer_stats = param_tlvs->peer_stats;
1767*5113495bSYour Name 	rate_stats = param_tlvs->peer_rate_stats;
1768*5113495bSYour Name 
1769*5113495bSYour Name 	if (!fixed_param || !peer_stats ||
1770*5113495bSYour Name 	    (peer_stats->num_rates && !rate_stats)) {
1771*5113495bSYour Name 		wma_err("Invalid param_tlvs for Peer Stats");
1772*5113495bSYour Name 		return -EINVAL;
1773*5113495bSYour Name 	}
1774*5113495bSYour Name 
1775*5113495bSYour Name 	do {
1776*5113495bSYour Name 		if (fixed_param->num_peers >
1777*5113495bSYour Name 		    WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats) ||
1778*5113495bSYour Name 		    fixed_param->num_peers > param_tlvs->num_peer_stats) {
1779*5113495bSYour Name 			excess_data = true;
1780*5113495bSYour Name 			break;
1781*5113495bSYour Name 		} else {
1782*5113495bSYour Name 			buf_len = fixed_param->num_peers *
1783*5113495bSYour Name 				sizeof(wmi_peer_link_stats);
1784*5113495bSYour Name 		}
1785*5113495bSYour Name 		temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1786*5113495bSYour Name 		for (count = 0; count < fixed_param->num_peers; count++) {
1787*5113495bSYour Name 			if (temp_peer_stats->num_rates >
1788*5113495bSYour Name 			    WMI_SVC_MSG_MAX_SIZE / sizeof(wmi_rate_stats)) {
1789*5113495bSYour Name 				excess_data = true;
1790*5113495bSYour Name 				break;
1791*5113495bSYour Name 			} else {
1792*5113495bSYour Name 				total_num_rates += temp_peer_stats->num_rates;
1793*5113495bSYour Name 				if (total_num_rates >
1794*5113495bSYour Name 				    WMI_SVC_MSG_MAX_SIZE /
1795*5113495bSYour Name 				    sizeof(wmi_rate_stats) || total_num_rates >
1796*5113495bSYour Name 				    param_tlvs->num_peer_rate_stats) {
1797*5113495bSYour Name 					excess_data = true;
1798*5113495bSYour Name 					break;
1799*5113495bSYour Name 				}
1800*5113495bSYour Name 				buf_len += temp_peer_stats->num_rates *
1801*5113495bSYour Name 					sizeof(wmi_rate_stats);
1802*5113495bSYour Name 			}
1803*5113495bSYour Name 			temp_peer_stats++;
1804*5113495bSYour Name 		}
1805*5113495bSYour Name 	} while (0);
1806*5113495bSYour Name 
1807*5113495bSYour Name 	if (excess_data ||
1808*5113495bSYour Name 	    (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param))) {
1809*5113495bSYour Name 		wma_err("excess wmi buffer: rates:%d, peers:%d",
1810*5113495bSYour Name 			peer_stats->num_rates, fixed_param->num_peers);
1811*5113495bSYour Name 		return -EINVAL;
1812*5113495bSYour Name 	}
1813*5113495bSYour Name 
1814*5113495bSYour Name 	peer_stats_size = sizeof(struct wifi_peer_stat);
1815*5113495bSYour Name 	peer_info_size = sizeof(struct wifi_peer_info);
1816*5113495bSYour Name 	rate_stats_size = sizeof(struct wifi_rate_stat);
1817*5113495bSYour Name 	link_stats_results_size =
1818*5113495bSYour Name 		sizeof(*link_stats_results) + peer_stats_size +
1819*5113495bSYour Name 		(fixed_param->num_peers * peer_info_size) +
1820*5113495bSYour Name 		(total_num_rates * rate_stats_size);
1821*5113495bSYour Name 
1822*5113495bSYour Name 	link_stats_results = qdf_mem_malloc(link_stats_results_size);
1823*5113495bSYour Name 	if (!link_stats_results)
1824*5113495bSYour Name 		return -ENOMEM;
1825*5113495bSYour Name 
1826*5113495bSYour Name 	qdf_mem_zero(link_stats_results, link_stats_results_size);
1827*5113495bSYour Name 
1828*5113495bSYour Name 	link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1829*5113495bSYour Name 	link_stats_results->rspId = fixed_param->request_id;
1830*5113495bSYour Name 	link_stats_results->ifaceId = fixed_param->vdev_id_info.vdev_id;
1831*5113495bSYour Name 	link_stats_results->num_peers = fixed_param->num_peers;
1832*5113495bSYour Name 	link_stats_results->peer_event_number = fixed_param->peer_event_number;
1833*5113495bSYour Name 	link_stats_results->moreResultToFollow = fixed_param->more_data;
1834*5113495bSYour Name 
1835*5113495bSYour Name 	qdf_mem_copy(link_stats_results->results,
1836*5113495bSYour Name 		     &fixed_param->num_peers, peer_stats_size);
1837*5113495bSYour Name 	dp_stats = qdf_mem_malloc(sizeof(*dp_stats));
1838*5113495bSYour Name 	if (!dp_stats) {
1839*5113495bSYour Name 		qdf_mem_free(link_stats_results);
1840*5113495bSYour Name 		return -ENOMEM;
1841*5113495bSYour Name 	}
1842*5113495bSYour Name 
1843*5113495bSYour Name 	results = (uint8_t *) link_stats_results->results;
1844*5113495bSYour Name 	t_peer_stats = (uint8_t *) peer_stats;
1845*5113495bSYour Name 	t_rate_stats = (uint8_t *) rate_stats;
1846*5113495bSYour Name 	next_res_offset = peer_stats_size;
1847*5113495bSYour Name 	next_peer_offset = WMI_TLV_HDR_SIZE;
1848*5113495bSYour Name 	next_rate_offset = WMI_TLV_HDR_SIZE;
1849*5113495bSYour Name 	for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
1850*5113495bSYour Name 		qdf_mem_copy(results + next_res_offset,
1851*5113495bSYour Name 			     t_peer_stats + next_peer_offset, peer_info_size);
1852*5113495bSYour Name 		next_res_offset += peer_info_size;
1853*5113495bSYour Name 
1854*5113495bSYour Name 		peer_mac = (uint8_t *)&peer_stats->peer_mac_address;
1855*5113495bSYour Name 		status = wma_get_dp_peer_stats(wma_handle->wmi_handle,
1856*5113495bSYour Name 					       dp_stats, peer_mac);
1857*5113495bSYour Name 
1858*5113495bSYour Name 		/* Copy rate stats associated with this peer */
1859*5113495bSYour Name 		for (count = 0; count < peer_stats->num_rates; count++) {
1860*5113495bSYour Name 			mcs_index = RATE_STAT_GET_MCS_INDEX(rate_stats->rate);
1861*5113495bSYour Name 			if (QDF_IS_STATUS_SUCCESS(status)) {
1862*5113495bSYour Name 				if (mcs_index < MAX_MCS)
1863*5113495bSYour Name 					rate_stats->rx_mpdu =
1864*5113495bSYour Name 					    dp_stats->rx.rx_mpdu_cnt[mcs_index];
1865*5113495bSYour Name 				else
1866*5113495bSYour Name 					rate_stats->rx_mpdu = 0;
1867*5113495bSYour Name 			}
1868*5113495bSYour Name 			rate_stats++;
1869*5113495bSYour Name 
1870*5113495bSYour Name 			qdf_mem_copy(results + next_res_offset,
1871*5113495bSYour Name 				     t_rate_stats + next_rate_offset,
1872*5113495bSYour Name 				     rate_stats_size);
1873*5113495bSYour Name 			next_res_offset += rate_stats_size;
1874*5113495bSYour Name 			next_rate_offset += sizeof(*rate_stats);
1875*5113495bSYour Name 		}
1876*5113495bSYour Name 		next_peer_offset += sizeof(*peer_stats);
1877*5113495bSYour Name 		peer_stats++;
1878*5113495bSYour Name 	}
1879*5113495bSYour Name 
1880*5113495bSYour Name 	qdf_mem_free(dp_stats);
1881*5113495bSYour Name 	/* call hdd callback with Link Layer Statistics
1882*5113495bSYour Name 	 * vdev_id/ifacId in link_stats_results will be
1883*5113495bSYour Name 	 * used to retrieve the correct HDD context
1884*5113495bSYour Name 	 */
1885*5113495bSYour Name 	mac->sme.link_layer_stats_cb(mac->hdd_handle,
1886*5113495bSYour Name 				     WMA_LINK_LAYER_STATS_RESULTS_RSP,
1887*5113495bSYour Name 				     link_stats_results,
1888*5113495bSYour Name 				     mac->sme.ll_stats_context);
1889*5113495bSYour Name 	qdf_mem_free(link_stats_results);
1890*5113495bSYour Name 
1891*5113495bSYour Name 	return 0;
1892*5113495bSYour Name }
1893*5113495bSYour Name 
1894*5113495bSYour Name /**
1895*5113495bSYour Name  * wma_unified_link_stats_results_mem_free() - Free link stats results memory
1896*5113495bSYour Name  * @link_stats_results: pointer to link stats result
1897*5113495bSYour Name  *
1898*5113495bSYour Name  * Return: 0 on success, error number otherwise.
1899*5113495bSYour Name  */
wma_unified_link_stats_results_mem_free(tSirLLStatsResults * link_stats_results)1900*5113495bSYour Name void wma_unified_link_stats_results_mem_free(
1901*5113495bSYour Name 			tSirLLStatsResults *link_stats_results)
1902*5113495bSYour Name {
1903*5113495bSYour Name 	struct wifi_radio_stats *rs_results;
1904*5113495bSYour Name 	uint32_t i = 0;
1905*5113495bSYour Name 
1906*5113495bSYour Name 	if (!link_stats_results)
1907*5113495bSYour Name 		return;
1908*5113495bSYour Name 
1909*5113495bSYour Name 	rs_results = (struct wifi_radio_stats *)
1910*5113495bSYour Name 				&link_stats_results->results[0];
1911*5113495bSYour Name 	for (i = 0; i < link_stats_results->num_radio; i++) {
1912*5113495bSYour Name 		if (rs_results->tx_time_per_power_level) {
1913*5113495bSYour Name 			qdf_mem_free(rs_results->tx_time_per_power_level);
1914*5113495bSYour Name 			rs_results->tx_time_per_power_level = NULL;
1915*5113495bSYour Name 		}
1916*5113495bSYour Name 
1917*5113495bSYour Name 		if (rs_results->channels) {
1918*5113495bSYour Name 			qdf_mem_free(rs_results->channels);
1919*5113495bSYour Name 			rs_results->channels = NULL;
1920*5113495bSYour Name 		}
1921*5113495bSYour Name 		rs_results++;
1922*5113495bSYour Name 	}
1923*5113495bSYour Name }
1924*5113495bSYour Name 
1925*5113495bSYour Name 
__wma_unified_radio_tx_mem_free(tp_wma_handle wma_handle)1926*5113495bSYour Name static int __wma_unified_radio_tx_mem_free(tp_wma_handle wma_handle)
1927*5113495bSYour Name {
1928*5113495bSYour Name 	wma_unified_link_stats_results_mem_free(wma_handle->link_stats_results);
1929*5113495bSYour Name 
1930*5113495bSYour Name 	qdf_mem_free(wma_handle->link_stats_results);
1931*5113495bSYour Name 	wma_handle->link_stats_results = NULL;
1932*5113495bSYour Name 
1933*5113495bSYour Name 	return 0;
1934*5113495bSYour Name }
1935*5113495bSYour Name 
1936*5113495bSYour Name /**
1937*5113495bSYour Name  * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1938*5113495bSYour Name  * @handle: WMI handle
1939*5113495bSYour Name  *
1940*5113495bSYour Name  * Return: 0 on success, error number otherwise.
1941*5113495bSYour Name  */
wma_unified_radio_tx_mem_free(void * handle)1942*5113495bSYour Name int wma_unified_radio_tx_mem_free(void *handle)
1943*5113495bSYour Name {
1944*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
1945*5113495bSYour Name 	int ret;
1946*5113495bSYour Name 
1947*5113495bSYour Name 	if (!wma_handle->link_stats_results)
1948*5113495bSYour Name 		return 0;
1949*5113495bSYour Name 
1950*5113495bSYour Name 	wma_debug("free link_stats_results");
1951*5113495bSYour Name 	qdf_mutex_acquire(&wma_handle->radio_stats_lock);
1952*5113495bSYour Name 	ret = __wma_unified_radio_tx_mem_free(wma_handle);
1953*5113495bSYour Name 	qdf_mutex_release(&wma_handle->radio_stats_lock);
1954*5113495bSYour Name 
1955*5113495bSYour Name 	return ret;
1956*5113495bSYour Name }
1957*5113495bSYour Name 
__wma_unified_radio_tx_power_level_stats_event_handler(tp_wma_handle wma_handle,u_int8_t * cmd_param_info,u_int32_t len)1958*5113495bSYour Name static int __wma_unified_radio_tx_power_level_stats_event_handler(
1959*5113495bSYour Name 						tp_wma_handle wma_handle,
1960*5113495bSYour Name 						u_int8_t *cmd_param_info,
1961*5113495bSYour Name 						u_int32_t len)
1962*5113495bSYour Name {
1963*5113495bSYour Name 	WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1964*5113495bSYour Name 	wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1965*5113495bSYour Name 	uint8_t *tx_power_level_values;
1966*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
1967*5113495bSYour Name 	struct wifi_radio_stats *rs_results;
1968*5113495bSYour Name 	uint32_t max_total_num_tx_power_levels = MAX_TPC_LEVELS * NUM_OF_BANDS *
1969*5113495bSYour Name 						MAX_SPATIAL_STREAM_ANY_V3;
1970*5113495bSYour Name 
1971*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
1972*5113495bSYour Name 
1973*5113495bSYour Name 	if (!mac) {
1974*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
1975*5113495bSYour Name 		return -EINVAL;
1976*5113495bSYour Name 	}
1977*5113495bSYour Name 
1978*5113495bSYour Name 	if (!mac->sme.link_layer_stats_cb) {
1979*5113495bSYour Name 		wma_debug("HDD callback is null");
1980*5113495bSYour Name 		return -EINVAL;
1981*5113495bSYour Name 	}
1982*5113495bSYour Name 
1983*5113495bSYour Name 	param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1984*5113495bSYour Name 								cmd_param_info;
1985*5113495bSYour Name 	if (!param_tlvs) {
1986*5113495bSYour Name 		wma_err("Invalid tx power level stats event");
1987*5113495bSYour Name 		return -EINVAL;
1988*5113495bSYour Name 	}
1989*5113495bSYour Name 
1990*5113495bSYour Name 	fixed_param = param_tlvs->fixed_param;
1991*5113495bSYour Name 	if (!fixed_param) {
1992*5113495bSYour Name 		wma_err("Invalid param_tlvs for Radio tx_power level Stats");
1993*5113495bSYour Name 		return -EINVAL;
1994*5113495bSYour Name 	}
1995*5113495bSYour Name 
1996*5113495bSYour Name 	link_stats_results = wma_handle->link_stats_results;
1997*5113495bSYour Name 	if (!link_stats_results) {
1998*5113495bSYour Name 		wma_err("link_stats_results is NULL");
1999*5113495bSYour Name 		return -EINVAL;
2000*5113495bSYour Name 	}
2001*5113495bSYour Name 
2002*5113495bSYour Name 	if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
2003*5113495bSYour Name 	    sizeof(*fixed_param)) / sizeof(uint32_t)) ||
2004*5113495bSYour Name 	    fixed_param->num_tx_power_levels >
2005*5113495bSYour Name 	    param_tlvs->num_tx_time_per_power_level) {
2006*5113495bSYour Name 		wma_err("excess tx_power buffers:%d, num_tx_time_per_power_level:%d",
2007*5113495bSYour Name 			fixed_param->num_tx_power_levels,
2008*5113495bSYour Name 			param_tlvs->num_tx_time_per_power_level);
2009*5113495bSYour Name 		return -EINVAL;
2010*5113495bSYour Name 	}
2011*5113495bSYour Name 
2012*5113495bSYour Name 	if (fixed_param->radio_id >= link_stats_results->num_radio) {
2013*5113495bSYour Name 		wma_err("Invalid radio_id %d num_radio %d",
2014*5113495bSYour Name 			 fixed_param->radio_id,
2015*5113495bSYour Name 			 link_stats_results->num_radio);
2016*5113495bSYour Name 		return -EINVAL;
2017*5113495bSYour Name 	}
2018*5113495bSYour Name 
2019*5113495bSYour Name 	if (fixed_param->total_num_tx_power_levels >
2020*5113495bSYour Name 	    max_total_num_tx_power_levels) {
2021*5113495bSYour Name 		wma_debug("Invalid total_num_tx_power_levels %d",
2022*5113495bSYour Name 			 fixed_param->total_num_tx_power_levels);
2023*5113495bSYour Name 		return -EINVAL;
2024*5113495bSYour Name 	}
2025*5113495bSYour Name 
2026*5113495bSYour Name 	rs_results = (struct wifi_radio_stats *) &link_stats_results->results[0] +
2027*5113495bSYour Name 							 fixed_param->radio_id;
2028*5113495bSYour Name 	tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
2029*5113495bSYour Name 
2030*5113495bSYour Name 	if (rs_results->total_num_tx_power_levels &&
2031*5113495bSYour Name 	    fixed_param->total_num_tx_power_levels >
2032*5113495bSYour Name 		rs_results->total_num_tx_power_levels) {
2033*5113495bSYour Name 		wma_err("excess tx_power buffers:%d, total_num_tx_power_levels:%d",
2034*5113495bSYour Name 			 fixed_param->total_num_tx_power_levels,
2035*5113495bSYour Name 			 rs_results->total_num_tx_power_levels);
2036*5113495bSYour Name 		return -EINVAL;
2037*5113495bSYour Name 	}
2038*5113495bSYour Name 
2039*5113495bSYour Name 	rs_results->total_num_tx_power_levels =
2040*5113495bSYour Name 				fixed_param->total_num_tx_power_levels;
2041*5113495bSYour Name 	if (!rs_results->total_num_tx_power_levels) {
2042*5113495bSYour Name 		link_stats_results->nr_received++;
2043*5113495bSYour Name 		goto post_stats;
2044*5113495bSYour Name 	}
2045*5113495bSYour Name 
2046*5113495bSYour Name 	if ((fixed_param->power_level_offset >
2047*5113495bSYour Name 	    rs_results->total_num_tx_power_levels) ||
2048*5113495bSYour Name 	    (fixed_param->num_tx_power_levels >
2049*5113495bSYour Name 	    rs_results->total_num_tx_power_levels -
2050*5113495bSYour Name 	    fixed_param->power_level_offset)) {
2051*5113495bSYour Name 		wma_err("Invalid offset %d total_num %d num %d",
2052*5113495bSYour Name 			 fixed_param->power_level_offset,
2053*5113495bSYour Name 			 rs_results->total_num_tx_power_levels,
2054*5113495bSYour Name 			 fixed_param->num_tx_power_levels);
2055*5113495bSYour Name 		return -EINVAL;
2056*5113495bSYour Name 	}
2057*5113495bSYour Name 
2058*5113495bSYour Name 	if (!rs_results->tx_time_per_power_level) {
2059*5113495bSYour Name 		rs_results->tx_time_per_power_level =
2060*5113495bSYour Name 			qdf_mem_malloc(sizeof(uint32_t) *
2061*5113495bSYour Name 				       rs_results->total_num_tx_power_levels);
2062*5113495bSYour Name 		if (!rs_results->tx_time_per_power_level) {
2063*5113495bSYour Name 			/* In error case, atleast send the radio stats without
2064*5113495bSYour Name 			 * tx_power_level stats
2065*5113495bSYour Name 			 */
2066*5113495bSYour Name 			rs_results->total_num_tx_power_levels = 0;
2067*5113495bSYour Name 			link_stats_results->nr_received++;
2068*5113495bSYour Name 			goto post_stats;
2069*5113495bSYour Name 		}
2070*5113495bSYour Name 	}
2071*5113495bSYour Name 	qdf_mem_copy(&rs_results->tx_time_per_power_level[
2072*5113495bSYour Name 					fixed_param->power_level_offset],
2073*5113495bSYour Name 		tx_power_level_values,
2074*5113495bSYour Name 		sizeof(uint32_t) * fixed_param->num_tx_power_levels);
2075*5113495bSYour Name 	if (rs_results->total_num_tx_power_levels ==
2076*5113495bSYour Name 	   (fixed_param->num_tx_power_levels +
2077*5113495bSYour Name 					 fixed_param->power_level_offset)) {
2078*5113495bSYour Name 		link_stats_results->moreResultToFollow = 0;
2079*5113495bSYour Name 		link_stats_results->nr_received++;
2080*5113495bSYour Name 	}
2081*5113495bSYour Name 	wma_debug("num tx pwr lvls %u num tx pwr lvls %u pwr lvl offset %u radio_id %u moretofollow: %u nr_received: %u",
2082*5113495bSYour Name 		 fixed_param->total_num_tx_power_levels,
2083*5113495bSYour Name 		 fixed_param->num_tx_power_levels,
2084*5113495bSYour Name 		 fixed_param->power_level_offset, fixed_param->radio_id,
2085*5113495bSYour Name 		 link_stats_results->moreResultToFollow,
2086*5113495bSYour Name 		 link_stats_results->nr_received);
2087*5113495bSYour Name 
2088*5113495bSYour Name 	/* If still data to receive, return from here */
2089*5113495bSYour Name 	if (link_stats_results->moreResultToFollow)
2090*5113495bSYour Name 		return 0;
2091*5113495bSYour Name 
2092*5113495bSYour Name post_stats:
2093*5113495bSYour Name 	if (link_stats_results->num_radio != link_stats_results->nr_received) {
2094*5113495bSYour Name 		/* Not received all radio stats yet, don't post yet */
2095*5113495bSYour Name 		return 0;
2096*5113495bSYour Name 	}
2097*5113495bSYour Name 
2098*5113495bSYour Name 	/* call hdd callback with Link Layer Statistics
2099*5113495bSYour Name 	 * vdev_id/ifacId in link_stats_results will be
2100*5113495bSYour Name 	 * used to retrieve the correct HDD context
2101*5113495bSYour Name 	 */
2102*5113495bSYour Name 	mac->sme.link_layer_stats_cb(mac->hdd_handle,
2103*5113495bSYour Name 		WMA_LINK_LAYER_STATS_RESULTS_RSP,
2104*5113495bSYour Name 		link_stats_results,
2105*5113495bSYour Name 		mac->sme.ll_stats_context);
2106*5113495bSYour Name 
2107*5113495bSYour Name 	return 0;
2108*5113495bSYour Name }
2109*5113495bSYour Name 
2110*5113495bSYour Name /**
2111*5113495bSYour Name  * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
2112*5113495bSYour Name  * @handle: WMI handle
2113*5113495bSYour Name  * @cmd_param_info: command param info
2114*5113495bSYour Name  * @len: Length of @cmd_param_info
2115*5113495bSYour Name  *
2116*5113495bSYour Name  * This is the WMI event handler function to receive radio stats tx
2117*5113495bSYour Name  * power level stats.
2118*5113495bSYour Name  *
2119*5113495bSYour Name  * Return: 0 on success, error number otherwise.
2120*5113495bSYour Name  */
wma_unified_radio_tx_power_level_stats_event_handler(void * handle,u_int8_t * cmd_param_info,u_int32_t len)2121*5113495bSYour Name static int wma_unified_radio_tx_power_level_stats_event_handler(
2122*5113495bSYour Name 						void *handle,
2123*5113495bSYour Name 						u_int8_t *cmd_param_info,
2124*5113495bSYour Name 						u_int32_t len)
2125*5113495bSYour Name {
2126*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2127*5113495bSYour Name 	int ret;
2128*5113495bSYour Name 
2129*5113495bSYour Name 	qdf_mutex_acquire(&wma_handle->radio_stats_lock);
2130*5113495bSYour Name 	ret = __wma_unified_radio_tx_power_level_stats_event_handler(
2131*5113495bSYour Name 								wma_handle,
2132*5113495bSYour Name 								cmd_param_info,
2133*5113495bSYour Name 								len);
2134*5113495bSYour Name 	qdf_mutex_release(&wma_handle->radio_stats_lock);
2135*5113495bSYour Name 
2136*5113495bSYour Name 	return ret;
2137*5113495bSYour Name }
2138*5113495bSYour Name 
wma_copy_chan_stats(uint32_t num_chan,struct wifi_channel_stats * channels,struct wifi_radio_stats * rs_results)2139*5113495bSYour Name static int wma_copy_chan_stats(uint32_t num_chan,
2140*5113495bSYour Name 			       struct wifi_channel_stats *channels,
2141*5113495bSYour Name 			       struct wifi_radio_stats *rs_results)
2142*5113495bSYour Name {
2143*5113495bSYour Name 	uint32_t num_chan_in_prev_event = rs_results->num_channels;
2144*5113495bSYour Name 	struct wifi_channel_stats *channels_in_prev_event =
2145*5113495bSYour Name 							rs_results->channels;
2146*5113495bSYour Name 	if (!rs_results->channels) {
2147*5113495bSYour Name 		wma_debug("Num of channels in first event %d", num_chan);
2148*5113495bSYour Name 		/* It means this is the first event for this radio */
2149*5113495bSYour Name 		rs_results->num_channels = num_chan;
2150*5113495bSYour Name 		rs_results->channels = channels;
2151*5113495bSYour Name 		return 0;
2152*5113495bSYour Name 	}
2153*5113495bSYour Name 	if (rs_results->num_channels + num_chan > NUM_CHANNELS) {
2154*5113495bSYour Name 		wma_err("total chan stats num unexpected %d new %d",
2155*5113495bSYour Name 			rs_results->num_channels, num_chan);
2156*5113495bSYour Name 		/* do not add more */
2157*5113495bSYour Name 		qdf_mem_free(channels);
2158*5113495bSYour Name 		return 0;
2159*5113495bSYour Name 	}
2160*5113495bSYour Name 
2161*5113495bSYour Name 	wma_debug("Num of channels in Second event %d", num_chan);
2162*5113495bSYour Name 	rs_results->num_channels += num_chan;
2163*5113495bSYour Name 	rs_results->channels = qdf_mem_malloc(rs_results->num_channels *
2164*5113495bSYour Name 					      sizeof(*channels));
2165*5113495bSYour Name 	if (!rs_results->channels) {
2166*5113495bSYour Name 		qdf_mem_free(channels);
2167*5113495bSYour Name 		qdf_mem_free(channels_in_prev_event);
2168*5113495bSYour Name 		return -ENOMEM;
2169*5113495bSYour Name 	}
2170*5113495bSYour Name 
2171*5113495bSYour Name 	/* copy the previous event's information */
2172*5113495bSYour Name 	qdf_mem_copy(rs_results->channels, channels_in_prev_event,
2173*5113495bSYour Name 		     num_chan_in_prev_event * sizeof(*channels_in_prev_event));
2174*5113495bSYour Name 
2175*5113495bSYour Name 	/* copy the current event's information */
2176*5113495bSYour Name 	qdf_mem_copy(rs_results->channels + num_chan_in_prev_event, channels,
2177*5113495bSYour Name 		     num_chan * sizeof(*channels));
2178*5113495bSYour Name 
2179*5113495bSYour Name 	qdf_mem_free(channels);
2180*5113495bSYour Name 	qdf_mem_free(channels_in_prev_event);
2181*5113495bSYour Name 	return 0;
2182*5113495bSYour Name }
2183*5113495bSYour Name 
2184*5113495bSYour Name #define WMI_MAX_RADIO_STATS_LOGS 350
2185*5113495bSYour Name 
2186*5113495bSYour Name /*
2187*5113495bSYour Name  * Consider 4 char each for center_freq, channel_width, center_freq0,
2188*5113495bSYour Name  * center_freq1 and 10 char each for radio_awake_time, cca_busy_time,
2189*5113495bSYour Name  * tx_time and rx_time 14 char for parenthesis, 1 for space and 1 to
2190*5113495bSYour Name  * end string, making it a total of 72 chars.
2191*5113495bSYour Name  */
2192*5113495bSYour Name #define WMI_MAX_RADIO_SINGLE_STATS_LEN 72
2193*5113495bSYour Name 
2194*5113495bSYour Name static int
__wma_unified_link_radio_stats_event_handler(tp_wma_handle wma_handle,uint8_t * cmd_param_info,uint32_t len)2195*5113495bSYour Name __wma_unified_link_radio_stats_event_handler(tp_wma_handle wma_handle,
2196*5113495bSYour Name 					     uint8_t *cmd_param_info,
2197*5113495bSYour Name 					     uint32_t len)
2198*5113495bSYour Name {
2199*5113495bSYour Name 	WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
2200*5113495bSYour Name 	wmi_radio_link_stats_event_fixed_param *fixed_param;
2201*5113495bSYour Name 	wmi_radio_link_stats *radio_stats;
2202*5113495bSYour Name 	wmi_channel_stats *channel_stats;
2203*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
2204*5113495bSYour Name 	uint8_t *results, *t_radio_stats, *t_channel_stats;
2205*5113495bSYour Name 	uint32_t next_chan_offset, count;
2206*5113495bSYour Name 	uint32_t num_chan_in_this_event = 0;
2207*5113495bSYour Name 	size_t radio_stats_size, chan_stats_size;
2208*5113495bSYour Name 	size_t link_stats_results_size;
2209*5113495bSYour Name 	struct wifi_radio_stats *rs_results = NULL;
2210*5113495bSYour Name 	struct wifi_channel_stats *chn_results;
2211*5113495bSYour Name 	struct wifi_channel_stats *channels_in_this_event;
2212*5113495bSYour Name 	bool per_chan_rx_tx_time_enabled = false;
2213*5113495bSYour Name 	int32_t status;
2214*5113495bSYour Name 	uint8_t *info;
2215*5113495bSYour Name 	uint32_t stats_len = 0;
2216*5113495bSYour Name 	int ret;
2217*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2218*5113495bSYour Name 	struct wma_ini_config *cfg = wma_get_ini_handle(wma_handle);
2219*5113495bSYour Name 	bool exclude_selftx_from_cca_busy;
2220*5113495bSYour Name 
2221*5113495bSYour Name 	if (!mac) {
2222*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
2223*5113495bSYour Name 		return -EINVAL;
2224*5113495bSYour Name 	}
2225*5113495bSYour Name 
2226*5113495bSYour Name 	if (!cfg) {
2227*5113495bSYour Name 		wma_err("NULL WMA ini handle");
2228*5113495bSYour Name 		return 0;
2229*5113495bSYour Name 	}
2230*5113495bSYour Name 
2231*5113495bSYour Name 	exclude_selftx_from_cca_busy = cfg->exclude_selftx_from_cca_busy;
2232*5113495bSYour Name 
2233*5113495bSYour Name 	if (!mac->sme.link_layer_stats_cb) {
2234*5113495bSYour Name 		wma_debug("HDD callback is null");
2235*5113495bSYour Name 		return -EINVAL;
2236*5113495bSYour Name 	}
2237*5113495bSYour Name 
2238*5113495bSYour Name 	param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2239*5113495bSYour Name 	if (!param_tlvs) {
2240*5113495bSYour Name 		wma_err("Invalid stats event");
2241*5113495bSYour Name 		return -EINVAL;
2242*5113495bSYour Name 	}
2243*5113495bSYour Name 
2244*5113495bSYour Name 	/*
2245*5113495bSYour Name 	 * cmd_param_info contains
2246*5113495bSYour Name 	 * wmi_radio_link_stats_event_fixed_param fixed_param;
2247*5113495bSYour Name 	 * size of(struct wmi_radio_link_stats);
2248*5113495bSYour Name 	 * num_channels * size of(struct wmi_channel_stats)
2249*5113495bSYour Name 	 */
2250*5113495bSYour Name 	fixed_param = param_tlvs->fixed_param;
2251*5113495bSYour Name 	if (fixed_param && !fixed_param->num_radio &&
2252*5113495bSYour Name 	    !fixed_param->more_radio_events) {
2253*5113495bSYour Name 		wma_debug("FW indicates dummy link radio stats");
2254*5113495bSYour Name 		if (!wma_handle->link_stats_results) {
2255*5113495bSYour Name 			wma_handle->link_stats_results = qdf_mem_malloc(
2256*5113495bSYour Name 						sizeof(*link_stats_results));
2257*5113495bSYour Name 			if (!wma_handle->link_stats_results)
2258*5113495bSYour Name 				return -ENOMEM;
2259*5113495bSYour Name 		}
2260*5113495bSYour Name 
2261*5113495bSYour Name 		/*
2262*5113495bSYour Name 		 * Free the already allocated memory, if any, before setting
2263*5113495bSYour Name 		 * the num_radio to 0
2264*5113495bSYour Name 		 */
2265*5113495bSYour Name 		wma_unified_link_stats_results_mem_free(
2266*5113495bSYour Name 					wma_handle->link_stats_results);
2267*5113495bSYour Name 
2268*5113495bSYour Name 		link_stats_results = wma_handle->link_stats_results;
2269*5113495bSYour Name 		link_stats_results->num_radio = fixed_param->num_radio;
2270*5113495bSYour Name 		goto link_radio_stats_cb;
2271*5113495bSYour Name 	}
2272*5113495bSYour Name 
2273*5113495bSYour Name 	radio_stats = param_tlvs->radio_stats;
2274*5113495bSYour Name 	channel_stats = param_tlvs->channel_stats;
2275*5113495bSYour Name 
2276*5113495bSYour Name 	if (!fixed_param || !radio_stats ||
2277*5113495bSYour Name 	    (radio_stats->num_channels && !channel_stats)) {
2278*5113495bSYour Name 		wma_err("Invalid param_tlvs for Radio Stats");
2279*5113495bSYour Name 		return -EINVAL;
2280*5113495bSYour Name 	}
2281*5113495bSYour Name 	if (radio_stats->num_channels > NUM_CHANNELS ||
2282*5113495bSYour Name 	    radio_stats->num_channels > param_tlvs->num_channel_stats) {
2283*5113495bSYour Name 		wma_err("Too many channels %d", radio_stats->num_channels);
2284*5113495bSYour Name 		return -EINVAL;
2285*5113495bSYour Name 	}
2286*5113495bSYour Name 
2287*5113495bSYour Name 	radio_stats_size = sizeof(struct wifi_radio_stats);
2288*5113495bSYour Name 	chan_stats_size = sizeof(struct wifi_channel_stats);
2289*5113495bSYour Name 	if (fixed_param->num_radio >
2290*5113495bSYour Name 		(UINT_MAX - sizeof(*link_stats_results))/radio_stats_size) {
2291*5113495bSYour Name 		wma_err("excess num_radio %d is leading to int overflow",
2292*5113495bSYour Name 			fixed_param->num_radio);
2293*5113495bSYour Name 		return -EINVAL;
2294*5113495bSYour Name 	}
2295*5113495bSYour Name 	link_stats_results_size = sizeof(*link_stats_results) +
2296*5113495bSYour Name 				  fixed_param->num_radio * radio_stats_size;
2297*5113495bSYour Name 
2298*5113495bSYour Name 	if (radio_stats->radio_id >= fixed_param->num_radio) {
2299*5113495bSYour Name 		wma_err("invalid radio id:%d, num radio:%d",
2300*5113495bSYour Name 			radio_stats->radio_id,
2301*5113495bSYour Name 			fixed_param->num_radio);
2302*5113495bSYour Name 		return -EINVAL;
2303*5113495bSYour Name 	}
2304*5113495bSYour Name 	if (wma_handle->link_stats_results &&
2305*5113495bSYour Name 	    !wma_handle->link_stats_results->num_radio)
2306*5113495bSYour Name 		__wma_unified_radio_tx_mem_free(wma_handle);
2307*5113495bSYour Name 
2308*5113495bSYour Name 	if (!wma_handle->link_stats_results) {
2309*5113495bSYour Name 		wma_handle->link_stats_results = qdf_mem_malloc(
2310*5113495bSYour Name 						link_stats_results_size);
2311*5113495bSYour Name 		if (!wma_handle->link_stats_results)
2312*5113495bSYour Name 			return -ENOMEM;
2313*5113495bSYour Name 	}
2314*5113495bSYour Name 	link_stats_results = wma_handle->link_stats_results;
2315*5113495bSYour Name 	if (link_stats_results->num_radio == 0) {
2316*5113495bSYour Name 		link_stats_results->num_radio = fixed_param->num_radio;
2317*5113495bSYour Name 	} else if (link_stats_results->num_radio < fixed_param->num_radio) {
2318*5113495bSYour Name 		/*
2319*5113495bSYour Name 		 * The link stats results size allocated based on num_radio of
2320*5113495bSYour Name 		 * first event must be same as following events. Otherwise these
2321*5113495bSYour Name 		 * events may be spoofed. Drop all of them and report error.
2322*5113495bSYour Name 		 */
2323*5113495bSYour Name 		wma_err("Invalid following WMI_RADIO_LINK_STATS_EVENTID. Discarding this set");
2324*5113495bSYour Name 		return -EINVAL;
2325*5113495bSYour Name 	}
2326*5113495bSYour Name 
2327*5113495bSYour Name 	wma_debug("Radio stats Fixed Param: req_id: %u num_radio: %u more_radio_events: %u more_channels %u",
2328*5113495bSYour Name 		  fixed_param->request_id, fixed_param->num_radio,
2329*5113495bSYour Name 		  fixed_param->more_radio_events, fixed_param->more_channels);
2330*5113495bSYour Name 
2331*5113495bSYour Name 	results = (uint8_t *) link_stats_results->results;
2332*5113495bSYour Name 	t_radio_stats = (uint8_t *) radio_stats;
2333*5113495bSYour Name 	t_channel_stats = (uint8_t *) channel_stats;
2334*5113495bSYour Name 
2335*5113495bSYour Name 	rs_results = (struct wifi_radio_stats *) &results[0] + radio_stats->radio_id;
2336*5113495bSYour Name 
2337*5113495bSYour Name 	/*
2338*5113495bSYour Name 	 * If more channels is true, means this is the second event for the
2339*5113495bSYour Name 	 * same radio so no need to process radio stats again as the second
2340*5113495bSYour Name 	 * event will only contain remaining channel stats.
2341*5113495bSYour Name 	 */
2342*5113495bSYour Name 	if (!rs_results->more_channels) {
2343*5113495bSYour Name 		rs_results->radio = radio_stats->radio_id;
2344*5113495bSYour Name 		rs_results->on_time = radio_stats->on_time;
2345*5113495bSYour Name 		rs_results->tx_time = radio_stats->tx_time;
2346*5113495bSYour Name 		rs_results->rx_time = radio_stats->rx_time;
2347*5113495bSYour Name 		rs_results->on_time_scan = radio_stats->on_time_scan;
2348*5113495bSYour Name 		rs_results->on_time_nbd = radio_stats->on_time_nbd;
2349*5113495bSYour Name 		rs_results->on_time_gscan = radio_stats->on_time_gscan;
2350*5113495bSYour Name 		rs_results->on_time_roam_scan = radio_stats->on_time_roam_scan;
2351*5113495bSYour Name 		rs_results->on_time_pno_scan = radio_stats->on_time_pno_scan;
2352*5113495bSYour Name 		rs_results->on_time_hs20 = radio_stats->on_time_hs20;
2353*5113495bSYour Name 		rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
2354*5113495bSYour Name 		rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
2355*5113495bSYour Name 		if (rs_results->channels) {
2356*5113495bSYour Name 			qdf_mem_free(rs_results->channels);
2357*5113495bSYour Name 			rs_results->channels = NULL;
2358*5113495bSYour Name 		}
2359*5113495bSYour Name 	}
2360*5113495bSYour Name 
2361*5113495bSYour Name 	rs_results->total_num_tx_power_levels = 0;
2362*5113495bSYour Name 	if (rs_results->tx_time_per_power_level) {
2363*5113495bSYour Name 		qdf_mem_free(rs_results->tx_time_per_power_level);
2364*5113495bSYour Name 		rs_results->tx_time_per_power_level = NULL;
2365*5113495bSYour Name 	}
2366*5113495bSYour Name 
2367*5113495bSYour Name 	per_chan_rx_tx_time_enabled = wmi_service_enabled(
2368*5113495bSYour Name 		wma_handle->wmi_handle,
2369*5113495bSYour Name 		wmi_service_ll_stats_per_chan_rx_tx_time);
2370*5113495bSYour Name 	if (!per_chan_rx_tx_time_enabled)
2371*5113495bSYour Name 		wma_nofl_debug("LL Stats per channel tx time and rx time are not supported.");
2372*5113495bSYour Name 
2373*5113495bSYour Name 	rs_results->more_channels = fixed_param->more_channels;
2374*5113495bSYour Name 	num_chan_in_this_event = radio_stats->num_channels;
2375*5113495bSYour Name 
2376*5113495bSYour Name 	if (num_chan_in_this_event) {
2377*5113495bSYour Name 		channels_in_this_event = qdf_mem_malloc(
2378*5113495bSYour Name 					radio_stats->num_channels *
2379*5113495bSYour Name 					chan_stats_size);
2380*5113495bSYour Name 		if (!channels_in_this_event)
2381*5113495bSYour Name 			return -ENOMEM;
2382*5113495bSYour Name 
2383*5113495bSYour Name 		chn_results =
2384*5113495bSYour Name 			(struct wifi_channel_stats *)&channels_in_this_event[0];
2385*5113495bSYour Name 		next_chan_offset = WMI_TLV_HDR_SIZE;
2386*5113495bSYour Name 		wma_debug("Channel Stats Info, radio id %d, total channels %d",
2387*5113495bSYour Name 			  radio_stats->radio_id, radio_stats->num_channels);
2388*5113495bSYour Name 
2389*5113495bSYour Name 		info = qdf_mem_malloc(WMI_MAX_RADIO_STATS_LOGS);
2390*5113495bSYour Name 		if (!info) {
2391*5113495bSYour Name 			qdf_mem_free(channels_in_this_event);
2392*5113495bSYour Name 			return -ENOMEM;
2393*5113495bSYour Name 		}
2394*5113495bSYour Name 
2395*5113495bSYour Name 		for (count = 0; count < radio_stats->num_channels; count++) {
2396*5113495bSYour Name 			if (exclude_selftx_from_cca_busy &&
2397*5113495bSYour Name 			    channel_stats->cca_busy_time >=
2398*5113495bSYour Name 			    channel_stats->tx_time)
2399*5113495bSYour Name 				channel_stats->cca_busy_time -=
2400*5113495bSYour Name 						channel_stats->tx_time;
2401*5113495bSYour Name 
2402*5113495bSYour Name 			ret = qdf_scnprintf(info + stats_len,
2403*5113495bSYour Name 					WMI_MAX_RADIO_STATS_LOGS - stats_len,
2404*5113495bSYour Name 					" %d[%d][%d][%d]",
2405*5113495bSYour Name 					channel_stats->center_freq,
2406*5113495bSYour Name 					channel_stats->channel_width,
2407*5113495bSYour Name 					channel_stats->center_freq0,
2408*5113495bSYour Name 					channel_stats->center_freq1);
2409*5113495bSYour Name 			if (ret <= 0)
2410*5113495bSYour Name 				break;
2411*5113495bSYour Name 			stats_len += ret;
2412*5113495bSYour Name 
2413*5113495bSYour Name 			ret = qdf_scnprintf(info + stats_len,
2414*5113495bSYour Name 					WMI_MAX_RADIO_STATS_LOGS - stats_len,
2415*5113495bSYour Name 					"[%d][%d][%d][%d]",
2416*5113495bSYour Name 					channel_stats->radio_awake_time,
2417*5113495bSYour Name 					channel_stats->cca_busy_time,
2418*5113495bSYour Name 					channel_stats->tx_time,
2419*5113495bSYour Name 					channel_stats->rx_time);
2420*5113495bSYour Name 			if (ret <= 0)
2421*5113495bSYour Name 				break;
2422*5113495bSYour Name 			stats_len += ret;
2423*5113495bSYour Name 
2424*5113495bSYour Name 			if (stats_len >= (WMI_MAX_RADIO_STATS_LOGS -
2425*5113495bSYour Name 					WMI_MAX_RADIO_SINGLE_STATS_LEN)) {
2426*5113495bSYour Name 				wmi_nofl_debug("freq[width][freq0][freq1][awake time][cca busy time][tx time][rx time] :%s",
2427*5113495bSYour Name 					       info);
2428*5113495bSYour Name 				stats_len = 0;
2429*5113495bSYour Name 			}
2430*5113495bSYour Name 
2431*5113495bSYour Name 			channel_stats++;
2432*5113495bSYour Name 
2433*5113495bSYour Name 			qdf_mem_copy(chn_results,
2434*5113495bSYour Name 				     t_channel_stats + next_chan_offset,
2435*5113495bSYour Name 				     chan_stats_size);
2436*5113495bSYour Name 
2437*5113495bSYour Name 			chn_results++;
2438*5113495bSYour Name 			next_chan_offset += sizeof(*channel_stats);
2439*5113495bSYour Name 		}
2440*5113495bSYour Name 
2441*5113495bSYour Name 		if (stats_len)
2442*5113495bSYour Name 			wmi_nofl_debug("freq[width][freq0][freq1][awake time][cca busy time][tx time][rx time] :%s",
2443*5113495bSYour Name 				       info);
2444*5113495bSYour Name 
2445*5113495bSYour Name 		qdf_mem_free(info);
2446*5113495bSYour Name 
2447*5113495bSYour Name 		status = wma_copy_chan_stats(num_chan_in_this_event,
2448*5113495bSYour Name 					     channels_in_this_event,
2449*5113495bSYour Name 					     rs_results);
2450*5113495bSYour Name 		if (status) {
2451*5113495bSYour Name 			wma_err("Failed to copy channel stats");
2452*5113495bSYour Name 			return status;
2453*5113495bSYour Name 		}
2454*5113495bSYour Name 	}
2455*5113495bSYour Name 
2456*5113495bSYour Name link_radio_stats_cb:
2457*5113495bSYour Name 	link_stats_results->paramId = WMI_LINK_STATS_RADIO;
2458*5113495bSYour Name 	link_stats_results->rspId = fixed_param->request_id;
2459*5113495bSYour Name 	link_stats_results->ifaceId = fixed_param->vdev_id_info.vdev_id;
2460*5113495bSYour Name 	link_stats_results->peer_event_number = 0;
2461*5113495bSYour Name 
2462*5113495bSYour Name 	/*
2463*5113495bSYour Name 	 * Backward compatibility:
2464*5113495bSYour Name 	 * There are firmware(s) which will send Radio stats only with
2465*5113495bSYour Name 	 * more_radio_events set to 0 and firmware which sends Radio stats
2466*5113495bSYour Name 	 * followed by tx_power level stats with more_radio_events set to 1.
2467*5113495bSYour Name 	 * if more_radio_events is set to 1, buffer the radio stats and
2468*5113495bSYour Name 	 * wait for tx_power_level stats.
2469*5113495bSYour Name 	 */
2470*5113495bSYour Name 	link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
2471*5113495bSYour Name 
2472*5113495bSYour Name 	if ((rs_results && rs_results->more_channels) ||
2473*5113495bSYour Name 	    link_stats_results->moreResultToFollow) {
2474*5113495bSYour Name 		/* More results coming, don't post yet */
2475*5113495bSYour Name 		return 0;
2476*5113495bSYour Name 	}
2477*5113495bSYour Name 	if (link_stats_results->num_radio) {
2478*5113495bSYour Name 		link_stats_results->nr_received++;
2479*5113495bSYour Name 
2480*5113495bSYour Name 		if (link_stats_results->num_radio !=
2481*5113495bSYour Name 		    link_stats_results->nr_received) {
2482*5113495bSYour Name 			/* Not received all radio stats yet, don't post yet */
2483*5113495bSYour Name 			return 0;
2484*5113495bSYour Name 		}
2485*5113495bSYour Name 	}
2486*5113495bSYour Name 
2487*5113495bSYour Name 	mac->sme.link_layer_stats_cb(mac->hdd_handle,
2488*5113495bSYour Name 				     WMA_LINK_LAYER_STATS_RESULTS_RSP,
2489*5113495bSYour Name 				     link_stats_results,
2490*5113495bSYour Name 				     mac->sme.ll_stats_context);
2491*5113495bSYour Name 
2492*5113495bSYour Name 	return 0;
2493*5113495bSYour Name }
2494*5113495bSYour Name 
2495*5113495bSYour Name /**
2496*5113495bSYour Name  * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
2497*5113495bSYour Name  * @handle:          wma handle
2498*5113495bSYour Name  * @cmd_param_info:  data received with event from fw
2499*5113495bSYour Name  * @len:             length of data
2500*5113495bSYour Name  *
2501*5113495bSYour Name  * Return: 0 for success or error code
2502*5113495bSYour Name  */
wma_unified_link_radio_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)2503*5113495bSYour Name static int wma_unified_link_radio_stats_event_handler(void *handle,
2504*5113495bSYour Name 						      uint8_t *cmd_param_info,
2505*5113495bSYour Name 						      uint32_t len)
2506*5113495bSYour Name {
2507*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2508*5113495bSYour Name 	int ret;
2509*5113495bSYour Name 
2510*5113495bSYour Name 	qdf_mutex_acquire(&wma_handle->radio_stats_lock);
2511*5113495bSYour Name 	ret = __wma_unified_link_radio_stats_event_handler(wma_handle,
2512*5113495bSYour Name 							   cmd_param_info, len);
2513*5113495bSYour Name 	qdf_mutex_release(&wma_handle->radio_stats_lock);
2514*5113495bSYour Name 
2515*5113495bSYour Name 	return ret;
2516*5113495bSYour Name }
2517*5113495bSYour Name 
2518*5113495bSYour Name #ifdef WLAN_PEER_PS_NOTIFICATION
2519*5113495bSYour Name /**
2520*5113495bSYour Name  * wma_peer_ps_evt_handler() - handler for PEER power state change.
2521*5113495bSYour Name  * @handle: wma handle
2522*5113495bSYour Name  * @event: FW event
2523*5113495bSYour Name  * @len: length of FW event
2524*5113495bSYour Name  *
2525*5113495bSYour Name  * Once peer STA power state changes, an event will be indicated by
2526*5113495bSYour Name  * FW. This function send a link layer state change msg to HDD. HDD
2527*5113495bSYour Name  * link layer callback will converts the event to NL msg.
2528*5113495bSYour Name  *
2529*5113495bSYour Name  * Return: 0 Success. Others fail.
2530*5113495bSYour Name  */
wma_peer_ps_evt_handler(void * handle,u_int8_t * event,u_int32_t len)2531*5113495bSYour Name static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
2532*5113495bSYour Name 				   u_int32_t len)
2533*5113495bSYour Name {
2534*5113495bSYour Name 	WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
2535*5113495bSYour Name 	wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
2536*5113495bSYour Name 	struct wifi_peer_stat *peer_stat;
2537*5113495bSYour Name 	struct wifi_peer_info *peer_info;
2538*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
2539*5113495bSYour Name 	tSirMacAddr mac_address;
2540*5113495bSYour Name 	uint32_t result_len;
2541*5113495bSYour Name 	cds_msg_t sme_msg = { 0 };
2542*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
2543*5113495bSYour Name 
2544*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2545*5113495bSYour Name 
2546*5113495bSYour Name 	if (!mac) {
2547*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
2548*5113495bSYour Name 		return -EINVAL;
2549*5113495bSYour Name 	}
2550*5113495bSYour Name 
2551*5113495bSYour Name 	if (!mac->sme.link_layer_stats_ext_cb) {
2552*5113495bSYour Name 		wma_debug("HDD callback is null");
2553*5113495bSYour Name 		return -EINVAL;
2554*5113495bSYour Name 	}
2555*5113495bSYour Name 
2556*5113495bSYour Name 	wma_debug("Posting Peer Stats PS event to HDD");
2557*5113495bSYour Name 
2558*5113495bSYour Name 	param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
2559*5113495bSYour Name 	fixed_param = param_buf->fixed_param;
2560*5113495bSYour Name 
2561*5113495bSYour Name 	result_len = sizeof(tSirLLStatsResults) +
2562*5113495bSYour Name 			sizeof(struct wifi_peer_stat) +
2563*5113495bSYour Name 			sizeof(struct wifi_peer_info);
2564*5113495bSYour Name 	link_stats_results = qdf_mem_malloc(result_len);
2565*5113495bSYour Name 	if (!link_stats_results)
2566*5113495bSYour Name 		return -EINVAL;
2567*5113495bSYour Name 
2568*5113495bSYour Name 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
2569*5113495bSYour Name 	wma_debug("Peer power state change event from FW");
2570*5113495bSYour Name 	wma_debug("Fixed Param:");
2571*5113495bSYour Name 	wma_nofl_debug("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
2572*5113495bSYour Name 		 mac_address[0], mac_address[1], mac_address[2],
2573*5113495bSYour Name 		 mac_address[3], mac_address[4], mac_address[5],
2574*5113495bSYour Name 		 fixed_param->peer_ps_state);
2575*5113495bSYour Name 
2576*5113495bSYour Name 	link_stats_results->paramId            = WMI_LL_STATS_EXT_PS_CHG;
2577*5113495bSYour Name 	link_stats_results->num_peers          = 1;
2578*5113495bSYour Name 	link_stats_results->peer_event_number  = 1;
2579*5113495bSYour Name 	link_stats_results->moreResultToFollow = 0;
2580*5113495bSYour Name 
2581*5113495bSYour Name 	peer_stat = (struct wifi_peer_stat *)link_stats_results->results;
2582*5113495bSYour Name 	peer_stat->num_peers = 1;
2583*5113495bSYour Name 	peer_info = (struct wifi_peer_info *)peer_stat->peer_info;
2584*5113495bSYour Name 	qdf_mem_copy(&peer_info->peer_macaddr,
2585*5113495bSYour Name 		     &mac_address,
2586*5113495bSYour Name 		     sizeof(tSirMacAddr));
2587*5113495bSYour Name 	peer_info->power_saving = fixed_param->peer_ps_state;
2588*5113495bSYour Name 
2589*5113495bSYour Name 	sme_msg.type = eWMI_SME_LL_STATS_IND;
2590*5113495bSYour Name 	sme_msg.bodyptr = link_stats_results;
2591*5113495bSYour Name 	sme_msg.bodyval = 0;
2592*5113495bSYour Name 
2593*5113495bSYour Name 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
2594*5113495bSYour Name 					    QDF_MODULE_ID_SME,
2595*5113495bSYour Name 					    QDF_MODULE_ID_SME, &sme_msg);
2596*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2597*5113495bSYour Name 		wma_err("Fail to post ps change ind msg");
2598*5113495bSYour Name 		qdf_mem_free(link_stats_results);
2599*5113495bSYour Name 	}
2600*5113495bSYour Name 
2601*5113495bSYour Name 	return 0;
2602*5113495bSYour Name }
2603*5113495bSYour Name #else
2604*5113495bSYour Name /**
2605*5113495bSYour Name  * wma_peer_ps_evt_handler() - handler for PEER power state change.
2606*5113495bSYour Name  * @handle: wma handle
2607*5113495bSYour Name  * @event: FW event
2608*5113495bSYour Name  * @len: length of FW event
2609*5113495bSYour Name  *
2610*5113495bSYour Name  * Once peer STA power state changes, an event will be indicated by
2611*5113495bSYour Name  * FW. This function send a link layer state change msg to HDD. HDD
2612*5113495bSYour Name  * link layer callback will converts the event to NL msg.
2613*5113495bSYour Name  *
2614*5113495bSYour Name  * Return: 0 Success. Others fail.
2615*5113495bSYour Name  */
wma_peer_ps_evt_handler(void * handle,u_int8_t * event,u_int32_t len)2616*5113495bSYour Name static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
2617*5113495bSYour Name 					  u_int32_t len)
2618*5113495bSYour Name {
2619*5113495bSYour Name 	return 0;
2620*5113495bSYour Name }
2621*5113495bSYour Name #endif
2622*5113495bSYour Name 
2623*5113495bSYour Name /**
2624*5113495bSYour Name  * wma_register_ll_stats_event_handler() - register link layer stats related
2625*5113495bSYour Name  *                                         event handler
2626*5113495bSYour Name  * @wma_handle: wma handle
2627*5113495bSYour Name  *
2628*5113495bSYour Name  * Return: none
2629*5113495bSYour Name  */
wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)2630*5113495bSYour Name void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
2631*5113495bSYour Name {
2632*5113495bSYour Name 	if (wma_validate_handle(wma_handle))
2633*5113495bSYour Name 		return;
2634*5113495bSYour Name 
2635*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2636*5113495bSYour Name 				wmi_iface_link_stats_event_id,
2637*5113495bSYour Name 				wma_unified_link_iface_stats_event_handler,
2638*5113495bSYour Name 				WMA_RX_WORK_CTX);
2639*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2640*5113495bSYour Name 				wmi_peer_link_stats_event_id,
2641*5113495bSYour Name 				wma_unified_link_peer_stats_event_handler,
2642*5113495bSYour Name 				WMA_RX_WORK_CTX);
2643*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2644*5113495bSYour Name 				wmi_radio_link_stats_link,
2645*5113495bSYour Name 				wma_unified_link_radio_stats_event_handler,
2646*5113495bSYour Name 				WMA_RX_WORK_CTX);
2647*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2648*5113495bSYour Name 			wmi_radio_tx_power_level_stats_event_id,
2649*5113495bSYour Name 			wma_unified_radio_tx_power_level_stats_event_handler,
2650*5113495bSYour Name 			WMA_RX_WORK_CTX);
2651*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2652*5113495bSYour Name 					   wmi_peer_sta_ps_statechg_event_id,
2653*5113495bSYour Name 					   wma_peer_ps_evt_handler,
2654*5113495bSYour Name 					   WMA_RX_WORK_CTX);
2655*5113495bSYour Name 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
2656*5113495bSYour Name 					   wmi_report_stats_event_id,
2657*5113495bSYour Name 					   wma_ll_stats_evt_handler,
2658*5113495bSYour Name 					   WMA_RX_WORK_CTX);
2659*5113495bSYour Name 
2660*5113495bSYour Name }
2661*5113495bSYour Name 
wma_process_ll_stats_clear_req(tp_wma_handle wma,const tpSirLLStatsClearReq clearReq)2662*5113495bSYour Name QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
2663*5113495bSYour Name 				 const tpSirLLStatsClearReq clearReq)
2664*5113495bSYour Name {
2665*5113495bSYour Name 	uint8_t *addr;
2666*5113495bSYour Name 	struct ll_stats_clear_params cmd = {0};
2667*5113495bSYour Name 	int ret;
2668*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2669*5113495bSYour Name 
2670*5113495bSYour Name 	if (!clearReq || !wma) {
2671*5113495bSYour Name 		wma_err("input pointer is NULL");
2672*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2673*5113495bSYour Name 	}
2674*5113495bSYour Name 
2675*5113495bSYour Name 	vdev = wma->interfaces[clearReq->staId].vdev;
2676*5113495bSYour Name 	if (!vdev) {
2677*5113495bSYour Name 		wma_err("vdev is NULL for vdev_%d", clearReq->staId);
2678*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2679*5113495bSYour Name 	}
2680*5113495bSYour Name 
2681*5113495bSYour Name 	cmd.stop_req = clearReq->stopReq;
2682*5113495bSYour Name 	cmd.vdev_id = clearReq->staId;
2683*5113495bSYour Name 	cmd.stats_clear_mask = clearReq->statsClearReqMask;
2684*5113495bSYour Name 
2685*5113495bSYour Name 	vdev = wma->interfaces[clearReq->staId].vdev;
2686*5113495bSYour Name 	if (!vdev) {
2687*5113495bSYour Name 		wma_err("Failed to get vdev for vdev_%d", clearReq->staId);
2688*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2689*5113495bSYour Name 	}
2690*5113495bSYour Name 	addr = wlan_vdev_mlme_get_macaddr(vdev);
2691*5113495bSYour Name 	if (!addr) {
2692*5113495bSYour Name 		wma_err("Failed to get macaddr for vdev_%d", clearReq->staId);
2693*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2694*5113495bSYour Name 	}
2695*5113495bSYour Name 	qdf_mem_copy(cmd.peer_macaddr.bytes, addr, QDF_MAC_ADDR_SIZE);
2696*5113495bSYour Name 	ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd);
2697*5113495bSYour Name 	if (ret) {
2698*5113495bSYour Name 		wma_err("Failed to send clear link stats req");
2699*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2700*5113495bSYour Name 	}
2701*5113495bSYour Name 
2702*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2703*5113495bSYour Name }
2704*5113495bSYour Name 
2705*5113495bSYour Name /**
2706*5113495bSYour Name  * wma_process_ll_stats_set_req() - link layer stats set request
2707*5113495bSYour Name  * @wma:       wma handle
2708*5113495bSYour Name  * @setReq:  ll stats set request command params
2709*5113495bSYour Name  *
2710*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS for success or error code
2711*5113495bSYour Name  */
wma_process_ll_stats_set_req(tp_wma_handle wma,const tpSirLLStatsSetReq setReq)2712*5113495bSYour Name QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
2713*5113495bSYour Name 				 const tpSirLLStatsSetReq setReq)
2714*5113495bSYour Name {
2715*5113495bSYour Name 	struct ll_stats_set_params cmd = {0};
2716*5113495bSYour Name 	int ret;
2717*5113495bSYour Name 
2718*5113495bSYour Name 	if (!setReq || !wma) {
2719*5113495bSYour Name 		wma_err("input pointer is NULL");
2720*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2721*5113495bSYour Name 	}
2722*5113495bSYour Name 
2723*5113495bSYour Name 	cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
2724*5113495bSYour Name 	cmd.aggressive_statistics_gathering =
2725*5113495bSYour Name 		setReq->aggressiveStatisticsGathering;
2726*5113495bSYour Name 
2727*5113495bSYour Name 	ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
2728*5113495bSYour Name 					 &cmd);
2729*5113495bSYour Name 	if (ret) {
2730*5113495bSYour Name 		wma_err("Failed to send set link stats request");
2731*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2732*5113495bSYour Name 	}
2733*5113495bSYour Name 
2734*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2735*5113495bSYour Name }
2736*5113495bSYour Name 
2737*5113495bSYour Name #ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION
2738*5113495bSYour Name static QDF_STATUS
wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle,struct ll_stats_get_params * cmd)2739*5113495bSYour Name wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle,
2740*5113495bSYour Name 			  struct ll_stats_get_params *cmd)
2741*5113495bSYour Name {
2742*5113495bSYour Name 	if (!(cfg_get(wma_handle->psoc, CFG_CLUB_LL_STA_AND_GET_STATION) &&
2743*5113495bSYour Name 	      wmi_service_enabled(wma_handle->wmi_handle,
2744*5113495bSYour Name 				  wmi_service_get_station_in_ll_stats_req) &&
2745*5113495bSYour Name 	      wma_handle->interfaces[cmd->vdev_id].type == WMI_VDEV_TYPE_STA))
2746*5113495bSYour Name 		return wmi_unified_process_ll_stats_get_cmd(
2747*5113495bSYour Name 						wma_handle->wmi_handle, cmd);
2748*5113495bSYour Name 
2749*5113495bSYour Name 	return wmi_process_unified_ll_stats_get_sta_cmd(wma_handle->wmi_handle,
2750*5113495bSYour Name 							cmd);
2751*5113495bSYour Name }
2752*5113495bSYour Name #else
2753*5113495bSYour Name static QDF_STATUS
wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle,struct ll_stats_get_params * cmd)2754*5113495bSYour Name wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle,
2755*5113495bSYour Name 			  struct ll_stats_get_params *cmd)
2756*5113495bSYour Name {
2757*5113495bSYour Name 	return wmi_unified_process_ll_stats_get_cmd(wma_handle->wmi_handle,
2758*5113495bSYour Name 						    cmd);
2759*5113495bSYour Name }
2760*5113495bSYour Name #endif
2761*5113495bSYour Name 
2762*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO
2763*5113495bSYour Name static QDF_STATUS
wma_update_params_for_mlo_stats(tp_wma_handle wma,const tpSirLLStatsGetReq getReq,struct ll_stats_get_params * cmd)2764*5113495bSYour Name wma_update_params_for_mlo_stats(tp_wma_handle wma,
2765*5113495bSYour Name 				const tpSirLLStatsGetReq getReq,
2766*5113495bSYour Name 				struct ll_stats_get_params *cmd)
2767*5113495bSYour Name {
2768*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2769*5113495bSYour Name 	uint8_t *mld_addr;
2770*5113495bSYour Name 
2771*5113495bSYour Name 	cmd->is_mlo_req = getReq->is_mlo_req;
2772*5113495bSYour Name 
2773*5113495bSYour Name 	vdev = wma->interfaces[getReq->staId].vdev;
2774*5113495bSYour Name 	if (!vdev) {
2775*5113495bSYour Name 		wma_err("Failed to get vdev for vdev_%d", getReq->staId);
2776*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2777*5113495bSYour Name 	}
2778*5113495bSYour Name 	if (getReq->is_mlo_req) {
2779*5113495bSYour Name 		cmd->vdev_id_bitmap = getReq->mlo_vdev_id_bitmap;
2780*5113495bSYour Name 		mld_addr = wlan_vdev_mlme_get_mldaddr(vdev);
2781*5113495bSYour Name 		if (!mld_addr) {
2782*5113495bSYour Name 			wma_err("Failed to get mld_macaddr for vdev_%d",
2783*5113495bSYour Name 				getReq->staId);
2784*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
2785*5113495bSYour Name 		}
2786*5113495bSYour Name 		qdf_mem_copy(cmd->mld_macaddr.bytes, mld_addr,
2787*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
2788*5113495bSYour Name 	}
2789*5113495bSYour Name 
2790*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2791*5113495bSYour Name }
2792*5113495bSYour Name #else
2793*5113495bSYour Name static QDF_STATUS
wma_update_params_for_mlo_stats(tp_wma_handle wma,const tpSirLLStatsGetReq getReq,struct ll_stats_get_params * cmd)2794*5113495bSYour Name wma_update_params_for_mlo_stats(tp_wma_handle wma,
2795*5113495bSYour Name 				const tpSirLLStatsGetReq getReq,
2796*5113495bSYour Name 				struct ll_stats_get_params *cmd)
2797*5113495bSYour Name {
2798*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2799*5113495bSYour Name }
2800*5113495bSYour Name #endif
2801*5113495bSYour Name 
wma_process_ll_stats_get_req(tp_wma_handle wma,const tpSirLLStatsGetReq getReq)2802*5113495bSYour Name QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
2803*5113495bSYour Name 				 const tpSirLLStatsGetReq getReq)
2804*5113495bSYour Name {
2805*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2806*5113495bSYour Name 	uint8_t *addr;
2807*5113495bSYour Name 	struct ll_stats_get_params cmd = {0};
2808*5113495bSYour Name 	int ret;
2809*5113495bSYour Name 	QDF_STATUS status;
2810*5113495bSYour Name 
2811*5113495bSYour Name 	if (!getReq || !wma) {
2812*5113495bSYour Name 		wma_err("input pointer is NULL");
2813*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2814*5113495bSYour Name 	}
2815*5113495bSYour Name 
2816*5113495bSYour Name 	if (!wma_is_vdev_valid(getReq->staId)) {
2817*5113495bSYour Name 		wma_err("vdev:%d not created yet", getReq->staId);
2818*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2819*5113495bSYour Name 	}
2820*5113495bSYour Name 
2821*5113495bSYour Name 	cmd.req_id = getReq->reqId;
2822*5113495bSYour Name 	cmd.param_id_mask = getReq->paramIdMask;
2823*5113495bSYour Name 	cmd.vdev_id = getReq->staId;
2824*5113495bSYour Name 
2825*5113495bSYour Name 	vdev = wma->interfaces[getReq->staId].vdev;
2826*5113495bSYour Name 	if (!vdev) {
2827*5113495bSYour Name 		wma_err("Failed to get vdev for vdev_%d", getReq->staId);
2828*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2829*5113495bSYour Name 	}
2830*5113495bSYour Name 	addr = wlan_vdev_mlme_get_macaddr(vdev);
2831*5113495bSYour Name 	if (!addr) {
2832*5113495bSYour Name 		wma_err("Failed to get macaddr for vdev_%d", getReq->staId);
2833*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2834*5113495bSYour Name 	}
2835*5113495bSYour Name 	qdf_mem_copy(cmd.peer_macaddr.bytes, addr, QDF_MAC_ADDR_SIZE);
2836*5113495bSYour Name 
2837*5113495bSYour Name 	if (getReq->mlo_vdev_id_bitmap) {
2838*5113495bSYour Name 		status = wma_update_params_for_mlo_stats(wma, getReq, &cmd);
2839*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2840*5113495bSYour Name 			wma_err("Failed to update params for mlo_stats");
2841*5113495bSYour Name 			return status;
2842*5113495bSYour Name 		}
2843*5113495bSYour Name 	}
2844*5113495bSYour Name 
2845*5113495bSYour Name 	ret = wma_send_ll_stats_get_cmd(wma, &cmd);
2846*5113495bSYour Name 	if (ret) {
2847*5113495bSYour Name 		wma_err("Failed to send get link stats request");
2848*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2849*5113495bSYour Name 	}
2850*5113495bSYour Name 
2851*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2852*5113495bSYour Name }
2853*5113495bSYour Name 
2854*5113495bSYour Name /**
2855*5113495bSYour Name  * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
2856*5113495bSYour Name  * @handle: wma handle
2857*5113495bSYour Name  * @cmd_param_info: data from event
2858*5113495bSYour Name  * @len: length
2859*5113495bSYour Name  *
2860*5113495bSYour Name  * Return: 0 for success or error code
2861*5113495bSYour Name  */
wma_unified_link_iface_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)2862*5113495bSYour Name int wma_unified_link_iface_stats_event_handler(void *handle,
2863*5113495bSYour Name 					       uint8_t *cmd_param_info,
2864*5113495bSYour Name 					       uint32_t len)
2865*5113495bSYour Name {
2866*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
2867*5113495bSYour Name 	WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
2868*5113495bSYour Name 	wmi_iface_link_stats_event_fixed_param *fixed_param;
2869*5113495bSYour Name 	wmi_iface_link_stats *link_stats, *iface_link_stats;
2870*5113495bSYour Name 	wmi_wmm_ac_stats *ac_stats, *iface_ac_stats;
2871*5113495bSYour Name 	wmi_iface_offload_stats *offload_stats, *iface_offload_stats;
2872*5113495bSYour Name 	wmi_iface_powersave_stats *powersave_stats;
2873*5113495bSYour Name 	tSirLLStatsResults *link_stats_results;
2874*5113495bSYour Name 	struct wifi_interface_stats *iface_stat;
2875*5113495bSYour Name 	uint32_t count;
2876*5113495bSYour Name 	size_t link_stats_size, ac_stats_size, iface_info_size;
2877*5113495bSYour Name 	size_t link_stats_results_size, offload_stats_size;
2878*5113495bSYour Name 	size_t total_ac_size, total_offload_size;
2879*5113495bSYour Name 	bool db2dbm_enabled;
2880*5113495bSYour Name 
2881*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2882*5113495bSYour Name 
2883*5113495bSYour Name 	if (!mac) {
2884*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
2885*5113495bSYour Name 		return -EINVAL;
2886*5113495bSYour Name 	}
2887*5113495bSYour Name 
2888*5113495bSYour Name 	if (!mac->sme.link_layer_stats_cb) {
2889*5113495bSYour Name 		wma_debug("HDD callback is null");
2890*5113495bSYour Name 		return -EINVAL;
2891*5113495bSYour Name 	}
2892*5113495bSYour Name 
2893*5113495bSYour Name 	param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
2894*5113495bSYour Name 	if (!param_tlvs) {
2895*5113495bSYour Name 		wma_err("Invalid stats event");
2896*5113495bSYour Name 		return -EINVAL;
2897*5113495bSYour Name 	}
2898*5113495bSYour Name 
2899*5113495bSYour Name 	/*
2900*5113495bSYour Name 	 * cmd_param_info contains
2901*5113495bSYour Name 	 * wmi_iface_link_stats_event_fixed_param fixed_param;
2902*5113495bSYour Name 	 * wmi_iface_link_stats iface_link_stats;
2903*5113495bSYour Name 	 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
2904*5113495bSYour Name 	 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
2905*5113495bSYour Name 	 */
2906*5113495bSYour Name 	fixed_param = param_tlvs->fixed_param;
2907*5113495bSYour Name 	link_stats = param_tlvs->iface_link_stats;
2908*5113495bSYour Name 	ac_stats = param_tlvs->ac;
2909*5113495bSYour Name 	offload_stats = param_tlvs->iface_offload_stats;
2910*5113495bSYour Name 
2911*5113495bSYour Name 	if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2912*5113495bSYour Name 	    (fixed_param->num_offload_stats && !offload_stats)) {
2913*5113495bSYour Name 		wma_err("Invalid param_tlvs for Iface Stats");
2914*5113495bSYour Name 		return -EINVAL;
2915*5113495bSYour Name 	}
2916*5113495bSYour Name 	if (link_stats->num_ac > WIFI_AC_MAX || link_stats->num_ac >
2917*5113495bSYour Name 	    param_tlvs->num_ac) {
2918*5113495bSYour Name 		wma_err("Excess data received from firmware num_ac %d, param_tlvs->num_ac %d",
2919*5113495bSYour Name 			link_stats->num_ac, param_tlvs->num_ac);
2920*5113495bSYour Name 		return -EINVAL;
2921*5113495bSYour Name 	}
2922*5113495bSYour Name 	if (fixed_param->num_offload_stats > WMI_OFFLOAD_STATS_TYPE_MAX ||
2923*5113495bSYour Name 	    fixed_param->num_offload_stats >
2924*5113495bSYour Name 	    param_tlvs->num_iface_offload_stats) {
2925*5113495bSYour Name 		wma_err("Excess num offload stats recvd from fw: %d, um_iface_offload_stats: %d",
2926*5113495bSYour Name 			fixed_param->num_offload_stats,
2927*5113495bSYour Name 			param_tlvs->num_iface_offload_stats);
2928*5113495bSYour Name 		return -EINVAL;
2929*5113495bSYour Name 	}
2930*5113495bSYour Name 
2931*5113495bSYour Name 	link_stats_size = sizeof(struct wifi_interface_stats);
2932*5113495bSYour Name 	iface_info_size = sizeof(struct wifi_interface_info);
2933*5113495bSYour Name 
2934*5113495bSYour Name 	ac_stats_size = sizeof(wmi_wmm_ac_stats);
2935*5113495bSYour Name 	offload_stats_size = sizeof(wmi_iface_offload_stats);
2936*5113495bSYour Name 
2937*5113495bSYour Name 	total_ac_size = ac_stats_size * WIFI_AC_MAX;
2938*5113495bSYour Name 	total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2939*5113495bSYour Name 			      member_size(struct wifi_interface_stats,
2940*5113495bSYour Name 					  num_offload_stats);
2941*5113495bSYour Name 
2942*5113495bSYour Name 	link_stats_results_size = sizeof(*link_stats_results) +	link_stats_size;
2943*5113495bSYour Name 
2944*5113495bSYour Name 	link_stats_results = qdf_mem_malloc(link_stats_results_size);
2945*5113495bSYour Name 	if (!link_stats_results)
2946*5113495bSYour Name 		return -ENOMEM;
2947*5113495bSYour Name 
2948*5113495bSYour Name 	qdf_mem_zero(link_stats_results, link_stats_results_size);
2949*5113495bSYour Name 
2950*5113495bSYour Name 	link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2951*5113495bSYour Name 	link_stats_results->rspId = fixed_param->request_id;
2952*5113495bSYour Name 	link_stats_results->ifaceId = fixed_param->vdev_id;
2953*5113495bSYour Name 	link_stats_results->num_peers = link_stats->num_peers;
2954*5113495bSYour Name 	link_stats_results->peer_event_number = 0;
2955*5113495bSYour Name 	link_stats_results->moreResultToFollow = 0;
2956*5113495bSYour Name 
2957*5113495bSYour Name 	/* results is copied to struct wifi_interface_stats in upper layer
2958*5113495bSYour Name 	 *   struct wifi_interface_stats
2959*5113495bSYour Name 	 *    - struct wifi_interface_info (all fields except roaming is
2960*5113495bSYour Name 	 *                             filled by host in the upper layer)
2961*5113495bSYour Name 	 *    - various members of struct wifi_interface_stats (from
2962*5113495bSYour Name 	 *                             wmi_iface_link_stats)
2963*5113495bSYour Name 	 *    - ACs information (from wmi_wmm_ac_stats)
2964*5113495bSYour Name 	 *    - num_offload_stats (from fixed param)
2965*5113495bSYour Name 	 *    - offload stats (from wmi_iface_offload_stats)
2966*5113495bSYour Name 	 */
2967*5113495bSYour Name 
2968*5113495bSYour Name 	iface_stat = (struct wifi_interface_stats *)link_stats_results->results;
2969*5113495bSYour Name 
2970*5113495bSYour Name 	iface_link_stats = &iface_stat->link_stats;
2971*5113495bSYour Name 	*iface_link_stats = *link_stats;
2972*5113495bSYour Name 	db2dbm_enabled = wmi_service_enabled(wma_handle->wmi_handle,
2973*5113495bSYour Name 					     wmi_service_hw_db2dbm_support);
2974*5113495bSYour Name 	if (!db2dbm_enabled) {
2975*5113495bSYour Name 		/* FW doesn't indicate support for HW db2dbm conversion */
2976*5113495bSYour Name 		iface_link_stats->rssi_mgmt += WMA_TGT_NOISE_FLOOR_DBM;
2977*5113495bSYour Name 		iface_link_stats->rssi_data += WMA_TGT_NOISE_FLOOR_DBM;
2978*5113495bSYour Name 		iface_link_stats->rssi_ack += WMA_TGT_NOISE_FLOOR_DBM;
2979*5113495bSYour Name 	}
2980*5113495bSYour Name 
2981*5113495bSYour Name 	/* Copy roaming state */
2982*5113495bSYour Name 	iface_stat->info.roaming = link_stats->roam_state;
2983*5113495bSYour Name 	/* Copy time slicing duty cycle */
2984*5113495bSYour Name 	iface_stat->info.time_slice_duty_cycle =
2985*5113495bSYour Name 		link_stats->time_slice_duty_cycle;
2986*5113495bSYour Name 
2987*5113495bSYour Name 	wma_debug("db2dbm: %d, rssi_mgmt: %d, rssi_data: %d, rssi_ack: %d, beacon_rx %u, time_slice_duty_cycle %u",
2988*5113495bSYour Name 		  db2dbm_enabled, iface_link_stats->rssi_mgmt,
2989*5113495bSYour Name 		  iface_link_stats->rssi_data, iface_link_stats->rssi_ack,
2990*5113495bSYour Name 		  iface_link_stats->beacon_rx,
2991*5113495bSYour Name 		  iface_stat->info.time_slice_duty_cycle);
2992*5113495bSYour Name 
2993*5113495bSYour Name 	iface_ac_stats = &iface_stat->ac_stats[0];
2994*5113495bSYour Name 	for (count = 0; count < link_stats->num_ac; count++) {
2995*5113495bSYour Name 		*iface_ac_stats = *ac_stats;
2996*5113495bSYour Name 		ac_stats++;
2997*5113495bSYour Name 		iface_ac_stats++;
2998*5113495bSYour Name 	}
2999*5113495bSYour Name 
3000*5113495bSYour Name 	/* Copy wmi_iface_offload_stats to wifi_iface_offload_stat */
3001*5113495bSYour Name 	iface_stat->num_offload_stats = fixed_param->num_offload_stats;
3002*5113495bSYour Name 	iface_offload_stats = &iface_stat->offload_stats[0];
3003*5113495bSYour Name 	for (count = 0; count < fixed_param->num_offload_stats; count++) {
3004*5113495bSYour Name 		*iface_offload_stats = *offload_stats;
3005*5113495bSYour Name 		offload_stats++;
3006*5113495bSYour Name 		iface_offload_stats++;
3007*5113495bSYour Name 	}
3008*5113495bSYour Name 
3009*5113495bSYour Name 	powersave_stats = param_tlvs->iface_powersave_stats;
3010*5113495bSYour Name 	if (powersave_stats)
3011*5113495bSYour Name 		iface_stat->powersave_stats = *powersave_stats;
3012*5113495bSYour Name 
3013*5113495bSYour Name 	/* Copying vdev_id info into the iface_stat for MLO*/
3014*5113495bSYour Name 	iface_stat->vdev_id = fixed_param->vdev_id;
3015*5113495bSYour Name 
3016*5113495bSYour Name 	/* call hdd callback with Link Layer Statistics
3017*5113495bSYour Name 	 * vdev_id/ifacId in link_stats_results will be
3018*5113495bSYour Name 	 * used to retrieve the correct HDD context
3019*5113495bSYour Name 	 */
3020*5113495bSYour Name 	mac->sme.link_layer_stats_cb(mac->hdd_handle,
3021*5113495bSYour Name 				     WMA_LINK_LAYER_STATS_RESULTS_RSP,
3022*5113495bSYour Name 				     link_stats_results,
3023*5113495bSYour Name 				     mac->sme.ll_stats_context);
3024*5113495bSYour Name 	qdf_mem_free(link_stats_results);
3025*5113495bSYour Name 
3026*5113495bSYour Name 	return 0;
3027*5113495bSYour Name }
3028*5113495bSYour Name 
3029*5113495bSYour Name /**
3030*5113495bSYour Name  * wma_config_stats_ext_threshold - set threthold for MAC counters
3031*5113495bSYour Name  * @wma: wma handler
3032*5113495bSYour Name  * @thresh: threshold for MAC counters
3033*5113495bSYour Name  *
3034*5113495bSYour Name  * For each MAC layer counter, FW holds two copies. One is the current value.
3035*5113495bSYour Name  * The other is the last report. Once a current counter's increment is larger
3036*5113495bSYour Name  * than the threshold, FW will indicate that counter to host even if the
3037*5113495bSYour Name  * monitoring timer does not expire.
3038*5113495bSYour Name  *
3039*5113495bSYour Name  * Return: None
3040*5113495bSYour Name  */
wma_config_stats_ext_threshold(tp_wma_handle wma,struct sir_ll_ext_stats_threshold * thresh)3041*5113495bSYour Name void wma_config_stats_ext_threshold(tp_wma_handle wma,
3042*5113495bSYour Name 				    struct sir_ll_ext_stats_threshold *thresh)
3043*5113495bSYour Name {
3044*5113495bSYour Name 	QDF_STATUS status;
3045*5113495bSYour Name 	uint32_t len, tag, hdr_len;
3046*5113495bSYour Name 	uint8_t *buf_ptr;
3047*5113495bSYour Name 	wmi_buf_t buf;
3048*5113495bSYour Name 	wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
3049*5113495bSYour Name 	wmi_chan_cca_stats_thresh *cca;
3050*5113495bSYour Name 	wmi_peer_signal_stats_thresh *signal;
3051*5113495bSYour Name 	wmi_tx_stats_thresh *tx;
3052*5113495bSYour Name 	wmi_rx_stats_thresh *rx;
3053*5113495bSYour Name 
3054*5113495bSYour Name 	if (!thresh) {
3055*5113495bSYour Name 		wma_err("Invalid threshold input");
3056*5113495bSYour Name 		return;
3057*5113495bSYour Name 	}
3058*5113495bSYour Name 
3059*5113495bSYour Name 	len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
3060*5113495bSYour Name 	      sizeof(wmi_chan_cca_stats_thresh) +
3061*5113495bSYour Name 	      sizeof(wmi_peer_signal_stats_thresh) +
3062*5113495bSYour Name 	      sizeof(wmi_tx_stats_thresh) +
3063*5113495bSYour Name 	      sizeof(wmi_rx_stats_thresh) +
3064*5113495bSYour Name 	      5 * WMI_TLV_HDR_SIZE;
3065*5113495bSYour Name 	buf = wmi_buf_alloc(wma->wmi_handle, len);
3066*5113495bSYour Name 	if (!buf)
3067*5113495bSYour Name 		return;
3068*5113495bSYour Name 
3069*5113495bSYour Name 	buf_ptr = (u_int8_t *)wmi_buf_data(buf);
3070*5113495bSYour Name 	tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
3071*5113495bSYour Name 	hdr_len = WMITLV_GET_STRUCT_TLVLEN(
3072*5113495bSYour Name 			wmi_pdev_set_stats_threshold_cmd_fixed_param);
3073*5113495bSYour Name 	wma_debug("Setting fixed parameters. tag=%d, len=%d", tag, hdr_len);
3074*5113495bSYour Name 	cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
3075*5113495bSYour Name 	WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
3076*5113495bSYour Name 	cmd->enable_thresh = thresh->enable;
3077*5113495bSYour Name 	cmd->use_thresh_bitmap = thresh->enable_bitmap;
3078*5113495bSYour Name 	cmd->gbl_thresh = thresh->global_threshold;
3079*5113495bSYour Name 	cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
3080*5113495bSYour Name 	cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
3081*5113495bSYour Name 	cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
3082*5113495bSYour Name 	cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
3083*5113495bSYour Name 	len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
3084*5113495bSYour Name 
3085*5113495bSYour Name 	tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
3086*5113495bSYour Name 	hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
3087*5113495bSYour Name 	cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
3088*5113495bSYour Name 	WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
3089*5113495bSYour Name 	wma_debug("Setting cca parameters. tag=%d, len=%d", tag, hdr_len);
3090*5113495bSYour Name 	cca->idle_time = thresh->cca.idle_time;
3091*5113495bSYour Name 	cca->tx_time = thresh->cca.tx_time;
3092*5113495bSYour Name 	cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
3093*5113495bSYour Name 	cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
3094*5113495bSYour Name 	cca->rx_busy_time = thresh->cca.rx_busy_time;
3095*5113495bSYour Name 	cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
3096*5113495bSYour Name 	cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
3097*5113495bSYour Name 	cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
3098*5113495bSYour Name 	wma_debug("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d",
3099*5113495bSYour Name 		 cca->idle_time, cca->tx_time,
3100*5113495bSYour Name 		 cca->rx_in_bss_time, cca->rx_out_bss_time);
3101*5113495bSYour Name 	wma_debug("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d",
3102*5113495bSYour Name 		 cca->rx_busy_time, cca->rx_in_bad_cond_time,
3103*5113495bSYour Name 		 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
3104*5113495bSYour Name 	len += sizeof(wmi_chan_cca_stats_thresh);
3105*5113495bSYour Name 
3106*5113495bSYour Name 	signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
3107*5113495bSYour Name 	tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
3108*5113495bSYour Name 	hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
3109*5113495bSYour Name 	wma_debug("Setting signal parameters. tag=%d, len=%d", tag, hdr_len);
3110*5113495bSYour Name 	WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
3111*5113495bSYour Name 	signal->per_chain_snr = thresh->signal.snr;
3112*5113495bSYour Name 	signal->per_chain_nf = thresh->signal.nf;
3113*5113495bSYour Name 	wma_debug("snr=%d, nf=%d", signal->per_chain_snr,
3114*5113495bSYour Name 		 signal->per_chain_nf);
3115*5113495bSYour Name 	len += sizeof(wmi_peer_signal_stats_thresh);
3116*5113495bSYour Name 
3117*5113495bSYour Name 	tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
3118*5113495bSYour Name 	tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
3119*5113495bSYour Name 	hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
3120*5113495bSYour Name 	wma_debug("Setting TX parameters. tag=%d, len=%d", tag, len);
3121*5113495bSYour Name 	WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
3122*5113495bSYour Name 	tx->tx_msdu_cnt = thresh->tx.msdu;
3123*5113495bSYour Name 	tx->tx_mpdu_cnt = thresh->tx.mpdu;
3124*5113495bSYour Name 	tx->tx_ppdu_cnt = thresh->tx.ppdu;
3125*5113495bSYour Name 	tx->tx_bytes = thresh->tx.bytes;
3126*5113495bSYour Name 	tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
3127*5113495bSYour Name 	tx->tx_drop_bytes = thresh->tx.byte_drop;
3128*5113495bSYour Name 	tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
3129*5113495bSYour Name 	tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
3130*5113495bSYour Name 	tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
3131*5113495bSYour Name 	tx->tx_mpdu_aggr = thresh->tx.aggregation;
3132*5113495bSYour Name 	tx->tx_succ_mcs = thresh->tx.succ_mcs;
3133*5113495bSYour Name 	tx->tx_fail_mcs = thresh->tx.fail_mcs;
3134*5113495bSYour Name 	tx->tx_ppdu_delay = thresh->tx.delay;
3135*5113495bSYour Name 	wma_debug("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d",
3136*5113495bSYour Name 		 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
3137*5113495bSYour Name 		 tx->tx_bytes, tx->tx_msdu_drop_cnt);
3138*5113495bSYour Name 	wma_debug("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d",
3139*5113495bSYour Name 		 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
3140*5113495bSYour Name 		 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
3141*5113495bSYour Name 	wma_debug("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d",
3142*5113495bSYour Name 		 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
3143*5113495bSYour Name 		 tx->tx_ppdu_delay);
3144*5113495bSYour Name 	len += sizeof(wmi_tx_stats_thresh);
3145*5113495bSYour Name 
3146*5113495bSYour Name 	rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
3147*5113495bSYour Name 	tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
3148*5113495bSYour Name 	hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
3149*5113495bSYour Name 	WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
3150*5113495bSYour Name 	wma_debug("Setting RX parameters. tag=%d, len=%d", tag, hdr_len);
3151*5113495bSYour Name 	rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
3152*5113495bSYour Name 	rx->mac_rx_bytes = thresh->rx.bytes;
3153*5113495bSYour Name 	rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
3154*5113495bSYour Name 	rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
3155*5113495bSYour Name 	rx->rx_disorder_cnt = thresh->rx.disorder;
3156*5113495bSYour Name 	rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
3157*5113495bSYour Name 	rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
3158*5113495bSYour Name 	rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
3159*5113495bSYour Name 	rx->rx_mpdu_aggr = thresh->rx.aggregation;
3160*5113495bSYour Name 	rx->rx_mcs = thresh->rx.mcs;
3161*5113495bSYour Name 	rx->sta_ps_inds = thresh->rx.ps_inds;
3162*5113495bSYour Name 	rx->sta_ps_durs = thresh->rx.ps_durs;
3163*5113495bSYour Name 	rx->rx_probe_reqs = thresh->rx.probe_reqs;
3164*5113495bSYour Name 	rx->rx_oth_mgmts = thresh->rx.other_mgmt;
3165*5113495bSYour Name 	wma_debug("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d",
3166*5113495bSYour Name 		 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
3167*5113495bSYour Name 		 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
3168*5113495bSYour Name 	wma_debug("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d",
3169*5113495bSYour Name 		 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
3170*5113495bSYour Name 		 rx->rx_mpdu_aggr, rx->rx_mcs);
3171*5113495bSYour Name 	wma_debug("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d",
3172*5113495bSYour Name 		 rx->sta_ps_inds, rx->sta_ps_durs,
3173*5113495bSYour Name 		 rx->rx_probe_reqs, rx->rx_oth_mgmts);
3174*5113495bSYour Name 	len += sizeof(wmi_rx_stats_thresh);
3175*5113495bSYour Name 
3176*5113495bSYour Name 	wma_alert("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
3177*5113495bSYour Name 		 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
3178*5113495bSYour Name 	status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
3179*5113495bSYour Name 				      WMI_PDEV_SET_STATS_THRESHOLD_CMDID);
3180*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
3181*5113495bSYour Name 		wmi_buf_free(buf);
3182*5113495bSYour Name }
3183*5113495bSYour Name #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
3184*5113495bSYour Name 
3185*5113495bSYour Name /**
3186*5113495bSYour Name  * wma_post_link_status() - post link status to SME
3187*5113495bSYour Name  * @pGetLinkStatus: SME Link status
3188*5113495bSYour Name  * @link_status: Link status
3189*5113495bSYour Name  *
3190*5113495bSYour Name  * Return: none
3191*5113495bSYour Name  */
wma_post_link_status(tAniGetLinkStatus * pGetLinkStatus,uint8_t link_status)3192*5113495bSYour Name void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
3193*5113495bSYour Name 			  uint8_t link_status)
3194*5113495bSYour Name {
3195*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
3196*5113495bSYour Name 	struct scheduler_msg sme_msg = { 0 };
3197*5113495bSYour Name 
3198*5113495bSYour Name 	pGetLinkStatus->linkStatus = link_status;
3199*5113495bSYour Name 	sme_msg.type = eWNI_SME_LINK_STATUS_IND;
3200*5113495bSYour Name 	sme_msg.bodyptr = pGetLinkStatus;
3201*5113495bSYour Name 	sme_msg.bodyval = 0;
3202*5113495bSYour Name 
3203*5113495bSYour Name 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
3204*5113495bSYour Name 					    QDF_MODULE_ID_SME,
3205*5113495bSYour Name 					    QDF_MODULE_ID_SME, &sme_msg);
3206*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3207*5113495bSYour Name 		wma_err("Fail to post link status ind msg");
3208*5113495bSYour Name 		qdf_mem_free(pGetLinkStatus);
3209*5113495bSYour Name 	}
3210*5113495bSYour Name }
3211*5113495bSYour Name 
wma_link_status_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)3212*5113495bSYour Name int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
3213*5113495bSYour Name 				  uint32_t len)
3214*5113495bSYour Name {
3215*5113495bSYour Name 	tp_wma_handle wma = (tp_wma_handle) handle;
3216*5113495bSYour Name 	WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
3217*5113495bSYour Name 	wmi_vdev_rate_stats_event_fixed_param *event;
3218*5113495bSYour Name 	wmi_vdev_rate_ht_info *ht_info;
3219*5113495bSYour Name 	struct wma_txrx_node *intr = wma->interfaces;
3220*5113495bSYour Name 	uint8_t link_status = LINK_STATUS_LEGACY;
3221*5113495bSYour Name 	uint32_t i, rate_flag;
3222*5113495bSYour Name 	QDF_STATUS status;
3223*5113495bSYour Name 
3224*5113495bSYour Name 	param_buf =
3225*5113495bSYour Name 	      (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
3226*5113495bSYour Name 	if (!param_buf) {
3227*5113495bSYour Name 		wma_err("Invalid stats event");
3228*5113495bSYour Name 		return -EINVAL;
3229*5113495bSYour Name 	}
3230*5113495bSYour Name 
3231*5113495bSYour Name 	event = (wmi_vdev_rate_stats_event_fixed_param *)
3232*5113495bSYour Name 						param_buf->fixed_param;
3233*5113495bSYour Name 	ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
3234*5113495bSYour Name 
3235*5113495bSYour Name 	if (!ht_info) {
3236*5113495bSYour Name 		wma_err("Invalid ht_info");
3237*5113495bSYour Name 		return -EINVAL;
3238*5113495bSYour Name 	}
3239*5113495bSYour Name 
3240*5113495bSYour Name 	wma_debug("num_vdev_stats: %d", event->num_vdev_stats);
3241*5113495bSYour Name 
3242*5113495bSYour Name 	if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
3243*5113495bSYour Name 	    sizeof(*event)) / sizeof(*ht_info)) ||
3244*5113495bSYour Name 	    event->num_vdev_stats > param_buf->num_ht_info) {
3245*5113495bSYour Name 		wma_err("excess vdev_stats buffers:%d, num_ht_info:%d",
3246*5113495bSYour Name 			event->num_vdev_stats,
3247*5113495bSYour Name 			param_buf->num_ht_info);
3248*5113495bSYour Name 		return -EINVAL;
3249*5113495bSYour Name 	}
3250*5113495bSYour Name 
3251*5113495bSYour Name 	if (!wma_is_vdev_valid(ht_info->vdevid)) {
3252*5113495bSYour Name 		wma_err("Invalid vdevid %d", ht_info->vdevid);
3253*5113495bSYour Name 		return -EINVAL;
3254*5113495bSYour Name 	}
3255*5113495bSYour Name 
3256*5113495bSYour Name 	if (!intr[ht_info->vdevid].vdev) {
3257*5113495bSYour Name 		wma_err("Vdev is NULL");
3258*5113495bSYour Name 		return -EINVAL;
3259*5113495bSYour Name 	}
3260*5113495bSYour Name 
3261*5113495bSYour Name 	status = wma_get_vdev_rate_flag(intr[ht_info->vdevid].vdev, &rate_flag);
3262*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
3263*5113495bSYour Name 		wma_err("Failed to get rate flag");
3264*5113495bSYour Name 		return -EINVAL;
3265*5113495bSYour Name 	}
3266*5113495bSYour Name 
3267*5113495bSYour Name 	for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
3268*5113495bSYour Name 		wma_debug("vdevId:%d  tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
3269*5113495bSYour Name 			ht_info->vdevid, ht_info->tx_nss,
3270*5113495bSYour Name 			ht_info->rx_nss, ht_info->tx_preamble,
3271*5113495bSYour Name 			ht_info->rx_preamble);
3272*5113495bSYour Name 		if (ht_info->vdevid < wma->max_bssid
3273*5113495bSYour Name 		    && intr[ht_info->vdevid].plink_status_req) {
3274*5113495bSYour Name 			if (ht_info->tx_nss || ht_info->rx_nss)
3275*5113495bSYour Name 				link_status = LINK_STATUS_MIMO;
3276*5113495bSYour Name 
3277*5113495bSYour Name 			if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
3278*5113495bSYour Name 			    (ht_info->rx_preamble == LINK_RATE_VHT))
3279*5113495bSYour Name 				link_status |= LINK_STATUS_VHT;
3280*5113495bSYour Name 
3281*5113495bSYour Name 			if (intr[ht_info->vdevid].nss == 2)
3282*5113495bSYour Name 				link_status |= LINK_SUPPORT_MIMO;
3283*5113495bSYour Name 
3284*5113495bSYour Name 			if (rate_flag &
3285*5113495bSYour Name 				(TX_RATE_VHT20 | TX_RATE_VHT40 |
3286*5113495bSYour Name 				TX_RATE_VHT80))
3287*5113495bSYour Name 				link_status |= LINK_SUPPORT_VHT;
3288*5113495bSYour Name 
3289*5113495bSYour Name 			wma_post_link_status(
3290*5113495bSYour Name 					intr[ht_info->vdevid].plink_status_req,
3291*5113495bSYour Name 					link_status);
3292*5113495bSYour Name 			intr[ht_info->vdevid].plink_status_req = NULL;
3293*5113495bSYour Name 			link_status = LINK_STATUS_LEGACY;
3294*5113495bSYour Name 		}
3295*5113495bSYour Name 
3296*5113495bSYour Name 		ht_info++;
3297*5113495bSYour Name 	}
3298*5113495bSYour Name 
3299*5113495bSYour Name 	return 0;
3300*5113495bSYour Name }
3301*5113495bSYour Name 
wma_rso_cmd_status_event_handler(uint8_t vdev_id,enum cm_roam_notif notif)3302*5113495bSYour Name int wma_rso_cmd_status_event_handler(uint8_t vdev_id, enum cm_roam_notif notif)
3303*5113495bSYour Name {
3304*5113495bSYour Name 	struct rso_cmd_status *rso_status;
3305*5113495bSYour Name 	struct scheduler_msg sme_msg = {0};
3306*5113495bSYour Name 	QDF_STATUS qdf_status;
3307*5113495bSYour Name 
3308*5113495bSYour Name 	rso_status = qdf_mem_malloc(sizeof(*rso_status));
3309*5113495bSYour Name 	if (!rso_status)
3310*5113495bSYour Name 		return -ENOMEM;
3311*5113495bSYour Name 
3312*5113495bSYour Name 	rso_status->vdev_id = vdev_id;
3313*5113495bSYour Name 	if (notif == CM_ROAM_NOTIF_SCAN_MODE_SUCCESS)
3314*5113495bSYour Name 		rso_status->status = true;
3315*5113495bSYour Name 	else if (notif == CM_ROAM_NOTIF_SCAN_MODE_FAIL)
3316*5113495bSYour Name 		rso_status->status = false;
3317*5113495bSYour Name 	sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
3318*5113495bSYour Name 	sme_msg.bodyptr = rso_status;
3319*5113495bSYour Name 	sme_msg.bodyval = 0;
3320*5113495bSYour Name 	wma_debug("Post RSO cmd status to SME");
3321*5113495bSYour Name 
3322*5113495bSYour Name 	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
3323*5113495bSYour Name 					    QDF_MODULE_ID_SME,
3324*5113495bSYour Name 					    QDF_MODULE_ID_SME, &sme_msg);
3325*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3326*5113495bSYour Name 		wma_err("fail to post RSO cmd status to SME");
3327*5113495bSYour Name 		qdf_mem_free(rso_status);
3328*5113495bSYour Name 	}
3329*5113495bSYour Name 	return 0;
3330*5113495bSYour Name }
3331*5113495bSYour Name 
3332*5113495bSYour Name /**
3333*5113495bSYour Name  * wma_send_link_speed() - send link speed to SME
3334*5113495bSYour Name  * @link_speed: link speed
3335*5113495bSYour Name  *
3336*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS for success or error code
3337*5113495bSYour Name  */
wma_send_link_speed(uint32_t link_speed)3338*5113495bSYour Name QDF_STATUS wma_send_link_speed(uint32_t link_speed)
3339*5113495bSYour Name {
3340*5113495bSYour Name 	struct mac_context *mac_ctx;
3341*5113495bSYour Name 	struct link_speed_info *ls_ind;
3342*5113495bSYour Name 
3343*5113495bSYour Name 	mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3344*5113495bSYour Name 	if (!mac_ctx) {
3345*5113495bSYour Name 		wma_debug("NULL mac ptr. Exiting");
3346*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
3347*5113495bSYour Name 	}
3348*5113495bSYour Name 
3349*5113495bSYour Name 	ls_ind = qdf_mem_malloc(sizeof(*ls_ind));
3350*5113495bSYour Name 	if (!ls_ind)
3351*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
3352*5113495bSYour Name 
3353*5113495bSYour Name 	ls_ind->estLinkSpeed = link_speed;
3354*5113495bSYour Name 	if (mac_ctx->sme.link_speed_cb)
3355*5113495bSYour Name 		mac_ctx->sme.link_speed_cb(ls_ind,
3356*5113495bSYour Name 					   mac_ctx->sme.link_speed_context);
3357*5113495bSYour Name 	else
3358*5113495bSYour Name 		wma_debug("link_speed_cb is null");
3359*5113495bSYour Name 	qdf_mem_free(ls_ind);
3360*5113495bSYour Name 
3361*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3362*5113495bSYour Name }
3363*5113495bSYour Name 
3364*5113495bSYour Name /**
3365*5113495bSYour Name  * wma_link_speed_event_handler() - link speed event handler
3366*5113495bSYour Name  * @handle: wma handle
3367*5113495bSYour Name  * @cmd_param_info: event data
3368*5113495bSYour Name  * @len: length
3369*5113495bSYour Name  *
3370*5113495bSYour Name  * Return: 0 for success or error code
3371*5113495bSYour Name  */
wma_link_speed_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)3372*5113495bSYour Name int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3373*5113495bSYour Name 				 uint32_t len)
3374*5113495bSYour Name {
3375*5113495bSYour Name 	WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3376*5113495bSYour Name 	wmi_peer_estimated_linkspeed_event_fixed_param *event;
3377*5113495bSYour Name 	QDF_STATUS qdf_status;
3378*5113495bSYour Name 
3379*5113495bSYour Name 	param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3380*5113495bSYour Name 							 cmd_param_info;
3381*5113495bSYour Name 	if (!param_buf) {
3382*5113495bSYour Name 		wma_err("Invalid linkspeed event");
3383*5113495bSYour Name 		return -EINVAL;
3384*5113495bSYour Name 	}
3385*5113495bSYour Name 	event = param_buf->fixed_param;
3386*5113495bSYour Name 	qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
3387*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3388*5113495bSYour Name 		return -EINVAL;
3389*5113495bSYour Name 	return 0;
3390*5113495bSYour Name }
3391*5113495bSYour Name 
3392*5113495bSYour Name #define BIG_ENDIAN_MAX_DEBUG_BUF   500
3393*5113495bSYour Name /**
3394*5113495bSYour Name  * wma_unified_debug_print_event_handler() - debug print event handler
3395*5113495bSYour Name  * @handle: wma handle
3396*5113495bSYour Name  * @datap: data pointer
3397*5113495bSYour Name  * @len: length
3398*5113495bSYour Name  *
3399*5113495bSYour Name  * Return: 0 for success or error code
3400*5113495bSYour Name  */
wma_unified_debug_print_event_handler(void * handle,uint8_t * datap,uint32_t len)3401*5113495bSYour Name int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3402*5113495bSYour Name 					  uint32_t len)
3403*5113495bSYour Name {
3404*5113495bSYour Name 	WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3405*5113495bSYour Name 	uint8_t *data;
3406*5113495bSYour Name 	uint32_t datalen;
3407*5113495bSYour Name 
3408*5113495bSYour Name 	param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
3409*5113495bSYour Name 	if (!param_buf || !param_buf->data) {
3410*5113495bSYour Name 		wma_err("Get NULL point message from FW");
3411*5113495bSYour Name 		return -ENOMEM;
3412*5113495bSYour Name 	}
3413*5113495bSYour Name 	data = param_buf->data;
3414*5113495bSYour Name 	datalen = param_buf->num_data;
3415*5113495bSYour Name 	if (datalen > WMI_SVC_MSG_MAX_SIZE) {
3416*5113495bSYour Name 		wma_err("Received data len %d exceeds max value %d",
3417*5113495bSYour Name 			datalen, WMI_SVC_MSG_MAX_SIZE);
3418*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3419*5113495bSYour Name 	}
3420*5113495bSYour Name 	data[datalen - 1] = '\0';
3421*5113495bSYour Name 
3422*5113495bSYour Name #ifdef BIG_ENDIAN_HOST
3423*5113495bSYour Name 	{
3424*5113495bSYour Name 		if (datalen >= BIG_ENDIAN_MAX_DEBUG_BUF) {
3425*5113495bSYour Name 			wma_err("Invalid data len %d, limiting to max",
3426*5113495bSYour Name 				datalen);
3427*5113495bSYour Name 			datalen = BIG_ENDIAN_MAX_DEBUG_BUF - 1;
3428*5113495bSYour Name 		}
3429*5113495bSYour Name 		char dbgbuf[BIG_ENDIAN_MAX_DEBUG_BUF] = { 0 };
3430*5113495bSYour Name 
3431*5113495bSYour Name 		memcpy(dbgbuf, data, datalen);
3432*5113495bSYour Name 		SWAPME(dbgbuf, datalen);
3433*5113495bSYour Name 		wma_debug("FIRMWARE:%s", dbgbuf);
3434*5113495bSYour Name 		return 0;
3435*5113495bSYour Name 	}
3436*5113495bSYour Name #else
3437*5113495bSYour Name 	wma_debug("FIRMWARE:%s", data);
3438*5113495bSYour Name 	return 0;
3439*5113495bSYour Name #endif /* BIG_ENDIAN_HOST */
3440*5113495bSYour Name }
3441*5113495bSYour Name 
3442*5113495bSYour Name enum wlan_phymode
wma_peer_phymode(tSirNwType nw_type,uint8_t sta_type,uint8_t is_ht,uint8_t ch_width,uint8_t is_vht,bool is_he,bool is_eht)3443*5113495bSYour Name wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3444*5113495bSYour Name 		 uint8_t is_ht, uint8_t ch_width,
3445*5113495bSYour Name 		 uint8_t is_vht, bool is_he, bool is_eht)
3446*5113495bSYour Name {
3447*5113495bSYour Name 	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
3448*5113495bSYour Name 
3449*5113495bSYour Name 	switch (nw_type) {
3450*5113495bSYour Name 	case eSIR_11B_NW_TYPE:
3451*5113495bSYour Name #ifdef FEATURE_WLAN_TDLS
3452*5113495bSYour Name 	if (STA_ENTRY_TDLS_PEER == sta_type) {
3453*5113495bSYour Name 		if (is_he)
3454*5113495bSYour Name 			phymode = WLAN_PHYMODE_11AXG_HE20;
3455*5113495bSYour Name 		else if (is_vht)
3456*5113495bSYour Name 			phymode = WLAN_PHYMODE_11AC_VHT20_2G;
3457*5113495bSYour Name 		else if (is_ht)
3458*5113495bSYour Name 			phymode = WLAN_PHYMODE_11NG_HT20;
3459*5113495bSYour Name 		else
3460*5113495bSYour Name 			phymode = WLAN_PHYMODE_11B;
3461*5113495bSYour Name 	} else
3462*5113495bSYour Name #endif /* FEATURE_WLAN_TDLS */
3463*5113495bSYour Name 	{
3464*5113495bSYour Name 		phymode = WLAN_PHYMODE_11B;
3465*5113495bSYour Name 		if (is_ht || is_vht || is_he || is_eht)
3466*5113495bSYour Name 			wma_err("HT/VHT is enabled with 11B NW type");
3467*5113495bSYour Name 	}
3468*5113495bSYour Name 		break;
3469*5113495bSYour Name 	case eSIR_11G_NW_TYPE:
3470*5113495bSYour Name 		if (!(is_ht || is_vht || is_he || is_eht)) {
3471*5113495bSYour Name 			phymode = WLAN_PHYMODE_11G;
3472*5113495bSYour Name 			break;
3473*5113495bSYour Name 		}
3474*5113495bSYour Name 		if (CH_WIDTH_40MHZ < ch_width)
3475*5113495bSYour Name 			wma_err("80/160 MHz BW sent in 11G, configured 40MHz");
3476*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
3477*5113495bSYour Name 		if (ch_width)
3478*5113495bSYour Name 			phymode = (is_eht) ? WLAN_PHYMODE_11BEG_EHT40 :
3479*5113495bSYour Name 					(is_he) ? WLAN_PHYMODE_11AXG_HE40 :
3480*5113495bSYour Name 					(is_vht) ? WLAN_PHYMODE_11AC_VHT40_2G :
3481*5113495bSYour Name 					WLAN_PHYMODE_11NG_HT40;
3482*5113495bSYour Name 		else
3483*5113495bSYour Name 			phymode = (is_eht) ? WLAN_PHYMODE_11BEG_EHT20 :
3484*5113495bSYour Name 					(is_he) ? WLAN_PHYMODE_11AXG_HE20 :
3485*5113495bSYour Name 					(is_vht) ? WLAN_PHYMODE_11AC_VHT20_2G :
3486*5113495bSYour Name 					WLAN_PHYMODE_11NG_HT20;
3487*5113495bSYour Name #else
3488*5113495bSYour Name 		if (ch_width)
3489*5113495bSYour Name 			phymode = (is_he) ? WLAN_PHYMODE_11AXG_HE40 : (is_vht) ?
3490*5113495bSYour Name 					WLAN_PHYMODE_11AC_VHT40_2G :
3491*5113495bSYour Name 					WLAN_PHYMODE_11NG_HT40;
3492*5113495bSYour Name 		else
3493*5113495bSYour Name 			phymode = (is_he) ? WLAN_PHYMODE_11AXG_HE20 : (is_vht) ?
3494*5113495bSYour Name 					WLAN_PHYMODE_11AC_VHT20_2G :
3495*5113495bSYour Name 					WLAN_PHYMODE_11NG_HT20;
3496*5113495bSYour Name #endif
3497*5113495bSYour Name 		break;
3498*5113495bSYour Name 	case eSIR_11A_NW_TYPE:
3499*5113495bSYour Name 		if (!(is_ht || is_vht || is_he || is_eht)) {
3500*5113495bSYour Name 			phymode = WLAN_PHYMODE_11A;
3501*5113495bSYour Name 			break;
3502*5113495bSYour Name 		}
3503*5113495bSYour Name #if defined(WLAN_FEATURE_11BE)
3504*5113495bSYour Name 		if (is_eht) {
3505*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ)
3506*5113495bSYour Name 				phymode = WLAN_PHYMODE_11BEA_EHT160;
3507*5113495bSYour Name 			else if (ch_width == CH_WIDTH_320MHZ)
3508*5113495bSYour Name 				phymode = WLAN_PHYMODE_11BEA_EHT320;
3509*5113495bSYour Name 			else if (ch_width == CH_WIDTH_80MHZ)
3510*5113495bSYour Name 				phymode = WLAN_PHYMODE_11BEA_EHT80;
3511*5113495bSYour Name 			else
3512*5113495bSYour Name 				phymode = (ch_width) ?
3513*5113495bSYour Name 					  WLAN_PHYMODE_11BEA_EHT40 :
3514*5113495bSYour Name 					  WLAN_PHYMODE_11BEA_EHT20;
3515*5113495bSYour Name 		} else
3516*5113495bSYour Name #endif
3517*5113495bSYour Name 		if (is_he) {
3518*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ)
3519*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AXA_HE160;
3520*5113495bSYour Name 			else if (ch_width == CH_WIDTH_80P80MHZ)
3521*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AXA_HE80_80;
3522*5113495bSYour Name 			else if (ch_width == CH_WIDTH_80MHZ)
3523*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AXA_HE80;
3524*5113495bSYour Name 			else
3525*5113495bSYour Name 				phymode = (ch_width) ?
3526*5113495bSYour Name 					  WLAN_PHYMODE_11AXA_HE40 :
3527*5113495bSYour Name 					  WLAN_PHYMODE_11AXA_HE20;
3528*5113495bSYour Name 		} else if (is_vht) {
3529*5113495bSYour Name 			if (ch_width == CH_WIDTH_160MHZ)
3530*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AC_VHT160;
3531*5113495bSYour Name 			else if (ch_width == CH_WIDTH_80P80MHZ)
3532*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AC_VHT80_80;
3533*5113495bSYour Name 			else if (ch_width == CH_WIDTH_80MHZ)
3534*5113495bSYour Name 				phymode = WLAN_PHYMODE_11AC_VHT80;
3535*5113495bSYour Name 			else
3536*5113495bSYour Name 				phymode = (ch_width) ?
3537*5113495bSYour Name 					  WLAN_PHYMODE_11AC_VHT40 :
3538*5113495bSYour Name 					  WLAN_PHYMODE_11AC_VHT20;
3539*5113495bSYour Name 		} else
3540*5113495bSYour Name 			phymode = (ch_width) ? WLAN_PHYMODE_11NA_HT40 :
3541*5113495bSYour Name 						WLAN_PHYMODE_11NA_HT20;
3542*5113495bSYour Name 		break;
3543*5113495bSYour Name 	default:
3544*5113495bSYour Name 		wma_err("Invalid nw type %d", nw_type);
3545*5113495bSYour Name 		break;
3546*5113495bSYour Name 	}
3547*5113495bSYour Name 	wma_debug("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d is_eht %d phymode %d",
3548*5113495bSYour Name 		  nw_type, is_ht, ch_width, is_vht, is_he, is_eht, phymode);
3549*5113495bSYour Name 
3550*5113495bSYour Name 	return phymode;
3551*5113495bSYour Name }
3552*5113495bSYour Name 
3553*5113495bSYour Name /**
3554*5113495bSYour Name  * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3555*5113495bSYour Name  * @wma_handle: wma handle
3556*5113495bSYour Name  * @vdev_id: vdev id
3557*5113495bSYour Name  * @value: value
3558*5113495bSYour Name  *
3559*5113495bSYour Name  * Return: 0 for success or return error
3560*5113495bSYour Name  */
wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,uint8_t vdev_id,uint32_t value)3561*5113495bSYour Name int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3562*5113495bSYour Name 				uint8_t vdev_id, uint32_t value)
3563*5113495bSYour Name {
3564*5113495bSYour Name 	struct ol_txrx_stats_req req;
3565*5113495bSYour Name 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3566*5113495bSYour Name 
3567*5113495bSYour Name 	if (!soc) {
3568*5113495bSYour Name 		wma_err("SOC context is NULL");
3569*5113495bSYour Name 		return -EINVAL;
3570*5113495bSYour Name 	}
3571*5113495bSYour Name 
3572*5113495bSYour Name 	qdf_mem_zero(&req, sizeof(req));
3573*5113495bSYour Name 	req.stats_type_reset_mask = value;
3574*5113495bSYour Name 	cdp_fw_stats_get(soc, vdev_id, &req, false, false);
3575*5113495bSYour Name 
3576*5113495bSYour Name 	return 0;
3577*5113495bSYour Name }
3578*5113495bSYour Name 
3579*5113495bSYour Name #ifdef HELIUMPLUS
3580*5113495bSYour Name #define SET_UPLOAD_MASK(_mask, _rate_info)	\
3581*5113495bSYour Name 	((_mask) = 1 << (_rate_info ## _V2))
3582*5113495bSYour Name #else  /* !HELIUMPLUS */
3583*5113495bSYour Name #define SET_UPLOAD_MASK(_mask, _rate_info)	\
3584*5113495bSYour Name 	((_mask) = 1 << (_rate_info))
3585*5113495bSYour Name #endif
3586*5113495bSYour Name 
3587*5113495bSYour Name #if defined(HELIUMPLUS) || defined(QCN7605_SUPPORT)
wma_is_valid_fw_stats_cmd(uint32_t value)3588*5113495bSYour Name static bool wma_is_valid_fw_stats_cmd(uint32_t value)
3589*5113495bSYour Name {
3590*5113495bSYour Name 	if (value > (HTT_DBG_NUM_STATS + 1) ||
3591*5113495bSYour Name 		value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3592*5113495bSYour Name 		value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3593*5113495bSYour Name 		value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3594*5113495bSYour Name 		wma_err("Not supported");
3595*5113495bSYour Name 		return false;
3596*5113495bSYour Name 	}
3597*5113495bSYour Name 	return true;
3598*5113495bSYour Name }
3599*5113495bSYour Name #else
wma_is_valid_fw_stats_cmd(uint32_t value)3600*5113495bSYour Name static bool wma_is_valid_fw_stats_cmd(uint32_t value)
3601*5113495bSYour Name {
3602*5113495bSYour Name 	if (value > (HTT_DBG_NUM_STATS + 1) ||
3603*5113495bSYour Name 		value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3604*5113495bSYour Name 		value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3605*5113495bSYour Name 		value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3606*5113495bSYour Name 		wma_err("Not supported");
3607*5113495bSYour Name 		return false;
3608*5113495bSYour Name 	}
3609*5113495bSYour Name 	return true;
3610*5113495bSYour Name }
3611*5113495bSYour Name #endif
3612*5113495bSYour Name 
3613*5113495bSYour Name /**
3614*5113495bSYour Name  * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3615*5113495bSYour Name  * @wma_handle: wma handle
3616*5113495bSYour Name  * @vdev_id: vdev id
3617*5113495bSYour Name  * @value: value
3618*5113495bSYour Name  *
3619*5113495bSYour Name  * Return: 0 for success or return error
3620*5113495bSYour Name  */
wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,uint8_t vdev_id,uint32_t value)3621*5113495bSYour Name int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3622*5113495bSYour Name 				    uint8_t vdev_id, uint32_t value)
3623*5113495bSYour Name {
3624*5113495bSYour Name 	struct ol_txrx_stats_req req;
3625*5113495bSYour Name 	uint32_t l_up_mask;
3626*5113495bSYour Name 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3627*5113495bSYour Name 
3628*5113495bSYour Name 	if (!soc) {
3629*5113495bSYour Name 		wma_err("SOC context is NULL");
3630*5113495bSYour Name 		return -EINVAL;
3631*5113495bSYour Name 	}
3632*5113495bSYour Name 
3633*5113495bSYour Name 	if (wma_is_valid_fw_stats_cmd(value) == false)
3634*5113495bSYour Name 		return -EINVAL;
3635*5113495bSYour Name 
3636*5113495bSYour Name 	qdf_mem_zero(&req, sizeof(req));
3637*5113495bSYour Name 	req.print.verbose = 1;
3638*5113495bSYour Name 
3639*5113495bSYour Name 	/* TODO: Need to check how to avoid mem leak*/
3640*5113495bSYour Name 	l_up_mask = 1 << (value - 1);
3641*5113495bSYour Name 	req.stats_type_upload_mask = l_up_mask;
3642*5113495bSYour Name 
3643*5113495bSYour Name 	cdp_fw_stats_get(soc, vdev_id, &req, false, true);
3644*5113495bSYour Name 
3645*5113495bSYour Name 	return 0;
3646*5113495bSYour Name }
3647*5113495bSYour Name 
3648*5113495bSYour Name /**
3649*5113495bSYour Name  * wma_get_cca_stats() - send request to fw to get CCA
3650*5113495bSYour Name  * @wma_handle: wma handle
3651*5113495bSYour Name  * @vdev_id: vdev id
3652*5113495bSYour Name  *
3653*5113495bSYour Name  * Return: QDF status
3654*5113495bSYour Name  */
wma_get_cca_stats(tp_wma_handle wma_handle,uint8_t vdev_id)3655*5113495bSYour Name QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3656*5113495bSYour Name 				uint8_t vdev_id)
3657*5113495bSYour Name {
3658*5113495bSYour Name 	if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3659*5113495bSYour Name 			vdev_id)) {
3660*5113495bSYour Name 		wma_err("Failed to congestion request to fw");
3661*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3662*5113495bSYour Name 	}
3663*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3664*5113495bSYour Name }
3665*5113495bSYour Name 
3666*5113495bSYour Name /**
3667*5113495bSYour Name  * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3668*5113495bSYour Name  * @vdev_id: vdev id
3669*5113495bSYour Name  * @buffer_size: size of buffer
3670*5113495bSYour Name  *
3671*5113495bSYour Name  * Return: none
3672*5113495bSYour Name  */
wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id,uint32_t * buffer_size)3673*5113495bSYour Name void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3674*5113495bSYour Name {
3675*5113495bSYour Name 	tp_wma_handle wma;
3676*5113495bSYour Name 	struct beacon_info *beacon;
3677*5113495bSYour Name 	uint8_t *buf;
3678*5113495bSYour Name 	uint32_t buf_size;
3679*5113495bSYour Name 
3680*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
3681*5113495bSYour Name 	if (!wma)
3682*5113495bSYour Name 		return NULL;
3683*5113495bSYour Name 
3684*5113495bSYour Name 	if (vdev_id >= wma->max_bssid) {
3685*5113495bSYour Name 		wma_err("Invalid vdev_id %u", vdev_id);
3686*5113495bSYour Name 		return NULL;
3687*5113495bSYour Name 	}
3688*5113495bSYour Name 
3689*5113495bSYour Name 	if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
3690*5113495bSYour Name 		wma_err("vdevid %d is not in AP mode", vdev_id);
3691*5113495bSYour Name 		return NULL;
3692*5113495bSYour Name 	}
3693*5113495bSYour Name 
3694*5113495bSYour Name 	beacon = wma->interfaces[vdev_id].beacon;
3695*5113495bSYour Name 
3696*5113495bSYour Name 	if (!beacon) {
3697*5113495bSYour Name 		wma_err("beacon invalid");
3698*5113495bSYour Name 		return NULL;
3699*5113495bSYour Name 	}
3700*5113495bSYour Name 
3701*5113495bSYour Name 	qdf_spin_lock_bh(&beacon->lock);
3702*5113495bSYour Name 
3703*5113495bSYour Name 	buf_size = qdf_nbuf_len(beacon->buf);
3704*5113495bSYour Name 	buf = qdf_mem_malloc(buf_size);
3705*5113495bSYour Name 	if (!buf) {
3706*5113495bSYour Name 		qdf_spin_unlock_bh(&beacon->lock);
3707*5113495bSYour Name 		return NULL;
3708*5113495bSYour Name 	}
3709*5113495bSYour Name 
3710*5113495bSYour Name 	qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
3711*5113495bSYour Name 
3712*5113495bSYour Name 	qdf_spin_unlock_bh(&beacon->lock);
3713*5113495bSYour Name 
3714*5113495bSYour Name 	if (buffer_size)
3715*5113495bSYour Name 		*buffer_size = buf_size;
3716*5113495bSYour Name 
3717*5113495bSYour Name 	return buf;
3718*5113495bSYour Name }
3719*5113495bSYour Name 
wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)3720*5113495bSYour Name uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
3721*5113495bSYour Name {
3722*5113495bSYour Name 	tp_wma_handle wma;
3723*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
3724*5113495bSYour Name 
3725*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
3726*5113495bSYour Name 	if (!wma)
3727*5113495bSYour Name 		return NULL;
3728*5113495bSYour Name 
3729*5113495bSYour Name 	if (vdev_id >= wma->max_bssid) {
3730*5113495bSYour Name 		wma_err("Invalid vdev_id %u", vdev_id);
3731*5113495bSYour Name 		return NULL;
3732*5113495bSYour Name 	}
3733*5113495bSYour Name 	vdev = wma->interfaces[vdev_id].vdev;
3734*5113495bSYour Name 	if (!vdev) {
3735*5113495bSYour Name 		wma_err("Invalid vdev for vdev_id %u", vdev_id);
3736*5113495bSYour Name 		return NULL;
3737*5113495bSYour Name 	}
3738*5113495bSYour Name 	return wlan_vdev_mlme_get_macaddr(vdev);
3739*5113495bSYour Name }
3740*5113495bSYour Name 
wma_get_connection_info(uint8_t vdev_id,struct policy_mgr_vdev_entry_info * conn_table_entry)3741*5113495bSYour Name QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
3742*5113495bSYour Name 		struct policy_mgr_vdev_entry_info *conn_table_entry)
3743*5113495bSYour Name {
3744*5113495bSYour Name 	struct wma_txrx_node *wma_conn_table_entry;
3745*5113495bSYour Name 
3746*5113495bSYour Name 	wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
3747*5113495bSYour Name 	if (!wma_conn_table_entry) {
3748*5113495bSYour Name 		wma_err("can't find vdev_id %d in WMA table", vdev_id);
3749*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3750*5113495bSYour Name 	}
3751*5113495bSYour Name 	conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
3752*5113495bSYour Name 	conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
3753*5113495bSYour Name 	conn_table_entry->mhz = wma_conn_table_entry->ch_freq;
3754*5113495bSYour Name 	conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
3755*5113495bSYour Name 	conn_table_entry->type = wma_conn_table_entry->type;
3756*5113495bSYour Name 	conn_table_entry->ch_flagext = wma_conn_table_entry->ch_flagext;
3757*5113495bSYour Name 
3758*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3759*5113495bSYour Name }
3760*5113495bSYour Name 
wma_ndi_update_connection_info(uint8_t vdev_id,struct nan_datapath_channel_info * ndp_chan_info)3761*5113495bSYour Name QDF_STATUS wma_ndi_update_connection_info(uint8_t vdev_id,
3762*5113495bSYour Name 				struct nan_datapath_channel_info *ndp_chan_info)
3763*5113495bSYour Name {
3764*5113495bSYour Name 	struct wma_txrx_node *wma_iface_entry;
3765*5113495bSYour Name 
3766*5113495bSYour Name 	wma_iface_entry = wma_get_interface_by_vdev_id(vdev_id);
3767*5113495bSYour Name 	if (!wma_iface_entry) {
3768*5113495bSYour Name 		wma_err("can't find vdev_id %d in WMA table", vdev_id);
3769*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3770*5113495bSYour Name 	}
3771*5113495bSYour Name 
3772*5113495bSYour Name 	if (WMI_VDEV_TYPE_NDI != wma_iface_entry->type) {
3773*5113495bSYour Name 		wma_err("Given vdev id(%d) not of type NDI!", vdev_id);
3774*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3775*5113495bSYour Name 	}
3776*5113495bSYour Name 
3777*5113495bSYour Name 	if (!ndp_chan_info) {
3778*5113495bSYour Name 		wma_err("Provided chan info is NULL!");
3779*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
3780*5113495bSYour Name 	}
3781*5113495bSYour Name 
3782*5113495bSYour Name 	wma_iface_entry->chan_width = ndp_chan_info->ch_width;
3783*5113495bSYour Name 	wma_iface_entry->ch_freq = ndp_chan_info->freq;
3784*5113495bSYour Name 	wma_iface_entry->nss = ndp_chan_info->nss;
3785*5113495bSYour Name 	wma_iface_entry->mac_id = ndp_chan_info->mac_id;
3786*5113495bSYour Name 
3787*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
3788*5113495bSYour Name }
3789*5113495bSYour Name 
3790*5113495bSYour Name /**
3791*5113495bSYour Name  * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
3792*5113495bSYour Name  * @vdev_id: vdev id
3793*5113495bSYour Name  *
3794*5113495bSYour Name  * Return: entry from vdev table
3795*5113495bSYour Name  */
wma_get_interface_by_vdev_id(uint8_t vdev_id)3796*5113495bSYour Name struct wma_txrx_node  *wma_get_interface_by_vdev_id(uint8_t vdev_id)
3797*5113495bSYour Name {
3798*5113495bSYour Name 	tp_wma_handle wma;
3799*5113495bSYour Name 
3800*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
3801*5113495bSYour Name 	if (!wma)
3802*5113495bSYour Name 		return NULL;
3803*5113495bSYour Name 
3804*5113495bSYour Name 	if (vdev_id >= wma->max_bssid) {
3805*5113495bSYour Name 		wma_err("Invalid vdev_id %u", vdev_id);
3806*5113495bSYour Name 		return NULL;
3807*5113495bSYour Name 	}
3808*5113495bSYour Name 
3809*5113495bSYour Name 	return &wma->interfaces[vdev_id];
3810*5113495bSYour Name }
3811*5113495bSYour Name 
3812*5113495bSYour Name #ifdef WLAN_FEATURE_PKT_CAPTURE
wma_get_rmf_status(uint8_t vdev_id)3813*5113495bSYour Name int wma_get_rmf_status(uint8_t vdev_id)
3814*5113495bSYour Name {
3815*5113495bSYour Name 	struct wma_txrx_node *iface;
3816*5113495bSYour Name 
3817*5113495bSYour Name 	iface = wma_get_interface_by_vdev_id(vdev_id);
3818*5113495bSYour Name 	if (!iface) {
3819*5113495bSYour Name 		wma_err("Unable to get wma interface");
3820*5113495bSYour Name 		return -EINVAL;
3821*5113495bSYour Name 	}
3822*5113495bSYour Name 
3823*5113495bSYour Name 	return iface->rmfEnabled;
3824*5113495bSYour Name }
3825*5113495bSYour Name #endif
3826*5113495bSYour Name 
3827*5113495bSYour Name /**
3828*5113495bSYour Name  * wma_update_intf_hw_mode_params() - Update WMA params
3829*5113495bSYour Name  * @vdev_id: VDEV id whose params needs to be updated
3830*5113495bSYour Name  * @mac_id: MAC id to be updated
3831*5113495bSYour Name  * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
3832*5113495bSYour Name  *
3833*5113495bSYour Name  * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
3834*5113495bSYour Name  *
3835*5113495bSYour Name  * Return: None
3836*5113495bSYour Name  */
wma_update_intf_hw_mode_params(uint32_t vdev_id,uint32_t mac_id,uint32_t cfgd_hw_mode_index)3837*5113495bSYour Name void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
3838*5113495bSYour Name 				    uint32_t cfgd_hw_mode_index)
3839*5113495bSYour Name {
3840*5113495bSYour Name 	tp_wma_handle wma;
3841*5113495bSYour Name 	struct policy_mgr_hw_mode_params hw_mode;
3842*5113495bSYour Name 	QDF_STATUS status;
3843*5113495bSYour Name 
3844*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
3845*5113495bSYour Name 	if (!wma)
3846*5113495bSYour Name 		return;
3847*5113495bSYour Name 
3848*5113495bSYour Name 	if (!wma->interfaces) {
3849*5113495bSYour Name 		wma_err("Interface is NULL");
3850*5113495bSYour Name 		return;
3851*5113495bSYour Name 	}
3852*5113495bSYour Name 
3853*5113495bSYour Name 	status = policy_mgr_get_hw_mode_from_idx(wma->psoc, cfgd_hw_mode_index,
3854*5113495bSYour Name 						 &hw_mode);
3855*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
3856*5113495bSYour Name 		wma_err("cfgd_hw_mode_index %d not found",
3857*5113495bSYour Name 			 cfgd_hw_mode_index);
3858*5113495bSYour Name 		return;
3859*5113495bSYour Name 	}
3860*5113495bSYour Name 	wma->interfaces[vdev_id].mac_id = mac_id;
3861*5113495bSYour Name 	if (mac_id == 0)
3862*5113495bSYour Name 		wma->interfaces[vdev_id].tx_streams =
3863*5113495bSYour Name 			hw_mode.mac0_tx_ss;
3864*5113495bSYour Name 	else
3865*5113495bSYour Name 		wma->interfaces[vdev_id].tx_streams =
3866*5113495bSYour Name 			hw_mode.mac1_tx_ss;
3867*5113495bSYour Name }
3868*5113495bSYour Name 
3869*5113495bSYour Name /**
3870*5113495bSYour Name  * wma_get_vht_ch_width - return vht channel width
3871*5113495bSYour Name  *
3872*5113495bSYour Name  * Return: return vht channel width
3873*5113495bSYour Name  */
wma_get_vht_ch_width(void)3874*5113495bSYour Name uint32_t wma_get_vht_ch_width(void)
3875*5113495bSYour Name {
3876*5113495bSYour Name 	uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
3877*5113495bSYour Name 	tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
3878*5113495bSYour Name 	struct target_psoc_info *tgt_hdl;
3879*5113495bSYour Name 	int vht_cap_info;
3880*5113495bSYour Name 
3881*5113495bSYour Name 	if (!wm_hdl)
3882*5113495bSYour Name 		return fw_ch_wd;
3883*5113495bSYour Name 
3884*5113495bSYour Name 	tgt_hdl = wlan_psoc_get_tgt_if_handle(wm_hdl->psoc);
3885*5113495bSYour Name 	if (!tgt_hdl)
3886*5113495bSYour Name 		return fw_ch_wd;
3887*5113495bSYour Name 
3888*5113495bSYour Name 	vht_cap_info = target_if_get_vht_cap_info(tgt_hdl);
3889*5113495bSYour Name 	if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
3890*5113495bSYour Name 		fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
3891*5113495bSYour Name 	else if (vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3892*5113495bSYour Name 		fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
3893*5113495bSYour Name 
3894*5113495bSYour Name 	return fw_ch_wd;
3895*5113495bSYour Name }
3896*5113495bSYour Name 
3897*5113495bSYour Name /**
3898*5113495bSYour Name  * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
3899*5113495bSYour Name  * @mask: given bitmask
3900*5113495bSYour Name  *
3901*5113495bSYour Name  * This helper function should return number of setbits from bitmask
3902*5113495bSYour Name  *
3903*5113495bSYour Name  * Return: number of setbits from bitmask
3904*5113495bSYour Name  */
wma_get_num_of_setbits_from_bitmask(uint32_t mask)3905*5113495bSYour Name uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
3906*5113495bSYour Name {
3907*5113495bSYour Name 	uint32_t num_of_setbits = 0;
3908*5113495bSYour Name 
3909*5113495bSYour Name 	while (mask) {
3910*5113495bSYour Name 		mask &= (mask - 1);
3911*5113495bSYour Name 		num_of_setbits++;
3912*5113495bSYour Name 	}
3913*5113495bSYour Name 	return num_of_setbits;
3914*5113495bSYour Name }
3915*5113495bSYour Name 
3916*5113495bSYour Name /**
3917*5113495bSYour Name  * wma_is_csa_offload_enabled - checks fw CSA offload capability
3918*5113495bSYour Name  *
3919*5113495bSYour Name  * Return: true or false
3920*5113495bSYour Name  */
3921*5113495bSYour Name 
wma_is_csa_offload_enabled(void)3922*5113495bSYour Name bool wma_is_csa_offload_enabled(void)
3923*5113495bSYour Name {
3924*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3925*5113495bSYour Name 
3926*5113495bSYour Name 	if (!wma)
3927*5113495bSYour Name 		return false;
3928*5113495bSYour Name 
3929*5113495bSYour Name 	return wmi_service_enabled(wma->wmi_handle,
3930*5113495bSYour Name 				   wmi_service_csa_offload);
3931*5113495bSYour Name }
3932*5113495bSYour Name 
wma_is_mbssid_enabled(void)3933*5113495bSYour Name bool wma_is_mbssid_enabled(void)
3934*5113495bSYour Name {
3935*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3936*5113495bSYour Name 
3937*5113495bSYour Name 	if (!wma)
3938*5113495bSYour Name 		return false;
3939*5113495bSYour Name 
3940*5113495bSYour Name 	return wmi_service_enabled(wma->wmi_handle,
3941*5113495bSYour Name 				   wmi_service_infra_mbssid);
3942*5113495bSYour Name }
3943*5113495bSYour Name 
3944*5113495bSYour Name #ifdef FEATURE_FW_LOG_PARSING
3945*5113495bSYour Name /**
3946*5113495bSYour Name  * wma_config_debug_module_cmd - set debug log config
3947*5113495bSYour Name  * @wmi_handle: wmi layer handle
3948*5113495bSYour Name  * @param: debug log parameter
3949*5113495bSYour Name  * @val: debug log value
3950*5113495bSYour Name  * @module_id_bitmap: debug module id bitmap
3951*5113495bSYour Name  * @bitmap_len:  debug module bitmap length
3952*5113495bSYour Name  *
3953*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS for success or error code
3954*5113495bSYour Name  */
3955*5113495bSYour Name QDF_STATUS
wma_config_debug_module_cmd(wmi_unified_t wmi_handle,A_UINT32 param,A_UINT32 val,A_UINT32 * module_id_bitmap,A_UINT32 bitmap_len)3956*5113495bSYour Name wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
3957*5113495bSYour Name 			    A_UINT32 val, A_UINT32 *module_id_bitmap,
3958*5113495bSYour Name 			    A_UINT32 bitmap_len)
3959*5113495bSYour Name {
3960*5113495bSYour Name 	struct dbglog_params dbg_param;
3961*5113495bSYour Name 
3962*5113495bSYour Name 	dbg_param.param = param;
3963*5113495bSYour Name 	dbg_param.val = val;
3964*5113495bSYour Name 	dbg_param.module_id_bitmap = module_id_bitmap;
3965*5113495bSYour Name 	dbg_param.bitmap_len = bitmap_len;
3966*5113495bSYour Name 
3967*5113495bSYour Name 	return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
3968*5113495bSYour Name }
3969*5113495bSYour Name #endif
3970*5113495bSYour Name #ifdef FEATURE_P2P_LISTEN_OFFLOAD
3971*5113495bSYour Name /**
3972*5113495bSYour Name  * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
3973*5113495bSYour Name  *
3974*5113495bSYour Name  * This function checks if driver is capable of p2p listen offload
3975*5113495bSYour Name  *    true: capable of p2p offload
3976*5113495bSYour Name  *    false: not capable
3977*5113495bSYour Name  *
3978*5113495bSYour Name  * Return: true - capable, false - not capable
3979*5113495bSYour Name  */
wma_is_p2p_lo_capable(void)3980*5113495bSYour Name bool wma_is_p2p_lo_capable(void)
3981*5113495bSYour Name {
3982*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
3983*5113495bSYour Name 
3984*5113495bSYour Name 	if (wma) {
3985*5113495bSYour Name 		return wmi_service_enabled
3986*5113495bSYour Name 				(wma->wmi_handle,
3987*5113495bSYour Name 				 wmi_service_p2p_listen_offload_support);
3988*5113495bSYour Name 	}
3989*5113495bSYour Name 
3990*5113495bSYour Name 	return 0;
3991*5113495bSYour Name }
3992*5113495bSYour Name #endif
3993*5113495bSYour Name 
3994*5113495bSYour Name #ifdef WLAN_FEATURE_ROAM_OFFLOAD
wma_get_roam_scan_ch(wmi_unified_t wmi_handle,uint8_t vdev_id)3995*5113495bSYour Name QDF_STATUS wma_get_roam_scan_ch(wmi_unified_t wmi_handle,
3996*5113495bSYour Name 				uint8_t vdev_id)
3997*5113495bSYour Name {
3998*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3999*5113495bSYour Name 	struct roam_scan_ch_resp *roam_ch;
4000*5113495bSYour Name 	struct scheduler_msg sme_msg = {0};
4001*5113495bSYour Name 
4002*5113495bSYour Name 	if (!wma_is_vdev_valid(vdev_id)) {
4003*5113495bSYour Name 		wma_err("vdev_id: %d is not active", vdev_id);
4004*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4005*5113495bSYour Name 	}
4006*5113495bSYour Name 
4007*5113495bSYour Name 	status = wmi_unified_get_roam_scan_ch_list(wmi_handle, vdev_id);
4008*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
4009*5113495bSYour Name 		return status;
4010*5113495bSYour Name 	roam_ch = qdf_mem_malloc(sizeof(struct roam_scan_ch_resp));
4011*5113495bSYour Name 	if (!roam_ch)
4012*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4013*5113495bSYour Name 
4014*5113495bSYour Name 	roam_ch->command_resp = 1;
4015*5113495bSYour Name 	roam_ch->num_channels = 0;
4016*5113495bSYour Name 	roam_ch->chan_list = NULL;
4017*5113495bSYour Name 	roam_ch->vdev_id = vdev_id;
4018*5113495bSYour Name 	sme_msg.type = eWNI_SME_GET_ROAM_SCAN_CH_LIST_EVENT;
4019*5113495bSYour Name 	sme_msg.bodyptr = roam_ch;
4020*5113495bSYour Name 
4021*5113495bSYour Name 	if (scheduler_post_message(QDF_MODULE_ID_WMA,
4022*5113495bSYour Name 				   QDF_MODULE_ID_SME,
4023*5113495bSYour Name 				   QDF_MODULE_ID_SME, &sme_msg)) {
4024*5113495bSYour Name 		wma_err("Failed to post msg to SME");
4025*5113495bSYour Name 		qdf_mem_free(roam_ch);
4026*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4027*5113495bSYour Name 	}
4028*5113495bSYour Name 
4029*5113495bSYour Name 	return status;
4030*5113495bSYour Name }
4031*5113495bSYour Name #endif
4032*5113495bSYour Name 
wma_capability_enhanced_mcast_filter(void)4033*5113495bSYour Name bool wma_capability_enhanced_mcast_filter(void)
4034*5113495bSYour Name {
4035*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4036*5113495bSYour Name 
4037*5113495bSYour Name 	if (wma) {
4038*5113495bSYour Name 		return wmi_service_enabled(wma->wmi_handle,
4039*5113495bSYour Name 					   wmi_service_enhanced_mcast_filter);
4040*5113495bSYour Name 	}
4041*5113495bSYour Name 
4042*5113495bSYour Name 	return 0;
4043*5113495bSYour Name }
4044*5113495bSYour Name 
4045*5113495bSYour Name 
wma_is_vdev_up(uint8_t vdev_id)4046*5113495bSYour Name bool wma_is_vdev_up(uint8_t vdev_id)
4047*5113495bSYour Name {
4048*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4049*5113495bSYour Name 
4050*5113495bSYour Name 	if (!wma)
4051*5113495bSYour Name 		return false;
4052*5113495bSYour Name 
4053*5113495bSYour Name 	return wlan_is_vdev_id_up(wma->pdev, vdev_id);
4054*5113495bSYour Name }
4055*5113495bSYour Name 
wma_acquire_wakelock(qdf_wake_lock_t * wl,uint32_t msec)4056*5113495bSYour Name void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
4057*5113495bSYour Name {
4058*5113495bSYour Name 	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4059*5113495bSYour Name 
4060*5113495bSYour Name 	cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4061*5113495bSYour Name 	qdf_wake_lock_timeout_acquire(wl, msec);
4062*5113495bSYour Name 	qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
4063*5113495bSYour Name }
4064*5113495bSYour Name 
wma_release_wakelock(qdf_wake_lock_t * wl)4065*5113495bSYour Name void wma_release_wakelock(qdf_wake_lock_t *wl)
4066*5113495bSYour Name {
4067*5113495bSYour Name 	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4068*5113495bSYour Name 
4069*5113495bSYour Name 	qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4070*5113495bSYour Name 	qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
4071*5113495bSYour Name }
4072*5113495bSYour Name 
wma_send_vdev_stop_to_fw(t_wma_handle * wma,uint8_t vdev_id)4073*5113495bSYour Name QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4074*5113495bSYour Name {
4075*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
4076*5113495bSYour Name 	struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
4077*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme = NULL;
4078*5113495bSYour Name 
4079*5113495bSYour Name 	if (!wma_is_vdev_valid(vdev_id)) {
4080*5113495bSYour Name 		wma_err("Invalid vdev id:%d", vdev_id);
4081*5113495bSYour Name 		return status;
4082*5113495bSYour Name 	}
4083*5113495bSYour Name 
4084*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev);
4085*5113495bSYour Name 	if (!vdev_mlme) {
4086*5113495bSYour Name 		wma_err("Failed to get vdev mlme obj for vdev id %d", vdev_id);
4087*5113495bSYour Name 		return status;
4088*5113495bSYour Name 	}
4089*5113495bSYour Name 
4090*5113495bSYour Name 	/*
4091*5113495bSYour Name 	 * Reset the dynamic nss chains config to the ini values, as when the
4092*5113495bSYour Name 	 * vdev gets its started again, this would be a fresh connection,
4093*5113495bSYour Name 	 * and we dont want the config of previous connection to affect the
4094*5113495bSYour Name 	 * current connection.
4095*5113495bSYour Name 	 */
4096*5113495bSYour Name 	qdf_mem_copy(mlme_get_dynamic_vdev_config(iface->vdev),
4097*5113495bSYour Name 		     mlme_get_ini_vdev_config(iface->vdev),
4098*5113495bSYour Name 		     sizeof(struct wlan_mlme_nss_chains));
4099*5113495bSYour Name 
4100*5113495bSYour Name 	status = vdev_mgr_stop_send(vdev_mlme);
4101*5113495bSYour Name 
4102*5113495bSYour Name 	/*
4103*5113495bSYour Name 	 * If vdev_stop send to fw during channel switch, it means channel
4104*5113495bSYour Name 	 * switch failure. Clean flag chan_switch_in_progress.
4105*5113495bSYour Name 	 */
4106*5113495bSYour Name 	mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
4107*5113495bSYour Name 
4108*5113495bSYour Name 	return status;
4109*5113495bSYour Name }
4110*5113495bSYour Name 
wma_get_rcpi_req(WMA_HANDLE handle,struct sme_rcpi_req * rcpi_request)4111*5113495bSYour Name QDF_STATUS wma_get_rcpi_req(WMA_HANDLE handle,
4112*5113495bSYour Name 			    struct sme_rcpi_req *rcpi_request)
4113*5113495bSYour Name {
4114*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
4115*5113495bSYour Name 	struct rcpi_req  cmd = {0};
4116*5113495bSYour Name 	struct wma_txrx_node *iface;
4117*5113495bSYour Name 	struct sme_rcpi_req *node_rcpi_req;
4118*5113495bSYour Name 
4119*5113495bSYour Name 	wma_debug("Enter");
4120*5113495bSYour Name 	iface = &wma_handle->interfaces[rcpi_request->session_id];
4121*5113495bSYour Name 	/* command is in progress */
4122*5113495bSYour Name 	if (iface->rcpi_req) {
4123*5113495bSYour Name 		wma_err("previous rcpi request is pending");
4124*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4125*5113495bSYour Name 	}
4126*5113495bSYour Name 
4127*5113495bSYour Name 	node_rcpi_req = qdf_mem_malloc(sizeof(*node_rcpi_req));
4128*5113495bSYour Name 	if (!node_rcpi_req)
4129*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
4130*5113495bSYour Name 
4131*5113495bSYour Name 	*node_rcpi_req = *rcpi_request;
4132*5113495bSYour Name 	iface->rcpi_req = node_rcpi_req;
4133*5113495bSYour Name 
4134*5113495bSYour Name 	cmd.vdev_id = rcpi_request->session_id;
4135*5113495bSYour Name 	qdf_mem_copy(cmd.mac_addr, &rcpi_request->mac_addr, QDF_MAC_ADDR_SIZE);
4136*5113495bSYour Name 	cmd.measurement_type = rcpi_request->measurement_type;
4137*5113495bSYour Name 
4138*5113495bSYour Name 	if (wmi_unified_send_request_get_rcpi_cmd(wma_handle->wmi_handle,
4139*5113495bSYour Name 						  &cmd)) {
4140*5113495bSYour Name 		wma_err("Failed to send WMI_REQUEST_RCPI_CMDID");
4141*5113495bSYour Name 		iface->rcpi_req = NULL;
4142*5113495bSYour Name 		qdf_mem_free(node_rcpi_req);
4143*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4144*5113495bSYour Name 	}
4145*5113495bSYour Name 
4146*5113495bSYour Name 	wma_debug("Exit");
4147*5113495bSYour Name 
4148*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4149*5113495bSYour Name }
4150*5113495bSYour Name 
wma_rcpi_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)4151*5113495bSYour Name int wma_rcpi_event_handler(void *handle, uint8_t *cmd_param_info,
4152*5113495bSYour Name 			   uint32_t len)
4153*5113495bSYour Name {
4154*5113495bSYour Name 	struct rcpi_res res = {0};
4155*5113495bSYour Name 	struct sme_rcpi_req *rcpi_req;
4156*5113495bSYour Name 	struct qdf_mac_addr qdf_mac;
4157*5113495bSYour Name 	struct wma_txrx_node *iface;
4158*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4159*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
4160*5113495bSYour Name 
4161*5113495bSYour Name 	status = wmi_extract_rcpi_response_event(wma_handle->wmi_handle,
4162*5113495bSYour Name 						 cmd_param_info, &res);
4163*5113495bSYour Name 	if (status == QDF_STATUS_E_INVAL)
4164*5113495bSYour Name 		return -EINVAL;
4165*5113495bSYour Name 
4166*5113495bSYour Name 	if (res.vdev_id >= wma_handle->max_bssid) {
4167*5113495bSYour Name 		wma_err("received invalid vdev_id %d", res.vdev_id);
4168*5113495bSYour Name 		return -EINVAL;
4169*5113495bSYour Name 	}
4170*5113495bSYour Name 
4171*5113495bSYour Name 	iface = &wma_handle->interfaces[res.vdev_id];
4172*5113495bSYour Name 	if (!iface->rcpi_req) {
4173*5113495bSYour Name 		wmi_err("rcpi_req buffer not available");
4174*5113495bSYour Name 		return 0;
4175*5113495bSYour Name 	}
4176*5113495bSYour Name 
4177*5113495bSYour Name 	rcpi_req = iface->rcpi_req;
4178*5113495bSYour Name 	if (!rcpi_req->rcpi_callback) {
4179*5113495bSYour Name 		iface->rcpi_req = NULL;
4180*5113495bSYour Name 		qdf_mem_free(rcpi_req);
4181*5113495bSYour Name 		return 0;
4182*5113495bSYour Name 	}
4183*5113495bSYour Name 
4184*5113495bSYour Name 	if ((res.measurement_type == RCPI_MEASUREMENT_TYPE_INVALID) ||
4185*5113495bSYour Name 	    (res.vdev_id != rcpi_req->session_id) ||
4186*5113495bSYour Name 	    (res.measurement_type != rcpi_req->measurement_type) ||
4187*5113495bSYour Name 	    (qdf_mem_cmp(res.mac_addr, &rcpi_req->mac_addr,
4188*5113495bSYour Name 			 QDF_MAC_ADDR_SIZE))) {
4189*5113495bSYour Name 		wmi_err("Invalid rcpi_response");
4190*5113495bSYour Name 		iface->rcpi_req = NULL;
4191*5113495bSYour Name 		qdf_mem_free(rcpi_req);
4192*5113495bSYour Name 		return 0;
4193*5113495bSYour Name 	}
4194*5113495bSYour Name 
4195*5113495bSYour Name 	qdf_mem_copy(&qdf_mac, res.mac_addr, QDF_MAC_ADDR_SIZE);
4196*5113495bSYour Name 	(rcpi_req->rcpi_callback)(rcpi_req->rcpi_context, qdf_mac,
4197*5113495bSYour Name 				  res.rcpi_value, status);
4198*5113495bSYour Name 	iface->rcpi_req = NULL;
4199*5113495bSYour Name 	qdf_mem_free(rcpi_req);
4200*5113495bSYour Name 
4201*5113495bSYour Name 	return 0;
4202*5113495bSYour Name }
4203*5113495bSYour Name 
wma_send_vdev_down_to_fw(t_wma_handle * wma,uint8_t vdev_id)4204*5113495bSYour Name QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4205*5113495bSYour Name {
4206*5113495bSYour Name 	struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
4207*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme;
4208*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = iface->vdev;
4209*5113495bSYour Name 
4210*5113495bSYour Name 	if (!wma_is_vdev_valid(vdev_id)) {
4211*5113495bSYour Name 		wma_err("Invalid vdev id:%d", vdev_id);
4212*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4213*5113495bSYour Name 	}
4214*5113495bSYour Name 
4215*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
4216*5113495bSYour Name 	if (!vdev_mlme) {
4217*5113495bSYour Name 		wma_err("Failed to get vdev mlme obj for vdev id %d", vdev_id);
4218*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4219*5113495bSYour Name 	}
4220*5113495bSYour Name 
4221*5113495bSYour Name 	return vdev_mgr_down_send(vdev_mlme);
4222*5113495bSYour Name }
4223*5113495bSYour Name 
4224*5113495bSYour Name #ifdef WLAN_FEATURE_LINK_LAYER_STATS
wmi_to_sir_peer_type(enum wmi_peer_type type)4225*5113495bSYour Name tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4226*5113495bSYour Name {
4227*5113495bSYour Name 	switch (type) {
4228*5113495bSYour Name 	case WMI_PEER_TYPE_DEFAULT:
4229*5113495bSYour Name 		return WIFI_PEER_STA;
4230*5113495bSYour Name 	case WMI_PEER_TYPE_BSS:
4231*5113495bSYour Name 		return WIFI_PEER_AP;
4232*5113495bSYour Name 	case WMI_PEER_TYPE_TDLS:
4233*5113495bSYour Name 		return WIFI_PEER_TDLS;
4234*5113495bSYour Name 	case WMI_PEER_TYPE_NAN_DATA:
4235*5113495bSYour Name 		return WIFI_PEER_NAN;
4236*5113495bSYour Name 	default:
4237*5113495bSYour Name 		wma_err("Cannot map wmi_peer_type %d to HAL peer type", type);
4238*5113495bSYour Name 		return WIFI_PEER_INVALID;
4239*5113495bSYour Name 	}
4240*5113495bSYour Name }
4241*5113495bSYour Name #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
4242*5113495bSYour Name 
4243*5113495bSYour Name #ifdef FEATURE_WLAN_DYNAMIC_CVM
4244*5113495bSYour Name /**
4245*5113495bSYour Name  * wma_set_vc_mode_config() - set voltage corner mode config to FW.
4246*5113495bSYour Name  * @wma_handle:	pointer to wma handle.
4247*5113495bSYour Name  * @vc_bitmap:	value needs to set to firmware.
4248*5113495bSYour Name  *
4249*5113495bSYour Name  * At the time of driver startup, set operating voltage corner mode
4250*5113495bSYour Name  * for differenet phymode and bw configurations.
4251*5113495bSYour Name  *
4252*5113495bSYour Name  * Return: QDF_STATUS.
4253*5113495bSYour Name  */
wma_set_vc_mode_config(void * wma_handle,uint32_t vc_bitmap)4254*5113495bSYour Name QDF_STATUS wma_set_vc_mode_config(void *wma_handle,
4255*5113495bSYour Name 		uint32_t vc_bitmap)
4256*5113495bSYour Name {
4257*5113495bSYour Name 	int32_t ret;
4258*5113495bSYour Name 	tp_wma_handle wma = (tp_wma_handle)wma_handle;
4259*5113495bSYour Name 	struct pdev_params pdevparam = {};
4260*5113495bSYour Name 
4261*5113495bSYour Name 	pdevparam.param_id = WMI_PDEV_UPDATE_WDCVS_ALGO;
4262*5113495bSYour Name 	pdevparam.param_value = vc_bitmap;
4263*5113495bSYour Name 
4264*5113495bSYour Name 	ret = wmi_unified_pdev_param_send(wma->wmi_handle,
4265*5113495bSYour Name 			&pdevparam,
4266*5113495bSYour Name 			WMA_WILDCARD_PDEV_ID);
4267*5113495bSYour Name 	if (ret) {
4268*5113495bSYour Name 		wma_err("Fail to Set Voltage Corner config (0x%x)",
4269*5113495bSYour Name 			vc_bitmap);
4270*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4271*5113495bSYour Name 	}
4272*5113495bSYour Name 
4273*5113495bSYour Name 	wma_debug("Successfully Set Voltage Corner config (0x%x)",
4274*5113495bSYour Name 		vc_bitmap);
4275*5113495bSYour Name 
4276*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4277*5113495bSYour Name }
4278*5113495bSYour Name #endif
4279*5113495bSYour Name 
wma_chip_power_save_failure_detected_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)4280*5113495bSYour Name int wma_chip_power_save_failure_detected_handler(void *handle,
4281*5113495bSYour Name 						 uint8_t  *cmd_param_info,
4282*5113495bSYour Name 						 uint32_t len)
4283*5113495bSYour Name {
4284*5113495bSYour Name 	tp_wma_handle wma = (tp_wma_handle)handle;
4285*5113495bSYour Name 	WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4286*5113495bSYour Name 	wmi_chip_power_save_failure_detected_fixed_param  *event;
4287*5113495bSYour Name 	struct chip_pwr_save_fail_detected_params  pwr_save_fail_params;
4288*5113495bSYour Name 	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
4289*5113495bSYour Name 	if (wma_validate_handle(wma))
4290*5113495bSYour Name 		return -EINVAL;
4291*5113495bSYour Name 
4292*5113495bSYour Name 	if (!mac)
4293*5113495bSYour Name 		return -EINVAL;
4294*5113495bSYour Name 
4295*5113495bSYour Name 	if (!mac->sme.chip_power_save_fail_cb) {
4296*5113495bSYour Name 		wma_err("Callback not registered");
4297*5113495bSYour Name 		return -EINVAL;
4298*5113495bSYour Name 	}
4299*5113495bSYour Name 
4300*5113495bSYour Name 	param_buf =
4301*5113495bSYour Name 	(WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4302*5113495bSYour Name 	cmd_param_info;
4303*5113495bSYour Name 	if (!param_buf) {
4304*5113495bSYour Name 		wma_err("Invalid pwr_save_fail_params breached event");
4305*5113495bSYour Name 		return -EINVAL;
4306*5113495bSYour Name 	}
4307*5113495bSYour Name 	event = param_buf->fixed_param;
4308*5113495bSYour Name 	pwr_save_fail_params.failure_reason_code =
4309*5113495bSYour Name 				event->power_save_failure_reason_code;
4310*5113495bSYour Name 	pwr_save_fail_params.wake_lock_bitmap[0] =
4311*5113495bSYour Name 				event->protocol_wake_lock_bitmap[0];
4312*5113495bSYour Name 	pwr_save_fail_params.wake_lock_bitmap[1] =
4313*5113495bSYour Name 				event->protocol_wake_lock_bitmap[1];
4314*5113495bSYour Name 	pwr_save_fail_params.wake_lock_bitmap[2] =
4315*5113495bSYour Name 				event->protocol_wake_lock_bitmap[2];
4316*5113495bSYour Name 	pwr_save_fail_params.wake_lock_bitmap[3] =
4317*5113495bSYour Name 				event->protocol_wake_lock_bitmap[3];
4318*5113495bSYour Name 	mac->sme.chip_power_save_fail_cb(mac->hdd_handle,
4319*5113495bSYour Name 				&pwr_save_fail_params);
4320*5113495bSYour Name 
4321*5113495bSYour Name 	wma_debug("Invoke HDD pwr_save_fail callback");
4322*5113495bSYour Name 	return 0;
4323*5113495bSYour Name }
4324*5113495bSYour Name 
wma_roam_scan_stats_event_handler(void * handle,uint8_t * event,uint32_t len)4325*5113495bSYour Name int wma_roam_scan_stats_event_handler(void *handle, uint8_t *event,
4326*5113495bSYour Name 				      uint32_t len)
4327*5113495bSYour Name {
4328*5113495bSYour Name 	tp_wma_handle wma_handle;
4329*5113495bSYour Name 	wmi_unified_t wmi_handle;
4330*5113495bSYour Name 	struct sir_roam_scan_stats *roam_scan_stats_req = NULL;
4331*5113495bSYour Name 	struct wma_txrx_node *iface = NULL;
4332*5113495bSYour Name 	struct wmi_roam_scan_stats_res *res = NULL;
4333*5113495bSYour Name 	int ret = 0;
4334*5113495bSYour Name 	uint32_t vdev_id;
4335*5113495bSYour Name 	QDF_STATUS status;
4336*5113495bSYour Name 
4337*5113495bSYour Name 	wma_handle = handle;
4338*5113495bSYour Name 	if (wma_validate_handle(wma_handle))
4339*5113495bSYour Name 		return -EINVAL;
4340*5113495bSYour Name 
4341*5113495bSYour Name 	wmi_handle = wma_handle->wmi_handle;
4342*5113495bSYour Name 	if (wmi_validate_handle(wmi_handle))
4343*5113495bSYour Name 		return -EINVAL;
4344*5113495bSYour Name 
4345*5113495bSYour Name 	status = wmi_extract_roam_scan_stats_res_evt(wmi_handle, event,
4346*5113495bSYour Name 						     &vdev_id,
4347*5113495bSYour Name 						     &res);
4348*5113495bSYour Name 
4349*5113495bSYour Name 	/* vdev_id can be invalid though status is success, hence validate */
4350*5113495bSYour Name 	if (vdev_id >= wma_handle->max_bssid) {
4351*5113495bSYour Name 		wma_err("Received invalid vdev_id: %d", vdev_id);
4352*5113495bSYour Name 		ret  = -EINVAL;
4353*5113495bSYour Name 		goto free_res;
4354*5113495bSYour Name 	}
4355*5113495bSYour Name 
4356*5113495bSYour Name 	/* Get interface for valid vdev_id */
4357*5113495bSYour Name 	iface = &wma_handle->interfaces[vdev_id];
4358*5113495bSYour Name 	if (!iface) {
4359*5113495bSYour Name 		wmi_err("Interface not available for vdev_id: %d", vdev_id);
4360*5113495bSYour Name 		ret  = -EINVAL;
4361*5113495bSYour Name 		goto free_res;
4362*5113495bSYour Name 	}
4363*5113495bSYour Name 
4364*5113495bSYour Name 	roam_scan_stats_req = iface->roam_scan_stats_req;
4365*5113495bSYour Name 	iface->roam_scan_stats_req = NULL;
4366*5113495bSYour Name 	if (!roam_scan_stats_req) {
4367*5113495bSYour Name 		wmi_err("No pending request vdev_id: %d", vdev_id);
4368*5113495bSYour Name 		ret  = -EINVAL;
4369*5113495bSYour Name 		goto free_res;
4370*5113495bSYour Name 	}
4371*5113495bSYour Name 
4372*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status) ||
4373*5113495bSYour Name 	    !roam_scan_stats_req->cb ||
4374*5113495bSYour Name 	    roam_scan_stats_req->vdev_id != vdev_id) {
4375*5113495bSYour Name 		wmi_err("roam_scan_stats buffer not available");
4376*5113495bSYour Name 		ret = -EINVAL;
4377*5113495bSYour Name 		goto free_roam_scan_stats_req;
4378*5113495bSYour Name 	}
4379*5113495bSYour Name 
4380*5113495bSYour Name 	roam_scan_stats_req->cb(roam_scan_stats_req->context, res);
4381*5113495bSYour Name 
4382*5113495bSYour Name free_roam_scan_stats_req:
4383*5113495bSYour Name 	qdf_mem_free(roam_scan_stats_req);
4384*5113495bSYour Name 	roam_scan_stats_req = NULL;
4385*5113495bSYour Name 
4386*5113495bSYour Name free_res:
4387*5113495bSYour Name 	qdf_mem_free(res);
4388*5113495bSYour Name 	res = NULL;
4389*5113495bSYour Name 
4390*5113495bSYour Name 	return ret;
4391*5113495bSYour Name }
4392*5113495bSYour Name 
wma_get_roam_scan_stats(WMA_HANDLE handle,struct sir_roam_scan_stats * req)4393*5113495bSYour Name QDF_STATUS wma_get_roam_scan_stats(WMA_HANDLE handle,
4394*5113495bSYour Name 				   struct sir_roam_scan_stats *req)
4395*5113495bSYour Name {
4396*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)handle;
4397*5113495bSYour Name 	struct wmi_roam_scan_stats_req cmd = {0};
4398*5113495bSYour Name 	struct wma_txrx_node *iface;
4399*5113495bSYour Name 	struct sir_roam_scan_stats *node_req = NULL;
4400*5113495bSYour Name 
4401*5113495bSYour Name 	wma_debug("Enter");
4402*5113495bSYour Name 	iface = &wma_handle->interfaces[req->vdev_id];
4403*5113495bSYour Name 	/* command is in progress */
4404*5113495bSYour Name 	if (iface->roam_scan_stats_req) {
4405*5113495bSYour Name 		wma_err("previous roam scan stats req is pending");
4406*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4407*5113495bSYour Name 	}
4408*5113495bSYour Name 
4409*5113495bSYour Name 	node_req = qdf_mem_malloc(sizeof(*node_req));
4410*5113495bSYour Name 	if (!node_req)
4411*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
4412*5113495bSYour Name 
4413*5113495bSYour Name 	*node_req = *req;
4414*5113495bSYour Name 	iface->roam_scan_stats_req = node_req;
4415*5113495bSYour Name 	cmd.vdev_id = req->vdev_id;
4416*5113495bSYour Name 
4417*5113495bSYour Name 	if (wmi_unified_send_roam_scan_stats_cmd(wma_handle->wmi_handle,
4418*5113495bSYour Name 						 &cmd)) {
4419*5113495bSYour Name 		wma_err("Failed to send WMI_REQUEST_ROAM_SCAN_STATS_CMDID");
4420*5113495bSYour Name 		iface->roam_scan_stats_req = NULL;
4421*5113495bSYour Name 		qdf_mem_free(node_req);
4422*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4423*5113495bSYour Name 	}
4424*5113495bSYour Name 
4425*5113495bSYour Name 	wma_debug("Exit");
4426*5113495bSYour Name 
4427*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4428*5113495bSYour Name }
4429*5113495bSYour Name 
wma_remove_bss_peer_on_failure(tp_wma_handle wma,uint8_t vdev_id)4430*5113495bSYour Name void wma_remove_bss_peer_on_failure(tp_wma_handle wma, uint8_t vdev_id)
4431*5113495bSYour Name {
4432*5113495bSYour Name 	uint8_t pdev_id = WMI_PDEV_ID_SOC;
4433*5113495bSYour Name 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4434*5113495bSYour Name 	QDF_STATUS status;
4435*5113495bSYour Name 	struct qdf_mac_addr bss_peer;
4436*5113495bSYour Name 	struct wma_txrx_node *iface;
4437*5113495bSYour Name 
4438*5113495bSYour Name 	iface = &wma->interfaces[vdev_id];
4439*5113495bSYour Name 
4440*5113495bSYour Name 	status = wlan_vdev_get_bss_peer_mac(iface->vdev, &bss_peer);
4441*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
4442*5113495bSYour Name 		return;
4443*5113495bSYour Name 
4444*5113495bSYour Name 	wma_err("connect failure for vdev %d", vdev_id);
4445*5113495bSYour Name 
4446*5113495bSYour Name 	if (!cdp_find_peer_exist(soc, pdev_id, bss_peer.bytes)) {
4447*5113495bSYour Name 		wma_err("Failed to find peer "QDF_MAC_ADDR_FMT,
4448*5113495bSYour Name 			QDF_MAC_ADDR_REF(bss_peer.bytes));
4449*5113495bSYour Name 		return;
4450*5113495bSYour Name 	}
4451*5113495bSYour Name 
4452*5113495bSYour Name 	wma_delete_peer_mlo(wma->psoc, bss_peer.bytes);
4453*5113495bSYour Name 
4454*5113495bSYour Name 	wma_remove_peer(wma, bss_peer.bytes, vdev_id, false);
4455*5113495bSYour Name }
4456*5113495bSYour Name 
wma_remove_bss_peer_before_join(tp_wma_handle wma,uint8_t vdev_id,void * cm_join_req)4457*5113495bSYour Name QDF_STATUS wma_remove_bss_peer_before_join(
4458*5113495bSYour Name 	tp_wma_handle wma, uint8_t vdev_id,
4459*5113495bSYour Name 	void *cm_join_req)
4460*5113495bSYour Name {
4461*5113495bSYour Name 	uint8_t *mac_addr;
4462*5113495bSYour Name 	struct wma_target_req *del_req;
4463*5113495bSYour Name 	QDF_STATUS qdf_status;
4464*5113495bSYour Name 	struct qdf_mac_addr bssid;
4465*5113495bSYour Name 	enum QDF_OPMODE mode;
4466*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
4467*5113495bSYour Name 
4468*5113495bSYour Name 	if (!wma || !wma->interfaces)
4469*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4470*5113495bSYour Name 
4471*5113495bSYour Name 	if (vdev_id >= WLAN_MAX_VDEVS) {
4472*5113495bSYour Name 		wma_err("Invalid vdev id %d", vdev_id);
4473*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4474*5113495bSYour Name 	}
4475*5113495bSYour Name 	vdev = wma->interfaces[vdev_id].vdev;
4476*5113495bSYour Name 	if (!vdev) {
4477*5113495bSYour Name 		wma_err("Invalid vdev, %d", vdev_id);
4478*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4479*5113495bSYour Name 	}
4480*5113495bSYour Name 
4481*5113495bSYour Name 	mode = wlan_vdev_mlme_get_opmode(vdev);
4482*5113495bSYour Name 	if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE) {
4483*5113495bSYour Name 		wma_err("unexpected mode %d vdev %d", mode, vdev_id);
4484*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4485*5113495bSYour Name 	}
4486*5113495bSYour Name 
4487*5113495bSYour Name 	qdf_status = wlan_vdev_get_bss_peer_mac(vdev, &bssid);
4488*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
4489*5113495bSYour Name 		wma_err("Failed to get bssid for vdev_id: %d", vdev_id);
4490*5113495bSYour Name 		return qdf_status;
4491*5113495bSYour Name 	}
4492*5113495bSYour Name 	mac_addr = bssid.bytes;
4493*5113495bSYour Name 
4494*5113495bSYour Name 	wma_delete_peer_mlo(wma->psoc, mac_addr);
4495*5113495bSYour Name 
4496*5113495bSYour Name 	qdf_status = wma_remove_peer(wma, mac_addr, vdev_id, false);
4497*5113495bSYour Name 
4498*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
4499*5113495bSYour Name 		wma_err("wma_remove_peer failed vdev_id:%d", vdev_id);
4500*5113495bSYour Name 		return qdf_status;
4501*5113495bSYour Name 	}
4502*5113495bSYour Name 
4503*5113495bSYour Name 	if (cds_is_driver_recovering())
4504*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4505*5113495bSYour Name 
4506*5113495bSYour Name 	if (wmi_service_enabled(wma->wmi_handle,
4507*5113495bSYour Name 				wmi_service_sync_delete_cmds)) {
4508*5113495bSYour Name 		wma_debug("Wait for the peer delete. vdev_id %d", vdev_id);
4509*5113495bSYour Name 		del_req = wma_fill_hold_req(wma, vdev_id,
4510*5113495bSYour Name 					    WMA_DELETE_STA_REQ,
4511*5113495bSYour Name 					    WMA_DELETE_STA_CONNECT_RSP,
4512*5113495bSYour Name 					    cm_join_req,
4513*5113495bSYour Name 					    WMA_DELETE_STA_TIMEOUT);
4514*5113495bSYour Name 		if (!del_req) {
4515*5113495bSYour Name 			wma_err("Failed to allocate request. vdev_id %d",
4516*5113495bSYour Name 				vdev_id);
4517*5113495bSYour Name 			qdf_status = QDF_STATUS_E_NOMEM;
4518*5113495bSYour Name 		} else {
4519*5113495bSYour Name 			qdf_status = QDF_STATUS_E_PENDING;
4520*5113495bSYour Name 		}
4521*5113495bSYour Name 	}
4522*5113495bSYour Name 
4523*5113495bSYour Name 	return qdf_status;
4524*5113495bSYour Name }
4525*5113495bSYour Name 
wma_sta_vdev_up_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4526*5113495bSYour Name QDF_STATUS wma_sta_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
4527*5113495bSYour Name 				uint16_t data_len, void *data)
4528*5113495bSYour Name {
4529*5113495bSYour Name 	uint8_t vdev_id;
4530*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4531*5113495bSYour Name 	QDF_STATUS status;
4532*5113495bSYour Name 	struct wma_txrx_node *iface;
4533*5113495bSYour Name 
4534*5113495bSYour Name 	if (!wma)
4535*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4536*5113495bSYour Name 
4537*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
4538*5113495bSYour Name 	iface = &wma->interfaces[vdev_id];
4539*5113495bSYour Name 	vdev_mlme->proto.sta.assoc_id = iface->aid;
4540*5113495bSYour Name 
4541*5113495bSYour Name 	status = vdev_mgr_up_send(vdev_mlme);
4542*5113495bSYour Name 
4543*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
4544*5113495bSYour Name 		wma_err("Failed to send vdev up cmd: vdev %d", vdev_id);
4545*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
4546*5113495bSYour Name 	} else {
4547*5113495bSYour Name 		wma_set_vdev_mgmt_rate(wma, vdev_id);
4548*5113495bSYour Name 		if (iface->beacon_filter_enabled)
4549*5113495bSYour Name 			wma_add_beacon_filter(
4550*5113495bSYour Name 					wma,
4551*5113495bSYour Name 					&iface->beacon_filter);
4552*5113495bSYour Name 	}
4553*5113495bSYour Name 
4554*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4555*5113495bSYour Name }
4556*5113495bSYour Name 
wma_get_hidden_ssid_restart_in_progress(struct wma_txrx_node * iface)4557*5113495bSYour Name bool wma_get_hidden_ssid_restart_in_progress(struct wma_txrx_node *iface)
4558*5113495bSYour Name {
4559*5113495bSYour Name 	if (!iface)
4560*5113495bSYour Name 		return false;
4561*5113495bSYour Name 
4562*5113495bSYour Name 	return ap_mlme_is_hidden_ssid_restart_in_progress(iface->vdev);
4563*5113495bSYour Name }
4564*5113495bSYour Name 
wma_get_channel_switch_in_progress(struct wma_txrx_node * iface)4565*5113495bSYour Name bool wma_get_channel_switch_in_progress(struct wma_txrx_node *iface)
4566*5113495bSYour Name {
4567*5113495bSYour Name 	if (!iface)
4568*5113495bSYour Name 		return false;
4569*5113495bSYour Name 
4570*5113495bSYour Name 	return mlme_is_chan_switch_in_progress(iface->vdev);
4571*5113495bSYour Name }
4572*5113495bSYour Name 
wma_vdev_send_start_resp(tp_wma_handle wma,struct add_bss_rsp * add_bss_rsp)4573*5113495bSYour Name static QDF_STATUS wma_vdev_send_start_resp(tp_wma_handle wma,
4574*5113495bSYour Name 					  struct add_bss_rsp *add_bss_rsp)
4575*5113495bSYour Name {
4576*5113495bSYour Name 	wma_debug("Sending add bss rsp to umac(vdev %d status %d)",
4577*5113495bSYour Name 		 add_bss_rsp->vdev_id, add_bss_rsp->status);
4578*5113495bSYour Name 	lim_handle_add_bss_rsp(wma->mac_context, add_bss_rsp);
4579*5113495bSYour Name 
4580*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4581*5113495bSYour Name }
4582*5113495bSYour Name 
wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4583*5113495bSYour Name QDF_STATUS wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
4584*5113495bSYour Name 					    uint16_t data_len, void *data)
4585*5113495bSYour Name {
4586*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4587*5113495bSYour Name 	enum vdev_assoc_type assoc_type;
4588*5113495bSYour Name 
4589*5113495bSYour Name 	if (!wma)
4590*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
4591*5113495bSYour Name 
4592*5113495bSYour Name 	if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) {
4593*5113495bSYour Name 		mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
4594*5113495bSYour Name 		lim_process_switch_channel_rsp(wma->mac_context, data);
4595*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4596*5113495bSYour Name 	}
4597*5113495bSYour Name 
4598*5113495bSYour Name 	assoc_type = mlme_get_assoc_type(vdev_mlme->vdev);
4599*5113495bSYour Name 	switch (assoc_type) {
4600*5113495bSYour Name 	case VDEV_ASSOC:
4601*5113495bSYour Name 	case VDEV_REASSOC:
4602*5113495bSYour Name 		lim_process_switch_channel_rsp(wma->mac_context, data);
4603*5113495bSYour Name 		break;
4604*5113495bSYour Name 	case VDEV_FT_REASSOC:
4605*5113495bSYour Name 		lim_handle_add_bss_rsp(wma->mac_context, data);
4606*5113495bSYour Name 		break;
4607*5113495bSYour Name 	default:
4608*5113495bSYour Name 		wma_err("assoc_type %d is invalid", assoc_type);
4609*5113495bSYour Name 	}
4610*5113495bSYour Name 
4611*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4612*5113495bSYour Name }
4613*5113495bSYour Name 
wma_ap_mlme_vdev_start_continue(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4614*5113495bSYour Name QDF_STATUS wma_ap_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
4615*5113495bSYour Name 					   uint16_t data_len, void *data)
4616*5113495bSYour Name {
4617*5113495bSYour Name 	tp_wma_handle wma;
4618*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4619*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = vdev_mlme->vdev;
4620*5113495bSYour Name 	uint8_t vdev_id;
4621*5113495bSYour Name 
4622*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
4623*5113495bSYour Name 	if (!wma)
4624*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4625*5113495bSYour Name 
4626*5113495bSYour Name 	if (mlme_is_chan_switch_in_progress(vdev)) {
4627*5113495bSYour Name 		mlme_set_chan_switch_in_progress(vdev, false);
4628*5113495bSYour Name 		lim_process_switch_channel_rsp(wma->mac_context, data);
4629*5113495bSYour Name 	} else if (ap_mlme_is_hidden_ssid_restart_in_progress(vdev)) {
4630*5113495bSYour Name 		vdev_id = vdev->vdev_objmgr.vdev_id;
4631*5113495bSYour Name 		lim_process_mlm_update_hidden_ssid_rsp(wma->mac_context,
4632*5113495bSYour Name 						       vdev_id);
4633*5113495bSYour Name 		ap_mlme_set_hidden_ssid_restart_in_progress(vdev, false);
4634*5113495bSYour Name 	} else {
4635*5113495bSYour Name 		status = wma_vdev_send_start_resp(wma, data);
4636*5113495bSYour Name 	}
4637*5113495bSYour Name 
4638*5113495bSYour Name 	return status;
4639*5113495bSYour Name }
4640*5113495bSYour Name 
wma_mlme_vdev_stop_continue(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4641*5113495bSYour Name QDF_STATUS wma_mlme_vdev_stop_continue(struct vdev_mlme_obj *vdev_mlme,
4642*5113495bSYour Name 				       uint16_t data_len, void *data)
4643*5113495bSYour Name {
4644*5113495bSYour Name 	return __wma_handle_vdev_stop_rsp(
4645*5113495bSYour Name 			(struct vdev_stop_response *)data);
4646*5113495bSYour Name }
4647*5113495bSYour Name 
wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4648*5113495bSYour Name QDF_STATUS wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
4649*5113495bSYour Name 				      uint16_t data_len, void *data)
4650*5113495bSYour Name {
4651*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4652*5113495bSYour Name 
4653*5113495bSYour Name 	if (!wma)
4654*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4655*5113495bSYour Name 
4656*5113495bSYour Name 	return wma_send_vdev_down(wma, data);
4657*5113495bSYour Name }
4658*5113495bSYour Name 
4659*5113495bSYour Name QDF_STATUS
wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4660*5113495bSYour Name wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme,
4661*5113495bSYour Name 				   uint16_t data_len, void *data)
4662*5113495bSYour Name {
4663*5113495bSYour Name 	tp_wma_handle wma;
4664*5113495bSYour Name 	QDF_STATUS status;
4665*5113495bSYour Name 	uint32_t vdev_stop_type;
4666*5113495bSYour Name 	struct del_bss_resp *resp = (struct del_bss_resp *)data;
4667*5113495bSYour Name 
4668*5113495bSYour Name 	if (mlme_is_connection_fail(vdev_mlme->vdev) ||
4669*5113495bSYour Name 	    mlme_get_vdev_start_failed(vdev_mlme->vdev)) {
4670*5113495bSYour Name 		wma_debug("Vdev start req failed, no action required");
4671*5113495bSYour Name 		mlme_set_connection_fail(vdev_mlme->vdev, false);
4672*5113495bSYour Name 		mlme_set_vdev_start_failed(vdev_mlme->vdev, false);
4673*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4674*5113495bSYour Name 	}
4675*5113495bSYour Name 
4676*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
4677*5113495bSYour Name 	if (!wma) {
4678*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
4679*5113495bSYour Name 		goto end;
4680*5113495bSYour Name 	}
4681*5113495bSYour Name 
4682*5113495bSYour Name 	status = mlme_get_vdev_stop_type(wma->interfaces[resp->vdev_id].vdev,
4683*5113495bSYour Name 					 &vdev_stop_type);
4684*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
4685*5113495bSYour Name 		wma_err("Failed to get vdev stop type for vdev_id: %d",
4686*5113495bSYour Name 			resp->vdev_id);
4687*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
4688*5113495bSYour Name 		goto end;
4689*5113495bSYour Name 	}
4690*5113495bSYour Name 
4691*5113495bSYour Name 	/*
4692*5113495bSYour Name 	 * Need reset vdev_stop_type to 0 here, otherwise the vdev_stop_type
4693*5113495bSYour Name 	 * would be taken to next BSS stop in some stress test, then cause
4694*5113495bSYour Name 	 * unexpected behavior.
4695*5113495bSYour Name 	 */
4696*5113495bSYour Name 	mlme_set_vdev_stop_type(wma->interfaces[resp->vdev_id].vdev, 0);
4697*5113495bSYour Name 
4698*5113495bSYour Name 	if (vdev_stop_type == WMA_DELETE_BSS_HO_FAIL_REQ) {
4699*5113495bSYour Name 		resp->status = QDF_STATUS_SUCCESS;
4700*5113495bSYour Name 		wma_send_msg_high_priority(wma, WMA_DELETE_BSS_HO_FAIL_RSP,
4701*5113495bSYour Name 					   (void *)resp, 0);
4702*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4703*5113495bSYour Name 	}
4704*5113495bSYour Name 
4705*5113495bSYour Name 	if (vdev_stop_type == WMA_SET_LINK_STATE) {
4706*5113495bSYour Name 		lim_join_result_callback(wma->mac_context,
4707*5113495bSYour Name 					 wlan_vdev_get_id(vdev_mlme->vdev));
4708*5113495bSYour Name 	} else {
4709*5113495bSYour Name 		wma_send_del_bss_response(wma, resp);
4710*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
4711*5113495bSYour Name 	}
4712*5113495bSYour Name 
4713*5113495bSYour Name end:
4714*5113495bSYour Name 	qdf_mem_free(resp);
4715*5113495bSYour Name 
4716*5113495bSYour Name 	return status;
4717*5113495bSYour Name }
4718*5113495bSYour Name 
wma_ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj * vdev_mlme,enum vdev_cmd_type type,uint16_t data_len,void * data)4719*5113495bSYour Name QDF_STATUS wma_ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
4720*5113495bSYour Name 					    enum vdev_cmd_type type,
4721*5113495bSYour Name 					    uint16_t data_len, void *data)
4722*5113495bSYour Name {
4723*5113495bSYour Name 	tp_wma_handle wma;
4724*5113495bSYour Name 	struct add_bss_rsp *add_bss_rsp = data;
4725*5113495bSYour Name 
4726*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
4727*5113495bSYour Name 	if (!wma)
4728*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4729*5113495bSYour Name 
4730*5113495bSYour Name 	if (wma_send_vdev_stop_to_fw(wma, add_bss_rsp->vdev_id))
4731*5113495bSYour Name 		wma_err("Failed to send vdev stop for vdev id %d",
4732*5113495bSYour Name 			 add_bss_rsp->vdev_id);
4733*5113495bSYour Name 
4734*5113495bSYour Name 	wma_remove_bss_peer_on_failure(wma, add_bss_rsp->vdev_id);
4735*5113495bSYour Name 
4736*5113495bSYour Name 	return wma_vdev_send_start_resp(wma, add_bss_rsp);
4737*5113495bSYour Name }
4738*5113495bSYour Name 
4739*5113495bSYour Name #ifdef QCA_SUPPORT_CP_STATS
wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4740*5113495bSYour Name QDF_STATUS wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
4741*5113495bSYour Name 					    uint16_t data_len, void *data)
4742*5113495bSYour Name {
4743*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4744*5113495bSYour Name 	struct request_info info = {0};
4745*5113495bSYour Name 	uint8_t interval = 1;
4746*5113495bSYour Name 	QDF_STATUS status;
4747*5113495bSYour Name 	int pdev;
4748*5113495bSYour Name 
4749*5113495bSYour Name 	if (!wma)
4750*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4751*5113495bSYour Name 
4752*5113495bSYour Name 	if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev))
4753*5113495bSYour Name 		mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
4754*5113495bSYour Name 
4755*5113495bSYour Name 	pdev = target_if_mc_cp_get_mac_id(vdev_mlme);
4756*5113495bSYour Name 
4757*5113495bSYour Name 	/* Cancel periodic pdev stats update if running for other mac */
4758*5113495bSYour Name 	status = wma_cli_set_command(vdev_mlme->vdev->vdev_objmgr.vdev_id,
4759*5113495bSYour Name 				     wmi_pdev_param_pdev_stats_update_period,
4760*5113495bSYour Name 				     0, PDEV_CMD);
4761*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
4762*5113495bSYour Name 		pe_err("failed to clear fw stats request = %d", status);
4763*5113495bSYour Name 
4764*5113495bSYour Name 	/* send periodic fw stats to get chan noise floor for monitor mode */
4765*5113495bSYour Name 	info.vdev_id = vdev_mlme->vdev->vdev_objmgr.vdev_id;
4766*5113495bSYour Name 	info.pdev_id = pdev;
4767*5113495bSYour Name 	status = tgt_send_mc_cp_stats_req((wlan_vdev_get_psoc(vdev_mlme->vdev)),
4768*5113495bSYour Name 					  TYPE_STATION_STATS,
4769*5113495bSYour Name 					  &info);
4770*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
4771*5113495bSYour Name 		pe_err("failed to send fw stats request = %d", status);
4772*5113495bSYour Name 
4773*5113495bSYour Name 	status = wma_cli_set2_command(vdev_mlme->vdev->vdev_objmgr.vdev_id,
4774*5113495bSYour Name 				      wmi_pdev_param_pdev_stats_update_period,
4775*5113495bSYour Name 				      interval * 2000, pdev, PDEV_CMD);
4776*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
4777*5113495bSYour Name 		pe_err("failed to send fw stats request = %d", status);
4778*5113495bSYour Name 
4779*5113495bSYour Name 	lim_process_switch_channel_rsp(wma->mac_context, data);
4780*5113495bSYour Name 
4781*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4782*5113495bSYour Name }
4783*5113495bSYour Name #else
wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4784*5113495bSYour Name QDF_STATUS wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
4785*5113495bSYour Name 					    uint16_t data_len, void *data)
4786*5113495bSYour Name {
4787*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4788*5113495bSYour Name 
4789*5113495bSYour Name 	if (!wma)
4790*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4791*5113495bSYour Name 
4792*5113495bSYour Name 	if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev))
4793*5113495bSYour Name 		mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
4794*5113495bSYour Name 
4795*5113495bSYour Name 	lim_process_switch_channel_rsp(wma->mac_context, data);
4796*5113495bSYour Name 
4797*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
4798*5113495bSYour Name }
4799*5113495bSYour Name #endif /* QCA_SUPPORT_CP_STATS */
4800*5113495bSYour Name 
wma_mon_mlme_vdev_up_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4801*5113495bSYour Name QDF_STATUS wma_mon_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
4802*5113495bSYour Name 				     uint16_t data_len, void *data)
4803*5113495bSYour Name {
4804*5113495bSYour Name 	uint8_t vdev_id;
4805*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4806*5113495bSYour Name 	QDF_STATUS status;
4807*5113495bSYour Name 	struct wma_txrx_node *iface;
4808*5113495bSYour Name 
4809*5113495bSYour Name 	if (!wma)
4810*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4811*5113495bSYour Name 
4812*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
4813*5113495bSYour Name 	iface = &wma->interfaces[vdev_id];
4814*5113495bSYour Name 	vdev_mlme->proto.sta.assoc_id = 0;
4815*5113495bSYour Name 
4816*5113495bSYour Name 	status = vdev_mgr_up_send(vdev_mlme);
4817*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
4818*5113495bSYour Name 		wma_err("Failed to send vdev up cmd: vdev %d", vdev_id);
4819*5113495bSYour Name 
4820*5113495bSYour Name 	return status;
4821*5113495bSYour Name }
4822*5113495bSYour Name 
wma_mon_mlme_vdev_stop_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4823*5113495bSYour Name QDF_STATUS wma_mon_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
4824*5113495bSYour Name 				       uint16_t data_len, void *data)
4825*5113495bSYour Name {
4826*5113495bSYour Name 	uint8_t vdev_id;
4827*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4828*5113495bSYour Name 	QDF_STATUS status;
4829*5113495bSYour Name 
4830*5113495bSYour Name 	if (!wma)
4831*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4832*5113495bSYour Name 
4833*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
4834*5113495bSYour Name 
4835*5113495bSYour Name 	status = wma_send_vdev_stop_to_fw(wma, vdev_id);
4836*5113495bSYour Name 
4837*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
4838*5113495bSYour Name 		wma_err("Failed to send vdev stop cmd: vdev %d", vdev_id);
4839*5113495bSYour Name 
4840*5113495bSYour Name 	wlan_vdev_mlme_sm_deliver_evt(vdev_mlme->vdev,
4841*5113495bSYour Name 				      WLAN_VDEV_SM_EV_MLME_DOWN_REQ,
4842*5113495bSYour Name 				      0,
4843*5113495bSYour Name 				      NULL);
4844*5113495bSYour Name 
4845*5113495bSYour Name 	return status;
4846*5113495bSYour Name }
4847*5113495bSYour Name 
wma_mon_mlme_vdev_down_send(struct vdev_mlme_obj * vdev_mlme,uint16_t data_len,void * data)4848*5113495bSYour Name QDF_STATUS wma_mon_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
4849*5113495bSYour Name 				       uint16_t data_len, void *data)
4850*5113495bSYour Name {
4851*5113495bSYour Name 	uint8_t vdev_id;
4852*5113495bSYour Name 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4853*5113495bSYour Name 	QDF_STATUS status;
4854*5113495bSYour Name 
4855*5113495bSYour Name 	if (!wma)
4856*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
4857*5113495bSYour Name 
4858*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
4859*5113495bSYour Name 
4860*5113495bSYour Name 	status = wma_send_vdev_down_to_fw(wma, vdev_id);
4861*5113495bSYour Name 
4862*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
4863*5113495bSYour Name 		wma_err("Failed to send vdev down cmd: vdev %d", vdev_id);
4864*5113495bSYour Name 
4865*5113495bSYour Name 	wlan_vdev_mlme_sm_deliver_evt(vdev_mlme->vdev,
4866*5113495bSYour Name 				      WLAN_VDEV_SM_EV_DOWN_COMPLETE,
4867*5113495bSYour Name 				      0,
4868*5113495bSYour Name 				      NULL);
4869*5113495bSYour Name 
4870*5113495bSYour Name 	return status;
4871*5113495bSYour Name }
4872*5113495bSYour Name 
4873*5113495bSYour Name #ifdef FEATURE_WLM_STATS
wma_wlm_stats_req(int vdev_id,uint32_t bitmask,uint32_t max_size,wma_wlm_stats_cb cb,void * cookie)4874*5113495bSYour Name int wma_wlm_stats_req(int vdev_id, uint32_t bitmask, uint32_t max_size,
4875*5113495bSYour Name 		      wma_wlm_stats_cb cb, void *cookie)
4876*5113495bSYour Name {
4877*5113495bSYour Name 	tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
4878*5113495bSYour Name 	wmi_unified_t wmi_handle;
4879*5113495bSYour Name 	wmi_buf_t wmi_buf;
4880*5113495bSYour Name 	uint32_t buf_len, tlv_tag, tlv_len;
4881*5113495bSYour Name 	wmi_request_wlm_stats_cmd_fixed_param *cmd;
4882*5113495bSYour Name 	QDF_STATUS status;
4883*5113495bSYour Name 
4884*5113495bSYour Name 	if (!wma_handle)
4885*5113495bSYour Name 		return -EINVAL;
4886*5113495bSYour Name 
4887*5113495bSYour Name 	wmi_handle = wma_handle->wmi_handle;
4888*5113495bSYour Name 	if (wmi_validate_handle(wmi_handle))
4889*5113495bSYour Name 		return -EINVAL;
4890*5113495bSYour Name 
4891*5113495bSYour Name 	if (!wmi_service_enabled(wmi_handle, wmi_service_wlm_stats_support)) {
4892*5113495bSYour Name 		wma_err("Feature not supported by firmware");
4893*5113495bSYour Name 		return -ENOTSUPP;
4894*5113495bSYour Name 	}
4895*5113495bSYour Name 
4896*5113495bSYour Name 	wma_handle->wlm_data.wlm_stats_cookie = cookie;
4897*5113495bSYour Name 	wma_handle->wlm_data.wlm_stats_callback = cb;
4898*5113495bSYour Name 	wma_handle->wlm_data.wlm_stats_max_size = max_size;
4899*5113495bSYour Name 
4900*5113495bSYour Name 	buf_len = sizeof(*cmd);
4901*5113495bSYour Name 	wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, buf_len);
4902*5113495bSYour Name 	if (!wmi_buf)
4903*5113495bSYour Name 		return -EINVAL;
4904*5113495bSYour Name 
4905*5113495bSYour Name 	cmd = (void *)wmi_buf_data(wmi_buf);
4906*5113495bSYour Name 
4907*5113495bSYour Name 	tlv_tag = WMITLV_TAG_STRUC_wmi_request_wlm_stats_cmd_fixed_param;
4908*5113495bSYour Name 	tlv_len =
4909*5113495bSYour Name 		WMITLV_GET_STRUCT_TLVLEN(wmi_request_wlm_stats_cmd_fixed_param);
4910*5113495bSYour Name 	WMITLV_SET_HDR(&cmd->tlv_header, tlv_tag, tlv_len);
4911*5113495bSYour Name 
4912*5113495bSYour Name 	cmd->vdev_id = vdev_id;
4913*5113495bSYour Name 	cmd->request_bitmask = bitmask;
4914*5113495bSYour Name 	status = wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, buf_len,
4915*5113495bSYour Name 				      WMI_REQUEST_WLM_STATS_CMDID);
4916*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
4917*5113495bSYour Name 		wmi_buf_free(wmi_buf);
4918*5113495bSYour Name 		return -EINVAL;
4919*5113495bSYour Name 	}
4920*5113495bSYour Name 	/* info logging per test team request */
4921*5113495bSYour Name 	wma_info("---->sent request for vdev:%d", vdev_id);
4922*5113495bSYour Name 
4923*5113495bSYour Name 	return 0;
4924*5113495bSYour Name }
4925*5113495bSYour Name 
wma_wlm_stats_rsp(void * wma_ctx,uint8_t * event,uint32_t evt_len)4926*5113495bSYour Name int wma_wlm_stats_rsp(void *wma_ctx, uint8_t *event, uint32_t evt_len)
4927*5113495bSYour Name {
4928*5113495bSYour Name 	WMI_WLM_STATS_EVENTID_param_tlvs *param_tlvs;
4929*5113495bSYour Name 	wmi_wlm_stats_event_fixed_param *param;
4930*5113495bSYour Name 	tp_wma_handle wma_handle = wma_ctx;
4931*5113495bSYour Name 	char *data;
4932*5113495bSYour Name 	void *cookie;
4933*5113495bSYour Name 	uint32_t *raw_data;
4934*5113495bSYour Name 	uint32_t len, buffer_size, raw_data_num, i;
4935*5113495bSYour Name 
4936*5113495bSYour Name 	if (wma_validate_handle(wma_handle))
4937*5113495bSYour Name 		return -EINVAL;
4938*5113495bSYour Name 
4939*5113495bSYour Name 	if (!wma_handle->wlm_data.wlm_stats_callback) {
4940*5113495bSYour Name 		wma_err("No callback registered");
4941*5113495bSYour Name 		return -EINVAL;
4942*5113495bSYour Name 	}
4943*5113495bSYour Name 
4944*5113495bSYour Name 	param_tlvs = (WMI_WLM_STATS_EVENTID_param_tlvs *)event;
4945*5113495bSYour Name 	param = param_tlvs->fixed_param;
4946*5113495bSYour Name 	if (!param) {
4947*5113495bSYour Name 		wma_err("Fix size param is not present, something is wrong");
4948*5113495bSYour Name 		return -EINVAL;
4949*5113495bSYour Name 	}
4950*5113495bSYour Name 
4951*5113495bSYour Name 	/* info logging per test team request */
4952*5113495bSYour Name 	wma_info("---->Received response for vdev:%d", param->vdev_id);
4953*5113495bSYour Name 
4954*5113495bSYour Name 	raw_data = param_tlvs->data;
4955*5113495bSYour Name 	raw_data_num = param_tlvs->num_data;
4956*5113495bSYour Name 
4957*5113495bSYour Name 	len = 0;
4958*5113495bSYour Name 	buffer_size = wma_handle->wlm_data.wlm_stats_max_size;
4959*5113495bSYour Name 	data = qdf_mem_malloc(buffer_size);
4960*5113495bSYour Name 	if (!data)
4961*5113495bSYour Name 		return -ENOMEM;
4962*5113495bSYour Name 
4963*5113495bSYour Name 	len += qdf_scnprintf(data + len, buffer_size - len, "\n%x ",
4964*5113495bSYour Name 			     param->request_bitmask);
4965*5113495bSYour Name 	len += qdf_scnprintf(data + len, buffer_size - len, "%x ",
4966*5113495bSYour Name 			     param->vdev_id);
4967*5113495bSYour Name 	len += qdf_scnprintf(data + len, buffer_size - len, "%x ",
4968*5113495bSYour Name 			     param->timestamp);
4969*5113495bSYour Name 	len += qdf_scnprintf(data + len, buffer_size - len, "%x ",
4970*5113495bSYour Name 			     param->req_interval);
4971*5113495bSYour Name 	if (!raw_data)
4972*5113495bSYour Name 		goto send_data;
4973*5113495bSYour Name 
4974*5113495bSYour Name 	len += qdf_scnprintf(data + len, buffer_size - len, "\ndata:\n");
4975*5113495bSYour Name 
4976*5113495bSYour Name 	for (i = 0; i < raw_data_num; i++)
4977*5113495bSYour Name 		len += qdf_scnprintf(data + len, buffer_size - len, "%x ",
4978*5113495bSYour Name 				     *raw_data++);
4979*5113495bSYour Name 
4980*5113495bSYour Name send_data:
4981*5113495bSYour Name 	cookie = wma_handle->wlm_data.wlm_stats_cookie;
4982*5113495bSYour Name 	wma_handle->wlm_data.wlm_stats_callback(cookie, data);
4983*5113495bSYour Name 
4984*5113495bSYour Name 	qdf_mem_free(data);
4985*5113495bSYour Name 
4986*5113495bSYour Name 	return 0;
4987*5113495bSYour Name }
4988*5113495bSYour Name #endif /* FEATURE_WLM_STATS */
4989*5113495bSYour Name 
4990*5113495bSYour Name #ifdef FEATURE_WLAN_DIAG_SUPPORT
wma_send_cold_boot_cal_data(uint8_t * data,wmi_cold_boot_cal_data_fixed_param * event)4991*5113495bSYour Name static QDF_STATUS wma_send_cold_boot_cal_data(uint8_t *data,
4992*5113495bSYour Name 		wmi_cold_boot_cal_data_fixed_param *event)
4993*5113495bSYour Name {
4994*5113495bSYour Name 	struct host_log_cold_boot_cal_data_type *log_ptr = NULL;
4995*5113495bSYour Name 
4996*5113495bSYour Name 	WLAN_HOST_DIAG_LOG_ALLOC(log_ptr,
4997*5113495bSYour Name 				 struct host_log_cold_boot_cal_data_type,
4998*5113495bSYour Name 				 LOG_WLAN_COLD_BOOT_CAL_DATA_C);
4999*5113495bSYour Name 
5000*5113495bSYour Name 	if (!log_ptr)
5001*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
5002*5113495bSYour Name 
5003*5113495bSYour Name 	log_ptr->version = VERSION_LOG_WLAN_COLD_BOOT_CAL_DATA_C;
5004*5113495bSYour Name 	log_ptr->cb_cal_data_len = event->data_len;
5005*5113495bSYour Name 	log_ptr->flags = event->flags;
5006*5113495bSYour Name 	qdf_mem_copy(log_ptr->cb_cal_data, data, log_ptr->cb_cal_data_len);
5007*5113495bSYour Name 
5008*5113495bSYour Name 	WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
5009*5113495bSYour Name 
5010*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5011*5113495bSYour Name }
5012*5113495bSYour Name #else
wma_send_cold_boot_cal_data(uint8_t * data,wmi_cold_boot_cal_data_fixed_param * event)5013*5113495bSYour Name static QDF_STATUS wma_send_cold_boot_cal_data(uint8_t *data,
5014*5113495bSYour Name 		wmi_cold_boot_cal_data_fixed_param *event)
5015*5113495bSYour Name {
5016*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5017*5113495bSYour Name }
5018*5113495bSYour Name #endif
5019*5113495bSYour Name 
wma_cold_boot_cal_event_handler(void * wma_ctx,uint8_t * event_buff,uint32_t len)5020*5113495bSYour Name int wma_cold_boot_cal_event_handler(void *wma_ctx, uint8_t *event_buff,
5021*5113495bSYour Name 				    uint32_t len)
5022*5113495bSYour Name {
5023*5113495bSYour Name 	WMI_PDEV_COLD_BOOT_CAL_DATA_EVENTID_param_tlvs *param_buf;
5024*5113495bSYour Name 	wmi_cold_boot_cal_data_fixed_param *event;
5025*5113495bSYour Name 	QDF_STATUS status;
5026*5113495bSYour Name 	tp_wma_handle wma_handle = (tp_wma_handle)wma_ctx;
5027*5113495bSYour Name 
5028*5113495bSYour Name 	if (wma_validate_handle(wma_handle))
5029*5113495bSYour Name 		return -EINVAL;
5030*5113495bSYour Name 
5031*5113495bSYour Name 	param_buf =
5032*5113495bSYour Name 		   (WMI_PDEV_COLD_BOOT_CAL_DATA_EVENTID_param_tlvs *)event_buff;
5033*5113495bSYour Name 	if (!param_buf) {
5034*5113495bSYour Name 		wma_err("Invalid Cold Boot Cal Event");
5035*5113495bSYour Name 		return -EINVAL;
5036*5113495bSYour Name 	}
5037*5113495bSYour Name 
5038*5113495bSYour Name 	event = param_buf->fixed_param;
5039*5113495bSYour Name 	if ((event->data_len > param_buf->num_data) ||
5040*5113495bSYour Name 	    (param_buf->num_data > HOST_LOG_MAX_COLD_BOOT_CAL_DATA_SIZE)) {
5041*5113495bSYour Name 		wma_err("Excess data_len:%d, num_data:%d", event->data_len,
5042*5113495bSYour Name 			param_buf->num_data);
5043*5113495bSYour Name 		return -EINVAL;
5044*5113495bSYour Name 	}
5045*5113495bSYour Name 
5046*5113495bSYour Name 	status = wma_send_cold_boot_cal_data((uint8_t *)param_buf->data, event);
5047*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
5048*5113495bSYour Name 		wma_err("Cold Boot Cal Diag log not sent");
5049*5113495bSYour Name 		return -ENOMEM;
5050*5113495bSYour Name 	}
5051*5113495bSYour Name 
5052*5113495bSYour Name 	return 0;
5053*5113495bSYour Name }
5054*5113495bSYour Name 
5055*5113495bSYour Name #ifdef MULTI_CLIENT_LL_SUPPORT
wma_latency_level_event_handler(void * wma_ctx,uint8_t * event_buff,uint32_t len)5056*5113495bSYour Name int wma_latency_level_event_handler(void *wma_ctx, uint8_t *event_buff,
5057*5113495bSYour Name 				    uint32_t len)
5058*5113495bSYour Name {
5059*5113495bSYour Name 	WMI_VDEV_LATENCY_LEVEL_EVENTID_param_tlvs *param_buf;
5060*5113495bSYour Name 	struct mac_context *pmac =
5061*5113495bSYour Name 		(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5062*5113495bSYour Name 	wmi_vdev_latency_event_fixed_param *event;
5063*5113495bSYour Name 	struct latency_level_data event_data;
5064*5113495bSYour Name 	bool multi_client_ll_support, multi_client_ll_caps;
5065*5113495bSYour Name 
5066*5113495bSYour Name 	if (!pmac) {
5067*5113495bSYour Name 		wma_err("NULL mac handle");
5068*5113495bSYour Name 		return -EINVAL;
5069*5113495bSYour Name 	}
5070*5113495bSYour Name 
5071*5113495bSYour Name 	multi_client_ll_support =
5072*5113495bSYour Name 		pmac->mlme_cfg->wlm_config.multi_client_ll_support;
5073*5113495bSYour Name 	multi_client_ll_caps =
5074*5113495bSYour Name 		wlan_mlme_get_wlm_multi_client_ll_caps(pmac->psoc);
5075*5113495bSYour Name 
5076*5113495bSYour Name 	wma_debug("multi client ll INI:%d, caps:%d", multi_client_ll_support,
5077*5113495bSYour Name 		  multi_client_ll_caps);
5078*5113495bSYour Name 
5079*5113495bSYour Name 	if ((!multi_client_ll_support) || (!multi_client_ll_caps))
5080*5113495bSYour Name 		return -EINVAL;
5081*5113495bSYour Name 
5082*5113495bSYour Name 	if (!pmac->sme.latency_level_event_handler_cb) {
5083*5113495bSYour Name 		wma_err("latency level data handler cb is not registered");
5084*5113495bSYour Name 		return -EINVAL;
5085*5113495bSYour Name 	}
5086*5113495bSYour Name 
5087*5113495bSYour Name 	param_buf = (WMI_VDEV_LATENCY_LEVEL_EVENTID_param_tlvs *)event_buff;
5088*5113495bSYour Name 	if (!param_buf) {
5089*5113495bSYour Name 		wma_err("Invalid latency level data Event");
5090*5113495bSYour Name 		return -EINVAL;
5091*5113495bSYour Name 	}
5092*5113495bSYour Name 
5093*5113495bSYour Name 	event = param_buf->fixed_param;
5094*5113495bSYour Name 	if (!event) {
5095*5113495bSYour Name 		wma_err("Invalid fixed param in latency data Event");
5096*5113495bSYour Name 		return -EINVAL;
5097*5113495bSYour Name 	}
5098*5113495bSYour Name 
5099*5113495bSYour Name 	event_data.vdev_id = event->vdev_id;
5100*5113495bSYour Name 	event_data.latency_level = event->latency_level;
5101*5113495bSYour Name 	wma_debug("received event latency level :%d, vdev_id:%d",
5102*5113495bSYour Name 		  event->latency_level, event->vdev_id);
5103*5113495bSYour Name 	pmac->sme.latency_level_event_handler_cb(&event_data,
5104*5113495bSYour Name 						     event->vdev_id);
5105*5113495bSYour Name 
5106*5113495bSYour Name 	return 0;
5107*5113495bSYour Name }
5108*5113495bSYour Name #endif
5109*5113495bSYour Name 
5110*5113495bSYour Name #ifdef FEATURE_OEM_DATA
wma_oem_event_handler(void * wma_ctx,uint8_t * event_buff,uint32_t len)5111*5113495bSYour Name int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len)
5112*5113495bSYour Name {
5113*5113495bSYour Name 	WMI_OEM_DATA_EVENTID_param_tlvs *param_buf;
5114*5113495bSYour Name 	struct mac_context *pmac =
5115*5113495bSYour Name 		(struct mac_context *)cds_get_context(QDF_MODULE_ID_PE);
5116*5113495bSYour Name 	wmi_oem_data_event_fixed_param *event;
5117*5113495bSYour Name 	struct oem_data oem_event_data;
5118*5113495bSYour Name 
5119*5113495bSYour Name 	if (!pmac) {
5120*5113495bSYour Name 		wma_err("NULL mac handle");
5121*5113495bSYour Name 		return -EINVAL;
5122*5113495bSYour Name 	}
5123*5113495bSYour Name 
5124*5113495bSYour Name 	param_buf =
5125*5113495bSYour Name 		   (WMI_OEM_DATA_EVENTID_param_tlvs *)event_buff;
5126*5113495bSYour Name 	if (!param_buf) {
5127*5113495bSYour Name 		wma_err("Invalid oem data Event");
5128*5113495bSYour Name 		return -EINVAL;
5129*5113495bSYour Name 	}
5130*5113495bSYour Name 
5131*5113495bSYour Name 	event = param_buf->fixed_param;
5132*5113495bSYour Name 	if (!event) {
5133*5113495bSYour Name 		wma_err("Invalid fixed param in oem data Event");
5134*5113495bSYour Name 		return -EINVAL;
5135*5113495bSYour Name 	}
5136*5113495bSYour Name 
5137*5113495bSYour Name 	if (event->data_len > param_buf->num_data) {
5138*5113495bSYour Name 		wma_err("Invalid data len %d num_data %d", event->data_len,
5139*5113495bSYour Name 			param_buf->num_data);
5140*5113495bSYour Name 		return -EINVAL;
5141*5113495bSYour Name 	}
5142*5113495bSYour Name 
5143*5113495bSYour Name 	oem_event_data.data_len = event->data_len;
5144*5113495bSYour Name 	oem_event_data.data = param_buf->data;
5145*5113495bSYour Name 
5146*5113495bSYour Name 	if (param_buf->num_file_name) {
5147*5113495bSYour Name 		oem_event_data.file_name = param_buf->file_name;
5148*5113495bSYour Name 		oem_event_data.file_name_len = param_buf->num_file_name;
5149*5113495bSYour Name 	}
5150*5113495bSYour Name 
5151*5113495bSYour Name 	if (event->event_cause == WMI_OEM_DATA_EVT_CAUSE_UNSPECIFIED) {
5152*5113495bSYour Name 		if (pmac->sme.oem_data_event_handler_cb)
5153*5113495bSYour Name 			pmac->sme.oem_data_event_handler_cb(
5154*5113495bSYour Name 					&oem_event_data,
5155*5113495bSYour Name 					pmac->sme.oem_data_vdev_id);
5156*5113495bSYour Name 		else if (pmac->sme.oem_data_async_event_handler_cb)
5157*5113495bSYour Name 			pmac->sme.oem_data_async_event_handler_cb(
5158*5113495bSYour Name 					&oem_event_data);
5159*5113495bSYour Name 	} else if (event->event_cause == WMI_OEM_DATA_EVT_CAUSE_CMD_REQ) {
5160*5113495bSYour Name 		if (pmac->sme.oem_data_event_handler_cb)
5161*5113495bSYour Name 			pmac->sme.oem_data_event_handler_cb(
5162*5113495bSYour Name 					&oem_event_data,
5163*5113495bSYour Name 					pmac->sme.oem_data_vdev_id);
5164*5113495bSYour Name 	} else if (event->event_cause == WMI_OEM_DATA_EVT_CAUSE_ASYNC) {
5165*5113495bSYour Name 		if (pmac->sme.oem_data_async_event_handler_cb)
5166*5113495bSYour Name 			pmac->sme.oem_data_async_event_handler_cb(
5167*5113495bSYour Name 					&oem_event_data);
5168*5113495bSYour Name 	} else {
5169*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
5170*5113495bSYour Name 	}
5171*5113495bSYour Name 
5172*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
5173*5113495bSYour Name }
5174*5113495bSYour Name #endif
5175*5113495bSYour Name 
5176*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
wma_get_orig_eht_ch_width(void)5177*5113495bSYour Name uint32_t wma_get_orig_eht_ch_width(void)
5178*5113495bSYour Name {
5179*5113495bSYour Name 	tDot11fIEeht_cap eht_cap;
5180*5113495bSYour Name 	tp_wma_handle wma;
5181*5113495bSYour Name 	QDF_STATUS status;
5182*5113495bSYour Name 
5183*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
5184*5113495bSYour Name 	if (qdf_unlikely(!wma)) {
5185*5113495bSYour Name 		wma_err_rl("wma handle is NULL");
5186*5113495bSYour Name 		goto vht_ch_width;
5187*5113495bSYour Name 	}
5188*5113495bSYour Name 
5189*5113495bSYour Name 	status = mlme_cfg_get_orig_eht_caps(wma->psoc, &eht_cap);
5190*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
5191*5113495bSYour Name 		wma_err_rl("Failed to get eht caps");
5192*5113495bSYour Name 		goto vht_ch_width;
5193*5113495bSYour Name 	}
5194*5113495bSYour Name 
5195*5113495bSYour Name 	if (eht_cap.support_320mhz_6ghz)
5196*5113495bSYour Name 		return WNI_CFG_EHT_CHANNEL_WIDTH_320MHZ;
5197*5113495bSYour Name 
5198*5113495bSYour Name vht_ch_width:
5199*5113495bSYour Name 	return wma_get_vht_ch_width();
5200*5113495bSYour Name }
5201*5113495bSYour Name 
wma_get_eht_ch_width(void)5202*5113495bSYour Name uint32_t wma_get_eht_ch_width(void)
5203*5113495bSYour Name {
5204*5113495bSYour Name 	tDot11fIEeht_cap eht_cap;
5205*5113495bSYour Name 	tp_wma_handle wma;
5206*5113495bSYour Name 
5207*5113495bSYour Name 	wma = cds_get_context(QDF_MODULE_ID_WMA);
5208*5113495bSYour Name 	if (qdf_unlikely(!wma)) {
5209*5113495bSYour Name 		wma_err_rl("wma handle is NULL");
5210*5113495bSYour Name 		goto vht_ch_width;
5211*5113495bSYour Name 	}
5212*5113495bSYour Name 
5213*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(mlme_cfg_get_eht_caps(wma->psoc, &eht_cap))) {
5214*5113495bSYour Name 		wma_err_rl("Failed to get eht caps");
5215*5113495bSYour Name 		goto vht_ch_width;
5216*5113495bSYour Name 	}
5217*5113495bSYour Name 
5218*5113495bSYour Name 	if (eht_cap.support_320mhz_6ghz)
5219*5113495bSYour Name 		return WNI_CFG_EHT_CHANNEL_WIDTH_320MHZ;
5220*5113495bSYour Name 
5221*5113495bSYour Name vht_ch_width:
5222*5113495bSYour Name 	return wma_get_vht_ch_width();
5223*5113495bSYour Name }
5224*5113495bSYour Name #endif
5225