blob: 549b3dedbba79b1a7fe143a68bbaf546aa644817 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
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"
33
34#ifdef WLAN_FEATURE_LINK_LAYER_STATS
35
36/**
37 * struct hdd_ll_stats_context - hdd link layer stats context
38 *
39 * @request_id: userspace-assigned link layer stats request id
40 * @request_bitmap: userspace-assigned link layer stats request bitmap
41 * @response_event: LL stats request wait event
42 */
43struct hdd_ll_stats_context {
44 uint32_t request_id;
45 uint32_t request_bitmap;
46 struct completion response_event;
47 spinlock_t context_lock;
48};
49
50static struct hdd_ll_stats_context ll_stats_context;
51
52#endif /* End of WLAN_FEATURE_LINK_LAYER_STATS */
53
54/* 11B, 11G Rate table include Basic rate and Extended rate
55 * The IDX field is the rate index
56 * The HI field is the rate when RSSI is strong or being ignored
57 * (in this case we report actual rate)
58 * The MID field is the rate when RSSI is moderate
59 * (in this case we cap 11b rates at 5.5 and 11g rates at 24)
60 * The LO field is the rate when RSSI is low
61 * (in this case we don't report rates, actual current rate used)
62 */
63static const struct {
64 uint8_t beacon_rate_index;
65 uint16_t supported_rate[4];
66} supported_data_rate[] = {
67/* IDX HI HM LM LO (RSSI-based index */
68 {
69 2, {
70 10, 10, 10, 0
71 }
72 }, {
73 4, {
74 20, 20, 10, 0
75 }
76 }, {
77 11, {
78 55, 20, 10, 0
79 }
80 }, {
81 12, {
82 60, 55, 20, 0
83 }
84 }, {
85 18, {
86 90, 55, 20, 0
87 }
88 }, {
89 22, {
90 110, 55, 20, 0
91 }
92 }, {
93 24, {
94 120, 90, 60, 0
95 }
96 }, {
97 36, {
98 180, 120, 60, 0
99 }
100 }, {
101 44, {
102 220, 180, 60, 0
103 }
104 }, {
105 48, {
106 240, 180, 90, 0
107 }
108 }, {
109 66, {
110 330, 180, 90, 0
111 }
112 }, {
113 72, {
114 360, 240, 90, 0
115 }
116 }, {
117 96, {
118 480, 240, 120, 0
119 }
120 }, {
121 108, {
122 540, 240, 120, 0
123 }
124 }
125};
126/* MCS Based rate table HT MCS parameters with Nss = 1 */
127static struct index_data_rate_type supported_mcs_rate_nss1[] = {
128/* MCS L20 L40 S20 S40 */
129 {0, {65, 135, 72, 150} },
130 {1, {130, 270, 144, 300} },
131 {2, {195, 405, 217, 450} },
132 {3, {260, 540, 289, 600} },
133 {4, {390, 810, 433, 900} },
134 {5, {520, 1080, 578, 1200} },
135 {6, {585, 1215, 650, 1350} },
136 {7, {650, 1350, 722, 1500} }
137};
138
139/* HT MCS parameters with Nss = 2 */
140static struct index_data_rate_type supported_mcs_rate_nss2[] = {
141/* MCS L20 L40 S20 S40 */
142 {0, {130, 270, 144, 300} },
143 {1, {260, 540, 289, 600} },
144 {2, {390, 810, 433, 900} },
145 {3, {520, 1080, 578, 1200} },
146 {4, {780, 1620, 867, 1800} },
147 {5, {1040, 2160, 1156, 2400} },
148 {6, {1170, 2430, 1300, 2700} },
149 {7, {1300, 2700, 1444, 3000} }
150};
151
152#ifdef WLAN_FEATURE_11AC
153/* MCS Based VHT rate table MCS parameters with Nss = 1*/
154static struct index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = {
155/* MCS L80 S80 L40 S40 L20 S40*/
156 {0, {293, 325}, {135, 150}, {65, 72} },
157 {1, {585, 650}, {270, 300}, {130, 144} },
158 {2, {878, 975}, {405, 450}, {195, 217} },
159 {3, {1170, 1300}, {540, 600}, {260, 289} },
160 {4, {1755, 1950}, {810, 900}, {390, 433} },
161 {5, {2340, 2600}, {1080, 1200}, {520, 578} },
162 {6, {2633, 2925}, {1215, 1350}, {585, 650} },
163 {7, {2925, 3250}, {1350, 1500}, {650, 722} },
164 {8, {3510, 3900}, {1620, 1800}, {780, 867} },
165 {9, {3900, 4333}, {1800, 2000}, {780, 867} }
166};
167
168/*MCS parameters with Nss = 2*/
169static struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = {
170/* MCS L80 S80 L40 S40 L20 S40*/
171 {0, {585, 650}, {270, 300}, {130, 144} },
172 {1, {1170, 1300}, {540, 600}, {260, 289} },
173 {2, {1755, 1950}, {810, 900}, {390, 433} },
174 {3, {2340, 2600}, {1080, 1200}, {520, 578} },
175 {4, {3510, 3900}, {1620, 1800}, {780, 867} },
176 {5, {4680, 5200}, {2160, 2400}, {1040, 1156} },
177 {6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
178 {7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
179 {8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
180 {9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
181};
182#endif /* End of WLAN_FEATURE_11AC */
183
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)) {
238 hddLog(CDF_TRACE_LEVEL_ERROR,
239 FL("QCA_WLAN_VENDOR_ATTR put fail"));
240 return false;
241 }
242
243 return true;
244}
245
246/**
247 * put_wifi_peer_info() - put wifi peer info
248 * @stats: Pointer to stats context
249 * @vendor_event: Pointer to vendor event
250 *
251 * Return: bool
252 */
253static bool put_wifi_peer_info(tpSirWifiPeerInfo stats,
254 struct sk_buff *vendor_event)
255{
256 u32 i = 0;
257 tpSirWifiRateStat pRateStats;
258
259 if (nla_put_u32
260 (vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE,
261 stats->type) ||
262 nla_put(vendor_event,
263 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS,
264 CDF_MAC_ADDR_SIZE, &stats->peerMacAddress.bytes[0]) ||
265 nla_put_u32(vendor_event,
266 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES,
267 stats->capabilities) ||
268 nla_put_u32(vendor_event,
269 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES,
270 stats->numRate)) {
271 hddLog(CDF_TRACE_LEVEL_ERROR,
272 FL("QCA_WLAN_VENDOR_ATTR put fail"));
273 goto error;
274 }
275
276 if (stats->numRate) {
277 struct nlattr *rateInfo;
278 struct nlattr *rates;
279
280 rateInfo = nla_nest_start(vendor_event,
281 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO);
282 if (rateInfo == NULL)
283 goto error;
284
285 for (i = 0; i < stats->numRate; i++) {
286 pRateStats = (tpSirWifiRateStat) ((uint8_t *)
287 stats->rateStats +
288 (i *
289 sizeof
290 (tSirWifiRateStat)));
291 rates = nla_nest_start(vendor_event, i);
292 if (rates == NULL)
293 goto error;
294
295 if (false ==
296 put_wifi_rate_stat(pRateStats, vendor_event)) {
297 hddLog(CDF_TRACE_LEVEL_ERROR,
298 FL("QCA_WLAN_VENDOR_ATTR put fail"));
299 return false;
300 }
301 nla_nest_end(vendor_event, rates);
302 }
303 nla_nest_end(vendor_event, rateInfo);
304 }
305
306 return true;
307error:
308 return false;
309}
310
311/**
312 * put_wifi_wmm_ac_stat() - put wifi wmm ac stats
313 * @stats: Pointer to stats context
314 * @vendor_event: Pointer to vendor event
315 *
316 * Return: bool
317 */
318static bool put_wifi_wmm_ac_stat(tpSirWifiWmmAcStat stats,
319 struct sk_buff *vendor_event)
320{
321 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC,
322 stats->ac) ||
323 nla_put_u32(vendor_event,
324 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU,
325 stats->txMpdu) ||
326 nla_put_u32(vendor_event,
327 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU,
328 stats->rxMpdu) ||
329 nla_put_u32(vendor_event,
330 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST,
331 stats->txMcast) ||
332 nla_put_u32(vendor_event,
333 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST,
334 stats->rxMcast) ||
335 nla_put_u32(vendor_event,
336 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU,
337 stats->rxAmpdu) ||
338 nla_put_u32(vendor_event,
339 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU,
340 stats->txAmpdu) ||
341 nla_put_u32(vendor_event,
342 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST,
343 stats->mpduLost) ||
344 nla_put_u32(vendor_event,
345 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES,
346 stats->retries) ||
347 nla_put_u32(vendor_event,
348 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT,
349 stats->retriesShort) ||
350 nla_put_u32(vendor_event,
351 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG,
352 stats->retriesLong) ||
353 nla_put_u32(vendor_event,
354 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN,
355 stats->contentionTimeMin) ||
356 nla_put_u32(vendor_event,
357 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX,
358 stats->contentionTimeMax) ||
359 nla_put_u32(vendor_event,
360 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG,
361 stats->contentionTimeAvg) ||
362 nla_put_u32(vendor_event,
363 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES,
364 stats->contentionNumSamples)) {
365 hddLog(CDF_TRACE_LEVEL_ERROR,
366 FL("QCA_WLAN_VENDOR_ATTR put fail"));
367 return false;
368 }
369
370 return true;
371}
372
373/**
374 * put_wifi_interface_info() - put wifi interface info
375 * @stats: Pointer to stats context
376 * @vendor_event: Pointer to vendor event
377 *
378 * Return: bool
379 */
380static bool put_wifi_interface_info(tpSirWifiInterfaceInfo stats,
381 struct sk_buff *vendor_event)
382{
383 if (nla_put_u32(vendor_event,
384 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE,
385 stats->mode) ||
386 nla_put(vendor_event,
387 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR,
388 CDF_MAC_ADDR_SIZE, stats->macAddr.bytes) ||
389 nla_put_u32(vendor_event,
390 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE,
391 stats->state) ||
392 nla_put_u32(vendor_event,
393 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING,
394 stats->roaming) ||
395 nla_put_u32(vendor_event,
396 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES,
397 stats->capabilities) ||
398 nla_put(vendor_event,
399 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID,
400 strlen(stats->ssid), stats->ssid) ||
401 nla_put(vendor_event,
402 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID,
403 CDF_MAC_ADDR_SIZE, stats->bssid.bytes) ||
404 nla_put(vendor_event,
405 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR,
406 WNI_CFG_COUNTRY_CODE_LEN, stats->apCountryStr) ||
407 nla_put(vendor_event,
408 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR,
409 WNI_CFG_COUNTRY_CODE_LEN, stats->countryStr)) {
410 hddLog(CDF_TRACE_LEVEL_ERROR,
411 FL("QCA_WLAN_VENDOR_ATTR put fail"));
412 return false;
413 }
414
415 return true;
416}
417
418/**
419 * put_wifi_iface_stats() - put wifi interface stats
420 * @pWifiIfaceStat: Pointer to interface stats context
421 * @num_peer: Number of peers
422 * @vendor_event: Pointer to vendor event
423 *
424 * Return: bool
425 */
426static bool put_wifi_iface_stats(tpSirWifiIfaceStat pWifiIfaceStat,
427 u32 num_peers, struct sk_buff *vendor_event)
428{
429 int i = 0;
430 struct nlattr *wmmInfo;
431 struct nlattr *wmmStats;
432 u64 average_tsf_offset;
433
434 if (false == put_wifi_interface_info(&pWifiIfaceStat->info,
435 vendor_event)) {
436 hddLog(CDF_TRACE_LEVEL_ERROR,
437 FL("QCA_WLAN_VENDOR_ATTR put fail"));
438 return false;
439
440 }
441
442 average_tsf_offset = pWifiIfaceStat->avg_bcn_spread_offset_high;
443 average_tsf_offset = (average_tsf_offset << 32) |
444 pWifiIfaceStat->avg_bcn_spread_offset_low ;
445
446 if (nla_put_u32(vendor_event,
447 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
448 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE) ||
449 nla_put_u32(vendor_event,
450 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
451 num_peers) ||
452 nla_put_u32(vendor_event,
453 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX,
454 pWifiIfaceStat->beaconRx) ||
455 nla_put_u32(vendor_event,
456 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX,
457 pWifiIfaceStat->mgmtRx) ||
458 nla_put_u32(vendor_event,
459 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX,
460 pWifiIfaceStat->mgmtActionRx) ||
461 nla_put_u32(vendor_event,
462 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX,
463 pWifiIfaceStat->mgmtActionTx) ||
464 nla_put_u32(vendor_event,
465 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT,
466 pWifiIfaceStat->rssiMgmt) ||
467 nla_put_u32(vendor_event,
468 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA,
469 pWifiIfaceStat->rssiData) ||
470 nla_put_u32(vendor_event,
471 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK,
472 pWifiIfaceStat->rssiAck) ||
473 nla_put_u32(vendor_event,
474 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED,
475 pWifiIfaceStat->is_leaky_ap) ||
476 nla_put_u32(vendor_event,
477 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED,
478 pWifiIfaceStat->avg_rx_frms_leaked) ||
479 nla_put_u32(vendor_event,
480 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME,
481 pWifiIfaceStat->rx_leak_window) ||
482 nla_put_u64(vendor_event,
483 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET,
484 average_tsf_offset)) {
485 hddLog(CDF_TRACE_LEVEL_ERROR,
486 FL("QCA_WLAN_VENDOR_ATTR put fail"));
487 return false;
488 }
489
490 wmmInfo = nla_nest_start(vendor_event,
491 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO);
492 if (wmmInfo == NULL)
493 return false;
494
495 for (i = 0; i < WIFI_AC_MAX; i++) {
496 wmmStats = nla_nest_start(vendor_event, i);
497 if (wmmStats == NULL)
498 return false;
499
500 if (false ==
501 put_wifi_wmm_ac_stat(&pWifiIfaceStat->AccessclassStats[i],
502 vendor_event)) {
503 hddLog(CDF_TRACE_LEVEL_ERROR,
504 FL("put_wifi_wmm_ac_stat Fail"));
505 return false;
506 }
507
508 nla_nest_end(vendor_event, wmmStats);
509 }
510 nla_nest_end(vendor_event, wmmInfo);
511 return true;
512}
513
514/**
515 * hdd_map_device_to_ll_iface_mode() - map device to link layer interface mode
516 * @deviceMode: Device mode
517 *
518 * Return: interface mode
519 */
520static tSirWifiInterfaceMode hdd_map_device_to_ll_iface_mode(int deviceMode)
521{
522 switch (deviceMode) {
523 case WLAN_HDD_INFRA_STATION:
524 return WIFI_INTERFACE_STA;
525 case WLAN_HDD_SOFTAP:
526 return WIFI_INTERFACE_SOFTAP;
527 case WLAN_HDD_P2P_CLIENT:
528 return WIFI_INTERFACE_P2P_CLIENT;
529 case WLAN_HDD_P2P_GO:
530 return WIFI_INTERFACE_P2P_GO;
531 case WLAN_HDD_IBSS:
532 return WIFI_INTERFACE_IBSS;
533 default:
534 /* Return Interface Mode as STA for all the unsupported modes */
535 return WIFI_INTERFACE_STA;
536 }
537}
538
539/**
540 * hdd_get_interface_info() - get interface info
541 * @pAdapter: Pointer to device adapter
542 * @pInfo: Pointer to interface info
543 *
544 * Return: bool
545 */
546static bool hdd_get_interface_info(hdd_adapter_t *pAdapter,
547 tpSirWifiInterfaceInfo pInfo)
548{
549 uint8_t *staMac = NULL;
550 hdd_station_ctx_t *pHddStaCtx;
551 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
552 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
553
554 pInfo->mode = hdd_map_device_to_ll_iface_mode(pAdapter->device_mode);
555
556 cdf_copy_macaddr(&pInfo->macAddr, &pAdapter->macAddressCurrent);
557
558 if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
559 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
560 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))) {
561 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
562 if (eConnectionState_NotConnected ==
563 pHddStaCtx->conn_info.connState) {
564 pInfo->state = WIFI_DISCONNECTED;
565 }
566 if (eConnectionState_Connecting ==
567 pHddStaCtx->conn_info.connState) {
568 hddLog(CDF_TRACE_LEVEL_ERROR,
569 "%s: Session ID %d, Connection is in progress",
570 __func__, pAdapter->sessionId);
571 pInfo->state = WIFI_ASSOCIATING;
572 }
573 if ((eConnectionState_Associated ==
574 pHddStaCtx->conn_info.connState)
575 && (false == pHddStaCtx->conn_info.uIsAuthenticated)) {
576 staMac =
577 (uint8_t *) &(pAdapter->macAddressCurrent.
578 bytes[0]);
579 hddLog(CDF_TRACE_LEVEL_ERROR,
580 "%s: client " MAC_ADDRESS_STR
581 " is in the middle of WPS/EAPOL exchange.",
582 __func__, MAC_ADDR_ARRAY(staMac));
583 pInfo->state = WIFI_AUTHENTICATING;
584 }
585 if (eConnectionState_Associated ==
586 pHddStaCtx->conn_info.connState) {
587 pInfo->state = WIFI_ASSOCIATED;
588 cdf_copy_macaddr(&pInfo->bssid,
589 &pHddStaCtx->conn_info.bssId);
590 cdf_mem_copy(pInfo->ssid,
591 pHddStaCtx->conn_info.SSID.SSID.ssId,
592 pHddStaCtx->conn_info.SSID.SSID.length);
593 /*
594 * NULL Terminate the string
595 */
596 pInfo->ssid[pHddStaCtx->conn_info.SSID.SSID.length] = 0;
597 }
598 }
599
600 cdf_mem_copy(pInfo->countryStr,
601 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
602
603 cdf_mem_copy(pInfo->apCountryStr,
604 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
605
606 return true;
607}
608
609/**
610 * hdd_link_layer_process_peer_stats() - This function is called after
611 * @pAdapter: Pointer to device adapter
612 * @more_data: More data
613 * @pData: Pointer to stats data
614 *
615 * Receiving Link Layer Peer statistics from FW.This function converts
616 * the firmware data to the NL data and sends the same to the kernel/upper
617 * layers.
618 *
619 * Return: None
620 */
621static void hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter,
622 u32 more_data,
623 tpSirWifiPeerStat pData)
624{
625 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
626 tpSirWifiRateStat pWifiRateStat;
627 tpSirWifiPeerStat pWifiPeerStat;
628 tpSirWifiPeerInfo pWifiPeerInfo;
629 struct sk_buff *vendor_event;
630 int status, i, j;
631 struct nlattr *peers;
632 int numRate;
633
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530634 ENTER();
635
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 pWifiPeerStat = pData;
637
638 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530639 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641
642 hddLog(CDF_TRACE_LEVEL_INFO,
643 "LL_STATS_PEER_ALL : numPeers %u, more data = %u",
644 pWifiPeerStat->numPeers, more_data);
645
646 for (i = 0; i < pWifiPeerStat->numPeers; i++) {
647 pWifiPeerInfo = (tpSirWifiPeerInfo)
648 ((uint8_t *) pWifiPeerStat->peerInfo +
649 (i * sizeof(tSirWifiPeerInfo)));
650
651 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
652 pWifiPeerInfo->type = WIFI_PEER_AP;
653
654 if (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
655 pWifiPeerInfo->type = WIFI_PEER_P2P_GO;
656
657 hddLog(CDF_TRACE_LEVEL_INFO,
658 " %d) LL_STATS Channel Stats "
659 " Peer Type %u "
660 " peerMacAddress %pM "
661 " capabilities 0x%x "
662 " numRate %u ",
663 i,
664 pWifiPeerInfo->type,
665 pWifiPeerInfo->peerMacAddress.bytes,
666 pWifiPeerInfo->capabilities, pWifiPeerInfo->numRate);
667 {
668 for (j = 0; j < pWifiPeerInfo->numRate; j++) {
669 pWifiRateStat = (tpSirWifiRateStat)
670 ((uint8_t *) pWifiPeerInfo->rateStats +
671 (j * sizeof(tSirWifiRateStat)));
672
673 hddLog(CDF_TRACE_LEVEL_INFO,
674 " peer Rate Stats "
675 " preamble %u "
676 " nss %u "
677 " bw %u "
678 " rateMcsIdx %u "
679 " reserved %u "
680 " bitrate %u "
681 " txMpdu %u "
682 " rxMpdu %u "
683 " mpduLost %u "
684 " retries %u "
685 " retriesShort %u "
686 " retriesLong %u",
687 pWifiRateStat->rate.preamble,
688 pWifiRateStat->rate.nss,
689 pWifiRateStat->rate.bw,
690 pWifiRateStat->rate.rateMcsIdx,
691 pWifiRateStat->rate.reserved,
692 pWifiRateStat->rate.bitrate,
693 pWifiRateStat->txMpdu,
694 pWifiRateStat->rxMpdu,
695 pWifiRateStat->mpduLost,
696 pWifiRateStat->retries,
697 pWifiRateStat->retriesShort,
698 pWifiRateStat->retriesLong);
699 }
700 }
701 }
702
703 /*
704 * Allocate a size of 4096 for the peer stats comprising
705 * each of size = sizeof (tSirWifiPeerInfo) + numRate *
706 * sizeof (tSirWifiRateStat).Each field is put with an
707 * NL attribute.The size of 4096 is considered assuming
708 * that number of rates shall not exceed beyond 50 with
709 * the sizeof (tSirWifiRateStat) being 32.
710 */
711 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
712 LL_STATS_EVENT_BUF_SIZE);
713
714 if (!vendor_event) {
715 hddLog(LOGE,
716 FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
717 return;
718 }
719
720 if (nla_put_u32(vendor_event,
721 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
722 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER) ||
723 nla_put_u32(vendor_event,
724 QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA,
725 more_data) ||
726 nla_put_u32(vendor_event,
727 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
728 pWifiPeerStat->numPeers)) {
729 hddLog(CDF_TRACE_LEVEL_ERROR,
730 "%s: QCA_WLAN_VENDOR_ATTR put fail", __func__);
731
732 kfree_skb(vendor_event);
733 return;
734 }
735
736 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *)
737 pWifiPeerStat->peerInfo);
738
739 if (pWifiPeerStat->numPeers) {
740 struct nlattr *peerInfo;
741 peerInfo = nla_nest_start(vendor_event,
742 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO);
743 if (peerInfo == NULL) {
744 hddLog(LOGE, FL("nla_nest_start failed"));
745 kfree_skb(vendor_event);
746 return;
747 }
748
749 for (i = 1; i <= pWifiPeerStat->numPeers; i++) {
750 peers = nla_nest_start(vendor_event, i);
751 if (peers == NULL) {
752 hddLog(LOGE, FL("nla_nest_start failed"));
753 kfree_skb(vendor_event);
754 return;
755 }
756
757 numRate = pWifiPeerInfo->numRate;
758
759 if (false ==
760 put_wifi_peer_info(pWifiPeerInfo, vendor_event)) {
761 hddLog(CDF_TRACE_LEVEL_ERROR,
762 FL("put_wifi_peer_info fail"));
763 kfree_skb(vendor_event);
764 return;
765 }
766
767 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8_t *)
768 pWifiPeerStat->
769 peerInfo +
770 (i *
771 sizeof
772 (tSirWifiPeerInfo))
773 +
774 (numRate *
775 sizeof
776 (tSirWifiRateStat)));
777 nla_nest_end(vendor_event, peers);
778 }
779 nla_nest_end(vendor_event, peerInfo);
780 }
781 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530782 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 return;
784}
785
786/**
787 * hdd_link_layer_process_iface_stats() - This function is called after
788 * @pAdapter: Pointer to device adapter
789 * @pData: Pointer to stats data
790 * @num_peers: Number of peers
791 *
792 * Receiving Link Layer Interface statistics from FW.This function converts
793 * the firmware data to the NL data and sends the same to the kernel/upper
794 * layers.
795 *
796 * Return: None
797 */
798static void hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter,
799 tpSirWifiIfaceStat pData,
800 u32 num_peers)
801{
802 tpSirWifiIfaceStat pWifiIfaceStat;
803 struct sk_buff *vendor_event;
804 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
805 int status;
806 int i;
807
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530808 ENTER();
809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 pWifiIfaceStat = pData;
811
812 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530813 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815
816 /*
817 * Allocate a size of 4096 for the interface stats comprising
818 * sizeof (tpSirWifiIfaceStat).The size of 4096 is considered
819 * assuming that all these fit with in the limit.Please take
820 * a call on the limit based on the data requirements on
821 * interface statistics.
822 */
823 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
824 LL_STATS_EVENT_BUF_SIZE);
825
826 if (!vendor_event) {
827 hddLog(CDF_TRACE_LEVEL_ERROR,
828 FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
829 return;
830 }
831
832 hddLog(CDF_TRACE_LEVEL_INFO, "WMI_LINK_STATS_IFACE Data");
833
834 if (false == hdd_get_interface_info(pAdapter, &pWifiIfaceStat->info)) {
835 hddLog(CDF_TRACE_LEVEL_ERROR,
836 FL("hdd_get_interface_info get fail"));
837 kfree_skb(vendor_event);
838 return;
839 }
840
841 hddLog(CDF_TRACE_LEVEL_INFO,
842 " Num peers %u "
843 "LL_STATS_IFACE: "
844 " Mode %u "
845 " MAC %pM "
846 " State %u "
847 " Roaming %u "
848 " capabilities 0x%x "
849 " SSID %s "
850 " BSSID %pM",
851 num_peers,
852 pWifiIfaceStat->info.mode,
853 pWifiIfaceStat->info.macAddr.bytes,
854 pWifiIfaceStat->info.state,
855 pWifiIfaceStat->info.roaming,
856 pWifiIfaceStat->info.capabilities,
857 pWifiIfaceStat->info.ssid, pWifiIfaceStat->info.bssid.bytes);
858
859 hddLog(CDF_TRACE_LEVEL_INFO,
860 " AP country str: %c%c%c",
861 pWifiIfaceStat->info.apCountryStr[0],
862 pWifiIfaceStat->info.apCountryStr[1],
863 pWifiIfaceStat->info.apCountryStr[2]);
864
865 hddLog(CDF_TRACE_LEVEL_INFO,
866 " Country Str Association: %c%c%c",
867 pWifiIfaceStat->info.countryStr[0],
868 pWifiIfaceStat->info.countryStr[1],
869 pWifiIfaceStat->info.countryStr[2]);
870
871 hddLog(CDF_TRACE_LEVEL_INFO,
872 " beaconRx %u "
873 " mgmtRx %u "
874 " mgmtActionRx %u "
875 " mgmtActionTx %u "
876 " rssiMgmt %u "
877 " rssiData %u "
878 " rssiAck %u "
879 " avg_bcn_spread_offset_high %u"
880 " avg_bcn_spread_offset_low %u"
881 " is leaky_ap %u"
882 " avg_rx_frms_leaked %u"
883 " rx_leak_window %u",
884 pWifiIfaceStat->beaconRx,
885 pWifiIfaceStat->mgmtRx,
886 pWifiIfaceStat->mgmtActionRx,
887 pWifiIfaceStat->mgmtActionTx,
888 pWifiIfaceStat->rssiMgmt,
889 pWifiIfaceStat->rssiData,
890 pWifiIfaceStat->rssiAck,
891 pWifiIfaceStat->avg_bcn_spread_offset_high,
892 pWifiIfaceStat->avg_bcn_spread_offset_low,
893 pWifiIfaceStat->is_leaky_ap,
894 pWifiIfaceStat->avg_rx_frms_leaked,
895 pWifiIfaceStat->rx_leak_window);
896
897 for (i = 0; i < WIFI_AC_MAX; i++) {
898 hddLog(CDF_TRACE_LEVEL_INFO,
899 " %d) LL_STATS IFACE: "
900 " ac: %u txMpdu: %u "
901 " rxMpdu: %u txMcast: %u "
902 " rxMcast: %u rxAmpdu: %u "
903 " txAmpdu: %u mpduLost: %u "
904 " retries: %u retriesShort: %u "
905 " retriesLong: %u contentionTimeMin: %u "
906 " contentionTimeMax: %u contentionTimeAvg: %u "
907 " contentionNumSamples: %u",
908 i,
909 pWifiIfaceStat->AccessclassStats[i].ac,
910 pWifiIfaceStat->AccessclassStats[i].txMpdu,
911 pWifiIfaceStat->AccessclassStats[i].rxMpdu,
912 pWifiIfaceStat->AccessclassStats[i].txMcast,
913 pWifiIfaceStat->AccessclassStats[i].rxMcast,
914 pWifiIfaceStat->AccessclassStats[i].rxAmpdu,
915 pWifiIfaceStat->AccessclassStats[i].txAmpdu,
916 pWifiIfaceStat->AccessclassStats[i].mpduLost,
917 pWifiIfaceStat->AccessclassStats[i].retries,
918 pWifiIfaceStat->AccessclassStats[i].retriesShort,
919 pWifiIfaceStat->AccessclassStats[i].retriesLong,
920 pWifiIfaceStat->AccessclassStats[i].contentionTimeMin,
921 pWifiIfaceStat->AccessclassStats[i].contentionTimeMax,
922 pWifiIfaceStat->AccessclassStats[i].contentionTimeAvg,
923 pWifiIfaceStat->AccessclassStats[i].
924 contentionNumSamples);
925 }
926
927 if (false ==
928 put_wifi_iface_stats(pWifiIfaceStat, num_peers, vendor_event)) {
929 hddLog(CDF_TRACE_LEVEL_ERROR, FL("put_wifi_iface_stats fail"));
930 kfree_skb(vendor_event);
931 return;
932 }
933
934 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530935 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936 return;
937}
938
939/**
940 * hdd_link_layer_process_radio_stats() - This function is called after
941 * @pAdapter: Pointer to device adapter
942 * @more_data: More data
943 * @pData: Pointer to stats data
944 * @num_radios: Number of radios
945 *
946 * Receiving Link Layer Radio statistics from FW.This function converts
947 * the firmware data to the NL data and sends the same to the kernel/upper
948 * layers.
949 *
950 * Return: None
951 */
952static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter,
953 u32 more_data,
954 tpSirWifiRadioStat pData,
955 u32 num_radio)
956{
957 int status, i;
958 tpSirWifiRadioStat pWifiRadioStat;
959 tpSirWifiChannelStats pWifiChannelStats;
960 struct sk_buff *vendor_event;
961 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
962
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530963 ENTER();
964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965 pWifiRadioStat = pData;
966 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530967 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969
970 hddLog(CDF_TRACE_LEVEL_INFO,
971 "LL_STATS_RADIO"
972 " number of radios = %u"
973 " radio is %d onTime is %u"
974 " txTime is %u rxTime is %u"
975 " onTimeScan is %u onTimeNbd is %u"
976 " onTimeGscan is %u onTimeRoamScan is %u"
977 " onTimePnoScan is %u onTimeHs20 is %u"
978 " numChannels is %u",
979 num_radio,
980 pWifiRadioStat->radio,
981 pWifiRadioStat->onTime,
982 pWifiRadioStat->txTime,
983 pWifiRadioStat->rxTime,
984 pWifiRadioStat->onTimeScan,
985 pWifiRadioStat->onTimeNbd,
986 pWifiRadioStat->onTimeGscan,
987 pWifiRadioStat->onTimeRoamScan,
988 pWifiRadioStat->onTimePnoScan,
989 pWifiRadioStat->onTimeHs20, pWifiRadioStat->numChannels);
990
991 /*
992 * Allocate a size of 4096 for the Radio stats comprising
993 * sizeof (tSirWifiRadioStat) + numChannels * sizeof
994 * (tSirWifiChannelStats).Each channel data is put with an
995 * NL attribute.The size of 4096 is considered assuming that
996 * number of channels shall not exceed beyond 60 with the
997 * sizeof (tSirWifiChannelStats) being 24 bytes.
998 */
999
1000 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
1001 LL_STATS_EVENT_BUF_SIZE);
1002
1003 if (!vendor_event) {
1004 hddLog(LOGE,
1005 FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1006 return;
1007 }
1008
1009 if (nla_put_u32(vendor_event,
1010 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
1011 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO) ||
1012 nla_put_u32(vendor_event,
1013 QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA,
1014 more_data) ||
1015 nla_put_u32(vendor_event,
1016 QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS,
1017 num_radio) ||
1018 nla_put_u32(vendor_event,
1019 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID,
1020 pWifiRadioStat->radio) ||
1021 nla_put_u32(vendor_event,
1022 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME,
1023 pWifiRadioStat->onTime) ||
1024 nla_put_u32(vendor_event,
1025 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME,
1026 pWifiRadioStat->txTime) ||
1027 nla_put_u32(vendor_event,
1028 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME,
1029 pWifiRadioStat->rxTime) ||
1030 nla_put_u32(vendor_event,
1031 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN,
1032 pWifiRadioStat->onTimeScan) ||
1033 nla_put_u32(vendor_event,
1034 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD,
1035 pWifiRadioStat->onTimeNbd) ||
1036 nla_put_u32(vendor_event,
1037 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN,
1038 pWifiRadioStat->onTimeGscan) ||
1039 nla_put_u32(vendor_event,
1040 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN,
1041 pWifiRadioStat->onTimeRoamScan) ||
1042 nla_put_u32(vendor_event,
1043 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN,
1044 pWifiRadioStat->onTimePnoScan) ||
1045 nla_put_u32(vendor_event,
1046 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20,
1047 pWifiRadioStat->onTimeHs20) ||
1048 nla_put_u32(vendor_event,
1049 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS,
1050 pWifiRadioStat->numChannels)) {
1051 hddLog(CDF_TRACE_LEVEL_ERROR,
1052 FL("QCA_WLAN_VENDOR_ATTR put fail"));
1053
1054 kfree_skb(vendor_event);
1055 return;
1056 }
1057
1058 if (pWifiRadioStat->numChannels) {
1059 struct nlattr *chList;
1060 struct nlattr *chInfo;
1061
1062 chList = nla_nest_start(vendor_event,
1063 QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO);
1064 if (chList == NULL) {
1065 hddLog(LOGE, FL("nla_nest_start failed"));
1066 kfree_skb(vendor_event);
1067 return;
1068 }
1069
1070 for (i = 0; i < pWifiRadioStat->numChannels; i++) {
1071 pWifiChannelStats = (tpSirWifiChannelStats) ((uint8_t *)
1072 pWifiRadioStat->
1073 channels +
1074 (i *
1075 sizeof
1076 (tSirWifiChannelStats)));
1077
1078 hddLog(CDF_TRACE_LEVEL_INFO,
1079 " %d) Channel Info"
1080 " width is %u "
1081 " CenterFreq %u "
1082 " CenterFreq0 %u "
1083 " CenterFreq1 %u "
1084 " onTime %u "
1085 " ccaBusyTime %u",
1086 i,
1087 pWifiChannelStats->channel.width,
1088 pWifiChannelStats->channel.centerFreq,
1089 pWifiChannelStats->channel.centerFreq0,
1090 pWifiChannelStats->channel.centerFreq1,
1091 pWifiChannelStats->onTime,
1092 pWifiChannelStats->ccaBusyTime);
1093
1094 chInfo = nla_nest_start(vendor_event, i);
1095 if (chInfo == NULL) {
1096 hddLog(LOGE, FL("nla_nest_start failed"));
1097 kfree_skb(vendor_event);
1098 return;
1099 }
1100
1101 if (nla_put_u32(vendor_event,
1102 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH,
1103 pWifiChannelStats->channel.width) ||
1104 nla_put_u32(vendor_event,
1105 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ,
1106 pWifiChannelStats->channel.centerFreq) ||
1107 nla_put_u32(vendor_event,
1108 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0,
1109 pWifiChannelStats->channel.
1110 centerFreq0) ||
1111 nla_put_u32(vendor_event,
1112 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1,
1113 pWifiChannelStats->channel.
1114 centerFreq1) ||
1115 nla_put_u32(vendor_event,
1116 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME,
1117 pWifiChannelStats->onTime) ||
1118 nla_put_u32(vendor_event,
1119 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME,
1120 pWifiChannelStats->ccaBusyTime)) {
1121 hddLog(CDF_TRACE_LEVEL_ERROR,
1122 FL("nla_put failed"));
1123 kfree_skb(vendor_event);
1124 return;
1125 }
1126 nla_nest_end(vendor_event, chInfo);
1127 }
1128 nla_nest_end(vendor_event, chList);
1129 }
1130 cfg80211_vendor_cmd_reply(vendor_event);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301131 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 return;
1133}
1134
1135/**
1136 * wlan_hdd_cfg80211_link_layer_stats_callback() - This function is called
1137 * @ctx: Pointer to hdd context
1138 * @indType: Indication type
1139 * @pRsp: Pointer to response
1140 *
1141 * After receiving Link Layer indications from FW.This callback converts the
1142 * firmware data to the NL data and send the same to the kernel/upper layers.
1143 *
1144 * Return: None
1145 */
1146static void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx,
1147 int indType, void *pRsp)
1148{
1149 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1150 struct hdd_ll_stats_context *context;
1151 hdd_adapter_t *pAdapter = NULL;
1152 tpSirLLStatsResults linkLayerStatsResults = (tpSirLLStatsResults) pRsp;
1153 int status;
1154
1155 status = wlan_hdd_validate_context(pHddCtx);
1156
1157 if (0 != status) {
1158 hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
1159 return;
1160 }
1161
1162 pAdapter = hdd_get_adapter_by_vdev(pHddCtx,
1163 linkLayerStatsResults->ifaceId);
1164
1165 if (NULL == pAdapter) {
1166 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1167 "%s: vdev_id %d does not exist with host",
1168 __func__, linkLayerStatsResults->ifaceId);
1169 return;
1170 }
1171
1172 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
1173 "%s: Link Layer Indication indType: %d", __func__, indType);
1174
1175 switch (indType) {
1176 case SIR_HAL_LL_STATS_RESULTS_RSP:
1177 {
1178 hddLog(CDF_TRACE_LEVEL_INFO,
1179 FL("RESPONSE SIR_HAL_LL_STATS_RESULTS_RSP"));
1180 hddLog(CDF_TRACE_LEVEL_INFO,
1181 "LL_STATS RESULTS RESPONSE paramID = 0x%x",
1182 linkLayerStatsResults->paramId);
1183 hddLog(CDF_TRACE_LEVEL_INFO,
1184 "LL_STATS RESULTS RESPONSE ifaceId = %u",
1185 linkLayerStatsResults->ifaceId);
1186 hddLog(CDF_TRACE_LEVEL_INFO,
1187 "LL_STATS RESULTS RESPONSE respId = %u",
1188 linkLayerStatsResults->rspId);
1189 hddLog(CDF_TRACE_LEVEL_INFO,
1190 "LL_STATS RESULTS RESPONSE more data = %u",
1191 linkLayerStatsResults->moreResultToFollow);
1192 hddLog(CDF_TRACE_LEVEL_INFO,
1193 "LL_STATS RESULTS RESPONSE num radio = %u",
1194 linkLayerStatsResults->num_radio);
1195 hddLog(CDF_TRACE_LEVEL_INFO,
1196 "LL_STATS RESULTS RESPONSE result = %p",
1197 linkLayerStatsResults->results);
1198
1199 context = &ll_stats_context;
1200 spin_lock(&context->context_lock);
1201 /* validate response received from target */
1202 if ((context->request_id != linkLayerStatsResults->rspId) ||
1203 !(context->request_bitmap & linkLayerStatsResults->paramId)) {
1204 spin_unlock(&context->context_lock);
1205 hddLog(LOGE,
1206 FL("Error : Request id %d response id %d request bitmap 0x%x response bitmap 0x%x"),
1207 context->request_id, linkLayerStatsResults->rspId,
1208 context->request_bitmap, linkLayerStatsResults->paramId);
1209 return;
1210 }
1211 spin_unlock(&context->context_lock);
1212
1213 if (linkLayerStatsResults->
1214 paramId & WMI_LINK_STATS_RADIO) {
1215 hdd_link_layer_process_radio_stats(pAdapter,
1216 linkLayerStatsResults->moreResultToFollow,
1217 (tpSirWifiRadioStat)linkLayerStatsResults->results,
1218 linkLayerStatsResults->num_radio);
1219
1220 spin_lock(&context->context_lock);
1221 if (!linkLayerStatsResults->moreResultToFollow)
1222 context->request_bitmap &= ~(WMI_LINK_STATS_RADIO);
1223 spin_unlock(&context->context_lock);
1224
1225 } else if (linkLayerStatsResults->
1226 paramId & WMI_LINK_STATS_IFACE) {
1227 hdd_link_layer_process_iface_stats(pAdapter,
1228 (tpSirWifiIfaceStat)linkLayerStatsResults->results,
1229 linkLayerStatsResults->num_peers);
1230
1231 spin_lock(&context->context_lock);
Srinivas Dasari6946a792015-09-28 15:01:49 +05301232 /* Firmware doesn't send peerstats event if no peers are
1233 * connected. HDD should not wait for any peerstats in
1234 * this case and return the status to middleware after
1235 * receiving iface stats
1236 */
1237 if (!linkLayerStatsResults->num_peers)
1238 context->request_bitmap &=
1239 ~(WMI_LINK_STATS_ALL_PEER);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 context->request_bitmap &= ~(WMI_LINK_STATS_IFACE);
1241 spin_unlock(&context->context_lock);
1242
1243 } else if (linkLayerStatsResults->
1244 paramId & WMI_LINK_STATS_ALL_PEER) {
1245 hdd_link_layer_process_peer_stats(pAdapter,
1246 linkLayerStatsResults->moreResultToFollow,
1247 (tpSirWifiPeerStat)linkLayerStatsResults->results);
1248
1249 spin_lock(&context->context_lock);
1250 if (!linkLayerStatsResults->moreResultToFollow)
1251 context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
1252 spin_unlock(&context->context_lock);
1253
1254 } else {
1255 hddLog(LOGE,
1256 FL("INVALID LL_STATS_NOTIFY RESPONSE"));
1257 }
1258
1259 spin_lock(&context->context_lock);
1260 /* complete response event if all requests are completed */
1261 if (0 == context->request_bitmap)
1262 complete(&context->response_event);
1263 spin_unlock(&context->context_lock);
1264
1265 break;
1266 }
1267 default:
1268 hddLog(CDF_TRACE_LEVEL_ERROR, "invalid event type %d", indType);
1269 break;
1270 }
1271
1272 return;
1273}
1274
1275/**
1276 * wlan_hdd_cfg80211_link_layer_stats_init() - initialize link layer stats
1277 * @pHddCtx: Pointer to hdd context
1278 *
1279 * Return: None
1280 */
1281void wlan_hdd_cfg80211_link_layer_stats_init(hdd_context_t *pHddCtx)
1282{
1283 sme_set_link_layer_stats_ind_cb(pHddCtx->hHal,
1284 wlan_hdd_cfg80211_link_layer_stats_callback);
1285}
1286
1287const struct
1288nla_policy
1289 qca_wlan_vendor_ll_set_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1] = {
1290 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD] = {
1291 .type = NLA_U32},
1292 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING] = {
1293 .type = NLA_U32},
1294};
1295
1296/**
1297 * __wlan_hdd_cfg80211_ll_stats_set() - set link layer stats
1298 * @wiphy: Pointer to wiphy
1299 * @wdev: Pointer to wdev
1300 * @data: Pointer to data
1301 * @data_len: Data length
1302 *
1303 * Return: int
1304 */
1305static int
1306__wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1307 struct wireless_dev *wdev,
1308 const void *data,
1309 int data_len)
1310{
1311 int status;
1312 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1];
1313 tSirLLStatsSetReq LinkLayerStatsSetReq;
1314 struct net_device *dev = wdev->netdev;
1315 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1316 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1317
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301318 ENTER();
1319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 if (CDF_FTM_MODE == hdd_get_conparam()) {
1321 hdd_err("Command not allowed in FTM mode");
1322 return -EPERM;
1323 }
1324
1325 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301326 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328
1329 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX,
1330 (struct nlattr *)data,
1331 data_len, qca_wlan_vendor_ll_set_policy)) {
1332 hddLog(CDF_TRACE_LEVEL_ERROR,
1333 FL("maximum attribute not present"));
1334 return -EINVAL;
1335 }
1336
1337 if (!tb_vendor
1338 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]) {
1339 hddLog(CDF_TRACE_LEVEL_ERROR, FL("MPDU size Not present"));
1340 return -EINVAL;
1341 }
1342
1343 if (!tb_vendor
1344 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]) {
1345 hddLog(CDF_TRACE_LEVEL_ERROR,
1346 FL("Stats Gathering Not Present"));
1347 return -EINVAL;
1348 }
1349
1350 /* Shall take the request Id if the Upper layers pass. 1 For now. */
1351 LinkLayerStatsSetReq.reqId = 1;
1352
1353 LinkLayerStatsSetReq.mpduSizeThreshold =
1354 nla_get_u32(tb_vendor
1355 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]);
1356
1357 LinkLayerStatsSetReq.aggressiveStatisticsGathering =
1358 nla_get_u32(tb_vendor
1359 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]);
1360
1361 LinkLayerStatsSetReq.staId = pAdapter->sessionId;
1362
1363 hddLog(CDF_TRACE_LEVEL_INFO,
1364 "LL_STATS_SET reqId = %d", LinkLayerStatsSetReq.reqId);
1365 hddLog(CDF_TRACE_LEVEL_INFO,
1366 "LL_STATS_SET staId = %d", LinkLayerStatsSetReq.staId);
1367 hddLog(CDF_TRACE_LEVEL_INFO,
1368 "LL_STATS_SET mpduSizeThreshold = %d",
1369 LinkLayerStatsSetReq.mpduSizeThreshold);
1370 hddLog(CDF_TRACE_LEVEL_INFO,
1371 "LL_STATS_SET aggressive Statistics Gathering = %d",
1372 LinkLayerStatsSetReq.aggressiveStatisticsGathering);
1373
1374 if (CDF_STATUS_SUCCESS != sme_ll_stats_set_req(pHddCtx->hHal,
1375 &LinkLayerStatsSetReq)) {
1376 hddLog(CDF_TRACE_LEVEL_ERROR, "%s:"
1377 "sme_ll_stats_set_req Failed", __func__);
1378 return -EINVAL;
1379 }
1380
1381 pAdapter->isLinkLayerStatsSet = 1;
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301382 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return 0;
1384}
1385
1386/**
1387 * wlan_hdd_cfg80211_ll_stats_set() - set ll stats
1388 * @wiphy: Pointer to wiphy
1389 * @wdev: Pointer to wdev
1390 * @data: Pointer to data
1391 * @data_len: Data length
1392 *
1393 * Return: 0 if success, non-zero for failure
1394 */
1395int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1396 struct wireless_dev *wdev,
1397 const void *data,
1398 int data_len)
1399{
1400 int ret = 0;
1401
1402 cds_ssr_protect(__func__);
1403 ret = __wlan_hdd_cfg80211_ll_stats_set(wiphy, wdev, data, data_len);
1404 cds_ssr_unprotect(__func__);
1405
1406 return ret;
1407}
1408
1409const struct
1410nla_policy
1411 qca_wlan_vendor_ll_get_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1] = {
1412 /* Unsigned 32bit value provided by the caller issuing the GET stats
1413 * command. When reporting
1414 * the stats results, the driver uses the same value to indicate
1415 * which GET request the results
1416 * correspond to.
1417 */
1418 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID] = {.type = NLA_U32},
1419
1420 /* Unsigned 32bit value . bit mask to identify what statistics are
1421 requested for retrieval */
1422 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = {.type = NLA_U32}
1423};
1424
1425/**
1426 * __wlan_hdd_cfg80211_ll_stats_get() - get link layer stats
1427 * @wiphy: Pointer to wiphy
1428 * @wdev: Pointer to wdev
1429 * @data: Pointer to data
1430 * @data_len: Data length
1431 *
1432 * Return: int
1433 */
1434static int
1435__wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1436 struct wireless_dev *wdev,
1437 const void *data,
1438 int data_len)
1439{
1440 unsigned long rc;
1441 struct hdd_ll_stats_context *context;
1442 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1443 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1];
1444 tSirLLStatsGetReq LinkLayerStatsGetReq;
1445 struct net_device *dev = wdev->netdev;
1446 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1447 int status;
1448
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301449 ENTER();
1450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 if (CDF_FTM_MODE == hdd_get_conparam()) {
1452 hdd_err("Command not allowed in FTM mode");
1453 return -EPERM;
1454 }
1455
1456 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301457 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459
1460 if (!pAdapter->isLinkLayerStatsSet) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001461 hdd_warn("isLinkLayerStatsSet : %d", pAdapter->isLinkLayerStatsSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 return -EINVAL;
1463 }
1464
1465 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX,
1466 (struct nlattr *)data,
1467 data_len, qca_wlan_vendor_ll_get_policy)) {
1468 hddLog(CDF_TRACE_LEVEL_ERROR, FL("max attribute not present"));
1469 return -EINVAL;
1470 }
1471
1472 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]) {
1473 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Request Id Not present"));
1474 return -EINVAL;
1475 }
1476
1477 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]) {
1478 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Req Mask Not present"));
1479 return -EINVAL;
1480 }
1481
1482 LinkLayerStatsGetReq.reqId =
1483 nla_get_u32(tb_vendor
1484 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]);
1485 LinkLayerStatsGetReq.paramIdMask =
1486 nla_get_u32(tb_vendor
1487 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]);
1488
1489 LinkLayerStatsGetReq.staId = pAdapter->sessionId;
1490
1491 hddLog(LOG1,
1492 FL("LL_STATS_GET reqId = %d"), LinkLayerStatsGetReq.reqId);
1493 hddLog(LOG1,
1494 FL("LL_STATS_GET staId = %d"), LinkLayerStatsGetReq.staId);
1495 hddLog(LOG1,
1496 FL("LL_STATS_GET paramIdMask = %d"),
1497 LinkLayerStatsGetReq.paramIdMask);
1498
1499 context = &ll_stats_context;
1500 spin_lock(&context->context_lock);
1501 context->request_id = LinkLayerStatsGetReq.reqId;
1502 context->request_bitmap = LinkLayerStatsGetReq.paramIdMask;
1503 INIT_COMPLETION(context->response_event);
1504 spin_unlock(&context->context_lock);
1505
1506 if (CDF_STATUS_SUCCESS != sme_ll_stats_get_req(pHddCtx->hHal,
1507 &LinkLayerStatsGetReq)) {
1508 hddLog(CDF_TRACE_LEVEL_ERROR, "%s:"
1509 "sme_ll_stats_get_req Failed", __func__);
1510 return -EINVAL;
1511 }
1512
1513 rc = wait_for_completion_timeout(&context->response_event,
1514 msecs_to_jiffies(WLAN_WAIT_TIME_LL_STATS));
1515 if (!rc) {
1516 hddLog(LOGE,
1517 FL("Target response timed out request id %d request bitmap 0x%x"),
1518 context->request_id, context->request_bitmap);
1519 return -ETIMEDOUT;
1520 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301521 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522 return 0;
1523}
1524
1525/**
1526 * wlan_hdd_cfg80211_ll_stats_get() - get ll stats
1527 * @wiphy: Pointer to wiphy
1528 * @wdev: Pointer to wdev
1529 * @data: Pointer to data
1530 * @data_len: Data length
1531 *
1532 * Return: 0 if success, non-zero for failure
1533 */
1534int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1535 struct wireless_dev *wdev,
1536 const void *data,
1537 int data_len)
1538{
1539 int ret = 0;
1540
1541 cds_ssr_protect(__func__);
1542 ret = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len);
1543 cds_ssr_unprotect(__func__);
1544
1545 return ret;
1546}
1547
1548const struct
1549nla_policy
1550 qca_wlan_vendor_ll_clr_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1] = {
1551 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] = {.type = NLA_U32},
1552 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ] = {.type = NLA_U8},
1553 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK] = {.type = NLA_U32},
1554 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP] = {.type = NLA_U8},
1555};
1556
1557/**
1558 * __wlan_hdd_cfg80211_ll_stats_clear() - clear link layer stats
1559 * @wiphy: Pointer to wiphy
1560 * @wdev: Pointer to wdev
1561 * @data: Pointer to data
1562 * @data_len: Data length
1563 *
1564 * Return: int
1565 */
1566static int
1567__wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1568 struct wireless_dev *wdev,
1569 const void *data,
1570 int data_len)
1571{
1572 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1573 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
1574 tSirLLStatsClearReq LinkLayerStatsClearReq;
1575 struct net_device *dev = wdev->netdev;
1576 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1577 u32 statsClearReqMask;
1578 u8 stopReq;
1579 int status;
1580 struct sk_buff *temp_skbuff;
1581
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301582 ENTER();
1583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 if (CDF_FTM_MODE == hdd_get_conparam()) {
1585 hdd_err("Command not allowed in FTM mode");
1586 return -EPERM;
1587 }
1588
1589 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301590 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592
1593 if (!pAdapter->isLinkLayerStatsSet) {
1594 hddLog(CDF_TRACE_LEVEL_FATAL,
1595 "%s: isLinkLayerStatsSet : %d",
1596 __func__, pAdapter->isLinkLayerStatsSet);
1597 return -EINVAL;
1598 }
1599
1600 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
1601 (struct nlattr *)data,
1602 data_len, qca_wlan_vendor_ll_clr_policy)) {
1603 hddLog(CDF_TRACE_LEVEL_ERROR,
1604 FL("STATS_CLR_MAX is not present"));
1605 return -EINVAL;
1606 }
1607
1608 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] ||
1609 !tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]) {
1610 hddLog(CDF_TRACE_LEVEL_ERROR,
1611 FL("Error in LL_STATS CLR CONFIG PARA"));
1612 return -EINVAL;
1613 }
1614
1615 statsClearReqMask = LinkLayerStatsClearReq.statsClearReqMask =
1616 nla_get_u32(tb_vendor
1617 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]);
1618
1619 stopReq = LinkLayerStatsClearReq.stopReq =
1620 nla_get_u8(tb_vendor
1621 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]);
1622
1623 /*
1624 * Shall take the request Id if the Upper layers pass. 1 For now.
1625 */
1626 LinkLayerStatsClearReq.reqId = 1;
1627
1628 LinkLayerStatsClearReq.staId = pAdapter->sessionId;
1629
1630 hddLog(CDF_TRACE_LEVEL_INFO,
1631 "LL_STATS_CLEAR reqId = %d", LinkLayerStatsClearReq.reqId);
1632 hddLog(CDF_TRACE_LEVEL_INFO,
1633 "LL_STATS_CLEAR staId = %d", LinkLayerStatsClearReq.staId);
1634 hddLog(CDF_TRACE_LEVEL_INFO,
1635 "LL_STATS_CLEAR statsClearReqMask = 0x%X",
1636 LinkLayerStatsClearReq.statsClearReqMask);
1637 hddLog(CDF_TRACE_LEVEL_INFO,
1638 "LL_STATS_CLEAR stopReq = %d", LinkLayerStatsClearReq.stopReq);
1639
1640 if (CDF_STATUS_SUCCESS == sme_ll_stats_clear_req(pHddCtx->hHal,
1641 &LinkLayerStatsClearReq)) {
1642 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1643 2 *
1644 sizeof(u32) +
1645 2 *
1646 NLMSG_HDRLEN);
1647 if (temp_skbuff != NULL) {
1648 if (nla_put_u32(temp_skbuff,
1649 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK,
1650 statsClearReqMask) ||
1651 nla_put_u32(temp_skbuff,
1652 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP,
1653 stopReq)) {
1654 hddLog(CDF_TRACE_LEVEL_ERROR,
1655 FL("LL_STATS_CLR put fail"));
1656 kfree_skb(temp_skbuff);
1657 return -EINVAL;
1658 }
1659
1660 /* If the ask is to stop the stats collection as part of clear
1661 * (stopReq = 1) , ensure that no further requests of get
1662 * go to the firmware by having isLinkLayerStatsSet set to 0.
1663 * However it the stopReq as part of the clear request is 0 ,
1664 * the request to get the statistics are honoured as in this
1665 * case the firmware is just asked to clear the statistics.
1666 */
1667 if (stopReq == 1)
1668 pAdapter->isLinkLayerStatsSet = 0;
1669
1670 return cfg80211_vendor_cmd_reply(temp_skbuff);
1671 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301672 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 return -ENOMEM;
1674 }
1675
1676 return -EINVAL;
1677}
1678
1679/**
1680 * wlan_hdd_cfg80211_ll_stats_clear() - clear ll stats
1681 * @wiphy: Pointer to wiphy
1682 * @wdev: Pointer to wdev
1683 * @data: Pointer to data
1684 * @data_len: Data length
1685 *
1686 * Return: 0 if success, non-zero for failure
1687 */
1688int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1689 struct wireless_dev *wdev,
1690 const void *data,
1691 int data_len)
1692{
1693 int ret = 0;
1694
1695 cds_ssr_protect(__func__);
1696 ret = __wlan_hdd_cfg80211_ll_stats_clear(wiphy, wdev, data, data_len);
1697 cds_ssr_unprotect(__func__);
1698
1699 return ret;
1700}
1701
1702#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1703
1704#ifdef WLAN_FEATURE_STATS_EXT
1705/**
1706 * __wlan_hdd_cfg80211_stats_ext_request() - ext stats request
1707 * @wiphy: Pointer to wiphy
1708 * @wdev: Pointer to wdev
1709 * @data: Pointer to data
1710 * @data_len: Data length
1711 *
1712 * Return: int
1713 */
1714static int __wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy,
1715 struct wireless_dev *wdev,
1716 const void *data,
1717 int data_len)
1718{
1719 tStatsExtRequestReq stats_ext_req;
1720 struct net_device *dev = wdev->netdev;
1721 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1722 int ret_val;
1723 CDF_STATUS status;
1724 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1725
1726 ENTER();
1727
1728 ret_val = wlan_hdd_validate_context(hdd_ctx);
1729 if (ret_val)
1730 return ret_val;
1731
1732 if (CDF_FTM_MODE == hdd_get_conparam()) {
1733 hdd_err("Command not allowed in FTM mode");
1734 return -EPERM;
1735 }
1736
1737 stats_ext_req.request_data_len = data_len;
1738 stats_ext_req.request_data = (void *)data;
1739
1740 status = sme_stats_ext_request(pAdapter->sessionId, &stats_ext_req);
1741
1742 if (CDF_STATUS_SUCCESS != status)
1743 ret_val = -EINVAL;
1744
1745 return ret_val;
1746}
1747
1748/**
1749 * wlan_hdd_cfg80211_stats_ext_request() - ext stats request
1750 * @wiphy: Pointer to wiphy
1751 * @wdev: Pointer to wdev
1752 * @data: Pointer to data
1753 * @data_len: Data length
1754 *
1755 * Return: int
1756 */
1757int wlan_hdd_cfg80211_stats_ext_request(struct wiphy *wiphy,
1758 struct wireless_dev *wdev,
1759 const void *data,
1760 int data_len)
1761{
1762 int ret;
1763
1764 cds_ssr_protect(__func__);
1765 ret = __wlan_hdd_cfg80211_stats_ext_request(wiphy, wdev,
1766 data, data_len);
1767 cds_ssr_unprotect(__func__);
1768
1769 return ret;
1770}
1771
1772/**
1773 * wlan_hdd_cfg80211_stats_ext_callback() - ext stats callback
1774 * @ctx: Pointer to HDD context
1775 * @msg: Message received
1776 *
1777 * Return: nothing
1778 */
1779static void wlan_hdd_cfg80211_stats_ext_callback(void *ctx,
1780 tStatsExtEvent *msg)
1781{
1782
1783 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1784 struct sk_buff *vendor_event;
1785 int status;
1786 int ret_val;
1787 tStatsExtEvent *data = msg;
1788 hdd_adapter_t *pAdapter = NULL;
1789
1790 status = wlan_hdd_validate_context(pHddCtx);
1791
1792 if (0 != status) {
1793 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1794 "%s: HDD context is not valid", __func__);
1795 return;
1796 }
1797
1798 pAdapter = hdd_get_adapter_by_vdev(pHddCtx, data->vdev_id);
1799
1800 if (NULL == pAdapter) {
1801 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1802 "%s: vdev_id %d does not exist with host",
1803 __func__, data->vdev_id);
1804 return;
1805 }
1806
1807 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1808 NULL,
1809 data->event_data_len +
1810 sizeof(uint32_t) +
1811 NLMSG_HDRLEN + NLMSG_HDRLEN,
1812 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX,
1813 GFP_KERNEL);
1814
1815 if (!vendor_event) {
1816 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1817 "%s: cfg80211_vendor_event_alloc failed", __func__);
1818 return;
1819 }
1820
1821 ret_val = nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_IFINDEX,
1822 pAdapter->dev->ifindex);
1823 if (ret_val) {
1824 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1825 "%s: QCA_WLAN_VENDOR_ATTR_IFINDEX put fail",
1826 __func__);
1827 kfree_skb(vendor_event);
1828
1829 return;
1830 }
1831
1832 ret_val = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_STATS_EXT,
1833 data->event_data_len, data->event_data);
1834
1835 if (ret_val) {
1836 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
1837 "%s: QCA_WLAN_VENDOR_ATTR_STATS_EXT put fail",
1838 __func__);
1839 kfree_skb(vendor_event);
1840
1841 return;
1842 }
1843
1844 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1845
1846}
1847
1848/**
1849 * wlan_hdd_cfg80211_stats_ext_init() - ext stats init
1850 * @ctx: Pointer to HDD context
1851 *
1852 * Return: nothing
1853 */
1854void wlan_hdd_cfg80211_stats_ext_init(hdd_context_t *pHddCtx)
1855{
1856 sme_stats_ext_register_callback(pHddCtx->hHal,
1857 wlan_hdd_cfg80211_stats_ext_callback);
1858}
1859#endif /* End of WLAN_FEATURE_STATS_EXT */
1860
1861/**
1862 * __wlan_hdd_cfg80211_get_station() - get station statistics
1863 * @wiphy: Pointer to wiphy
1864 * @dev: Pointer to network device
1865 * @mac: Pointer to mac
1866 * @sinfo: Pointer to station info
1867 *
1868 * Return: 0 for success, non-zero for failure
1869 */
1870static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
1871 struct net_device *dev,
1872 const uint8_t *mac,
1873 struct station_info *sinfo)
1874{
1875 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1876 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1877 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
1878 uint8_t rate_flags;
1879
1880 hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy);
1881 struct hdd_config *pCfg = pHddCtx->config;
1882
1883 uint8_t OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
1884 uint32_t ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
1885 uint8_t ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
1886 uint32_t ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
1887 uint8_t MCSRates[SIZE_OF_BASIC_MCS_SET];
1888 uint32_t MCSLeng = SIZE_OF_BASIC_MCS_SET;
1889 uint16_t maxRate = 0;
1890 uint16_t myRate;
1891 uint16_t currentRate = 0;
1892 uint8_t maxSpeedMCS = 0;
1893 uint8_t maxMCSIdx = 0;
1894 uint8_t rateFlag = 1;
1895 uint8_t i, j, rssidx;
1896 uint8_t nss = 1;
1897 int status, mode = 0, maxHtIdx;
1898 struct index_vht_data_rate_type *supported_vht_mcs_rate;
1899 struct index_data_rate_type *supported_mcs_rate;
1900
1901#ifdef WLAN_FEATURE_11AC
1902 uint32_t vht_mcs_map;
1903 enum eDataRate11ACMaxMcs vhtMaxMcs;
1904#endif /* WLAN_FEATURE_11AC */
1905
1906
1907 ENTER();
1908
1909 if (CDF_FTM_MODE == hdd_get_conparam()) {
1910 hddLog(LOGE, FL("Command not allowed in FTM mode"));
1911 return -EINVAL;
1912 }
1913
1914 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
1915 (0 == ssidlen)) {
1916 hddLog(LOG1, FL("Not associated or Invalid ssidlen, %d"),
1917 ssidlen);
1918 /*To keep GUI happy */
1919 return 0;
1920 }
1921
1922 if (true == pHddStaCtx->hdd_ReassocScenario) {
1923 hddLog(LOG1,
1924 FL("Roaming is in progress, cannot continue with this request"));
1925 return 0;
1926 }
1927
1928 status = wlan_hdd_validate_context(pHddCtx);
1929
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301930 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932
1933 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
1934 sinfo->filled |= STATION_INFO_SIGNAL;
1935
1936#ifdef WLAN_FEATURE_LPSS
1937 if (!pAdapter->rssi_send) {
1938 pAdapter->rssi_send = true;
Yue Mae3eaebe2015-10-27 12:42:40 -07001939 if (pHddCtx->isUnloadInProgress != true)
1940 wlan_hdd_send_status_pkg(pAdapter, pHddStaCtx, 1, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941 }
1942#endif
1943
1944 wlan_hdd_get_station_stats(pAdapter);
1945 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
1946
1947 /* convert to the UI units of 100kbps */
1948 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
1949 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
1950 nss = pAdapter->hdd_stats.ClassA_stat.rx_frag_cnt;
1951
1952 if (eHDD_LINK_SPEED_REPORT_ACTUAL == pCfg->reportMaxLinkSpeed) {
1953 /* Get current rate flags if report actual */
1954 rate_flags =
1955 pAdapter->hdd_stats.ClassA_stat.
1956 promiscuous_rx_frag_cnt;
1957 }
1958
1959 if (pAdapter->hdd_stats.ClassA_stat.mcs_index ==
1960 INVALID_MCS_IDX) {
1961 rate_flags = eHAL_TX_RATE_LEGACY;
1962 pAdapter->hdd_stats.ClassA_stat.mcs_index = 0;
1963 }
1964 }
1965#ifdef LINKSPEED_DEBUG_ENABLED
1966 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
1967 sinfo->signal, pCfg->reportMaxLinkSpeed, myRate,
1968 (int)pCfg->linkSpeedRssiHigh, (int)pCfg->linkSpeedRssiMid,
1969 (int)pCfg->linkSpeedRssiLow, (int)rate_flags,
1970 (int)pAdapter->hdd_stats.ClassA_stat.mcs_index);
1971#endif /* LINKSPEED_DEBUG_ENABLED */
1972
1973 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) {
1974 /* we do not want to necessarily report the current speed */
1975 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) {
1976 /* report the max possible speed */
1977 rssidx = 0;
1978 } else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED ==
1979 pCfg->reportMaxLinkSpeed) {
1980 /* report the max possible speed with RSSI scaling */
1981 if (sinfo->signal >= pCfg->linkSpeedRssiHigh) {
1982 /* report the max possible speed */
1983 rssidx = 0;
1984 } else if (sinfo->signal >= pCfg->linkSpeedRssiMid) {
1985 /* report middle speed */
1986 rssidx = 1;
1987 } else if (sinfo->signal >= pCfg->linkSpeedRssiLow) {
1988 /* report middle speed */
1989 rssidx = 2;
1990 } else {
1991 /* report actual speed */
1992 rssidx = 3;
1993 }
1994 } else {
1995 /* unknown, treat as eHDD_LINK_SPEED_REPORT_MAX */
1996 hddLog(LOGE,
1997 FL("Invalid value for reportMaxLinkSpeed: %u"),
1998 pCfg->reportMaxLinkSpeed);
1999 rssidx = 0;
2000 }
2001
2002 maxRate = 0;
2003
2004 /* Get Basic Rate Set */
2005 if (0 !=
2006 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
2007 WNI_CFG_OPERATIONAL_RATE_SET,
2008 OperationalRates,
2009 &ORLeng)) {
2010 hddLog(LOGE, FL("cfg get returned failure"));
2011 /*To keep GUI happy */
2012 return 0;
2013 }
2014
2015 for (i = 0; i < ORLeng; i++) {
2016 for (j = 0;
2017 j < ARRAY_SIZE(supported_data_rate); j++) {
2018 /* Validate Rate Set */
2019 if (supported_data_rate[j].beacon_rate_index ==
2020 (OperationalRates[i] & 0x7F)) {
2021 currentRate =
2022 supported_data_rate[j].
2023 supported_rate[rssidx];
2024 break;
2025 }
2026 }
2027 /* Update MAX rate */
2028 maxRate =
2029 (currentRate > maxRate) ? currentRate : maxRate;
2030 }
2031
2032 /* Get Extended Rate Set */
2033 if (0 !=
2034 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
2035 WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
2036 ExtendedRates, &ERLeng)) {
2037 hddLog(LOGE, FL("cfg get returned failure"));
2038 /*To keep GUI happy */
2039 return 0;
2040 }
2041
2042 for (i = 0; i < ERLeng; i++) {
2043 for (j = 0;
2044 j < ARRAY_SIZE(supported_data_rate); j++) {
2045 if (supported_data_rate[j].beacon_rate_index ==
2046 (ExtendedRates[i] & 0x7F)) {
2047 currentRate =
2048 supported_data_rate[j].
2049 supported_rate[rssidx];
2050 break;
2051 }
2052 }
2053 /* Update MAX rate */
2054 maxRate =
2055 (currentRate > maxRate) ? currentRate : maxRate;
2056 }
2057 /* Get MCS Rate Set --
2058 Only if we are connected in non legacy mode and not reporting
2059 actual speed */
2060 if ((3 != rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY)) {
2061 if (0 !=
2062 sme_cfg_get_str(WLAN_HDD_GET_HAL_CTX(pAdapter),
2063 WNI_CFG_CURRENT_MCS_SET, MCSRates,
2064 &MCSLeng)) {
2065 hddLog(LOGE, FL("cfg get returned failure"));
2066 /*To keep GUI happy */
2067 return 0;
2068 }
2069 rateFlag = 0;
2070#ifdef WLAN_FEATURE_11AC
2071 supported_vht_mcs_rate =
2072 (struct index_vht_data_rate_type *)
2073 ((nss ==
2074 1) ? &supported_vht_mcs_rate_nss1 :
2075 &supported_vht_mcs_rate_nss2);
2076
2077 if (rate_flags & eHAL_TX_RATE_VHT80)
2078 mode = 2;
2079 else if ((rate_flags & eHAL_TX_RATE_VHT40) ||
2080 (rate_flags & eHAL_TX_RATE_HT40))
2081 mode = 1;
2082 else
2083 mode = 0;
2084
2085 /* VHT80 rate has seperate rate table */
2086 if (rate_flags &
2087 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
2088 eHAL_TX_RATE_VHT80)) {
2089 sme_cfg_get_int(WLAN_HDD_GET_HAL_CTX(pAdapter),
2090 WNI_CFG_VHT_TX_MCS_MAP,
2091 &vht_mcs_map);
2092 vhtMaxMcs = (enum eDataRate11ACMaxMcs)
2093 (vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
2094 if (rate_flags & eHAL_TX_RATE_SGI)
2095 rateFlag |= 1;
2096 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
2097 maxMCSIdx = 7;
2098 else if (DATA_RATE_11AC_MAX_MCS_8 ==
2099 vhtMaxMcs)
2100 maxMCSIdx = 8;
2101 else if (DATA_RATE_11AC_MAX_MCS_9 ==
2102 vhtMaxMcs) {
2103 /* VHT20 is supporting 0~8 */
2104 if (rate_flags & eHAL_TX_RATE_VHT20)
2105 maxMCSIdx = 8;
2106 else
2107 maxMCSIdx = 9;
2108 }
2109
2110 if (rssidx != 0) {
2111 for (i = 0; i <= maxMCSIdx; i++) {
2112 if (sinfo->signal <=
2113 rssi_mcs_tbl[mode][i]) {
2114 maxMCSIdx = i;
2115 break;
2116 }
2117 }
2118 }
2119
2120 if (rate_flags & eHAL_TX_RATE_VHT80) {
2121 currentRate =
2122 supported_vht_mcs_rate[pAdapter->
2123 hdd_stats.ClassA_stat.mcs_index].
2124 supported_VHT80_rate[rateFlag];
2125 maxRate =
2126 supported_vht_mcs_rate[maxMCSIdx].
2127 supported_VHT80_rate[rateFlag];
2128 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
2129 currentRate =
2130 supported_vht_mcs_rate[pAdapter->
2131 hdd_stats.ClassA_stat.mcs_index].
2132 supported_VHT40_rate[rateFlag];
2133 maxRate =
2134 supported_vht_mcs_rate[maxMCSIdx].
2135 supported_VHT40_rate[rateFlag];
2136 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
2137 currentRate =
2138 supported_vht_mcs_rate[pAdapter->
2139 hdd_stats.ClassA_stat.mcs_index].
2140 supported_VHT20_rate[rateFlag];
2141 maxRate =
2142 supported_vht_mcs_rate[maxMCSIdx].
2143 supported_VHT20_rate[rateFlag];
2144 }
2145
2146 maxSpeedMCS = 1;
2147 if (currentRate > maxRate)
2148 maxRate = currentRate;
2149
2150 } else
2151#endif /* WLAN_FEATURE_11AC */
2152 {
2153 if (rate_flags & eHAL_TX_RATE_HT40)
2154 rateFlag |= 1;
2155 if (rate_flags & eHAL_TX_RATE_SGI)
2156 rateFlag |= 2;
2157
2158 supported_mcs_rate =
2159 (struct index_data_rate_type *)
2160 ((nss ==
2161 1) ? &supported_mcs_rate_nss1 :
2162 &supported_mcs_rate_nss2);
2163
2164 maxHtIdx = MAX_HT_MCS_IDX;
2165 if (rssidx != 0) {
2166 for (i = 0; i < MAX_HT_MCS_IDX; i++) {
2167 if (sinfo->signal <=
2168 rssi_mcs_tbl[mode][i]) {
2169 maxHtIdx = i + 1;
2170 break;
2171 }
2172 }
2173 }
2174
2175 for (i = 0; i < MCSLeng; i++) {
2176 for (j = 0; j < maxHtIdx; j++) {
2177 if (supported_mcs_rate[j].
2178 beacon_rate_index ==
2179 MCSRates[i]) {
2180 currentRate =
2181 supported_mcs_rate[j].
2182 supported_rate
2183 [rateFlag];
Hanumantha Reddy Pothula616dfbe2015-10-01 14:14:46 +05302184 maxMCSIdx =
2185 supported_mcs_rate[j].
2186 beacon_rate_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 break;
2188 }
2189 }
2190
2191 if ((j < MAX_HT_MCS_IDX)
2192 && (currentRate > maxRate)) {
2193 maxRate = currentRate;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 }
Hanumantha Reddy Pothula616dfbe2015-10-01 14:14:46 +05302195 maxSpeedMCS = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196 }
2197 }
2198 }
2199
2200 else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
2201 maxRate = myRate;
2202 maxSpeedMCS = 1;
2203 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
2204 }
2205 /* report a value at least as big as current rate */
2206 if ((maxRate < myRate) || (0 == maxRate)) {
2207 maxRate = myRate;
2208 if (rate_flags & eHAL_TX_RATE_LEGACY) {
2209 maxSpeedMCS = 0;
2210 } else {
2211 maxSpeedMCS = 1;
2212 maxMCSIdx =
2213 pAdapter->hdd_stats.ClassA_stat.mcs_index;
2214 }
2215 }
2216
2217 if (rate_flags & eHAL_TX_RATE_LEGACY) {
2218 sinfo->txrate.legacy = maxRate;
2219#ifdef LINKSPEED_DEBUG_ENABLED
2220 pr_info("Reporting legacy rate %d\n",
2221 sinfo->txrate.legacy);
2222#endif /* LINKSPEED_DEBUG_ENABLED */
2223 } else {
2224 sinfo->txrate.mcs = maxMCSIdx;
2225#ifdef WLAN_FEATURE_11AC
2226 sinfo->txrate.nss = nss;
2227 if (rate_flags & eHAL_TX_RATE_VHT80) {
2228 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2229 sinfo->txrate.flags |=
2230 RATE_INFO_FLAGS_80_MHZ_WIDTH;
2231 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
2232 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2233 sinfo->txrate.flags |=
2234 RATE_INFO_FLAGS_40_MHZ_WIDTH;
2235 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
2236 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2237 } else
2238 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2239#endif /* WLAN_FEATURE_11AC */
2240 if (rate_flags &
2241 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
2242 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2243 if (rate_flags & eHAL_TX_RATE_HT40) {
2244 sinfo->txrate.flags |=
2245 RATE_INFO_FLAGS_40_MHZ_WIDTH;
2246 }
2247 }
2248 if (rate_flags & eHAL_TX_RATE_SGI) {
2249 if (!
2250 (sinfo->txrate.
2251 flags & RATE_INFO_FLAGS_VHT_MCS))
2252 sinfo->txrate.flags |=
2253 RATE_INFO_FLAGS_MCS;
2254 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
2255 }
2256#ifdef LINKSPEED_DEBUG_ENABLED
2257 pr_info("Reporting MCS rate %d flags %x\n",
2258 sinfo->txrate.mcs, sinfo->txrate.flags);
2259#endif /* LINKSPEED_DEBUG_ENABLED */
2260 }
2261 } else {
2262 /* report current rate instead of max rate */
2263
2264 if (rate_flags & eHAL_TX_RATE_LEGACY) {
2265 /* provide to the UI in units of 100kbps */
2266 sinfo->txrate.legacy = myRate;
2267#ifdef LINKSPEED_DEBUG_ENABLED
2268 pr_info("Reporting actual legacy rate %d\n",
2269 sinfo->txrate.legacy);
2270#endif /* LINKSPEED_DEBUG_ENABLED */
2271 } else {
2272 /* must be MCS */
2273 sinfo->txrate.mcs =
2274 pAdapter->hdd_stats.ClassA_stat.mcs_index;
2275#ifdef WLAN_FEATURE_11AC
2276 sinfo->txrate.nss = nss;
2277 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2278 if (rate_flags & eHAL_TX_RATE_VHT80) {
2279 sinfo->txrate.flags |=
2280 RATE_INFO_FLAGS_80_MHZ_WIDTH;
2281 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
2282 sinfo->txrate.flags |=
2283 RATE_INFO_FLAGS_40_MHZ_WIDTH;
2284 }
2285#endif /* WLAN_FEATURE_11AC */
2286 if (rate_flags &
2287 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
2288 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2289 if (rate_flags & eHAL_TX_RATE_HT40) {
2290 sinfo->txrate.flags |=
2291 RATE_INFO_FLAGS_40_MHZ_WIDTH;
2292 }
2293 }
2294 if (rate_flags & eHAL_TX_RATE_SGI) {
2295 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
2296 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
2297 }
2298#ifdef LINKSPEED_DEBUG_ENABLED
2299 pr_info("Reporting actual MCS rate %d flags %x\n",
2300 sinfo->txrate.mcs, sinfo->txrate.flags);
2301#endif /* LINKSPEED_DEBUG_ENABLED */
2302 }
2303 }
2304 sinfo->filled |= STATION_INFO_TX_BITRATE;
2305
2306 sinfo->tx_bytes = pAdapter->stats.tx_bytes;
2307 sinfo->filled |= STATION_INFO_TX_BYTES;
2308
2309 sinfo->tx_packets =
2310 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
2311 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
2312 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
2313 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
2314
2315 sinfo->tx_retries =
2316 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
2317 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
2318 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
2319 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
2320
2321 sinfo->tx_failed =
2322 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
2323 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
2324 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
2325 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
2326
2327 sinfo->filled |=
2328 STATION_INFO_TX_PACKETS |
2329 STATION_INFO_TX_RETRIES | STATION_INFO_TX_FAILED;
2330
2331 sinfo->rx_bytes = pAdapter->stats.rx_bytes;
2332 sinfo->filled |= STATION_INFO_RX_BYTES;
2333
2334 sinfo->rx_packets = pAdapter->stats.rx_packets;
2335 sinfo->filled |= STATION_INFO_RX_PACKETS;
2336
2337 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
2338 TRACE_CODE_HDD_CFG80211_GET_STA,
2339 pAdapter->sessionId, maxRate));
2340 EXIT();
2341 return 0;
2342}
2343
2344/**
2345 * wlan_hdd_cfg80211_get_station() - get station statistics
2346 * @wiphy: Pointer to wiphy
2347 * @dev: Pointer to network device
2348 * @mac: Pointer to mac
2349 * @sinfo: Pointer to station info
2350 *
2351 * Return: 0 for success, non-zero for failure
2352 */
2353#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
2354int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
2355 struct net_device *dev, const uint8_t *mac,
2356 struct station_info *sinfo)
2357#else
2358int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
2359 struct net_device *dev, uint8_t *mac,
2360 struct station_info *sinfo)
2361#endif
2362{
2363 int ret;
2364
2365 cds_ssr_protect(__func__);
2366 ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
2367 cds_ssr_unprotect(__func__);
2368
2369 return ret;
2370}
2371
2372/**
2373 * hdd_get_stats() - Function to retrieve interface statistics
2374 * @dev: pointer to network device
2375 *
2376 * This function is the ndo_get_stats method for all netdevs
2377 * registered with the kernel
2378 *
2379 * Return: pointer to net_device_stats structure
2380 */
2381struct net_device_stats *hdd_get_stats(struct net_device *dev)
2382{
2383 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2384
2385 return &adapter->stats;
2386}
2387/**
2388 * __wlan_hdd_cfg80211_dump_survey() - get survey related info
2389 * @wiphy: Pointer to wiphy
2390 * @dev: Pointer to network device
2391 * @idx: Index
2392 * @survey: Pointer to survey info
2393 *
2394 * Return: 0 for success, non-zero for failure
2395 */
2396static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
2397 struct net_device *dev,
2398 int idx, struct survey_info *survey)
2399{
2400 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2401 hdd_context_t *pHddCtx;
2402 hdd_station_ctx_t *pHddStaCtx;
2403 tHalHandle halHandle;
2404 uint32_t channel = 0, freq = 0; /* Initialization Required */
2405 int8_t snr, rssi;
2406 int status, i, j, filled = 0;
2407
2408 ENTER();
2409
2410 if (CDF_FTM_MODE == hdd_get_conparam()) {
2411 hddLog(LOGE, FL("Command not allowed in FTM mode"));
2412 return -EINVAL;
2413 }
2414
2415 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2416 status = wlan_hdd_validate_context(pHddCtx);
2417
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302418 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420
2421 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2422
2423 if (0 == pHddCtx->config->fEnableSNRMonitoring ||
2424 0 != pAdapter->survey_idx ||
2425 eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
2426 /* The survey dump ops when implemented completely is expected
2427 * to return a survey of all channels and the ops is called by
2428 * the kernel with incremental values of the argument 'idx'
2429 * till it returns -ENONET. But we can only support the survey
2430 * for the operating channel for now. survey_idx is used to
2431 * track that the ops is called only once and then return
2432 * -ENONET for the next iteration
2433 */
2434 pAdapter->survey_idx = 0;
2435 return -ENONET;
2436 }
2437
2438 if (!pHddStaCtx->hdd_ReassocScenario) {
2439 hdd_err("Roaming in progress, hence return");
2440 return -ENONET;
2441 }
2442
2443 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
2444
2445 wlan_hdd_get_snr(pAdapter, &snr);
2446 wlan_hdd_get_rssi(pAdapter, &rssi);
2447
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +05302448 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
2449 TRACE_CODE_HDD_CFG80211_DUMP_SURVEY,
2450 pAdapter->sessionId, pAdapter->device_mode));
2451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 sme_get_operation_channel(halHandle, &channel, pAdapter->sessionId);
2453 hdd_wlan_get_freq(channel, &freq);
2454
2455 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002456 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458
2459 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
2460 struct ieee80211_supported_band *band = wiphy->bands[i];
2461
2462 if (band->channels[j].center_freq == (uint16_t) freq) {
2463 survey->channel = &band->channels[j];
2464 /* The Rx BDs contain SNR values in dB for the
2465 * received frames while the supplicant expects
2466 * noise. So we calculate and return the value
2467 * of noise (dBm)
2468 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
2469 */
2470 survey->noise = rssi - snr;
2471 survey->filled = SURVEY_INFO_NOISE_DBM;
2472 filled = 1;
2473 }
2474 }
2475 }
2476
2477 if (filled)
2478 pAdapter->survey_idx = 1;
2479 else {
2480 pAdapter->survey_idx = 0;
2481 return -ENONET;
2482 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302483 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 return 0;
2485}
2486
2487/**
2488 * wlan_hdd_cfg80211_dump_survey() - get survey related info
2489 * @wiphy: Pointer to wiphy
2490 * @dev: Pointer to network device
2491 * @idx: Index
2492 * @survey: Pointer to survey info
2493 *
2494 * Return: 0 for success, non-zero for failure
2495 */
2496int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
2497 struct net_device *dev,
2498 int idx, struct survey_info *survey)
2499{
2500 int ret;
2501
2502 cds_ssr_protect(__func__);
2503 ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey);
2504 cds_ssr_unprotect(__func__);
2505
2506 return ret;
2507}
2508/**
2509 * hdd_init_ll_stats_ctx() - initialize link layer stats context
2510 *
2511 * Return: none
2512 */
2513inline void hdd_init_ll_stats_ctx(void)
2514{
2515 spin_lock_init(&ll_stats_context.context_lock);
2516 init_completion(&ll_stats_context.response_event);
2517 ll_stats_context.request_bitmap = 0;
2518
2519 return;
2520}