blob: ff7a538e5c3cbe5a691c279169b7bc1039fdb97e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC : wlan_hdd_stats.c
24 *
25 * WLAN Host Device Driver statistics related implementation
26 *
27 */
28
29#include "wlan_hdd_stats.h"
30#include "sme_api.h"
31#include "cds_sched.h"
32#include "wlan_hdd_trace.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070033#include "wlan_hdd_lpass.h"
Nirav Shahbf1b0332016-05-25 14:27:39 +053034#include "hif.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080035
36#ifdef WLAN_FEATURE_LINK_LAYER_STATS
37
38/**
39 * struct hdd_ll_stats_context - hdd link layer stats context
40 *
41 * @request_id: userspace-assigned link layer stats request id
42 * @request_bitmap: userspace-assigned link layer stats request bitmap
43 * @response_event: LL stats request wait event
44 */
45struct hdd_ll_stats_context {
46 uint32_t request_id;
47 uint32_t request_bitmap;
48 struct completion response_event;
49 spinlock_t context_lock;
50};
51
52static struct hdd_ll_stats_context ll_stats_context;
53
54#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */
55
56/* 11B, 11G Rate table include Basic rate and Extended rate
57 * The IDX field is the rate index
58 * The HI field is the rate when RSSI is strong or being ignored
59 * (in this case we report actual rate)
60 * The MID field is the rate when RSSI is moderate
61 * (in this case we cap 11b rates at 5.5 and 11g rates at 24)
62 * The LO field is the rate when RSSI is low
63 * (in this case we don't report rates, actual current rate used)
64 */
65static const struct {
66 uint8_t beacon_rate_index;
67 uint16_t supported_rate[4];
68} supported_data_rate[] = {
69/* IDX HI HM LM LO (RSSI-based index */
70 {
71 2, {
72 10, 10, 10, 0
73 }
74 }, {
75 4, {
76 20, 20, 10, 0
77 }
78 }, {
79 11, {
80 55, 20, 10, 0
81 }
82 }, {
83 12, {
84 60, 55, 20, 0
85 }
86 }, {
87 18, {
88 90, 55, 20, 0
89 }
90 }, {
91 22, {
92 110, 55, 20, 0
93 }
94 }, {
95 24, {
96 120, 90, 60, 0
97 }
98 }, {
99 36, {
100 180, 120, 60, 0
101 }
102 }, {
103 44, {
104 220, 180, 60, 0
105 }
106 }, {
107 48, {
108 240, 180, 90, 0
109 }
110 }, {
111 66, {
112 330, 180, 90, 0
113 }
114 }, {
115 72, {
116 360, 240, 90, 0
117 }
118 }, {
119 96, {
120 480, 240, 120, 0
121 }
122 }, {
123 108, {
124 540, 240, 120, 0
125 }
126 }
127};
128/* MCS Based rate table HT MCS parameters with Nss = 1 */
129static struct index_data_rate_type supported_mcs_rate_nss1[] = {
130/* MCS L20 L40 S20 S40 */
131 {0, {65, 135, 72, 150} },
132 {1, {130, 270, 144, 300} },
133 {2, {195, 405, 217, 450} },
134 {3, {260, 540, 289, 600} },
135 {4, {390, 810, 433, 900} },
136 {5, {520, 1080, 578, 1200} },
137 {6, {585, 1215, 650, 1350} },
138 {7, {650, 1350, 722, 1500} }
139};
140
141/* HT MCS parameters with Nss = 2 */
142static struct index_data_rate_type supported_mcs_rate_nss2[] = {
143/* MCS L20 L40 S20 S40 */
144 {0, {130, 270, 144, 300} },
145 {1, {260, 540, 289, 600} },
146 {2, {390, 810, 433, 900} },
147 {3, {520, 1080, 578, 1200} },
148 {4, {780, 1620, 867, 1800} },
149 {5, {1040, 2160, 1156, 2400} },
150 {6, {1170, 2430, 1300, 2700} },
151 {7, {1300, 2700, 1444, 3000} }
152};
153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154/* MCS Based VHT rate table MCS parameters with Nss = 1*/
155static struct index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = {
156/* MCS L80 S80 L40 S40 L20 S40*/
157 {0, {293, 325}, {135, 150}, {65, 72} },
158 {1, {585, 650}, {270, 300}, {130, 144} },
159 {2, {878, 975}, {405, 450}, {195, 217} },
160 {3, {1170, 1300}, {540, 600}, {260, 289} },
161 {4, {1755, 1950}, {810, 900}, {390, 433} },
162 {5, {2340, 2600}, {1080, 1200}, {520, 578} },
163 {6, {2633, 2925}, {1215, 1350}, {585, 650} },
164 {7, {2925, 3250}, {1350, 1500}, {650, 722} },
165 {8, {3510, 3900}, {1620, 1800}, {780, 867} },
166 {9, {3900, 4333}, {1800, 2000}, {780, 867} }
167};
168
169/*MCS parameters with Nss = 2*/
170static struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = {
171/* MCS L80 S80 L40 S40 L20 S40*/
172 {0, {585, 650}, {270, 300}, {130, 144} },
173 {1, {1170, 1300}, {540, 600}, {260, 289} },
174 {2, {1755, 1950}, {810, 900}, {390, 433} },
175 {3, {2340, 2600}, {1080, 1200}, {520, 578} },
176 {4, {3510, 3900}, {1620, 1800}, {780, 867} },
177 {5, {4680, 5200}, {2160, 2400}, {1040, 1156} },
178 {6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
179 {7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
180 {8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
181 {9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
182};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183
184/*array index ponints to MCS and array value points respective rssi*/
185static int rssi_mcs_tbl[][10] = {
186/*MCS 0 1 2 3 4 5 6 7 8 9*/
187 {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57}, /* 20 */
188 {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54}, /* 40 */
189 {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} /* 80 */
190};
191
192
193#ifdef WLAN_FEATURE_LINK_LAYER_STATS
194
195/**
196 * put_wifi_rate_stat() - put wifi rate stats
197 * @stats: Pointer to stats context
198 * @vendor_event: Pointer to vendor event
199 *
200 * Return: bool
201 */
202static bool put_wifi_rate_stat(tpSirWifiRateStat stats,
203 struct sk_buff *vendor_event)
204{
205 if (nla_put_u8(vendor_event,
206 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE,
207 stats->rate.preamble) ||
208 nla_put_u8(vendor_event,
209 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS,
210 stats->rate.nss) ||
211 nla_put_u8(vendor_event,
212 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW,
213 stats->rate.bw) ||
214 nla_put_u8(vendor_event,
215 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX,
216 stats->rate.rateMcsIdx) ||
217 nla_put_u32(vendor_event,
218 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE,
219 stats->rate.bitrate) ||
220 nla_put_u32(vendor_event,
221 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU,
222 stats->txMpdu) ||
223 nla_put_u32(vendor_event,
224 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU,
225 stats->rxMpdu) ||
226 nla_put_u32(vendor_event,
227 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST,
228 stats->mpduLost) ||
229 nla_put_u32(vendor_event,
230 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES,
231 stats->retries) ||
232 nla_put_u32(vendor_event,
233 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT,
234 stats->retriesShort) ||
235 nla_put_u32(vendor_event,
236 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG,
237 stats->retriesLong)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700238 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 return false;
240 }
241
242 return true;
243}
244
245/**
246 * put_wifi_peer_info() - put wifi peer info
247 * @stats: Pointer to stats context
248 * @vendor_event: Pointer to vendor event
249 *
250 * Return: bool
251 */
252static bool put_wifi_peer_info(tpSirWifiPeerInfo stats,
253 struct sk_buff *vendor_event)
254{
255 u32 i = 0;
256 tpSirWifiRateStat pRateStats;
257
258 if (nla_put_u32
259 (vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE,
260 stats->type) ||
261 nla_put(vendor_event,
262 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530263 QDF_MAC_ADDR_SIZE, &stats->peerMacAddress.bytes[0]) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800264 nla_put_u32(vendor_event,
265 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES,
266 stats->capabilities) ||
267 nla_put_u32(vendor_event,
268 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES,
269 stats->numRate)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700270 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 goto error;
272 }
273
274 if (stats->numRate) {
275 struct nlattr *rateInfo;
276 struct nlattr *rates;
277
278 rateInfo = nla_nest_start(vendor_event,
279 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO);
280 if (rateInfo == NULL)
281 goto error;
282
283 for (i = 0; i < stats->numRate; i++) {
284 pRateStats = (tpSirWifiRateStat) ((uint8_t *)
285 stats->rateStats +
286 (i *
287 sizeof
288 (tSirWifiRateStat)));
289 rates = nla_nest_start(vendor_event, i);
290 if (rates == NULL)
291 goto error;
292
293 if (false ==
294 put_wifi_rate_stat(pRateStats, vendor_event)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700295 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 return false;
297 }
298 nla_nest_end(vendor_event, rates);
299 }
300 nla_nest_end(vendor_event, rateInfo);
301 }
302
303 return true;
304error:
305 return false;
306}
307
308/**
309 * put_wifi_wmm_ac_stat() - put wifi wmm ac stats
310 * @stats: Pointer to stats context
311 * @vendor_event: Pointer to vendor event
312 *
313 * Return: bool
314 */
315static bool put_wifi_wmm_ac_stat(tpSirWifiWmmAcStat stats,
316 struct sk_buff *vendor_event)
317{
318 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC,
319 stats->ac) ||
320 nla_put_u32(vendor_event,
321 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU,
322 stats->txMpdu) ||
323 nla_put_u32(vendor_event,
324 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU,
325 stats->rxMpdu) ||
326 nla_put_u32(vendor_event,
327 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST,
328 stats->txMcast) ||
329 nla_put_u32(vendor_event,
330 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST,
331 stats->rxMcast) ||
332 nla_put_u32(vendor_event,
333 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU,
334 stats->rxAmpdu) ||
335 nla_put_u32(vendor_event,
336 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU,
337 stats->txAmpdu) ||
338 nla_put_u32(vendor_event,
339 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST,
340 stats->mpduLost) ||
341 nla_put_u32(vendor_event,
342 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES,
343 stats->retries) ||
344 nla_put_u32(vendor_event,
345 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT,
346 stats->retriesShort) ||
347 nla_put_u32(vendor_event,
348 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG,
349 stats->retriesLong) ||
350 nla_put_u32(vendor_event,
351 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN,
352 stats->contentionTimeMin) ||
353 nla_put_u32(vendor_event,
354 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX,
355 stats->contentionTimeMax) ||
356 nla_put_u32(vendor_event,
357 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG,
358 stats->contentionTimeAvg) ||
359 nla_put_u32(vendor_event,
360 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES,
361 stats->contentionNumSamples)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700362 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 return false;
364 }
365
366 return true;
367}
368
369/**
370 * put_wifi_interface_info() - put wifi interface info
371 * @stats: Pointer to stats context
372 * @vendor_event: Pointer to vendor event
373 *
374 * Return: bool
375 */
376static bool put_wifi_interface_info(tpSirWifiInterfaceInfo stats,
377 struct sk_buff *vendor_event)
378{
379 if (nla_put_u32(vendor_event,
380 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE,
381 stats->mode) ||
382 nla_put(vendor_event,
383 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530384 QDF_MAC_ADDR_SIZE, stats->macAddr.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 nla_put_u32(vendor_event,
386 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE,
387 stats->state) ||
388 nla_put_u32(vendor_event,
389 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING,
390 stats->roaming) ||
391 nla_put_u32(vendor_event,
392 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES,
393 stats->capabilities) ||
394 nla_put(vendor_event,
395 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID,
396 strlen(stats->ssid), stats->ssid) ||
397 nla_put(vendor_event,
398 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530399 QDF_MAC_ADDR_SIZE, stats->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 nla_put(vendor_event,
401 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR,
402 WNI_CFG_COUNTRY_CODE_LEN, stats->apCountryStr) ||
403 nla_put(vendor_event,
404 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR,
405 WNI_CFG_COUNTRY_CODE_LEN, stats->countryStr)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700406 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407 return false;
408 }
409
410 return true;
411}
412
413/**
414 * put_wifi_iface_stats() - put wifi interface stats
415 * @pWifiIfaceStat: Pointer to interface stats context
416 * @num_peer: Number of peers
417 * @vendor_event: Pointer to vendor event
418 *
419 * Return: bool
420 */
421static bool put_wifi_iface_stats(tpSirWifiIfaceStat pWifiIfaceStat,
422 u32 num_peers, struct sk_buff *vendor_event)
423{
424 int i = 0;
425 struct nlattr *wmmInfo;
426 struct nlattr *wmmStats;
427 u64 average_tsf_offset;
428
429 if (false == put_wifi_interface_info(&pWifiIfaceStat->info,
430 vendor_event)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700431 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 return false;
433
434 }
435
436 average_tsf_offset = pWifiIfaceStat->avg_bcn_spread_offset_high;
437 average_tsf_offset = (average_tsf_offset << 32) |
438 pWifiIfaceStat->avg_bcn_spread_offset_low ;
439
440 if (nla_put_u32(vendor_event,
441 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
442 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE) ||
443 nla_put_u32(vendor_event,
444 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
445 num_peers) ||
446 nla_put_u32(vendor_event,
447 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX,
448 pWifiIfaceStat->beaconRx) ||
449 nla_put_u32(vendor_event,
450 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX,
451 pWifiIfaceStat->mgmtRx) ||
452 nla_put_u32(vendor_event,
453 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX,
454 pWifiIfaceStat->mgmtActionRx) ||
455 nla_put_u32(vendor_event,
456 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX,
457 pWifiIfaceStat->mgmtActionTx) ||
458 nla_put_u32(vendor_event,
459 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT,
460 pWifiIfaceStat->rssiMgmt) ||
461 nla_put_u32(vendor_event,
462 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA,
463 pWifiIfaceStat->rssiData) ||
464 nla_put_u32(vendor_event,
465 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK,
466 pWifiIfaceStat->rssiAck) ||
467 nla_put_u32(vendor_event,
468 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED,
469 pWifiIfaceStat->is_leaky_ap) ||
470 nla_put_u32(vendor_event,
471 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED,
472 pWifiIfaceStat->avg_rx_frms_leaked) ||
473 nla_put_u32(vendor_event,
474 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME,
475 pWifiIfaceStat->rx_leak_window) ||
476 nla_put_u64(vendor_event,
477 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET,
478 average_tsf_offset)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700479 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480 return false;
481 }
482
483 wmmInfo = nla_nest_start(vendor_event,
484 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO);
485 if (wmmInfo == NULL)
486 return false;
487
488 for (i = 0; i < WIFI_AC_MAX; i++) {
489 wmmStats = nla_nest_start(vendor_event, i);
490 if (wmmStats == NULL)
491 return false;
492
493 if (false ==
494 put_wifi_wmm_ac_stat(&pWifiIfaceStat->AccessclassStats[i],
495 vendor_event)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700496 hdd_err("put_wifi_wmm_ac_stat Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 return false;
498 }
499
500 nla_nest_end(vendor_event, wmmStats);
501 }
502 nla_nest_end(vendor_event, wmmInfo);
503 return true;
504}
505
506/**
507 * hdd_map_device_to_ll_iface_mode() - map device to link layer interface mode
508 * @deviceMode: Device mode
509 *
510 * Return: interface mode
511 */
512static tSirWifiInterfaceMode hdd_map_device_to_ll_iface_mode(int deviceMode)
513{
514 switch (deviceMode) {
Krunal Sonif07bb382016-03-10 13:02:11 -0800515 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516 return WIFI_INTERFACE_STA;
Krunal Sonif07bb382016-03-10 13:02:11 -0800517 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 return WIFI_INTERFACE_SOFTAP;
Krunal Sonif07bb382016-03-10 13:02:11 -0800519 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 return WIFI_INTERFACE_P2P_CLIENT;
Krunal Sonif07bb382016-03-10 13:02:11 -0800521 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 return WIFI_INTERFACE_P2P_GO;
Krunal Sonif07bb382016-03-10 13:02:11 -0800523 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 return WIFI_INTERFACE_IBSS;
525 default:
526 /* Return Interface Mode as STA for all the unsupported modes */
527 return WIFI_INTERFACE_STA;
528 }
529}
530
531/**
532 * hdd_get_interface_info() - get interface info
533 * @pAdapter: Pointer to device adapter
534 * @pInfo: Pointer to interface info
535 *
536 * Return: bool
537 */
538static bool hdd_get_interface_info(hdd_adapter_t *pAdapter,
539 tpSirWifiInterfaceInfo pInfo)
540{
541 uint8_t *staMac = NULL;
542 hdd_station_ctx_t *pHddStaCtx;
543 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
544 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
545
546 pInfo->mode = hdd_map_device_to_ll_iface_mode(pAdapter->device_mode);
547
Anurag Chouhanc5548422016-02-24 18:33:27 +0530548 qdf_copy_macaddr(&pInfo->macAddr, &pAdapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549
Krunal Sonif07bb382016-03-10 13:02:11 -0800550 if (((QDF_STA_MODE == pAdapter->device_mode) ||
551 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
552 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
554 if (eConnectionState_NotConnected ==
555 pHddStaCtx->conn_info.connState) {
556 pInfo->state = WIFI_DISCONNECTED;
557 }
558 if (eConnectionState_Connecting ==
559 pHddStaCtx->conn_info.connState) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700560 hdd_err("Session ID %d, Connection is in progress",
561 pAdapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 pInfo->state = WIFI_ASSOCIATING;
563 }
564 if ((eConnectionState_Associated ==
565 pHddStaCtx->conn_info.connState)
566 && (false == pHddStaCtx->conn_info.uIsAuthenticated)) {
567 staMac =
568 (uint8_t *) &(pAdapter->macAddressCurrent.
569 bytes[0]);
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700570 hdd_err("client " MAC_ADDRESS_STR
571 " is in the middle of WPS/EAPOL exchange.",
572 MAC_ADDR_ARRAY(staMac));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 pInfo->state = WIFI_AUTHENTICATING;
574 }
575 if (eConnectionState_Associated ==
576 pHddStaCtx->conn_info.connState) {
577 pInfo->state = WIFI_ASSOCIATED;
Anurag Chouhanc5548422016-02-24 18:33:27 +0530578 qdf_copy_macaddr(&pInfo->bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 &pHddStaCtx->conn_info.bssId);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530580 qdf_mem_copy(pInfo->ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 pHddStaCtx->conn_info.SSID.SSID.ssId,
582 pHddStaCtx->conn_info.SSID.SSID.length);
583 /*
584 * NULL Terminate the string
585 */
586 pInfo->ssid[pHddStaCtx->conn_info.SSID.SSID.length] = 0;
587 }
588 }
589
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530590 qdf_mem_copy(pInfo->countryStr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
592
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530593 qdf_mem_copy(pInfo->apCountryStr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
595
596 return true;
597}
598
599/**
600 * hdd_link_layer_process_peer_stats() - This function is called after
601 * @pAdapter: Pointer to device adapter
602 * @more_data: More data
603 * @pData: Pointer to stats data
604 *
605 * Receiving Link Layer Peer statistics from FW.This function converts
606 * the firmware data to the NL data and sends the same to the kernel/upper
607 * layers.
608 *
609 * Return: None
610 */
611static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter,
612 u32 more_data,
613 tpSirWifiPeerStat pData)
614{
615 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 tpSirWifiPeerStat pWifiPeerStat;
617 tpSirWifiPeerInfo pWifiPeerInfo;
618 struct sk_buff *vendor_event;
Sushant Kaushik7a535882015-11-02 13:31:21 +0530619 int status, i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 struct nlattr *peers;
621 int numRate;
622
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530623 ENTER();
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 pWifiPeerStat = pData;
626
627 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530628 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700631 hdd_notice("LL_STATS_PEER_ALL : numPeers %u, more data = %u",
632 pWifiPeerStat->numPeers, more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634 /*
635 * Allocate a size of 4096 for the peer stats comprising
636 * each of size = sizeof (tSirWifiPeerInfo) + numRate *
637 * sizeof (tSirWifiRateStat).Each field is put with an
638 * NL attribute.The size of 4096 is considered assuming
639 * that number of rates shall not exceed beyond 50 with
640 * the sizeof (tSirWifiRateStat) being 32.
641 */
642 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
643 LL_STATS_EVENT_BUF_SIZE);
644
645 if (!vendor_event) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700646 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647 return;
648 }
649
650 if (nla_put_u32(vendor_event,
651 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
652 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER) ||
653 nla_put_u32(vendor_event,
654 QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA,
655 more_data) ||
656 nla_put_u32(vendor_event,
657 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
658 pWifiPeerStat->numPeers)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700659 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660
661 kfree_skb(vendor_event);
662 return;
663 }
664
665 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *)
666 pWifiPeerStat->peerInfo);
667
668 if (pWifiPeerStat->numPeers) {
669 struct nlattr *peerInfo;
670 peerInfo = nla_nest_start(vendor_event,
671 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO);
672 if (peerInfo == NULL) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700673 hdd_err("nla_nest_start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674 kfree_skb(vendor_event);
675 return;
676 }
677
678 for (i = 1; i <= pWifiPeerStat->numPeers; i++) {
679 peers = nla_nest_start(vendor_event, i);
680 if (peers == NULL) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700681 hdd_err("nla_nest_start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800682 kfree_skb(vendor_event);
683 return;
684 }
685
686 numRate = pWifiPeerInfo->numRate;
687
688 if (false ==
689 put_wifi_peer_info(pWifiPeerInfo, vendor_event)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700690 hdd_err("put_wifi_peer_info fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 kfree_skb(vendor_event);
692 return;
693 }
694
695 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *)
696 pWifiPeerStat->
697 peerInfo +
698 (i *
699 sizeof
700 (tSirWifiPeerInfo))
701 +
702 (numRate *
703 sizeof
704 (tSirWifiRateStat)));
705 nla_nest_end(vendor_event, peers);
706 }
707 nla_nest_end(vendor_event, peerInfo);
708 }
709 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530710 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 return;
712}
713
714/**
715 * hdd_link_layer_process_iface_stats() - This function is called after
716 * @pAdapter: Pointer to device adapter
717 * @pData: Pointer to stats data
718 * @num_peers: Number of peers
719 *
720 * Receiving Link Layer Interface statistics from FW.This function converts
721 * the firmware data to the NL data and sends the same to the kernel/upper
722 * layers.
723 *
724 * Return: None
725 */
726static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter,
727 tpSirWifiIfaceStat pData,
728 u32 num_peers)
729{
730 tpSirWifiIfaceStat pWifiIfaceStat;
731 struct sk_buff *vendor_event;
732 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
733 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530735 ENTER();
736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800737 pWifiIfaceStat = pData;
738
739 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530740 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742
743 /*
744 * Allocate a size of 4096 for the interface stats comprising
745 * sizeof (tpSirWifiIfaceStat).The size of 4096 is considered
746 * assuming that all these fit with in the limit.Please take
747 * a call on the limit based on the data requirements on
748 * interface statistics.
749 */
750 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
751 LL_STATS_EVENT_BUF_SIZE);
752
753 if (!vendor_event) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700754 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 return;
756 }
757
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700758 hdd_notice("WMI_LINK_STATS_IFACE Data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759
760 if (false == hdd_get_interface_info(pAdapter, &pWifiIfaceStat->info)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700761 hdd_err("hdd_get_interface_info get fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 kfree_skb(vendor_event);
763 return;
764 }
765
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 if (false ==
767 put_wifi_iface_stats(pWifiIfaceStat, num_peers, vendor_event)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700768 hdd_err("put_wifi_iface_stats fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 kfree_skb(vendor_event);
770 return;
771 }
772
773 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530774 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return;
776}
777
778/**
779 * hdd_link_layer_process_radio_stats() - This function is called after
780 * @pAdapter: Pointer to device adapter
781 * @more_data: More data
782 * @pData: Pointer to stats data
783 * @num_radios: Number of radios
784 *
785 * Receiving Link Layer Radio statistics from FW.This function converts
786 * the firmware data to the NL data and sends the same to the kernel/upper
787 * layers.
788 *
789 * Return: None
790 */
791static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter,
792 u32 more_data,
793 tpSirWifiRadioStat pData,
794 u32 num_radio)
795{
796 int status, i;
797 tpSirWifiRadioStat pWifiRadioStat;
798 tpSirWifiChannelStats pWifiChannelStats;
799 struct sk_buff *vendor_event;
800 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
801
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530802 ENTER();
803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 pWifiRadioStat = pData;
805 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530806 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700809 hdd_notice("LL_STATS_RADIO"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 " number of radios = %u"
811 " radio is %d onTime is %u"
812 " txTime is %u rxTime is %u"
813 " onTimeScan is %u onTimeNbd is %u"
814 " onTimeGscan is %u onTimeRoamScan is %u"
815 " onTimePnoScan is %u onTimeHs20 is %u"
816 " numChannels is %u",
817 num_radio,
818 pWifiRadioStat->radio,
819 pWifiRadioStat->onTime,
820 pWifiRadioStat->txTime,
821 pWifiRadioStat->rxTime,
822 pWifiRadioStat->onTimeScan,
823 pWifiRadioStat->onTimeNbd,
824 pWifiRadioStat->onTimeGscan,
825 pWifiRadioStat->onTimeRoamScan,
826 pWifiRadioStat->onTimePnoScan,
827 pWifiRadioStat->onTimeHs20, pWifiRadioStat->numChannels);
828
829 /*
830 * Allocate a size of 4096 for the Radio stats comprising
831 * sizeof (tSirWifiRadioStat) + numChannels * sizeof
832 * (tSirWifiChannelStats).Each channel data is put with an
833 * NL attribute.The size of 4096 is considered assuming that
834 * number of channels shall not exceed beyond 60 with the
835 * sizeof (tSirWifiChannelStats) being 24 bytes.
836 */
837
838 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
839 LL_STATS_EVENT_BUF_SIZE);
840
841 if (!vendor_event) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700842 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 return;
844 }
845
846 if (nla_put_u32(vendor_event,
847 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
848 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO) ||
849 nla_put_u32(vendor_event,
850 QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA,
851 more_data) ||
852 nla_put_u32(vendor_event,
853 QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS,
854 num_radio) ||
855 nla_put_u32(vendor_event,
856 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID,
857 pWifiRadioStat->radio) ||
858 nla_put_u32(vendor_event,
859 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME,
860 pWifiRadioStat->onTime) ||
861 nla_put_u32(vendor_event,
862 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME,
863 pWifiRadioStat->txTime) ||
864 nla_put_u32(vendor_event,
865 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME,
866 pWifiRadioStat->rxTime) ||
867 nla_put_u32(vendor_event,
868 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN,
869 pWifiRadioStat->onTimeScan) ||
870 nla_put_u32(vendor_event,
871 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD,
872 pWifiRadioStat->onTimeNbd) ||
873 nla_put_u32(vendor_event,
874 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN,
875 pWifiRadioStat->onTimeGscan) ||
876 nla_put_u32(vendor_event,
877 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN,
878 pWifiRadioStat->onTimeRoamScan) ||
879 nla_put_u32(vendor_event,
880 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN,
881 pWifiRadioStat->onTimePnoScan) ||
882 nla_put_u32(vendor_event,
883 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20,
884 pWifiRadioStat->onTimeHs20) ||
885 nla_put_u32(vendor_event,
886 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS,
887 pWifiRadioStat->numChannels)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700888 hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889
890 kfree_skb(vendor_event);
891 return;
892 }
893
894 if (pWifiRadioStat->numChannels) {
895 struct nlattr *chList;
896 struct nlattr *chInfo;
897
898 chList = nla_nest_start(vendor_event,
899 QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO);
900 if (chList == NULL) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700901 hdd_err("nla_nest_start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 kfree_skb(vendor_event);
903 return;
904 }
905
906 for (i = 0; i < pWifiRadioStat->numChannels; i++) {
907 pWifiChannelStats = (tpSirWifiChannelStats) ((uint8_t *)
908 pWifiRadioStat->
909 channels +
910 (i *
911 sizeof
912 (tSirWifiChannelStats)));
913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 chInfo = nla_nest_start(vendor_event, i);
915 if (chInfo == NULL) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700916 hdd_err("nla_nest_start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 kfree_skb(vendor_event);
918 return;
919 }
920
921 if (nla_put_u32(vendor_event,
922 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH,
923 pWifiChannelStats->channel.width) ||
924 nla_put_u32(vendor_event,
925 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ,
926 pWifiChannelStats->channel.centerFreq) ||
927 nla_put_u32(vendor_event,
928 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0,
929 pWifiChannelStats->channel.
930 centerFreq0) ||
931 nla_put_u32(vendor_event,
932 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1,
933 pWifiChannelStats->channel.
934 centerFreq1) ||
935 nla_put_u32(vendor_event,
936 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME,
937 pWifiChannelStats->onTime) ||
938 nla_put_u32(vendor_event,
939 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME,
940 pWifiChannelStats->ccaBusyTime)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700941 hdd_err("nla_put failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 kfree_skb(vendor_event);
943 return;
944 }
945 nla_nest_end(vendor_event, chInfo);
946 }
947 nla_nest_end(vendor_event, chList);
948 }
949 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530950 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 return;
952}
953
954/**
955 * wlan_hdd_cfg80211_link_layer_stats_callback() - This function is called
956 * @ctx: Pointer to hdd context
957 * @indType: Indication type
958 * @pRsp: Pointer to response
959 *
960 * After receiving Link Layer indications from FW.This callback converts the
961 * firmware data to the NL data and send the same to the kernel/upper layers.
962 *
963 * Return: None
964 */
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530965void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 int indType, void *pRsp)
967{
968 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
969 struct hdd_ll_stats_context *context;
970 hdd_adapter_t *pAdapter = NULL;
971 tpSirLLStatsResults linkLayerStatsResults = (tpSirLLStatsResults) pRsp;
972 int status;
973
974 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530975 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977
978 pAdapter = hdd_get_adapter_by_vdev(pHddCtx,
979 linkLayerStatsResults->ifaceId);
980
981 if (NULL == pAdapter) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700982 hdd_err("vdev_id %d does not exist with host",
983 linkLayerStatsResults->ifaceId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800984 return;
985 }
986
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700987 hdd_notice("Link Layer Indication indType: %d", indType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
989 switch (indType) {
990 case SIR_HAL_LL_STATS_RESULTS_RSP:
991 {
Jeff Johnson0c1301d2016-05-17 16:16:35 -0700992 hdd_notice("LL_STATS RESP paramID = 0x%x, ifaceId = %u, respId= %u , moreResultToFollow = %u, num radio = %u result = %p",
Sushant Kaushik7a535882015-11-02 13:31:21 +0530993 linkLayerStatsResults->paramId,
994 linkLayerStatsResults->ifaceId,
995 linkLayerStatsResults->rspId,
996 linkLayerStatsResults->moreResultToFollow,
997 linkLayerStatsResults->num_radio,
998 linkLayerStatsResults->results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800999
1000 context = &ll_stats_context;
1001 spin_lock(&context->context_lock);
1002 /* validate response received from target */
1003 if ((context->request_id != linkLayerStatsResults->rspId) ||
1004 !(context->request_bitmap & linkLayerStatsResults->paramId)) {
1005 spin_unlock(&context->context_lock);
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001006 hdd_err("Error : Request id %d response id %d request bitmap 0x%x response bitmap 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007 context->request_id, linkLayerStatsResults->rspId,
1008 context->request_bitmap, linkLayerStatsResults->paramId);
1009 return;
1010 }
1011 spin_unlock(&context->context_lock);
1012
1013 if (linkLayerStatsResults->
1014 paramId & WMI_LINK_STATS_RADIO) {
1015 hdd_link_layer_process_radio_stats(pAdapter,
1016 linkLayerStatsResults->moreResultToFollow,
1017 (tpSirWifiRadioStat)linkLayerStatsResults->results,
1018 linkLayerStatsResults->num_radio);
1019
1020 spin_lock(&context->context_lock);
1021 if (!linkLayerStatsResults->moreResultToFollow)
1022 context->request_bitmap &= ~(WMI_LINK_STATS_RADIO);
1023 spin_unlock(&context->context_lock);
1024
1025 } else if (linkLayerStatsResults->
1026 paramId & WMI_LINK_STATS_IFACE) {
1027 hdd_link_layer_process_iface_stats(pAdapter,
1028 (tpSirWifiIfaceStat)linkLayerStatsResults->results,
1029 linkLayerStatsResults->num_peers);
1030
1031 spin_lock(&context->context_lock);
Srinivas Dasari6946a792015-09-28 15:01:49 +05301032 /* Firmware doesn't send peerstats event if no peers are
1033 * connected. HDD should not wait for any peerstats in
1034 * this case and return the status to middleware after
1035 * receiving iface stats
1036 */
1037 if (!linkLayerStatsResults->num_peers)
1038 context->request_bitmap &=
1039 ~(WMI_LINK_STATS_ALL_PEER);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 context->request_bitmap &= ~(WMI_LINK_STATS_IFACE);
1041 spin_unlock(&context->context_lock);
1042
1043 } else if (linkLayerStatsResults->
1044 paramId & WMI_LINK_STATS_ALL_PEER) {
1045 hdd_link_layer_process_peer_stats(pAdapter,
1046 linkLayerStatsResults->moreResultToFollow,
1047 (tpSirWifiPeerStat)linkLayerStatsResults->results);
1048
1049 spin_lock(&context->context_lock);
1050 if (!linkLayerStatsResults->moreResultToFollow)
1051 context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
1052 spin_unlock(&context->context_lock);
1053
1054 } else {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001055 hdd_err("INVALID LL_STATS_NOTIFY RESPONSE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001056 }
1057
1058 spin_lock(&context->context_lock);
1059 /* complete response event if all requests are completed */
1060 if (0 == context->request_bitmap)
1061 complete(&context->response_event);
1062 spin_unlock(&context->context_lock);
1063
1064 break;
1065 }
1066 default:
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001067 hdd_err("invalid event type %d", indType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 break;
1069 }
1070
1071 return;
1072}
1073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074const struct
1075nla_policy
1076 qca_wlan_vendor_ll_set_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1] = {
1077 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD] = {
1078 .type = NLA_U32},
1079 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING] = {
1080 .type = NLA_U32},
1081};
1082
1083/**
1084 * __wlan_hdd_cfg80211_ll_stats_set() - set link layer stats
1085 * @wiphy: Pointer to wiphy
1086 * @wdev: Pointer to wdev
1087 * @data: Pointer to data
1088 * @data_len: Data length
1089 *
1090 * Return: int
1091 */
1092static int
1093__wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1094 struct wireless_dev *wdev,
1095 const void *data,
1096 int data_len)
1097{
1098 int status;
1099 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1];
1100 tSirLLStatsSetReq LinkLayerStatsSetReq;
1101 struct net_device *dev = wdev->netdev;
1102 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1103 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1104
Jeff Johnson1f61b612016-02-12 16:28:33 -08001105 ENTER_DEV(dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301106
Anurag Chouhan6d760662016-02-20 16:05:43 +05301107 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 hdd_err("Command not allowed in FTM mode");
1109 return -EPERM;
1110 }
1111
1112 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301113 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115
1116 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX,
1117 (struct nlattr *)data,
1118 data_len, qca_wlan_vendor_ll_set_policy)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001119 hdd_err("maximum attribute not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120 return -EINVAL;
1121 }
1122
1123 if (!tb_vendor
1124 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001125 hdd_err("MPDU size Not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126 return -EINVAL;
1127 }
1128
1129 if (!tb_vendor
1130 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001131 hdd_err("Stats Gathering Not Present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 return -EINVAL;
1133 }
1134
1135 /* Shall take the request Id if the Upper layers pass. 1 For now. */
1136 LinkLayerStatsSetReq.reqId = 1;
1137
1138 LinkLayerStatsSetReq.mpduSizeThreshold =
1139 nla_get_u32(tb_vendor
1140 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]);
1141
1142 LinkLayerStatsSetReq.aggressiveStatisticsGathering =
1143 nla_get_u32(tb_vendor
1144 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]);
1145
1146 LinkLayerStatsSetReq.staId = pAdapter->sessionId;
1147
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001148 hdd_notice("LL_STATS_SET reqId = %d, staId = %d, mpduSizeThreshold = %d, Statistics Gathering = %d",
Sushant Kaushik7a535882015-11-02 13:31:21 +05301149 LinkLayerStatsSetReq.reqId, LinkLayerStatsSetReq.staId,
1150 LinkLayerStatsSetReq.mpduSizeThreshold,
1151 LinkLayerStatsSetReq.aggressiveStatisticsGathering);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301153 if (QDF_STATUS_SUCCESS != sme_ll_stats_set_req(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 &LinkLayerStatsSetReq)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001155 hdd_err("sme_ll_stats_set_req Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 return -EINVAL;
1157 }
1158
1159 pAdapter->isLinkLayerStatsSet = 1;
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301160 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 return 0;
1162}
1163
1164/**
1165 * wlan_hdd_cfg80211_ll_stats_set() - set ll stats
1166 * @wiphy: Pointer to wiphy
1167 * @wdev: Pointer to wdev
1168 * @data: Pointer to data
1169 * @data_len: Data length
1170 *
1171 * Return: 0 if success, non-zero for failure
1172 */
1173int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1174 struct wireless_dev *wdev,
1175 const void *data,
1176 int data_len)
1177{
1178 int ret = 0;
1179
1180 cds_ssr_protect(__func__);
1181 ret = __wlan_hdd_cfg80211_ll_stats_set(wiphy, wdev, data, data_len);
1182 cds_ssr_unprotect(__func__);
1183
1184 return ret;
1185}
1186
1187const struct
1188nla_policy
1189 qca_wlan_vendor_ll_get_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1] = {
1190 /* Unsigned 32bit value provided by the caller issuing the GET stats
1191 * command. When reporting
1192 * the stats results, the driver uses the same value to indicate
1193 * which GET request the results
1194 * correspond to.
1195 */
1196 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID] = {.type = NLA_U32},
1197
1198 /* Unsigned 32bit value . bit mask to identify what statistics are
1199 requested for retrieval */
1200 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = {.type = NLA_U32}
1201};
1202
1203/**
1204 * __wlan_hdd_cfg80211_ll_stats_get() - get link layer stats
1205 * @wiphy: Pointer to wiphy
1206 * @wdev: Pointer to wdev
1207 * @data: Pointer to data
1208 * @data_len: Data length
1209 *
1210 * Return: int
1211 */
1212static int
1213__wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1214 struct wireless_dev *wdev,
1215 const void *data,
1216 int data_len)
1217{
1218 unsigned long rc;
1219 struct hdd_ll_stats_context *context;
1220 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1221 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1];
1222 tSirLLStatsGetReq LinkLayerStatsGetReq;
1223 struct net_device *dev = wdev->netdev;
1224 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Anurag Chouhan22520002016-09-03 16:20:32 +05301225 hdd_station_ctx_t *hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 int status;
1227
Jeff Johnson1f61b612016-02-12 16:28:33 -08001228 ENTER_DEV(dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301229
Anurag Chouhan6d760662016-02-20 16:05:43 +05301230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 hdd_err("Command not allowed in FTM mode");
1232 return -EPERM;
1233 }
1234
1235 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301236 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238
1239 if (!pAdapter->isLinkLayerStatsSet) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001240 hdd_warn("isLinkLayerStatsSet: %d",
1241 pAdapter->isLinkLayerStatsSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 return -EINVAL;
1243 }
1244
Anurag Chouhan22520002016-09-03 16:20:32 +05301245 if (hddstactx->hdd_ReassocScenario) {
1246 hdd_err("Roaming in progress, so unable to proceed this request");
1247 return -EBUSY;
1248 }
1249
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX,
1251 (struct nlattr *)data,
1252 data_len, qca_wlan_vendor_ll_get_policy)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001253 hdd_err("max attribute not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 return -EINVAL;
1255 }
1256
1257 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001258 hdd_err("Request Id Not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 return -EINVAL;
1260 }
1261
1262 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001263 hdd_err("Req Mask Not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 return -EINVAL;
1265 }
1266
1267 LinkLayerStatsGetReq.reqId =
1268 nla_get_u32(tb_vendor
1269 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]);
1270 LinkLayerStatsGetReq.paramIdMask =
1271 nla_get_u32(tb_vendor
1272 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]);
1273
1274 LinkLayerStatsGetReq.staId = pAdapter->sessionId;
1275
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001276 hdd_notice("LL_STATS_GET reqId = %d, staId = %d, paramIdMask = %d",
Sushant Kaushik7a535882015-11-02 13:31:21 +05301277 LinkLayerStatsGetReq.reqId,
1278 LinkLayerStatsGetReq.staId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279 LinkLayerStatsGetReq.paramIdMask);
1280
1281 context = &ll_stats_context;
1282 spin_lock(&context->context_lock);
1283 context->request_id = LinkLayerStatsGetReq.reqId;
1284 context->request_bitmap = LinkLayerStatsGetReq.paramIdMask;
1285 INIT_COMPLETION(context->response_event);
1286 spin_unlock(&context->context_lock);
1287
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301288 if (QDF_STATUS_SUCCESS != sme_ll_stats_get_req(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 &LinkLayerStatsGetReq)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001290 hdd_err("sme_ll_stats_get_req Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 return -EINVAL;
1292 }
1293
1294 rc = wait_for_completion_timeout(&context->response_event,
1295 msecs_to_jiffies(WLAN_WAIT_TIME_LL_STATS));
1296 if (!rc) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001297 hdd_err("Target response timed out request id %d request bitmap 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 context->request_id, context->request_bitmap);
1299 return -ETIMEDOUT;
1300 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301301 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 return 0;
1303}
1304
1305/**
1306 * wlan_hdd_cfg80211_ll_stats_get() - get ll stats
1307 * @wiphy: Pointer to wiphy
1308 * @wdev: Pointer to wdev
1309 * @data: Pointer to data
1310 * @data_len: Data length
1311 *
1312 * Return: 0 if success, non-zero for failure
1313 */
1314int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1315 struct wireless_dev *wdev,
1316 const void *data,
1317 int data_len)
1318{
1319 int ret = 0;
1320
1321 cds_ssr_protect(__func__);
1322 ret = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len);
1323 cds_ssr_unprotect(__func__);
1324
1325 return ret;
1326}
1327
1328const struct
1329nla_policy
1330 qca_wlan_vendor_ll_clr_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1] = {
1331 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] = {.type = NLA_U32},
1332 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ] = {.type = NLA_U8},
1333 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK] = {.type = NLA_U32},
1334 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP] = {.type = NLA_U8},
1335};
1336
1337/**
1338 * __wlan_hdd_cfg80211_ll_stats_clear() - clear link layer stats
1339 * @wiphy: Pointer to wiphy
1340 * @wdev: Pointer to wdev
1341 * @data: Pointer to data
1342 * @data_len: Data length
1343 *
1344 * Return: int
1345 */
1346static int
1347__wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1348 struct wireless_dev *wdev,
1349 const void *data,
1350 int data_len)
1351{
1352 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1353 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
1354 tSirLLStatsClearReq LinkLayerStatsClearReq;
1355 struct net_device *dev = wdev->netdev;
1356 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1357 u32 statsClearReqMask;
1358 u8 stopReq;
1359 int status;
1360 struct sk_buff *temp_skbuff;
1361
Jeff Johnson1f61b612016-02-12 16:28:33 -08001362 ENTER_DEV(dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301363
Anurag Chouhan6d760662016-02-20 16:05:43 +05301364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 hdd_err("Command not allowed in FTM mode");
1366 return -EPERM;
1367 }
1368
1369 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301370 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372
1373 if (!pAdapter->isLinkLayerStatsSet) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001374 hdd_alert("isLinkLayerStatsSet : %d",
1375 pAdapter->isLinkLayerStatsSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 return -EINVAL;
1377 }
1378
1379 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
1380 (struct nlattr *)data,
1381 data_len, qca_wlan_vendor_ll_clr_policy)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001382 hdd_err("STATS_CLR_MAX is not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return -EINVAL;
1384 }
1385
1386 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] ||
1387 !tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001388 hdd_err("Error in LL_STATS CLR CONFIG PARA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 return -EINVAL;
1390 }
1391
1392 statsClearReqMask = LinkLayerStatsClearReq.statsClearReqMask =
1393 nla_get_u32(tb_vendor
1394 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]);
1395
1396 stopReq = LinkLayerStatsClearReq.stopReq =
1397 nla_get_u8(tb_vendor
1398 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]);
1399
1400 /*
1401 * Shall take the request Id if the Upper layers pass. 1 For now.
1402 */
1403 LinkLayerStatsClearReq.reqId = 1;
1404
1405 LinkLayerStatsClearReq.staId = pAdapter->sessionId;
1406
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001407 hdd_notice("LL_STATS_CLEAR reqId = %d, staId = %d, statsClearReqMask = 0x%X, stopReq = %d",
Sushant Kaushik7a535882015-11-02 13:31:21 +05301408 LinkLayerStatsClearReq.reqId,
1409 LinkLayerStatsClearReq.staId,
1410 LinkLayerStatsClearReq.statsClearReqMask,
1411 LinkLayerStatsClearReq.stopReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301413 if (QDF_STATUS_SUCCESS == sme_ll_stats_clear_req(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414 &LinkLayerStatsClearReq)) {
1415 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1416 2 *
1417 sizeof(u32) +
1418 2 *
1419 NLMSG_HDRLEN);
1420 if (temp_skbuff != NULL) {
1421 if (nla_put_u32(temp_skbuff,
1422 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK,
1423 statsClearReqMask) ||
1424 nla_put_u32(temp_skbuff,
1425 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP,
1426 stopReq)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001427 hdd_err("LL_STATS_CLR put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001428 kfree_skb(temp_skbuff);
1429 return -EINVAL;
1430 }
1431
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001432 /* If the ask is to stop the stats collection
1433 * as part of clear (stopReq = 1), ensure
1434 * that no further requests of get go to the
1435 * firmware by having isLinkLayerStatsSet set
1436 * to 0. However it the stopReq as part of
1437 * the clear request is 0, the request to get
1438 * the statistics are honoured as in this case
1439 * the firmware is just asked to clear the
1440 * statistics.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 */
1442 if (stopReq == 1)
1443 pAdapter->isLinkLayerStatsSet = 0;
1444
1445 return cfg80211_vendor_cmd_reply(temp_skbuff);
1446 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301447 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 return -ENOMEM;
1449 }
1450
1451 return -EINVAL;
1452}
1453
1454/**
1455 * wlan_hdd_cfg80211_ll_stats_clear() - clear ll stats
1456 * @wiphy: Pointer to wiphy
1457 * @wdev: Pointer to wdev
1458 * @data: Pointer to data
1459 * @data_len: Data length
1460 *
1461 * Return: 0 if success, non-zero for failure
1462 */
1463int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1464 struct wireless_dev *wdev,
1465 const void *data,
1466 int data_len)
1467{
1468 int ret = 0;
1469
1470 cds_ssr_protect(__func__);
1471 ret = __wlan_hdd_cfg80211_ll_stats_clear(wiphy, wdev, data, data_len);
1472 cds_ssr_unprotect(__func__);
1473
1474 return ret;
1475}
1476
1477#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1478
1479#ifdef WLAN_FEATURE_STATS_EXT
1480/**
1481 * __wlan_hdd_cfg80211_stats_ext_request() - ext stats request
1482 * @wiphy: Pointer to wiphy
1483 * @wdev: Pointer to wdev
1484 * @data: Pointer to data
1485 * @data_len: Data length
1486 *
1487 * Return: int
1488 */
1489static int __wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy,
1490 struct wireless_dev *wdev,
1491 const void *data,
1492 int data_len)
1493{
1494 tStatsExtRequestReq stats_ext_req;
1495 struct net_device *dev = wdev->netdev;
1496 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1497 int ret_val;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301498 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1500
Jeff Johnson1f61b612016-02-12 16:28:33 -08001501 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502
1503 ret_val = wlan_hdd_validate_context(hdd_ctx);
1504 if (ret_val)
1505 return ret_val;
1506
Anurag Chouhan6d760662016-02-20 16:05:43 +05301507 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 hdd_err("Command not allowed in FTM mode");
1509 return -EPERM;
1510 }
1511
1512 stats_ext_req.request_data_len = data_len;
1513 stats_ext_req.request_data = (void *)data;
1514
1515 status = sme_stats_ext_request(pAdapter->sessionId, &stats_ext_req);
1516
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 ret_val = -EINVAL;
1519
1520 return ret_val;
1521}
1522
1523/**
1524 * wlan_hdd_cfg80211_stats_ext_request() - ext stats request
1525 * @wiphy: Pointer to wiphy
1526 * @wdev: Pointer to wdev
1527 * @data: Pointer to data
1528 * @data_len: Data length
1529 *
1530 * Return: int
1531 */
1532int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy,
1533 struct wireless_dev *wdev,
1534 const void *data,
1535 int data_len)
1536{
1537 int ret;
1538
1539 cds_ssr_protect(__func__);
1540 ret = __wlan_hdd_cfg80211_stats_ext_request(wiphy, wdev,
1541 data, data_len);
1542 cds_ssr_unprotect(__func__);
1543
1544 return ret;
1545}
1546
1547/**
1548 * wlan_hdd_cfg80211_stats_ext_callback() - ext stats callback
1549 * @ctx: Pointer to HDD context
1550 * @msg: Message received
1551 *
1552 * Return: nothing
1553 */
Arun Khandavalli4b55da72016-07-19 19:55:01 +05301554void wlan_hdd_cfg80211_stats_ext_callback(void *ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 tStatsExtEvent *msg)
1556{
1557
1558 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1559 struct sk_buff *vendor_event;
1560 int status;
1561 int ret_val;
1562 tStatsExtEvent *data = msg;
1563 hdd_adapter_t *pAdapter = NULL;
1564
1565 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301566 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301568
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001569 pAdapter = hdd_get_adapter_by_vdev(pHddCtx, data->vdev_id);
1570
1571 if (NULL == pAdapter) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001572 hdd_err("vdev_id %d does not exist with host", data->vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 return;
1574 }
1575
1576 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1577 NULL,
1578 data->event_data_len +
1579 sizeof(uint32_t) +
1580 NLMSG_HDRLEN + NLMSG_HDRLEN,
1581 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX,
1582 GFP_KERNEL);
1583
1584 if (!vendor_event) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001585 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586 return;
1587 }
1588
1589 ret_val = nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_IFINDEX,
1590 pAdapter->dev->ifindex);
1591 if (ret_val) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001592 hdd_err("QCA_WLAN_VENDOR_ATTR_IFINDEX put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593 kfree_skb(vendor_event);
1594
1595 return;
1596 }
1597
1598 ret_val = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_STATS_EXT,
1599 data->event_data_len, data->event_data);
1600
1601 if (ret_val) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001602 hdd_err("QCA_WLAN_VENDOR_ATTR_STATS_EXT put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001603 kfree_skb(vendor_event);
1604
1605 return;
1606 }
1607
1608 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1609
1610}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611#endif /* End of WLAN_FEATURE_STATS_EXT */
1612
1613/**
1614 * __wlan_hdd_cfg80211_get_station() - get station statistics
1615 * @wiphy: Pointer to wiphy
1616 * @dev: Pointer to network device
1617 * @mac: Pointer to mac
1618 * @sinfo: Pointer to station info
1619 *
1620 * Return: 0 for success, non-zero for failure
1621 */
1622static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
1623 struct net_device *dev,
1624 const uint8_t *mac,
1625 struct station_info *sinfo)
1626{
1627 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1628 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1629 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
1630 uint8_t rate_flags;
1631
1632 hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy);
1633 struct hdd_config *pCfg = pHddCtx->config;
1634
1635 uint8_t OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
1636 uint32_t ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
1637 uint8_t ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
1638 uint32_t ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
1639 uint8_t MCSRates[SIZE_OF_BASIC_MCS_SET];
1640 uint32_t MCSLeng = SIZE_OF_BASIC_MCS_SET;
1641 uint16_t maxRate = 0;
Anurag Chouhan5de8d172016-07-13 14:44:28 +05301642 int8_t snr = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001643 uint16_t myRate;
1644 uint16_t currentRate = 0;
1645 uint8_t maxSpeedMCS = 0;
1646 uint8_t maxMCSIdx = 0;
1647 uint8_t rateFlag = 1;
1648 uint8_t i, j, rssidx;
1649 uint8_t nss = 1;
1650 int status, mode = 0, maxHtIdx;
1651 struct index_vht_data_rate_type *supported_vht_mcs_rate;
1652 struct index_data_rate_type *supported_mcs_rate;
1653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001654 uint32_t vht_mcs_map;
1655 enum eDataRate11ACMaxMcs vhtMaxMcs;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001657 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658
Anurag Chouhan6d760662016-02-20 16:05:43 +05301659 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001660 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001661 return -EINVAL;
1662 }
1663
1664 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
1665 (0 == ssidlen)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001666 hdd_notice("Not associated or Invalid ssidlen, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001667 ssidlen);
1668 /*To keep GUI happy */
1669 return 0;
1670 }
1671
1672 if (true == pHddStaCtx->hdd_ReassocScenario) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001673 hdd_notice("Roaming is in progress, cannot continue with this request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001674 return 0;
1675 }
1676
1677 status = wlan_hdd_validate_context(pHddCtx);
1678
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301679 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681
1682 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
Anurag Chouhan5de8d172016-07-13 14:44:28 +05301683 wlan_hdd_get_snr(pAdapter, &snr);
1684 pHddStaCtx->conn_info.signal = sinfo->signal;
1685 pHddStaCtx->conn_info.noise =
1686 pHddStaCtx->conn_info.signal - snr;
1687
Ryan Hsue7bc3a72016-01-18 12:08:22 -08001688#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 sinfo->filled |= STATION_INFO_SIGNAL;
Ryan Hsue7bc3a72016-01-18 12:08:22 -08001690#else
1691 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
1692#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693
1694#ifdef WLAN_FEATURE_LPSS
1695 if (!pAdapter->rssi_send) {
1696 pAdapter->rssi_send = true;
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001697 if (cds_is_driver_unloading())
Yue Mae3eaebe2015-10-27 12:42:40 -07001698 wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699 }
1700#endif
1701
1702 wlan_hdd_get_station_stats(pAdapter);
1703 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
1704
1705 /* convert to the UI units of 100kbps */
1706 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
1707 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
1708 nss = pAdapter->hdd_stats.ClassA_stat.rx_frag_cnt;
1709
1710 if (eHDD_LINK_SPEED_REPORT_ACTUAL == pCfg->reportMaxLinkSpeed) {
1711 /* Get current rate flags if report actual */
1712 rate_flags =
1713 pAdapter->hdd_stats.ClassA_stat.
1714 promiscuous_rx_frag_cnt;
1715 }
1716
1717 if (pAdapter->hdd_stats.ClassA_stat.mcs_index ==
1718 INVALID_MCS_IDX) {
1719 rate_flags = eHAL_TX_RATE_LEGACY;
1720 pAdapter->hdd_stats.ClassA_stat.mcs_index = 0;
1721 }
1722 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -08001723
1724 hdd_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d",
1725 sinfo->signal, pCfg->reportMaxLinkSpeed, myRate,
1726 (int)pCfg->linkSpeedRssiHigh, (int)pCfg->linkSpeedRssiMid,
1727 (int)pCfg->linkSpeedRssiLow, (int)rate_flags,
1728 (int)pAdapter->hdd_stats.ClassA_stat.mcs_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729
1730 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) {
1731 /* we do not want to necessarily report the current speed */
1732 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) {
1733 /* report the max possible speed */
1734 rssidx = 0;
1735 } else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED ==
1736 pCfg->reportMaxLinkSpeed) {
1737 /* report the max possible speed with RSSI scaling */
1738 if (sinfo->signal >= pCfg->linkSpeedRssiHigh) {
1739 /* report the max possible speed */
1740 rssidx = 0;
1741 } else if (sinfo->signal >= pCfg->linkSpeedRssiMid) {
1742 /* report middle speed */
1743 rssidx = 1;
1744 } else if (sinfo->signal >= pCfg->linkSpeedRssiLow) {
1745 /* report middle speed */
1746 rssidx = 2;
1747 } else {
1748 /* report actual speed */
1749 rssidx = 3;
1750 }
1751 } else {
1752 /* unknown, treat as eHDD_LINK_SPEED_REPORT_MAX */
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001753 hdd_err("Invalid value for reportMaxLinkSpeed: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754 pCfg->reportMaxLinkSpeed);
1755 rssidx = 0;
1756 }
1757
1758 maxRate = 0;
1759
1760 /* Get Basic Rate Set */
1761 if (0 !=
1762 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
1763 WNI_CFG_OPERATIONAL_RATE_SET,
1764 OperationalRates,
1765 &ORLeng)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001766 hdd_err("cfg get returned failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 /*To keep GUI happy */
1768 return 0;
1769 }
1770
1771 for (i = 0; i < ORLeng; i++) {
1772 for (j = 0;
1773 j < ARRAY_SIZE(supported_data_rate); j++) {
1774 /* Validate Rate Set */
1775 if (supported_data_rate[j].beacon_rate_index ==
1776 (OperationalRates[i] & 0x7F)) {
1777 currentRate =
1778 supported_data_rate[j].
1779 supported_rate[rssidx];
1780 break;
1781 }
1782 }
1783 /* Update MAX rate */
1784 maxRate =
1785 (currentRate > maxRate) ? currentRate : maxRate;
1786 }
1787
1788 /* Get Extended Rate Set */
1789 if (0 !=
1790 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
1791 WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
1792 ExtendedRates, &ERLeng)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001793 hdd_err("cfg get returned failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 /*To keep GUI happy */
1795 return 0;
1796 }
1797
1798 for (i = 0; i < ERLeng; i++) {
1799 for (j = 0;
1800 j < ARRAY_SIZE(supported_data_rate); j++) {
1801 if (supported_data_rate[j].beacon_rate_index ==
1802 (ExtendedRates[i] & 0x7F)) {
1803 currentRate =
1804 supported_data_rate[j].
1805 supported_rate[rssidx];
1806 break;
1807 }
1808 }
1809 /* Update MAX rate */
1810 maxRate =
1811 (currentRate > maxRate) ? currentRate : maxRate;
1812 }
1813 /* Get MCS Rate Set --
1814 Only if we are connected in non legacy mode and not reporting
1815 actual speed */
1816 if ((3 != rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY)) {
1817 if (0 !=
1818 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
1819 WNI_CFG_CURRENT_MCS_SET, MCSRates,
1820 &MCSLeng)) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07001821 hdd_err("cfg get returned failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 /*To keep GUI happy */
1823 return 0;
1824 }
1825 rateFlag = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 supported_vht_mcs_rate =
1827 (struct index_vht_data_rate_type *)
1828 ((nss ==
1829 1) ? &supported_vht_mcs_rate_nss1 :
1830 &supported_vht_mcs_rate_nss2);
1831
1832 if (rate_flags & eHAL_TX_RATE_VHT80)
1833 mode = 2;
1834 else if ((rate_flags & eHAL_TX_RATE_VHT40) ||
1835 (rate_flags & eHAL_TX_RATE_HT40))
1836 mode = 1;
1837 else
1838 mode = 0;
1839
1840 /* VHT80 rate has seperate rate table */
1841 if (rate_flags &
1842 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
1843 eHAL_TX_RATE_VHT80)) {
1844 sme_cfg_get_int(WLAN_HDD_GET_HAL_CTX(pAdapter),
1845 WNI_CFG_VHT_TX_MCS_MAP,
1846 &vht_mcs_map);
1847 vhtMaxMcs = (enum eDataRate11ACMaxMcs)
1848 (vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
1849 if (rate_flags & eHAL_TX_RATE_SGI)
1850 rateFlag |= 1;
1851 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
1852 maxMCSIdx = 7;
1853 else if (DATA_RATE_11AC_MAX_MCS_8 ==
1854 vhtMaxMcs)
1855 maxMCSIdx = 8;
1856 else if (DATA_RATE_11AC_MAX_MCS_9 ==
1857 vhtMaxMcs) {
1858 /* VHT20 is supporting 0~8 */
1859 if (rate_flags & eHAL_TX_RATE_VHT20)
1860 maxMCSIdx = 8;
1861 else
1862 maxMCSIdx = 9;
1863 }
1864
1865 if (rssidx != 0) {
1866 for (i = 0; i <= maxMCSIdx; i++) {
1867 if (sinfo->signal <=
1868 rssi_mcs_tbl[mode][i]) {
1869 maxMCSIdx = i;
1870 break;
1871 }
1872 }
1873 }
1874
1875 if (rate_flags & eHAL_TX_RATE_VHT80) {
1876 currentRate =
1877 supported_vht_mcs_rate[pAdapter->
1878 hdd_stats.ClassA_stat.mcs_index].
1879 supported_VHT80_rate[rateFlag];
1880 maxRate =
1881 supported_vht_mcs_rate[maxMCSIdx].
1882 supported_VHT80_rate[rateFlag];
1883 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
1884 currentRate =
1885 supported_vht_mcs_rate[pAdapter->
1886 hdd_stats.ClassA_stat.mcs_index].
1887 supported_VHT40_rate[rateFlag];
1888 maxRate =
1889 supported_vht_mcs_rate[maxMCSIdx].
1890 supported_VHT40_rate[rateFlag];
1891 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
1892 currentRate =
1893 supported_vht_mcs_rate[pAdapter->
1894 hdd_stats.ClassA_stat.mcs_index].
1895 supported_VHT20_rate[rateFlag];
1896 maxRate =
1897 supported_vht_mcs_rate[maxMCSIdx].
1898 supported_VHT20_rate[rateFlag];
1899 }
1900
1901 maxSpeedMCS = 1;
1902 if (currentRate > maxRate)
1903 maxRate = currentRate;
1904
Kiran Kumar Lokere9a733a72016-02-17 19:01:15 -08001905 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 if (rate_flags & eHAL_TX_RATE_HT40)
1907 rateFlag |= 1;
1908 if (rate_flags & eHAL_TX_RATE_SGI)
1909 rateFlag |= 2;
1910
1911 supported_mcs_rate =
1912 (struct index_data_rate_type *)
1913 ((nss ==
1914 1) ? &supported_mcs_rate_nss1 :
1915 &supported_mcs_rate_nss2);
1916
1917 maxHtIdx = MAX_HT_MCS_IDX;
1918 if (rssidx != 0) {
1919 for (i = 0; i < MAX_HT_MCS_IDX; i++) {
1920 if (sinfo->signal <=
1921 rssi_mcs_tbl[mode][i]) {
1922 maxHtIdx = i + 1;
1923 break;
1924 }
1925 }
1926 }
1927
1928 for (i = 0; i < MCSLeng; i++) {
1929 for (j = 0; j < maxHtIdx; j++) {
1930 if (supported_mcs_rate[j].
1931 beacon_rate_index ==
1932 MCSRates[i]) {
1933 currentRate =
1934 supported_mcs_rate[j].
1935 supported_rate
1936 [rateFlag];
Hanumantha Reddy Pothula616dfbe2015-10-01 14:14:46 +05301937 maxMCSIdx =
1938 supported_mcs_rate[j].
1939 beacon_rate_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 break;
1941 }
1942 }
1943
1944 if ((j < MAX_HT_MCS_IDX)
1945 && (currentRate > maxRate)) {
1946 maxRate = currentRate;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 }
Hanumantha Reddy Pothula616dfbe2015-10-01 14:14:46 +05301948 maxSpeedMCS = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 }
1950 }
1951 }
1952
1953 else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
1954 maxRate = myRate;
1955 maxSpeedMCS = 1;
1956 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
1957 }
1958 /* report a value at least as big as current rate */
1959 if ((maxRate < myRate) || (0 == maxRate)) {
1960 maxRate = myRate;
1961 if (rate_flags & eHAL_TX_RATE_LEGACY) {
1962 maxSpeedMCS = 0;
1963 } else {
1964 maxSpeedMCS = 1;
1965 maxMCSIdx =
1966 pAdapter->hdd_stats.ClassA_stat.mcs_index;
1967 }
1968 }
1969
1970 if (rate_flags & eHAL_TX_RATE_LEGACY) {
1971 sinfo->txrate.legacy = maxRate;
1972#ifdef LINKSPEED_DEBUG_ENABLED
1973 pr_info("Reporting legacy rate %d\n",
1974 sinfo->txrate.legacy);
1975#endif /* LINKSPEED_DEBUG_ENABLED */
1976 } else {
1977 sinfo->txrate.mcs = maxMCSIdx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 sinfo->txrate.nss = nss;
1979 if (rate_flags & eHAL_TX_RATE_VHT80) {
1980 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08001981#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
1982 sinfo->txrate.bw = RATE_INFO_BW_80;
1983#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 sinfo->txrate.flags |=
1985 RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08001986#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
1988 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08001989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
1990 sinfo->txrate.bw = RATE_INFO_BW_40;
1991#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 sinfo->txrate.flags |=
1993 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08001994#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
1996 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
1997 } else
1998 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 if (rate_flags &
2000 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
2001 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2002 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002003#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
2004 sinfo->txrate.bw = RATE_INFO_BW_40;
2005#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 sinfo->txrate.flags |=
2007 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002008#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 }
2010 }
2011 if (rate_flags & eHAL_TX_RATE_SGI) {
2012 if (!
2013 (sinfo->txrate.
2014 flags & RATE_INFO_FLAGS_VHT_MCS))
2015 sinfo->txrate.flags |=
2016 RATE_INFO_FLAGS_MCS;
2017 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
2018 }
2019#ifdef LINKSPEED_DEBUG_ENABLED
2020 pr_info("Reporting MCS rate %d flags %x\n",
2021 sinfo->txrate.mcs, sinfo->txrate.flags);
2022#endif /* LINKSPEED_DEBUG_ENABLED */
2023 }
2024 } else {
2025 /* report current rate instead of max rate */
2026
2027 if (rate_flags & eHAL_TX_RATE_LEGACY) {
2028 /* provide to the UI in units of 100kbps */
2029 sinfo->txrate.legacy = myRate;
2030#ifdef LINKSPEED_DEBUG_ENABLED
2031 pr_info("Reporting actual legacy rate %d\n",
2032 sinfo->txrate.legacy);
2033#endif /* LINKSPEED_DEBUG_ENABLED */
2034 } else {
2035 /* must be MCS */
2036 sinfo->txrate.mcs =
2037 pAdapter->hdd_stats.ClassA_stat.mcs_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 sinfo->txrate.nss = nss;
2039 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2040 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002041#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
2042 sinfo->txrate.bw = RATE_INFO_BW_80;
2043#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 sinfo->txrate.flags |=
2045 RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002046#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002048#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
2049 sinfo->txrate.bw = RATE_INFO_BW_40;
2050#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 sinfo->txrate.flags |=
2052 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002053#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 if (rate_flags &
2056 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
2057 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2058 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002059#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
2060 sinfo->txrate.bw = RATE_INFO_BW_40;
2061#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 sinfo->txrate.flags |=
2063 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08002064#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 }
2066 }
2067 if (rate_flags & eHAL_TX_RATE_SGI) {
2068 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2069 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
2070 }
2071#ifdef LINKSPEED_DEBUG_ENABLED
2072 pr_info("Reporting actual MCS rate %d flags %x\n",
2073 sinfo->txrate.mcs, sinfo->txrate.flags);
2074#endif /* LINKSPEED_DEBUG_ENABLED */
2075 }
2076 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -08002077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 sinfo->tx_bytes = pAdapter->stats.tx_bytes;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079
2080 sinfo->tx_packets =
2081 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
2082 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
2083 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
2084 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
2085
2086 sinfo->tx_retries =
2087 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
2088 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
2089 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
2090 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
2091
2092 sinfo->tx_failed =
2093 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
2094 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
2095 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
2096 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
2097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 sinfo->rx_bytes = pAdapter->stats.rx_bytes;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099 sinfo->rx_packets = pAdapter->stats.rx_packets;
Ryan Hsue7bc3a72016-01-18 12:08:22 -08002100
Anurag Chouhan5de8d172016-07-13 14:44:28 +05302101 qdf_mem_copy(&pHddStaCtx->conn_info.txrate,
2102 &sinfo->txrate, sizeof(sinfo->txrate));
2103
Ryan Hsue7bc3a72016-01-18 12:08:22 -08002104#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
2105 sinfo->filled |= STATION_INFO_TX_BITRATE |
2106 STATION_INFO_TX_BYTES |
2107 STATION_INFO_TX_PACKETS |
2108 STATION_INFO_TX_RETRIES |
2109 STATION_INFO_TX_FAILED |
2110 STATION_INFO_RX_BYTES |
2111 STATION_INFO_RX_PACKETS;
2112#else
2113 sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES) |
2114 BIT(NL80211_STA_INFO_TX_BITRATE) |
2115 BIT(NL80211_STA_INFO_TX_PACKETS) |
2116 BIT(NL80211_STA_INFO_TX_RETRIES) |
2117 BIT(NL80211_STA_INFO_TX_FAILED) |
2118 BIT(NL80211_STA_INFO_RX_BYTES) |
2119 BIT(NL80211_STA_INFO_RX_PACKETS);
2120#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121
Edhar, Mahesh Kumarabfad4f2016-01-27 16:33:05 +05302122 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson0c1301d2016-05-17 16:16:35 -07002123 hdd_notice("Reporting legacy rate %d pkt cnt tx %d rx %d",
Edhar, Mahesh Kumarabfad4f2016-01-27 16:33:05 +05302124 sinfo->txrate.legacy, sinfo->tx_packets,
2125 sinfo->rx_packets);
2126 else
Jeff Johnson0c1301d2016-05-17 16:16:35 -07002127 hdd_notice("Reporting MCS rate %d flags 0x%x pkt cnt tx %d rx %d",
Edhar, Mahesh Kumarabfad4f2016-01-27 16:33:05 +05302128 sinfo->txrate.mcs, sinfo->txrate.flags,
2129 sinfo->tx_packets, sinfo->rx_packets);
2130
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302131 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132 TRACE_CODE_HDD_CFG80211_GET_STA,
2133 pAdapter->sessionId, maxRate));
2134 EXIT();
2135 return 0;
2136}
2137
2138/**
2139 * wlan_hdd_cfg80211_get_station() - get station statistics
2140 * @wiphy: Pointer to wiphy
2141 * @dev: Pointer to network device
2142 * @mac: Pointer to mac
2143 * @sinfo: Pointer to station info
2144 *
2145 * Return: 0 for success, non-zero for failure
2146 */
2147#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
2148int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
2149 struct net_device *dev, const uint8_t *mac,
2150 struct station_info *sinfo)
2151#else
2152int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
2153 struct net_device *dev, uint8_t *mac,
2154 struct station_info *sinfo)
2155#endif
2156{
2157 int ret;
2158
2159 cds_ssr_protect(__func__);
2160 ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
2161 cds_ssr_unprotect(__func__);
2162
2163 return ret;
2164}
2165
2166/**
2167 * hdd_get_stats() - Function to retrieve interface statistics
2168 * @dev: pointer to network device
2169 *
2170 * This function is the ndo_get_stats method for all netdevs
2171 * registered with the kernel
2172 *
2173 * Return: pointer to net_device_stats structure
2174 */
2175struct net_device_stats *hdd_get_stats(struct net_device *dev)
2176{
2177 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2178
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002179 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 return &adapter->stats;
2181}
2182/**
2183 * __wlan_hdd_cfg80211_dump_survey() - get survey related info
2184 * @wiphy: Pointer to wiphy
2185 * @dev: Pointer to network device
2186 * @idx: Index
2187 * @survey: Pointer to survey info
2188 *
2189 * Return: 0 for success, non-zero for failure
2190 */
2191static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
2192 struct net_device *dev,
2193 int idx, struct survey_info *survey)
2194{
2195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2196 hdd_context_t *pHddCtx;
2197 hdd_station_ctx_t *pHddStaCtx;
2198 tHalHandle halHandle;
2199 uint32_t channel = 0, freq = 0; /* Initialization Required */
2200 int8_t snr, rssi;
2201 int status, i, j, filled = 0;
2202
Jeff Johnson0c1301d2016-05-17 16:16:35 -07002203 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204
Anurag Chouhan6d760662016-02-20 16:05:43 +05302205 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson0c1301d2016-05-17 16:16:35 -07002206 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 return -EINVAL;
2208 }
2209
2210 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2211 status = wlan_hdd_validate_context(pHddCtx);
2212
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302213 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215
2216 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2217
2218 if (0 == pHddCtx->config->fEnableSNRMonitoring ||
2219 0 != pAdapter->survey_idx ||
2220 eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
2221 /* The survey dump ops when implemented completely is expected
2222 * to return a survey of all channels and the ops is called by
2223 * the kernel with incremental values of the argument 'idx'
2224 * till it returns -ENONET. But we can only support the survey
2225 * for the operating channel for now. survey_idx is used to
2226 * track that the ops is called only once and then return
2227 * -ENONET for the next iteration
2228 */
2229 pAdapter->survey_idx = 0;
2230 return -ENONET;
2231 }
2232
2233 if (!pHddStaCtx->hdd_ReassocScenario) {
2234 hdd_err("Roaming in progress, hence return");
2235 return -ENONET;
2236 }
2237
2238 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
2239
2240 wlan_hdd_get_snr(pAdapter, &snr);
2241 wlan_hdd_get_rssi(pAdapter, &rssi);
2242
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302243 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +05302244 TRACE_CODE_HDD_CFG80211_DUMP_SURVEY,
2245 pAdapter->sessionId, pAdapter->device_mode));
2246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 sme_get_operation_channel(halHandle, &channel, pAdapter->sessionId);
2248 hdd_wlan_get_freq(channel, &freq);
2249
2250 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002251 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253
2254 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
2255 struct ieee80211_supported_band *band = wiphy->bands[i];
2256
2257 if (band->channels[j].center_freq == (uint16_t) freq) {
2258 survey->channel = &band->channels[j];
2259 /* The Rx BDs contain SNR values in dB for the
2260 * received frames while the supplicant expects
2261 * noise. So we calculate and return the value
2262 * of noise (dBm)
2263 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
2264 */
2265 survey->noise = rssi - snr;
2266 survey->filled = SURVEY_INFO_NOISE_DBM;
2267 filled = 1;
2268 }
2269 }
2270 }
2271
2272 if (filled)
2273 pAdapter->survey_idx = 1;
2274 else {
2275 pAdapter->survey_idx = 0;
2276 return -ENONET;
2277 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302278 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 return 0;
2280}
2281
2282/**
2283 * wlan_hdd_cfg80211_dump_survey() - get survey related info
2284 * @wiphy: Pointer to wiphy
2285 * @dev: Pointer to network device
2286 * @idx: Index
2287 * @survey: Pointer to survey info
2288 *
2289 * Return: 0 for success, non-zero for failure
2290 */
2291int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
2292 struct net_device *dev,
2293 int idx, struct survey_info *survey)
2294{
2295 int ret;
2296
2297 cds_ssr_protect(__func__);
2298 ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey);
2299 cds_ssr_unprotect(__func__);
2300
2301 return ret;
2302}
2303/**
2304 * hdd_init_ll_stats_ctx() - initialize link layer stats context
2305 *
2306 * Return: none
2307 */
2308inline void hdd_init_ll_stats_ctx(void)
2309{
2310 spin_lock_init(&ll_stats_context.context_lock);
2311 init_completion(&ll_stats_context.response_event);
2312 ll_stats_context.request_bitmap = 0;
2313
2314 return;
2315}
Nirav Shahbf1b0332016-05-25 14:27:39 +05302316
2317/**
2318 * hdd_display_hif_stats() - display hif stats
2319 *
2320 * Return: none
2321 *
2322 */
2323void hdd_display_hif_stats(void)
2324{
2325 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2326
2327 if (!hif_ctx)
2328 return;
2329 hif_display_stats(hif_ctx);
2330}
2331
2332/**
2333 * hdd_clear_hif_stats() - clear hif stats
2334 *
2335 * Return: none
2336 */
2337void hdd_clear_hif_stats(void)
2338{
2339 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2340
2341 if (!hif_ctx)
2342 return;
2343 hif_clear_stats(hif_ctx);
2344}