blob: 9dff6a6d9260fcb9d02c349b3826262ca31ff9a0 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyad07dc902017-01-11 12:49:53 -08002 * Copyright (c) 2013-2017 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 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_utis.c
30 * This file contains utilities and stats related functions.
31 */
32
33/* Header files */
34
35#include "wma.h"
36#include "wma_api.h"
37#include "cds_api.h"
38#include "wmi_unified_api.h"
39#include "wlan_qct_sys.h"
40#include "wni_api.h"
41#include "ani_global.h"
42#include "wmi_unified.h"
43#include "wni_cfg.h"
44#include "cfg_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045
Nirav Shahcbc6d722016-03-01 16:24:53 +053046#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053047#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053048#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049
50#include "wma_types.h"
51#include "lim_api.h"
52#include "lim_session_utils.h"
53
54#include "cds_utils.h"
55
56#if !defined(REMOVE_PKT_LOG)
57#include "pktlog_ac.h"
58#endif /* REMOVE_PKT_LOG */
59
60#include "dbglog_host.h"
61#include "csr_api.h"
62#include "ol_fw.h"
63
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064#include "wma_internal.h"
Tushnim Bhattacharyya51258a72017-03-13 12:55:02 -070065#include "wlan_policy_mgr_api.h"
Govind Singhd76a5b02016-03-08 15:12:14 +053066#include "wmi_unified_param.h"
Naveen Rawatc0c91cd2015-11-05 14:27:37 -080067#include "linux/ieee80211.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080068#include <cdp_txrx_handle.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080069/* MCS Based rate table */
70/* HT MCS parameters with Nss = 1 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080071static struct index_data_rate_type mcs_nss1[] = {
72 /* MCS L20 S20 L40 S40 */
73 {0, {65, 72}, {135, 150 } },
74 {1, {130, 144}, {270, 300 } },
75 {2, {195, 217}, {405, 450 } },
76 {3, {260, 289}, {540, 600 } },
77 {4, {390, 433}, {815, 900 } },
78 {5, {520, 578}, {1080, 1200} },
79 {6, {585, 650}, {1215, 1350} },
80 {7, {650, 722}, {1350, 1500} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081};
82
83/* HT MCS parameters with Nss = 2 */
Ryan Hsu6139d2d2015-11-04 17:29:00 -080084static struct index_data_rate_type mcs_nss2[] = {
85 /* MCS L20 S20 L40 S40 */
86 {0, {130, 144}, {270, 300 } },
87 {1, {260, 289}, {540, 600 } },
88 {2, {390, 433}, {810, 900 } },
89 {3, {520, 578}, {1080, 1200} },
90 {4, {780, 867}, {1620, 1800} },
91 {5, {1040, 1156}, {2160, 2400} },
92 {6, {1170, 1300}, {2430, 2700} },
93 {7, {1300, 1440}, {2700, 3000} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094};
95
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096/* MCS Based VHT rate table */
97/* MCS parameters with Nss = 1*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -080098static struct index_vht_data_rate_type vht_mcs_nss1[] = {
99 /* MCS L20 S20 L40 S40 L80 S80 */
100 {0, {65, 72 }, {135, 150}, {293, 325} },
101 {1, {130, 144}, {270, 300}, {585, 650} },
102 {2, {195, 217}, {405, 450}, {878, 975} },
103 {3, {260, 289}, {540, 600}, {1170, 1300} },
104 {4, {390, 433}, {810, 900}, {1755, 1950} },
105 {5, {520, 578}, {1080, 1200}, {2340, 2600} },
106 {6, {585, 650}, {1215, 1350}, {2633, 2925} },
107 {7, {650, 722}, {1350, 1500}, {2925, 3250} },
108 {8, {780, 867}, {1620, 1800}, {3510, 3900} },
109 {9, {865, 960}, {1800, 2000}, {3900, 4333} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110};
111
112/*MCS parameters with Nss = 2*/
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800113static struct index_vht_data_rate_type vht_mcs_nss2[] = {
114 /* MCS L20 S20 L40 S40 L80 S80 */
115 {0, {130, 144}, {270, 300}, { 585, 650} },
116 {1, {260, 289}, {540, 600}, {1170, 1300} },
117 {2, {390, 433}, {810, 900}, {1755, 1950} },
118 {3, {520, 578}, {1080, 1200}, {2340, 2600} },
119 {4, {780, 867}, {1620, 1800}, {3510, 3900} },
120 {5, {1040, 1156}, {2160, 2400}, {4680, 5200} },
121 {6, {1170, 1300}, {2430, 2700}, {5265, 5850} },
122 {7, {1300, 1444}, {2700, 3000}, {5850, 6500} },
123 {8, {1560, 1733}, {3240, 3600}, {7020, 7800} },
124 {9, {1730, 1920}, {3600, 4000}, {7800, 8667} }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126
127#ifdef BIG_ENDIAN_HOST
128
129/* ############# function definitions ############ */
130
131/**
132 * wma_swap_bytes() - swap bytes
133 * @pv: buffer
134 * @n: swap bytes
135 *
136 * Return: none
137 */
138void wma_swap_bytes(void *pv, uint32_t n)
139{
140 int32_t no_words;
141 int32_t i;
142 uint32_t *word_ptr;
143
144 no_words = n / sizeof(uint32_t);
145 word_ptr = (uint32_t *) pv;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700146 for (i = 0; i < no_words; i++)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147 *(word_ptr + i) = __cpu_to_le32(*(word_ptr + i));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700150#define SWAPME(x, len) wma_swap_bytes(&x, len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151#endif /* BIG_ENDIAN_HOST */
152
153/**
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800154 * wma_mcs_rate_match() - find the match mcs rate
155 * @match_rate: the rate to look up
156 * @is_sgi: return if the SGI rate is found
157 * @nss: the nss in use
158 * @nss1_rate: the nss1 rate
159 * @nss1_srate: the nss1 SGI rate
160 * @nss2_rate: the nss2 rate
161 * @nss2_srate: the nss2 SGI rate
162 *
163 * This is a helper function to find the match of the tx_rate
164 * in terms of the nss1/nss2 rate with non-SGI/SGI.
165 *
166 * Return: the found rate or 0 otherwise
167 */
168static inline uint16_t wma_mcs_rate_match(uint16_t match_rate, bool *is_sgi,
169 uint8_t nss, uint16_t nss1_rate,
170 uint16_t nss1_srate,
171 uint16_t nss2_rate,
172 uint16_t nss2_srate)
173{
174 WMA_LOGD("%s match_rate: %d, %d %d %d %d",
175 __func__, match_rate, nss1_rate, nss1_srate, nss2_rate,
176 nss2_srate);
177
178 if (match_rate == nss1_rate) {
179 return nss1_rate;
180 } else if (match_rate == nss1_srate) {
181 *is_sgi = true;
182 return nss1_srate;
183 } else if (nss == 2 && match_rate == nss2_rate)
184 return nss2_rate;
185 else if (nss == 2 && match_rate == nss2_srate) {
186 *is_sgi = true;
187 return nss2_srate;
188 } else
189 return 0;
190}
191
192/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 * wma_get_mcs_idx() - get mcs index
194 * @maxRate: max rate
195 * @rate_flags: rate flags
196 * @nss: number of nss
197 * @mcsRateFlag: mcs rate flag
198 *
199 * Return: return mcs index
200 */
201static uint8_t wma_get_mcs_idx(uint16_t maxRate, uint8_t rate_flags,
202 uint8_t nss, uint8_t *mcsRateFlag)
203{
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800204 uint8_t index = 0;
Arif Hussainb8fef842016-07-19 09:43:13 -0700205 uint16_t match_rate = 0;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800206 bool is_sgi = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800208 WMA_LOGD("%s rate:%d rate_flgs: 0x%x, nss: %d",
209 __func__, maxRate, rate_flags, nss);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210
211 *mcsRateFlag = rate_flags;
212 *mcsRateFlag &= ~eHAL_TX_RATE_SGI;
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800213 for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 if (rate_flags & eHAL_TX_RATE_VHT80) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800215 /* check for vht80 nss1/2 rate set */
216 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
217 vht_mcs_nss1[index].ht80_rate[0],
218 vht_mcs_nss1[index].ht80_rate[1],
219 vht_mcs_nss2[index].ht80_rate[0],
220 vht_mcs_nss2[index].ht80_rate[1]);
221 if (match_rate)
222 goto rate_found;
223 }
224 if ((rate_flags & eHAL_TX_RATE_VHT40) |
225 (rate_flags & eHAL_TX_RATE_VHT80)) {
226 /* check for vht40 nss1/2 rate set */
227 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
228 vht_mcs_nss1[index].ht40_rate[0],
229 vht_mcs_nss1[index].ht40_rate[1],
230 vht_mcs_nss2[index].ht40_rate[0],
231 vht_mcs_nss2[index].ht40_rate[1]);
232 if (match_rate) {
233 *mcsRateFlag &= ~eHAL_TX_RATE_VHT80;
234 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 }
236 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800237 if ((rate_flags & eHAL_TX_RATE_VHT20) |
238 (rate_flags & eHAL_TX_RATE_VHT40) |
239 (rate_flags & eHAL_TX_RATE_VHT80)) {
240 /* check for vht20 nss1/2 rate set */
241 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
242 vht_mcs_nss1[index].ht20_rate[0],
243 vht_mcs_nss1[index].ht20_rate[1],
244 vht_mcs_nss2[index].ht20_rate[0],
245 vht_mcs_nss2[index].ht20_rate[1]);
246 if (match_rate) {
247 *mcsRateFlag &= ~(eHAL_TX_RATE_VHT80 |
248 eHAL_TX_RATE_VHT40);
249 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 }
251 }
252 }
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800253 for (index = 0; index < MAX_HT_MCS_IDX; index++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254 if (rate_flags & eHAL_TX_RATE_HT40) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800255 /* check for ht40 nss1/2 rate set */
256 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
257 mcs_nss1[index].ht40_rate[0],
258 mcs_nss1[index].ht40_rate[1],
259 mcs_nss2[index].ht40_rate[0],
260 mcs_nss2[index].ht40_rate[1]);
261 if (match_rate) {
262 *mcsRateFlag = eHAL_TX_RATE_HT40;
263 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800264 }
265 }
wadesongbf665542017-02-28 14:30:51 +0800266 if ((rate_flags & eHAL_TX_RATE_HT20) ||
267 (rate_flags & eHAL_TX_RATE_HT40)) {
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800268 /* check for ht20 nss1/2 rate set */
269 match_rate = wma_mcs_rate_match(maxRate, &is_sgi, nss,
270 mcs_nss1[index].ht20_rate[0],
271 mcs_nss1[index].ht20_rate[1],
272 mcs_nss2[index].ht20_rate[0],
273 mcs_nss2[index].ht20_rate[1]);
274 if (match_rate) {
275 *mcsRateFlag = eHAL_TX_RATE_HT20;
276 goto rate_found;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 }
278 }
279 }
280
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800281rate_found:
282 /* set SGI flag only if this is SGI rate */
283 if (match_rate && is_sgi == true)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284 *mcsRateFlag |= eHAL_TX_RATE_SGI;
285
Ryan Hsu6139d2d2015-11-04 17:29:00 -0800286 WMA_LOGD("%s - match_rate: %d index: %d rate_flag: 0x%x is_sgi: %d",
287 __func__, match_rate, index, *mcsRateFlag, is_sgi);
288
289 return match_rate ? index : INVALID_MCS_IDX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290}
291
292/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530293 * wma_peek_vdev_req() - peek what request message is queued for response.
294 * the function does not delete the node after found
295 * @wma: WMA handle
296 * @vdev_id: vdev ID
297 * @type: request message type
298 *
299 * Return: the request message found
300 */
301static struct wma_target_req *wma_peek_vdev_req(tp_wma_handle wma,
302 uint8_t vdev_id, uint8_t type)
303{
304 struct wma_target_req *req_msg = NULL;
305 bool found = false;
306 qdf_list_node_t *node1 = NULL, *node2 = NULL;
307
308 qdf_spin_lock_bh(&wma->vdev_respq_lock);
309 if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&wma->vdev_resp_queue,
310 &node2)) {
311 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530312 return NULL;
313 }
314
315 do {
316 node1 = node2;
317 req_msg = qdf_container_of(node1, struct wma_target_req, node);
318 if (req_msg->vdev_id != vdev_id)
319 continue;
320 if (req_msg->type != type)
321 continue;
322
323 found = true;
324 break;
325 } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&wma->vdev_resp_queue,
326 node1, &node2));
327 qdf_spin_unlock_bh(&wma->vdev_respq_lock);
328 if (!found) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800329 WMA_LOGE(FL("target request not found for vdev_id %d type %d"),
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530330 vdev_id, type);
331 return NULL;
332 }
333 WMA_LOGD(FL("target request found for vdev id: %d type %d msg %d"),
334 vdev_id, type, req_msg->msg_type);
335 return req_msg;
336}
337
338void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id,
339 int32_t rssi)
340{
341 struct sir_lost_link_info *lost_link_info;
342 QDF_STATUS qdf_status;
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800343 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530344
345 /* report lost link information only for STA mode */
Mukul Sharmaf9047232017-03-02 16:58:56 +0530346 if (wma_is_vdev_up(vdev_id) &&
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530347 (WMI_VDEV_TYPE_STA == wma->interfaces[vdev_id].type) &&
348 (0 == wma->interfaces[vdev_id].sub_type)) {
349 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
350 if (NULL == lost_link_info) {
351 WMA_LOGE("%s: failed to allocate memory", __func__);
352 return;
353 }
354 lost_link_info->vdev_id = vdev_id;
355 lost_link_info->rssi = rssi;
356 sme_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
357 sme_msg.bodyptr = lost_link_info;
358 sme_msg.bodyval = 0;
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -0800359 WMA_LOGD("%s: post msg to SME, bss_idx %d, rssi %d", __func__,
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530360 lost_link_info->vdev_id, lost_link_info->rssi);
361
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800362 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +0530363 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
364 WMA_LOGE("%s: fail to post msg to SME", __func__);
365 qdf_mem_free(lost_link_info);
366 }
367 }
368}
369
370/**
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700371 * host_map_smps_mode() - map fw smps mode to enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372 * @fw_smps_mode: fw smps mode
373 *
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700374 * Return: return enum eSmpsModeValue
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700376enum eSmpsModeValue host_map_smps_mode(A_UINT32 fw_smps_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700378 enum eSmpsModeValue smps_mode = SMPS_MODE_DISABLED;
379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 switch (fw_smps_mode) {
381 case WMI_SMPS_FORCED_MODE_STATIC:
382 smps_mode = STATIC_SMPS_MODE;
383 break;
384 case WMI_SMPS_FORCED_MODE_DYNAMIC:
385 smps_mode = DYNAMIC_SMPS_MODE;
386 break;
387 default:
388 smps_mode = SMPS_MODE_DISABLED;
389 }
390
391 return smps_mode;
392}
393
Archana Ramachandran20d2e232016-02-11 16:58:40 -0800394/**
395 * wma_smps_mode_to_force_mode_param() - Map smps mode to force
396 * mode commmand param
397 * @smps_mode: SMPS mode according to the protocol
398 *
399 * Return: int > 0 for success else failure
400 */
401int wma_smps_mode_to_force_mode_param(uint8_t smps_mode)
402{
403 int param = -EINVAL;
404
405 switch (smps_mode) {
406 case STATIC_SMPS_MODE:
407 param = WMI_SMPS_FORCED_MODE_STATIC;
408 break;
409 case DYNAMIC_SMPS_MODE:
410 param = WMI_SMPS_FORCED_MODE_DYNAMIC;
411 break;
412 case SMPS_MODE_DISABLED:
413 param = WMI_SMPS_FORCED_MODE_DISABLED;
414 break;
415 default:
416 WMA_LOGE(FL("smps mode cannot be mapped :%d "),
417 smps_mode);
418 }
419 return param;
420}
421
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422#ifdef WLAN_FEATURE_STATS_EXT
423/**
424 * wma_stats_ext_event_handler() - extended stats event handler
425 * @handle: wma handle
426 * @event_buf: event buffer received from fw
427 * @len: length of data
428 *
429 * Return: 0 for success or error code
430 */
431int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf,
432 uint32_t len)
433{
434 WMI_STATS_EXT_EVENTID_param_tlvs *param_buf;
435 tSirStatsExtEvent *stats_ext_event;
436 wmi_stats_ext_event_fixed_param *stats_ext_info;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530437 QDF_STATUS status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -0700438 struct scheduler_msg cds_msg = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 uint8_t *buf_ptr;
440 uint32_t alloc_len;
441
442 WMA_LOGD("%s: Posting stats ext event to SME", __func__);
443
444 param_buf = (WMI_STATS_EXT_EVENTID_param_tlvs *) event_buf;
445 if (!param_buf) {
446 WMA_LOGE("%s: Invalid stats ext event buf", __func__);
447 return -EINVAL;
448 }
449
450 stats_ext_info = param_buf->fixed_param;
451 buf_ptr = (uint8_t *) stats_ext_info;
452
453 alloc_len = sizeof(tSirStatsExtEvent);
454 alloc_len += stats_ext_info->data_len;
455
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530456 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 if (NULL == stats_ext_event) {
458 WMA_LOGE("%s: Memory allocation failure", __func__);
459 return -ENOMEM;
460 }
461
462 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
463
464 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
465 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530466 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467 buf_ptr, stats_ext_event->event_data_len);
468
469 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
470 cds_msg.bodyptr = (void *)stats_ext_event;
471 cds_msg.bodyval = 0;
472
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800473 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530474 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530476 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 return -EFAULT;
478 }
479
480 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
481 return 0;
482}
483#endif /* WLAN_FEATURE_STATS_EXT */
484
Nirav Shah93e789e2016-04-14 19:47:43 +0530485
Govind Singha471e5e2015-10-12 17:11:14 +0530486/**
487 * wma_profile_data_report_event_handler() - fw profiling handler
488 * @handle: wma handle
489 * @event_buf: event buffer received from fw
490 * @len: length of data
491 *
492 * Return: 0 for success or error code
493 */
494int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
495 uint32_t len)
496{
497 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
498 wmi_wlan_profile_ctx_t *profile_ctx;
499 wmi_wlan_profile_t *profile_data;
500 uint32_t i = 0;
501 uint32_t entries;
502 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530503 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530504
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700505 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530506 if (!param_buf) {
507 WMA_LOGE("%s: Invalid profile data event buf", __func__);
508 return -EINVAL;
509 }
510 profile_ctx = param_buf->profile_ctx;
511 buf_ptr = (uint8_t *)profile_ctx;
512 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
513 profile_data = (wmi_wlan_profile_t *) buf_ptr;
514 entries = profile_ctx->bin_count;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530515 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530516 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530517 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530518 "TOT: %d\n"
519 "tx_msdu_cnt: %d\n"
520 "tx_mpdu_cnt: %d\n"
521 "tx_ppdu_cnt: %d\n"
522 "rx_msdu_cnt: %d\n"
523 "rx_mpdu_cnt: %d\n"
524 "bin_count: %d\n",
525 profile_ctx->tot,
526 profile_ctx->tx_msdu_cnt,
527 profile_ctx->tx_mpdu_cnt,
528 profile_ctx->tx_ppdu_cnt,
529 profile_ctx->rx_msdu_cnt,
530 profile_ctx->rx_mpdu_cnt,
531 profile_ctx->bin_count);
532
Nirav Shah93e789e2016-04-14 19:47:43 +0530533 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
534 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
535
Govind Singha471e5e2015-10-12 17:11:14 +0530536 for (i = 0; i < entries; i++) {
537 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
538 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530539 snprintf(temp_str, sizeof(temp_str),
540 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530541 profile_data[i].id,
542 profile_data[i].cnt,
543 profile_data[i].tot,
544 profile_data[i].min,
545 profile_data[i].max,
546 profile_data[i].hist_intvl,
547 profile_data[i].hist[0],
548 profile_data[i].hist[1],
549 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530550 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
551 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530552 }
553
554 return 0;
555}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
557#ifdef WLAN_FEATURE_LINK_LAYER_STATS
558
Zhang Qian73c348a2017-03-13 16:15:55 +0800559#define WMA_FILL_TX_STATS(eve, msg) do {\
560 (msg)->msdus = (eve)->tx_msdu_cnt;\
561 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
562 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
563 (msg)->bytes = (eve)->tx_bytes;\
564 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
565 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
566 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
567 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
568} while (0)
569
570#define WMA_FILL_RX_STATS(eve, msg) do {\
571 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
572 (msg)->bytes = (eve)->mac_rx_bytes;\
573 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
574 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
575 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
576 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
577 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
578} while (0)
579
580/**
581 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
582 * @len: buffer length output
583 * @peer_num: peer number
584 * @fixed_param: fixed parameters in WMI event
585 *
586 * Structure of the stats message
587 * LL_EXT_STATS
588 * |
589 * |--Channel stats[1~n]
590 * |--Peer[1~n]
591 * |
592 * +---Signal
593 * +---TX
594 * | +---BE
595 * | +---BK
596 * | +---VI
597 * | +---VO
598 * |
599 * +---RX
600 * +---BE
601 * +---BK
602 * +---VI
603 * +---VO
604 * For each Access Category, the arregation and mcs
605 * stats are as this:
606 * TX
607 * +-BE/BK/VI/VO
608 * +----tx_mpdu_aggr_array
609 * +----tx_succ_mcs_array
610 * +----tx_fail_mcs_array
611 * +----tx_delay_array
612 * RX
613 * +-BE/BK/VI/VO
614 * +----rx_mpdu_aggr_array
615 * +----rx_mcs_array
616 *
617 * return: Address for result buffer.
618 */
619static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
620 uint32_t peer_num,
621 wmi_report_stats_event_fixed_param *fixed_param)
622{
623 tSirLLStatsResults *buf;
624 uint32_t buf_len;
625
626 if (!len || !fixed_param) {
627 WMA_LOGE(FL("Invalid input parameters."));
628 return NULL;
629 }
630
631 /*
632 * Result buffer has a structure like this:
633 * ---------------------------------
634 * | trigger_cond_i |
635 * +-------------------------------+
636 * | cca_chgd_bitmap |
637 * +-------------------------------+
638 * | sig_chgd_bitmap |
639 * +-------------------------------+
640 * | tx_chgd_bitmap |
641 * +-------------------------------+
642 * | rx_chgd_bitmap |
643 * +-------------------------------+
644 * | peer_num |
645 * +-------------------------------+
646 * | channel_num |
647 * +-------------------------------+
648 * | tx_mpdu_aggr_array_len |
649 * +-------------------------------+
650 * | tx_succ_mcs_array_len |
651 * +-------------------------------+
652 * | tx_fail_mcs_array_len |
653 * +-------------------------------+
654 * | tx_delay_array_len |
655 * +-------------------------------+
656 * | rx_mpdu_aggr_array_len |
657 * +-------------------------------+
658 * | rx_mcs_array_len |
659 * +-------------------------------+
660 * | pointer to CCA stats |
661 * +-------------------------------+
662 * | CCA stats |
663 * +-------------------------------+
664 * | peer_stats |----+
665 * +-------------------------------+ |
666 * | TX aggr/mcs parameters array | |
667 * | Length of this buffer is | |
668 * | not fixed. |<-+ |
669 * +-------------------------------+ | |
670 * | per peer tx stats |--+ |
671 * | BE | <--+
672 * | BK | |
673 * | VI | |
674 * | VO | |
675 * +-------------------------------+ |
676 * | TX aggr/mcs parameters array | |
677 * | Length of this buffer is | |
678 * | not fixed. |<-+ |
679 * +-------------------------------+ | |
680 * | peer peer rx stats |--+ |
681 * | BE | <--+
682 * | BK |
683 * | VI |
684 * | VO |
685 * ---------------------------------
686 */
687 buf_len = sizeof(tSirLLStatsResults) +
688 sizeof(struct sir_wifi_ll_ext_stats) +
689 fixed_param->num_chan_cca_stats *
690 sizeof(struct sir_wifi_chan_cca_stats) +
691 peer_num *
692 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
693 WLAN_MAX_AC *
694 (sizeof(struct sir_wifi_tx) +
695 sizeof(struct sir_wifi_rx)) +
696 sizeof(uint32_t) * WLAN_MAX_AC *
697 (fixed_param->tx_mpdu_aggr_array_len +
698 fixed_param->tx_succ_mcs_array_len +
699 fixed_param->tx_fail_mcs_array_len +
700 fixed_param->tx_ppdu_delay_array_len +
701 fixed_param->rx_mpdu_aggr_array_len +
702 fixed_param->rx_mcs_array_len));
703
704 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
705 if (buf == NULL) {
706 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
707 buf_len = 0;
708 return NULL;
709 }
710
711 *len = buf_len;
712 return buf;
713}
714
715/**
716 * wma_fill_tx_stats() - Fix TX stats into result buffer
717 * @ll_stats: LL stats buffer
718 * @fix_param: parameters with fixed length in WMI event
719 * @param_buf: parameters without fixed length in WMI event
720 * @buf: buffer for TLV parameters
721 *
722 * Return: None
723 */
724static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
725 wmi_report_stats_event_fixed_param *fix_param,
726 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
727 uint8_t **buf, uint32_t *buf_length)
728{
729 uint8_t *result;
730 uint32_t i, j, k;
731 wmi_peer_ac_tx_stats *wmi_peer_tx;
732 wmi_tx_stats *wmi_tx;
733 struct sir_wifi_tx *tx_stats;
734 struct sir_wifi_ll_ext_peer_stats *peer_stats;
735 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
736 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
737 tx_fail_mcs_array_len, tx_delay_array_len;
738
739 result = *buf;
740 dst_len = *buf_length;
741 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
742 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
743 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
744 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
745 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
746 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
747 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
748 ll_stats->tx_delay_array_len = tx_delay_array_len;
749 wmi_peer_tx = param_buf->peer_ac_tx_stats;
750 wmi_tx = param_buf->tx_stats;
751
752 len = fix_param->num_peer_ac_tx_stats *
753 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
754 if (len <= dst_len) {
755 tx_mpdu_aggr = (uint32_t *)result;
756 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
757 result += len;
758 dst_len -= len;
759 } else {
760 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
761 tx_mpdu_aggr = NULL;
762 }
763
764 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
765 tx_succ_mcs_array_len * sizeof(uint32_t);
766 if (len <= dst_len) {
767 tx_succ_mcs = (uint32_t *)result;
768 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
769 result += len;
770 dst_len -= len;
771 } else {
772 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
773 tx_succ_mcs = NULL;
774 }
775
776 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
777 tx_fail_mcs_array_len * sizeof(uint32_t);
778 if (len <= dst_len) {
779 tx_fail_mcs = (uint32_t *)result;
780 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
781 result += len;
782 dst_len -= len;
783 } else {
784 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
785 tx_fail_mcs = NULL;
786 }
787
788 len = fix_param->num_peer_ac_tx_stats *
789 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
790 if (len <= dst_len) {
791 tx_delay = (uint32_t *)result;
792 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
793 result += len;
794 dst_len -= len;
795 } else {
796 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
797 tx_delay = NULL;
798 }
799
800 /* per peer tx stats */
801 peer_stats = ll_stats->peer_stats;
802
803 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
804 uint32_t peer_id = wmi_peer_tx[i].peer_id;
805 struct sir_wifi_tx *ac;
806 wmi_tx_stats *wmi_tx_stats;
807
808 for (j = 0; j < ll_stats->peer_num; j++) {
809 peer_stats += j;
810 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
811 peer_stats->peer_id == peer_id)
812 break;
813 }
814
815 if (j < ll_stats->peer_num) {
816 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
817 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
818 tx_stats = (struct sir_wifi_tx *)result;
819 for (k = 0; k < WLAN_MAX_AC; k++) {
820 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
821 ac = &tx_stats[k];
822 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
823 ac->mpdu_aggr_size = tx_mpdu_aggr;
824 ac->aggr_len = tx_mpdu_aggr_array_len *
825 sizeof(uint32_t);
826 ac->success_mcs_len = tx_succ_mcs_array_len *
827 sizeof(uint32_t);
828 ac->success_mcs = tx_succ_mcs;
829 ac->fail_mcs = tx_fail_mcs;
830 ac->fail_mcs_len = tx_fail_mcs_array_len *
831 sizeof(uint32_t);
832 ac->delay = tx_delay;
833 ac->delay_len = tx_delay_array_len *
834 sizeof(uint32_t);
835 peer_stats->ac_stats[k].tx_stats = ac;
836 peer_stats->ac_stats[k].type = k;
837 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
838 tx_succ_mcs += tx_succ_mcs_array_len;
839 tx_fail_mcs += tx_fail_mcs_array_len;
840 tx_delay += tx_delay_array_len;
841 }
842 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
843 } else {
844 /*
845 * Buffer for Peer TX counter overflow.
846 * There is peer ID mismatch between TX, RX,
847 * signal counters.
848 */
849 WMA_LOGE(FL("One peer TX info is dropped."));
850
851 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
852 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
853 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
854 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
855 }
856 }
857 *buf = result;
858 *buf_length = dst_len;
859}
860
861/**
862 * wma_fill_rx_stats() - Fix RX stats into result buffer
863 * @ll_stats: LL stats buffer
864 * @fix_param: parameters with fixed length in WMI event
865 * @param_buf: parameters without fixed length in WMI event
866 * @buf: buffer for TLV parameters
867 *
868 * Return: None
869 */
870static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
871 wmi_report_stats_event_fixed_param *fix_param,
872 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
873 uint8_t **buf, uint32_t *buf_length)
874{
875 uint8_t *result;
876 uint32_t i, j, k;
877 uint32_t *rx_mpdu_aggr, *rx_mcs;
878 wmi_rx_stats *wmi_rx;
879 wmi_peer_ac_rx_stats *wmi_peer_rx;
880 struct sir_wifi_rx *rx_stats;
881 struct sir_wifi_ll_ext_peer_stats *peer_stats;
882 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
883
884 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
885 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
886 rx_mcs_array_len = fix_param->rx_mcs_array_len;
887 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
888 wmi_peer_rx = param_buf->peer_ac_rx_stats;
889 wmi_rx = param_buf->rx_stats;
890
891 result = *buf;
892 dst_len = *buf_length;
893 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
894 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
895 if (len <= dst_len) {
896 rx_mpdu_aggr = (uint32_t *)result;
897 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
898 result += len;
899 dst_len -= len;
900 } else {
901 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
902 rx_mpdu_aggr = NULL;
903 }
904
905 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
906 WLAN_MAX_AC * rx_mcs_array_len);
907 if (len <= dst_len) {
908 rx_mcs = (uint32_t *)result;
909 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
910 result += len;
911 dst_len -= len;
912 } else {
913 WMA_LOGE(FL("RX_MCS array length is wrong."));
914 rx_mcs = NULL;
915 }
916
917 /* per peer rx stats */
918 peer_stats = ll_stats->peer_stats;
919 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
920 uint32_t peer_id = wmi_peer_rx[i].peer_id;
921 struct sir_wifi_rx *ac;
922 wmi_rx_stats *wmi_rx_stats;
923
924 for (j = 0; j < ll_stats->peer_num; j++) {
925 peer_stats += j;
926 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
927 (peer_stats->peer_id == peer_id))
928 break;
929 }
930
931 if (j < ll_stats->peer_num) {
932 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
933 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
934 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
935 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
936 peer_stats->rx_probe_reqs =
937 wmi_peer_rx[i].rx_probe_reqs;
938 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
939 rx_stats = (struct sir_wifi_rx *)result;
940
941 for (k = 0; k < WLAN_MAX_AC; k++) {
942 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
943 ac = &rx_stats[k];
944 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
945 ac->mpdu_aggr = rx_mpdu_aggr;
946 ac->aggr_len = rx_mpdu_aggr_array_len *
947 sizeof(uint32_t);
948 ac->mcs = rx_mcs;
949 ac->mcs_len = rx_mcs_array_len *
950 sizeof(uint32_t);
951 peer_stats->ac_stats[k].rx_stats = ac;
952 peer_stats->ac_stats[k].type = k;
953 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
954 rx_mcs += rx_mcs_array_len;
955 }
956 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
957 } else {
958 /*
959 * Buffer for Peer RX counter overflow.
960 * There is peer ID mismatch between TX, RX,
961 * signal counters.
962 */
963 WMA_LOGE(FL("One peer RX info is dropped."));
964 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
965 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
966 }
967 }
968 *buf = result;
969 *buf_length = dst_len;
970}
971
972/**
973 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
974 * @handle - wma handle
975 * @event - FW event
976 * @len - length of FW event
977 *
978 * return: 0 success.
979 */
980static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
981 u_int32_t len)
982{
983 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
984 wmi_report_stats_event_fixed_param *fixed_param;
985 tSirLLStatsResults *link_stats_results;
986 wmi_chan_cca_stats *wmi_cca_stats;
987 wmi_peer_signal_stats *wmi_peer_signal;
988 wmi_peer_ac_rx_stats *wmi_peer_rx;
989 struct sir_wifi_ll_ext_stats *ll_stats;
990 struct sir_wifi_ll_ext_peer_stats *peer_stats;
991 struct sir_wifi_chan_cca_stats *cca_stats;
992 struct sir_wifi_peer_signal_stats *peer_signal;
993 uint8_t *result;
994 uint32_t i, peer_num, result_size, dst_len;
995 tpAniSirGlobal mac;
996 struct scheduler_msg sme_msg = { 0 };
997 QDF_STATUS qdf_status;
998
999 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1000 if (!mac) {
1001 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1002 return -EINVAL;
1003 }
1004
1005 if (!mac->sme.link_layer_stats_ext_cb) {
1006 WMA_LOGD("%s: HDD callback is null", __func__);
1007 return -EINVAL;
1008 }
1009
1010 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1011
1012 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1013 fixed_param = param_buf->fixed_param;
1014 wmi_cca_stats = param_buf->chan_cca_stats;
1015 wmi_peer_signal = param_buf->peer_signal_stats;
1016 wmi_peer_rx = param_buf->peer_ac_rx_stats;
1017
1018 /* Get the MAX of three peer numbers */
1019 peer_num = fixed_param->num_peer_signal_stats >
1020 fixed_param->num_peer_ac_tx_stats ?
1021 fixed_param->num_peer_signal_stats :
1022 fixed_param->num_peer_ac_tx_stats;
1023 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1024 peer_num : fixed_param->num_peer_ac_rx_stats;
1025
1026 if (peer_num == 0)
1027 return -EINVAL;
1028
1029 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1030 peer_num,
1031 fixed_param);
1032 if (!link_stats_results) {
1033 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1034 return -EINVAL;
1035 }
1036 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1037 link_stats_results->num_peers = peer_num;
1038 link_stats_results->peer_event_number = 1;
1039 link_stats_results->moreResultToFollow = 0;
1040
1041 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1042 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1043 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1044 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1045 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1046 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1047 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1048 ll_stats->peer_num = peer_num;
1049
1050 result = (uint8_t *)ll_stats->stats;
1051 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1052 ll_stats->peer_stats = peer_stats;
1053
1054 for (i = 0; i < peer_num; i++) {
1055 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1056 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1057 }
1058
1059 /* Per peer signal */
1060 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1061 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1062 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1063 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1064 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1065 peer_signal = &peer_stats[i].peer_signal_stats;
1066
Zhang Qian303ebe92017-05-18 13:59:07 +08001067 WMA_LOGD("%d antennas for peer %d",
1068 wmi_peer_signal->num_chains_valid,
1069 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001070 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001071 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1072 peer_signal->peer_id = wmi_peer_signal->peer_id;
1073 peer_signal->num_chain =
1074 wmi_peer_signal->num_chains_valid;
1075 qdf_mem_copy(peer_signal->per_ant_snr,
1076 wmi_peer_signal->per_chain_snr,
1077 sizeof(peer_signal->per_ant_snr));
1078 qdf_mem_copy(peer_signal->nf,
1079 wmi_peer_signal->per_chain_nf,
1080 sizeof(peer_signal->nf));
1081 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1082 wmi_peer_signal->per_antenna_rx_mpdus,
1083 sizeof(peer_signal->per_ant_rx_mpdus));
1084 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1085 wmi_peer_signal->per_antenna_tx_mpdus,
1086 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001087 result_size -= dst_len;
1088 } else {
1089 WMA_LOGE(FL("Invalid length of PEER signal."));
1090 }
1091 wmi_peer_signal++;
1092 }
1093
1094 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1095 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1096 ll_stats->cca = cca_stats;
1097 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1098 for (i = 0; i < ll_stats->channel_num; i++) {
1099 if (dst_len <= result_size) {
1100 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1101 dst_len);
1102 result_size -= dst_len;
1103 } else {
1104 WMA_LOGE(FL("Invalid length of CCA."));
1105 }
1106 }
1107
1108 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1109 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1110 &result, &result_size);
1111 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1112 &result, &result_size);
1113 sme_msg.type = eWMI_SME_LL_STATS_IND;
1114 sme_msg.bodyptr = (void *)link_stats_results;
1115 sme_msg.bodyval = 0;
1116 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1117 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1118 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1119 qdf_mem_free(link_stats_results);
1120 return -EINVAL;
1121 }
1122
1123 return 0;
1124}
1125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126/**
1127 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1128 * @handle: wma handle
1129 * @cmd_param_info: data received with event from fw
1130 * @len: length of data
1131 *
1132 * Return: 0 for success or error code
1133 */
1134static int wma_unified_link_peer_stats_event_handler(void *handle,
1135 uint8_t *cmd_param_info,
1136 uint32_t len)
1137{
1138 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1139 wmi_peer_stats_event_fixed_param *fixed_param;
1140 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1141 wmi_rate_stats *rate_stats;
1142 tSirLLStatsResults *link_stats_results;
1143 uint8_t *results, *t_peer_stats, *t_rate_stats;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301144 uint32_t count, num_rates = 0, rate_cnt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1146 size_t peer_info_size, peer_stats_size, rate_stats_size;
1147 size_t link_stats_results_size;
1148
Anurag Chouhan6d760662016-02-20 16:05:43 +05301149 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150
1151 if (!pMac) {
1152 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1153 return -EINVAL;
1154 }
1155
1156 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1157 WMA_LOGD("%s: HDD callback is null", __func__);
1158 return -EINVAL;
1159 }
1160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1162 if (!param_tlvs) {
1163 WMA_LOGA("%s: Invalid stats event", __func__);
1164 return -EINVAL;
1165 }
1166 /*
1167 * cmd_param_info contains
1168 * wmi_peer_stats_event_fixed_param fixed_param;
1169 * num_peers * size of(struct wmi_peer_link_stats)
1170 * num_rates * size of(struct wmi_rate_stats)
1171 * num_rates is the sum of the rates of all the peers.
1172 */
1173 fixed_param = param_tlvs->fixed_param;
1174 peer_stats = param_tlvs->peer_stats;
1175 rate_stats = param_tlvs->peer_rate_stats;
1176
1177 if (!fixed_param || !peer_stats ||
1178 (peer_stats->num_rates && !rate_stats)) {
1179 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1180 return -EINVAL;
1181 }
1182
1183 /*
1184 * num_rates - sum of the rates of all the peers
1185 */
1186 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1187 for (count = 0; count < fixed_param->num_peers; count++) {
1188 num_rates += temp_peer_stats->num_rates;
1189 temp_peer_stats++;
1190 }
1191
1192 peer_stats_size = sizeof(tSirWifiPeerStat);
1193 peer_info_size = sizeof(tSirWifiPeerInfo);
1194 rate_stats_size = sizeof(tSirWifiRateStat);
1195 link_stats_results_size =
1196 sizeof(*link_stats_results) + peer_stats_size +
1197 (fixed_param->num_peers * peer_info_size) +
1198 (num_rates * rate_stats_size);
1199
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301200 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201 if (NULL == link_stats_results) {
1202 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1203 __func__, link_stats_results_size);
1204 return -ENOMEM;
1205 }
1206
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301207 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208
1209 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1210 link_stats_results->rspId = fixed_param->request_id;
1211 link_stats_results->ifaceId = 0;
1212 link_stats_results->num_peers = fixed_param->num_peers;
1213 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1214 link_stats_results->moreResultToFollow = fixed_param->more_data;
1215
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301216 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 &fixed_param->num_peers, peer_stats_size);
1218
1219 results = (uint8_t *) link_stats_results->results;
1220 t_peer_stats = (uint8_t *) peer_stats;
1221 t_rate_stats = (uint8_t *) rate_stats;
1222 next_res_offset = peer_stats_size;
1223 next_peer_offset = WMI_TLV_HDR_SIZE;
1224 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301225 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301226 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 t_peer_stats + next_peer_offset, peer_info_size);
1228 next_res_offset += peer_info_size;
1229
1230 /* Copy rate stats associated with this peer */
1231 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 rate_stats++;
1233
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301234 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 t_rate_stats + next_rate_offset,
1236 rate_stats_size);
1237 next_res_offset += rate_stats_size;
1238 next_rate_offset += sizeof(*rate_stats);
1239 }
1240 next_peer_offset += sizeof(*peer_stats);
1241 peer_stats++;
1242 }
1243
1244 /* call hdd callback with Link Layer Statistics
1245 * vdev_id/ifacId in link_stats_results will be
1246 * used to retrieve the correct HDD context
1247 */
1248 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1249 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1250 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252
1253 return 0;
1254}
1255
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001256/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001257 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1258 * @handle: WMI handle
1259 *
1260 * Return: 0 on success, error number otherwise.
1261 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301262int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001263{
1264 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1265 tSirWifiRadioStat *rs_results;
1266 uint32_t i = 0;
1267
1268 if (!wma_handle->link_stats_results)
1269 return 0;
1270
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001271 rs_results = (tSirWifiRadioStat *)
1272 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001273 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1274 rs_results += i;
1275 if (rs_results->tx_time_per_power_level) {
1276 qdf_mem_free(rs_results->tx_time_per_power_level);
1277 rs_results->tx_time_per_power_level = NULL;
1278 }
1279
1280 if (rs_results->channels) {
1281 qdf_mem_free(rs_results->channels);
1282 rs_results->channels = NULL;
1283 }
1284 }
1285
1286 qdf_mem_free(wma_handle->link_stats_results);
1287 wma_handle->link_stats_results = NULL;
1288
1289 return 0;
1290}
1291
1292/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001293 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1294 * @handle: WMI handle
1295 * @cmd_param_info: command param info
1296 * @len: Length of @cmd_param_info
1297 *
1298 * This is the WMI event handler function to receive radio stats tx
1299 * power level stats.
1300 *
1301 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001302 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001303static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1304 u_int8_t *cmd_param_info, u_int32_t len)
1305{
1306 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1307 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1308 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1309 uint8_t *tx_power_level_values;
1310 tSirLLStatsResults *link_stats_results;
1311 tSirWifiRadioStat *rs_results;
1312
1313 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1314
1315 if (!mac) {
1316 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1317 return -EINVAL;
1318 }
1319
1320 if (!mac->sme.pLinkLayerStatsIndCallback) {
1321 WMA_LOGD("%s: HDD callback is null", __func__);
1322 return -EINVAL;
1323 }
1324
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001325 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1326 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001327 if (!param_tlvs) {
1328 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1329 return -EINVAL;
1330 }
1331
1332 fixed_param = param_tlvs->fixed_param;
1333 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001334 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1335 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001336 return -EINVAL;
1337 }
1338
1339 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001340 if (!link_stats_results) {
1341 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1342 return -EINVAL;
1343 }
1344
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001345 WMA_LOGD("%s: tot_num_tx_pwr_lvls: %u num_tx_pwr_lvls: %u pwr_lvl_offset: %u radio_id: %u",
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001346 __func__, fixed_param->total_num_tx_power_levels,
1347 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001348 fixed_param->power_level_offset,
1349 fixed_param->radio_id);
1350
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001351 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1352 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001353 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001354
1355 rs_results->total_num_tx_power_levels =
1356 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001357 if (!rs_results->total_num_tx_power_levels) {
1358 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001359 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001360 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001361
1362 if (!rs_results->tx_time_per_power_level) {
1363 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1364 sizeof(uint32_t) *
1365 rs_results->total_num_tx_power_levels);
1366 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001367 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1368 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001369 /* In error case, atleast send the radio stats without
1370 * tx_power_level stats */
1371 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001372 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001373 goto post_stats;
1374 }
1375 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001376 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1377 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001378 tx_power_level_values,
1379 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1380 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001381 (fixed_param->num_tx_power_levels +
1382 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001383 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001384 link_stats_results->nr_received++;
1385 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001386
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001387 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1388 __func__, link_stats_results->moreResultToFollow,
1389 link_stats_results->num_radio,
1390 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001391
1392 /* If still data to receive, return from here */
1393 if (link_stats_results->moreResultToFollow)
1394 return 0;
1395
1396post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001397 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1398 /* Not received all radio stats yet, don't post yet */
1399 return 0;
1400 }
1401
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001402 /* call hdd callback with Link Layer Statistics
1403 * vdev_id/ifacId in link_stats_results will be
1404 * used to retrieve the correct HDD context
1405 */
1406 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
1407 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1408 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001409 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001410
1411 return 0;
1412}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001413
1414/**
1415 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1416 * @handle: wma handle
1417 * @cmd_param_info: data received with event from fw
1418 * @len: length of data
1419 *
1420 * Return: 0 for success or error code
1421 */
1422static int wma_unified_link_radio_stats_event_handler(void *handle,
1423 uint8_t *cmd_param_info,
1424 uint32_t len)
1425{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001426 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1428 wmi_radio_link_stats_event_fixed_param *fixed_param;
1429 wmi_radio_link_stats *radio_stats;
1430 wmi_channel_stats *channel_stats;
1431 tSirLLStatsResults *link_stats_results;
1432 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001433 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 size_t radio_stats_size, chan_stats_size;
1435 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001436 tSirWifiRadioStat *rs_results;
1437 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438
Anurag Chouhan6d760662016-02-20 16:05:43 +05301439 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440
1441 if (!pMac) {
1442 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1443 return -EINVAL;
1444 }
1445
1446 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1447 WMA_LOGD("%s: HDD callback is null", __func__);
1448 return -EINVAL;
1449 }
1450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1452 if (!param_tlvs) {
1453 WMA_LOGA("%s: Invalid stats event", __func__);
1454 return -EINVAL;
1455 }
1456
1457 /*
1458 * cmd_param_info contains
1459 * wmi_radio_link_stats_event_fixed_param fixed_param;
1460 * size of(struct wmi_radio_link_stats);
1461 * num_channels * size of(struct wmi_channel_stats)
1462 */
1463 fixed_param = param_tlvs->fixed_param;
1464 radio_stats = param_tlvs->radio_stats;
1465 channel_stats = param_tlvs->channel_stats;
1466
1467 if (!fixed_param || !radio_stats ||
1468 (radio_stats->num_channels && !channel_stats)) {
1469 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1470 return -EINVAL;
1471 }
1472
1473 radio_stats_size = sizeof(tSirWifiRadioStat);
1474 chan_stats_size = sizeof(tSirWifiChannelStats);
1475 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001476 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001478 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001479 wma_handle->link_stats_results = qdf_mem_malloc(
1480 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001481 if (NULL == wma_handle->link_stats_results) {
1482 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1483 __func__, link_stats_results_size);
1484 return -ENOMEM;
1485 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001486 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001487 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001489 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001490 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491 fixed_param->request_id, fixed_param->num_radio,
1492 fixed_param->more_radio_events);
1493
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001494 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1495 radio_stats->radio_id, radio_stats->on_time,
1496 radio_stats->tx_time, radio_stats->rx_time,
1497 radio_stats->on_time_scan);
1498 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1499 radio_stats->on_time_nbd,
1500 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1501 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1502 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1503 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001504 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1505 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1508 link_stats_results->rspId = fixed_param->request_id;
1509 link_stats_results->ifaceId = 0;
1510 link_stats_results->num_radio = fixed_param->num_radio;
1511 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001512
1513 /*
1514 * Backward compatibility:
1515 * There are firmware(s) which will send Radio stats only with
1516 * more_radio_events set to 0 and firmware which sends Radio stats
1517 * followed by tx_power level stats with more_radio_events set to 1.
1518 * if more_radio_events is set to 1, buffer the radio stats and
1519 * wait for tx_power_level stats.
1520 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1522
1523 results = (uint8_t *) link_stats_results->results;
1524 t_radio_stats = (uint8_t *) radio_stats;
1525 t_channel_stats = (uint8_t *) channel_stats;
1526
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001527 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001528 rs_results->radio = radio_stats->radio_id;
1529 rs_results->onTime = radio_stats->on_time;
1530 rs_results->txTime = radio_stats->tx_time;
1531 rs_results->rxTime = radio_stats->rx_time;
1532 rs_results->onTimeScan = radio_stats->on_time_scan;
1533 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1534 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1535 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1536 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1537 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1538 rs_results->total_num_tx_power_levels = 0;
1539 rs_results->tx_time_per_power_level = NULL;
1540 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001541 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1542 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001543 rs_results->channels = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001545 if (rs_results->numChannels) {
1546 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1547 radio_stats->num_channels *
1548 chan_stats_size);
1549 if (rs_results->channels == NULL) {
1550 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1551 __func__, radio_stats->num_channels * chan_stats_size);
1552 wma_unified_radio_tx_mem_free(handle);
1553 return -ENOMEM;
1554 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001556 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1557 next_chan_offset = WMI_TLV_HDR_SIZE;
1558 WMA_LOGD("Channel Stats Info");
1559 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001560 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001561 channel_stats->channel_width,
1562 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001563 channel_stats->center_freq0);
1564 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001565 channel_stats->center_freq1,
1566 channel_stats->radio_awake_time,
1567 channel_stats->cca_busy_time);
1568 channel_stats++;
1569
1570 qdf_mem_copy(chn_results,
1571 t_channel_stats + next_chan_offset,
1572 chan_stats_size);
1573 chn_results++;
1574 next_chan_offset += sizeof(*channel_stats);
1575 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001576 }
1577
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001578 if (link_stats_results->moreResultToFollow) {
1579 /* More results coming, don't post yet */
1580 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001581 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001582 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001583
1584 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1585 /* Not received all radio stats yet, don't post yet */
1586 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001587 }
1588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1590 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1591 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001592 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593
1594 return 0;
1595}
1596
Zhang Qiana6e9c102016-12-22 16:47:24 +08001597#ifdef WLAN_PEER_PS_NOTIFICATION
1598/**
1599 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1600 * @handle: wma handle
1601 * @event: FW event
1602 * @len: length of FW event
1603 *
1604 * Once peer STA power state changes, an event will be indicated by
1605 * FW. This function send a link layer state change msg to HDD. HDD
1606 * link layer callback will converts the event to NL msg.
1607 *
1608 * Return: 0 Success. Others fail.
1609 */
1610static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1611 u_int32_t len)
1612{
1613 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1614 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1615 tSirWifiPeerStat *peer_stat;
1616 tSirWifiPeerInfo *peer_info;
1617 tSirLLStatsResults *link_stats_results;
1618 tSirMacAddr mac_address;
1619 uint32_t result_len;
1620 cds_msg_t sme_msg = { 0 };
1621 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1622
1623 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1624
1625 if (!mac) {
1626 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1627 return -EINVAL;
1628 }
1629
1630 if (!mac->sme.link_layer_stats_ext_cb) {
1631 WMA_LOGD("%s: HDD callback is null", __func__);
1632 return -EINVAL;
1633 }
1634
1635 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1636
1637 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1638 fixed_param = param_buf->fixed_param;
1639
1640 result_len = sizeof(tSirLLStatsResults) +
1641 sizeof(tSirWifiPeerStat) +
1642 sizeof(tSirWifiPeerInfo);
1643 link_stats_results = qdf_mem_malloc(result_len);
1644 if (link_stats_results == NULL) {
1645 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1646 return -EINVAL;
1647 }
1648
1649 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1650 WMA_LOGD("Peer power state change event from FW");
1651 WMA_LOGD("Fixed Param:");
1652 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1653 mac_address[0], mac_address[1], mac_address[2],
1654 mac_address[3], mac_address[4], mac_address[5],
1655 fixed_param->peer_ps_state);
1656
1657 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1658 link_stats_results->num_peers = 1;
1659 link_stats_results->peer_event_number = 1;
1660 link_stats_results->moreResultToFollow = 0;
1661
1662 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1663 peer_stat->numPeers = 1;
1664 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1665 qdf_mem_copy(&peer_info->peerMacAddress,
1666 &mac_address,
1667 sizeof(tSirMacAddr));
1668 peer_info->power_saving = fixed_param->peer_ps_state;
1669
1670 sme_msg.type = eWMI_SME_LL_STATS_IND;
1671 sme_msg.bodyptr = link_stats_results;
1672 sme_msg.bodyval = 0;
1673
Zhang Qian73c348a2017-03-13 16:15:55 +08001674 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001675 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1676 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1677 qdf_mem_free(link_stats_results);
1678 }
1679
1680 return 0;
1681}
1682#else
1683/**
1684 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1685 * @handle: wma handle
1686 * @event: FW event
1687 * @len: length of FW event
1688 *
1689 * Once peer STA power state changes, an event will be indicated by
1690 * FW. This function send a link layer state change msg to HDD. HDD
1691 * link layer callback will converts the event to NL msg.
1692 *
1693 * Return: 0 Success. Others fail.
1694 */
1695static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1696 u_int32_t len)
1697{
1698 return 0;
1699}
1700#endif
1701
1702/**
1703 * wma_tx_failure_cb() - TX failure callback
1704 * @ctx: txrx context
1705 * @num_msdu: number of msdu with the same status
1706 * @tid: TID number
1707 * @status: failure status
1708 */
1709void wma_tx_failure_cb(void *ctx, uint32_t num_msdu,
1710 uint8_t tid, enum htt_tx_status status)
1711{
1712 tSirLLStatsResults *results;
1713 struct sir_wifi_iface_tx_fail *tx_fail;
1714 struct scheduler_msg sme_msg = { 0 };
1715 QDF_STATUS qdf_status;
1716 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1717
1718 if (!mac) {
1719 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1720 return;
1721 }
1722
1723 if (!mac->sme.link_layer_stats_ext_cb) {
1724 WMA_LOGD("%s: HDD callback is null", __func__);
1725 return;
1726 }
1727
1728 results = qdf_mem_malloc(sizeof(tSirLLStatsResults) +
1729 sizeof(struct sir_wifi_iface_tx_fail));
1730 if (results == NULL) {
1731 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1732 return;
1733 }
1734
1735 results->paramId = WMI_LL_STATS_EXT_TX_FAIL;
1736 results->num_peers = 1;
1737 results->peer_event_number = 1;
1738 results->moreResultToFollow = 0;
1739
1740 tx_fail = (struct sir_wifi_iface_tx_fail *)results->results;
1741 tx_fail->tid = tid;
1742 tx_fail->msdu_num = num_msdu;
1743 tx_fail->status = status;
1744
1745 sme_msg.type = eWMI_SME_LL_STATS_IND;
1746 sme_msg.bodyptr = results;
1747 sme_msg.bodyval = 0;
1748
1749 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1750 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1751 WMA_LOGE("%s: Fail to post TX failure ind msg", __func__);
1752 qdf_mem_free(results);
1753 }
1754}
1755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756/**
1757 * wma_register_ll_stats_event_handler() - register link layer stats related
1758 * event handler
1759 * @wma_handle: wma handle
1760 *
1761 * Return: none
1762 */
1763void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1764{
1765 if (NULL == wma_handle) {
1766 WMA_LOGE("%s: wma_handle is NULL", __func__);
1767 return;
1768 }
1769
1770 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301771 WMI_IFACE_LINK_STATS_EVENTID,
1772 wma_unified_link_iface_stats_event_handler,
1773 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301775 WMI_PEER_LINK_STATS_EVENTID,
1776 wma_unified_link_peer_stats_event_handler,
1777 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301779 WMI_RADIO_LINK_STATS_EVENTID,
1780 wma_unified_link_radio_stats_event_handler,
1781 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001782 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1783 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID,
1784 wma_unified_radio_tx_power_level_stats_event_handler,
1785 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001786 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1787 WMI_PEER_STA_PS_STATECHG_EVENTID,
1788 wma_peer_ps_evt_handler,
1789 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001790 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1791 WMI_REPORT_STATS_EVENTID,
1792 wma_ll_stats_evt_handler,
1793 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795}
1796
1797
1798/**
1799 * wma_process_ll_stats_clear_req() - clear link layer stats
1800 * @wma: wma handle
1801 * @clearReq: ll stats clear request command params
1802 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301803 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001805QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1806 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807{
Govind Singh4863da42016-03-08 11:45:00 +05301808 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 int ret;
1810
1811 if (!clearReq || !wma) {
1812 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301813 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001814 }
1815
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001816 if (!wma->interfaces[clearReq->staId].handle) {
1817 WMA_LOGE("%s: vdev_id %d handle is NULL",
1818 __func__, clearReq->staId);
1819 return QDF_STATUS_E_FAILURE;
1820 }
1821
Govind Singh4863da42016-03-08 11:45:00 +05301822 cmd.stop_req = clearReq->stopReq;
1823 cmd.sta_id = clearReq->staId;
1824 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825
Govind Singh4863da42016-03-08 11:45:00 +05301826 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1827 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828 if (ret) {
1829 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301830 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 }
1832
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301833 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001834}
1835
1836/**
1837 * wma_process_ll_stats_set_req() - link layer stats set request
1838 * @wma: wma handle
1839 * @setReq: ll stats set request command params
1840 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301841 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001843QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1844 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845{
Govind Singh4863da42016-03-08 11:45:00 +05301846 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 int ret;
1848
1849 if (!setReq || !wma) {
1850 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301851 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852 }
1853
Govind Singh4863da42016-03-08 11:45:00 +05301854 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1855 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 setReq->aggressiveStatisticsGathering;
1857
Govind Singh4863da42016-03-08 11:45:00 +05301858 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
1859 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 if (ret) {
1861 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301862 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001863 }
1864
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301865 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866}
1867
1868/**
1869 * wma_process_ll_stats_get_req() - link layer stats get request
1870 * @wma:wma handle
1871 * @getReq:ll stats get request command params
1872 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301873 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001875QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
1876 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877{
Govind Singh4863da42016-03-08 11:45:00 +05301878 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 int ret;
1880
1881 if (!getReq || !wma) {
1882 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301883 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 }
1885
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05301886 if (!wma->interfaces[getReq->staId].vdev_active) {
1887 WMA_LOGE("%s: vdev not created yet", __func__);
1888 return QDF_STATUS_E_FAILURE;
1889 }
1890
Govind Singh4863da42016-03-08 11:45:00 +05301891 cmd.req_id = getReq->reqId;
1892 cmd.param_id_mask = getReq->paramIdMask;
1893 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894
Govind Singh4863da42016-03-08 11:45:00 +05301895 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
1896 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 if (ret) {
1898 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301899 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 }
1901
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301902 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903}
1904
1905/**
1906 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
1907 * @wma:wma handle
1908 * @cmd_param_info: data from event
1909 * @len: length
1910 *
1911 * Return: 0 for success or error code
1912 */
1913int wma_unified_link_iface_stats_event_handler(void *handle,
1914 uint8_t *cmd_param_info,
1915 uint32_t len)
1916{
1917 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1918 wmi_iface_link_stats_event_fixed_param *fixed_param;
1919 wmi_iface_link_stats *link_stats;
1920 wmi_wmm_ac_stats *ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001921 wmi_iface_offload_stats *offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 tSirLLStatsResults *link_stats_results;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001923 uint8_t *results, *t_link_stats, *t_ac_stats, *t_offload_stats;
1924 uint32_t next_res_offset, next_ac_offset, next_offload_offset, count;
1925 uint32_t roaming_offset, size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001927 size_t link_stats_results_size, offload_stats_size;
1928 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929
Anurag Chouhan6d760662016-02-20 16:05:43 +05301930 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931
1932 if (!pMac) {
1933 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1934 return -EINVAL;
1935 }
1936
1937 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1938 WMA_LOGD("%s: HDD callback is null", __func__);
1939 return -EINVAL;
1940 }
1941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1943 if (!param_tlvs) {
1944 WMA_LOGA("%s: Invalid stats event", __func__);
1945 return -EINVAL;
1946 }
1947
1948 /*
1949 * cmd_param_info contains
1950 * wmi_iface_link_stats_event_fixed_param fixed_param;
1951 * wmi_iface_link_stats iface_link_stats;
1952 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001953 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 */
1955 fixed_param = param_tlvs->fixed_param;
1956 link_stats = param_tlvs->iface_link_stats;
1957 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001958 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001960 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
1961 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
1963 return -EINVAL;
1964 }
1965
1966 link_stats_size = sizeof(tSirWifiIfaceStat);
1967 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001968
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 ac_stats_size = sizeof(tSirWifiWmmAcStat);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001970 offload_stats_size = sizeof(struct wifi_iface_offload_stat);
1971
1972 total_ac_size = ac_stats_size * WIFI_AC_MAX;
1973 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
1974 member_size(tSirWifiIfaceStat, num_offload_stats);
1975
1976 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301978 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 if (!link_stats_results) {
1980 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1981 __func__, link_stats_results_size);
1982 return -ENOMEM;
1983 }
1984
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301985 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986
1987 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
1988 link_stats_results->rspId = fixed_param->request_id;
1989 link_stats_results->ifaceId = fixed_param->vdev_id;
1990 link_stats_results->num_peers = link_stats->num_peers;
1991 link_stats_results->peer_event_number = 0;
1992 link_stats_results->moreResultToFollow = 0;
1993
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001994 /* results is copied to tSirWifiIfaceStat in upper layer
1995 * tSirWifiIfaceStat
1996 * - tSirWifiInterfaceInfo (all fields except roaming is
1997 * filled by host in the upper layer)
1998 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
1999 * - ACs information (from wmi_wmm_ac_stats)
2000 * - num_offload_stats (from fixed param)
2001 * - offload stats (from wmi_iface_offload_stats)
2002 */
2003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004 results = (uint8_t *) link_stats_results->results;
2005 t_link_stats = (uint8_t *) link_stats;
2006 t_ac_stats = (uint8_t *) ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002007 t_offload_stats = (uint8_t *) offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008
2009 /* Copy roaming state */
2010 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002011 size = member_size(tSirWifiInterfaceInfo, roaming);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002013 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002015 next_res_offset = iface_info_size;
2016 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 t_link_stats + WMI_TLV_HDR_SIZE,
2018 link_stats_size - iface_info_size -
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002019 total_ac_size - total_offload_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002021 next_res_offset = link_stats_size - total_ac_size - total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 next_ac_offset = WMI_TLV_HDR_SIZE;
2023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 ac_stats++;
2026
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302027 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 t_ac_stats + next_ac_offset, ac_stats_size);
2029 next_res_offset += ac_stats_size;
2030 next_ac_offset += sizeof(*ac_stats);
2031 }
2032
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002033 next_res_offset = link_stats_size - total_offload_size;
2034 /* copy num_offload_stats into result */
2035 size = member_size(tSirWifiIfaceStat, num_offload_stats);
2036 qdf_mem_copy(results + next_res_offset, &fixed_param->num_offload_stats,
2037 size);
2038
2039 next_res_offset += size;
2040 next_offload_offset = WMI_TLV_HDR_SIZE;
2041
2042 for (count = 0; count < fixed_param->num_offload_stats; count++) {
2043 qdf_mem_copy(results + next_res_offset,
2044 t_offload_stats + next_offload_offset,
2045 offload_stats_size);
2046 next_res_offset += offload_stats_size;
2047 next_offload_offset += sizeof(*offload_stats);
2048 }
2049
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 /* call hdd callback with Link Layer Statistics
2051 * vdev_id/ifacId in link_stats_results will be
2052 * used to retrieve the correct HDD context
2053 */
2054 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
2055 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2056 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302057 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058
2059 return 0;
2060}
2061
Zhang Qian73c348a2017-03-13 16:15:55 +08002062/**
2063 * wma_config_stats_ext_threshold - set threthold for MAC counters
2064 * @wma: wma handler
2065 * @threshold: threhold for MAC counters
2066 *
2067 * For each MAC layer counter, FW holds two copies. One is the current value.
2068 * The other is the last report. Once a current counter's increment is larger
2069 * than the threshold, FW will indicate that counter to host even if the
2070 * monitoring timer does not expire.
2071 *
2072 * Return: None
2073 */
2074void wma_config_stats_ext_threshold(tp_wma_handle wma,
2075 struct sir_ll_ext_stats_threshold *thresh)
2076{
2077 uint32_t len, tag, hdr_len;
2078 uint8_t *buf_ptr;
2079 wmi_buf_t buf;
2080 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2081 wmi_chan_cca_stats_thresh *cca;
2082 wmi_peer_signal_stats_thresh *signal;
2083 wmi_tx_stats_thresh *tx;
2084 wmi_rx_stats_thresh *rx;
2085
2086 if (!thresh) {
2087 WMA_LOGE(FL("Invalid threshold input."));
2088 return;
2089 }
2090
2091 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2092 sizeof(wmi_chan_cca_stats_thresh) +
2093 sizeof(wmi_peer_signal_stats_thresh) +
2094 sizeof(wmi_tx_stats_thresh) +
2095 sizeof(wmi_rx_stats_thresh) +
2096 5 * WMI_TLV_HDR_SIZE;
2097 buf = wmi_buf_alloc(wma->wmi_handle, len);
2098 if (!buf) {
2099 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2100 return;
2101 }
2102
2103 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2104 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2105 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2106 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2107 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2108 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2109 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2110 cmd->enable_thresh = thresh->enable;
2111 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2112 cmd->gbl_thresh = thresh->global_threshold;
2113 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2114 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2115 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2116 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2117 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2118
2119 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2120 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2121 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2122 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2123 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2124 cca->idle_time = thresh->cca.idle_time;
2125 cca->tx_time = thresh->cca.tx_time;
2126 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2127 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2128 cca->rx_busy_time = thresh->cca.rx_busy_time;
2129 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2130 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2131 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2132 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2133 cca->idle_time, cca->tx_time,
2134 cca->rx_in_bss_time, cca->rx_out_bss_time);
2135 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2136 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2137 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2138 len += sizeof(wmi_chan_cca_stats_thresh);
2139
2140 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2141 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2142 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2143 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2144 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2145 signal->per_chain_snr = thresh->signal.snr;
2146 signal->per_chain_nf = thresh->signal.nf;
2147 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2148 signal->per_chain_nf);
2149 len += sizeof(wmi_peer_signal_stats_thresh);
2150
2151 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2152 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2153 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2154 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2155 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2156 tx->tx_msdu_cnt = thresh->tx.msdu;
2157 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2158 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2159 tx->tx_bytes = thresh->tx.bytes;
2160 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2161 tx->tx_drop_bytes = thresh->tx.byte_drop;
2162 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2163 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2164 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2165 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2166 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2167 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2168 tx->tx_ppdu_delay = thresh->tx.delay;
2169 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2170 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2171 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2172 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2173 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2174 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2175 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2176 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2177 tx->tx_ppdu_delay);
2178 len += sizeof(wmi_tx_stats_thresh);
2179
2180 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2181 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2182 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2183 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2184 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2185 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2186 rx->mac_rx_bytes = thresh->rx.bytes;
2187 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2188 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2189 rx->rx_disorder_cnt = thresh->rx.disorder;
2190 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2191 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2192 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2193 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2194 rx->rx_mcs = thresh->rx.mcs;
2195 rx->sta_ps_inds = thresh->rx.ps_inds;
2196 rx->sta_ps_durs = thresh->rx.ps_durs;
2197 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2198 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2199 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2200 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2201 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2202 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2203 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2204 rx->rx_mpdu_aggr, rx->rx_mcs);
2205 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2206 rx->sta_ps_inds, rx->sta_ps_durs,
2207 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2208 len += sizeof(wmi_rx_stats_thresh);
2209
2210 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2211 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2212 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2213 buf, len,
2214 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2215 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2216 wmi_buf_free(buf);
2217 }
2218}
2219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2221
2222/**
2223 * wma_update_pdev_stats() - update pdev stats
2224 * @wma: wma handle
2225 * @pdev_stats: pdev stats
2226 *
2227 * Return: none
2228 */
2229static void wma_update_pdev_stats(tp_wma_handle wma,
2230 wmi_pdev_stats *pdev_stats)
2231{
2232 tAniGetPEStatsRsp *stats_rsp_params;
2233 uint32_t temp_mask;
2234 uint8_t *stats_buf;
2235 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2236 struct wma_txrx_node *node;
2237 uint8_t i;
2238
2239 for (i = 0; i < wma->max_bssid; i++) {
2240 node = &wma->interfaces[i];
2241 stats_rsp_params = node->stats_rsp;
2242 if (stats_rsp_params) {
2243 node->fw_stats_set |= FW_PDEV_STATS_SET;
2244 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2245 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2246 temp_mask = stats_rsp_params->statsMask;
2247 if (temp_mask & (1 << eCsrSummaryStats))
2248 stats_buf += sizeof(tCsrSummaryStatsInfo);
2249
2250 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2251 classa_stats =
2252 (tCsrGlobalClassAStatsInfo *) stats_buf;
2253 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2254 }
2255 }
2256 }
2257}
2258
2259/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302260 * wma_vdev_stats_lost_link_helper() - helper function to extract
2261 * lost link information from vdev statistics event while deleting BSS.
2262 * @wma: WMA handle
2263 * @vdev_stats: statistics information from firmware
2264 *
2265 * This is for informing HDD to collect lost link information while
2266 * disconnection. Following conditions to check
2267 * 1. vdev is up
2268 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2269 * zero, hence add the check here to indicate the event comes during deleting
2270 * BSS
2271 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2272 * last one as it consumes more resource searching entries in the list
2273 *
2274 * Return: none
2275 */
2276static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2277 wmi_vdev_stats *vdev_stats)
2278{
2279 struct wma_txrx_node *node;
2280 int32_t rssi;
2281 struct wma_target_req *req_msg;
2282 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002283 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302284
2285 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302286 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302287 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302288 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2289 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2290 if ((NULL == req_msg) ||
2291 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2292 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2293 return;
2294 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002295 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2296 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302297 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002298 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302299
2300 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002301 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302302 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002303 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302304 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302305 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302306
2307 /* Get the absolute rssi value from the current rssi value */
2308 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2309 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2310 }
2311}
2312
2313/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314 * wma_update_vdev_stats() - update vdev stats
2315 * @wma: wma handle
2316 * @vdev_stats: vdev stats
2317 *
2318 * Return: none
2319 */
2320static void wma_update_vdev_stats(tp_wma_handle wma,
2321 wmi_vdev_stats *vdev_stats)
2322{
2323 tAniGetPEStatsRsp *stats_rsp_params;
2324 tCsrSummaryStatsInfo *summary_stats = NULL;
2325 uint8_t *stats_buf;
2326 struct wma_txrx_node *node;
2327 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002328 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302329 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002331 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002332 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002334 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2335 dat_snr = vdev_stats->vdev_snr.dat_snr;
2336 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2337 vdev_stats->vdev_id, bcn_snr, dat_snr);
2338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 node = &wma->interfaces[vdev_stats->vdev_id];
2340 stats_rsp_params = node->stats_rsp;
2341 if (stats_rsp_params) {
2342 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2343 node->fw_stats_set |= FW_VDEV_STATS_SET;
2344 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2345 vdev_stats->vdev_id);
2346 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2347 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2348 for (i = 0; i < 4; i++) {
2349 summary_stats->tx_frm_cnt[i] =
2350 vdev_stats->tx_frm_cnt[i];
2351 summary_stats->fail_cnt[i] =
2352 vdev_stats->fail_cnt[i];
2353 summary_stats->multiple_retry_cnt[i] =
2354 vdev_stats->multiple_retry_cnt[i];
2355 }
2356
2357 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2358 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2359 summary_stats->rx_discard_cnt =
2360 vdev_stats->rx_discard_cnt;
2361 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2362 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2363 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002364 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302365 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002366 summary_stats->snr = bcn_snr;
2367 summary_stats->rssi =
2368 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302369 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002370 summary_stats->snr = dat_snr;
2371 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002372 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002373 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302374 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002375 summary_stats->rssi = 0;
2376 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 }
2378 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379
2380 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302381 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2382 rssi = bcn_snr;
2383 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2384 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2385 rssi = dat_snr;
2386 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2387 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 /*
2389 * Firmware sends invalid snr till it sees
2390 * Beacon/Data after connection since after
2391 * vdev up fw resets the snr to invalid.
2392 * In this duartion Host will return the last know
2393 * rssi during connection.
2394 */
2395 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 }
2397
2398 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2399 pGetRssiReq->sessionId);
2400
2401 /* update the average rssi value to UMAC layer */
2402 if (NULL != pGetRssiReq->rssiCallback) {
2403 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2404 pGetRssiReq->staId,
2405 pGetRssiReq->pDevContext);
2406 }
2407
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302408 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 wma->pGetRssiReq = NULL;
2410 }
2411
2412 if (node->psnr_req) {
2413 tAniGetSnrReq *p_snr_req = node->psnr_req;
2414
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302415 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002416 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302417 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002418 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002419 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302420 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421
2422 sme_msg.type = eWNI_SME_SNR_IND;
2423 sme_msg.bodyptr = p_snr_req;
2424 sme_msg.bodyval = 0;
2425
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002426 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302427 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302429 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 }
2431
2432 node->psnr_req = NULL;
2433 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302434 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435}
2436
2437/**
2438 * wma_post_stats() - update stats to PE
2439 * @wma: wma handle
2440 * @node: txrx node
2441 *
2442 * Return: none
2443 */
2444static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2445{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002447 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 node->stats_rsp = NULL;
2449 node->fw_stats_set = 0;
2450}
2451
2452/**
2453 * wma_update_peer_stats() - update peer stats
2454 * @wma: wma handle
2455 * @peer_stats: peer stats
2456 *
2457 * Return: none
2458 */
2459static void wma_update_peer_stats(tp_wma_handle wma,
2460 wmi_peer_stats *peer_stats)
2461{
2462 tAniGetPEStatsRsp *stats_rsp_params;
2463 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2464 struct wma_txrx_node *node;
2465 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2466 uint32_t temp_mask;
2467
2468 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2469 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2470 return;
2471
2472 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002473 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2474 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 node->fw_stats_set |= FW_PEER_STATS_SET;
2476 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2478 temp_mask = stats_rsp_params->statsMask;
2479 if (temp_mask & (1 << eCsrSummaryStats))
2480 stats_buf += sizeof(tCsrSummaryStatsInfo);
2481
2482 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2483 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2484 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002485 /* The linkspeed returned by fw is in kbps so convert
2486 * it in to units of 500kbps which is expected by UMAC
2487 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 if (peer_stats->peer_tx_rate) {
2489 classa_stats->tx_rate =
2490 peer_stats->peer_tx_rate / 500;
2491 }
2492
2493 classa_stats->tx_rate_flags = node->rate_flags;
2494 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
2495 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002496 wma_get_mcs_idx(
2497 (peer_stats->peer_tx_rate /
2498 100), node->rate_flags,
2499 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002500 classa_stats->nss = node->nss;
2501 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 }
2503 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002504 * Convert it back to intervals of 1 dBm
2505 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 classa_stats->max_pwr =
2507 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 }
2510}
2511
2512/**
2513 * wma_post_link_status() - post link status to SME
2514 * @pGetLinkStatus: SME Link status
2515 * @link_status: Link status
2516 *
2517 * Return: none
2518 */
2519void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2520 uint8_t link_status)
2521{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302522 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002523 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524
2525 pGetLinkStatus->linkStatus = link_status;
2526 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2527 sme_msg.bodyptr = pGetLinkStatus;
2528 sme_msg.bodyval = 0;
2529
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002530 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302531 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302533 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 }
2535}
2536
2537/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302538 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2539 * @wma: wma handle
2540 * @rssi_stats: rssi stats
2541 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2542 *
2543 * This function stores per chain rssi stats received from fw for all vdevs for
2544 * which the stats were requested into a csr stats structure.
2545 *
2546 * Return: void
2547 */
2548static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2549 wmi_rssi_stats *rssi_stats,
2550 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2551{
2552 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002553 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302554
2555 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2556 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2557 dat_snr = rssi_stats->rssi_avg_data[i];
2558 WMA_LOGD("chain %d beacon snr %d data snr %d",
2559 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302560 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302561 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302562 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2563 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302564 else
2565 /*
2566 * Firmware sends invalid snr till it sees
2567 * Beacon/Data after connection since after
2568 * vdev up fw resets the snr to invalid.
2569 * In this duartion Host will return an invalid rssi
2570 * value.
2571 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302572 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302573
2574 /*
2575 * Get the absolute rssi value from the current rssi value the
2576 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2577 */
2578 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2579 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2580 rssi_per_chain_stats->peer_mac_addr);
2581 }
2582}
2583
2584/**
2585 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2586 * for which the stats were requested.
2587 * @wma: wma handle
2588 * @rssi_stats: rssi stats
2589 *
2590 * This function updates the rssi stats for all vdevs for which
2591 * the stats were requested.
2592 *
2593 * Return: void
2594 */
2595static void wma_update_rssi_stats(tp_wma_handle wma,
2596 wmi_rssi_stats *rssi_stats)
2597{
2598 tAniGetPEStatsRsp *stats_rsp_params;
2599 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2600 struct wma_txrx_node *node;
2601 uint8_t *stats_buf;
2602 uint32_t temp_mask;
2603 uint8_t vdev_id;
2604
2605 vdev_id = rssi_stats->vdev_id;
2606 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002607 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2608 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302609 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2610 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2611 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302612 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2613 temp_mask = stats_rsp_params->statsMask;
2614
2615 if (temp_mask & (1 << eCsrSummaryStats))
2616 stats_buf += sizeof(tCsrSummaryStatsInfo);
2617 if (temp_mask & (1 << eCsrGlobalClassAStats))
2618 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302619 if (temp_mask & (1 << eCsrGlobalClassDStats))
2620 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302621
2622 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2623 rssi_per_chain_stats =
2624 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2625 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2626 rssi_per_chain_stats);
2627 }
2628 }
2629}
2630
2631
2632/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633 * wma_link_status_event_handler() - link status event handler
2634 * @handle: wma handle
2635 * @cmd_param_info: data from event
2636 * @len: length
2637 *
2638 * Return: 0 for success or error code
2639 */
2640int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2641 uint32_t len)
2642{
2643 tp_wma_handle wma = (tp_wma_handle) handle;
2644 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2645 wmi_vdev_rate_stats_event_fixed_param *event;
2646 wmi_vdev_rate_ht_info *ht_info;
2647 struct wma_txrx_node *intr = wma->interfaces;
2648 uint8_t link_status = LINK_STATUS_LEGACY;
2649 int i;
2650
2651 param_buf =
2652 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2653 if (!param_buf) {
2654 WMA_LOGA("%s: Invalid stats event", __func__);
2655 return -EINVAL;
2656 }
2657
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002658 event = (wmi_vdev_rate_stats_event_fixed_param *)
2659 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2661
2662 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
2663 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2664 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2665 __func__, ht_info->vdevid, ht_info->tx_nss,
2666 ht_info->rx_nss, ht_info->tx_preamble,
2667 ht_info->rx_preamble);
2668 if (ht_info->vdevid < wma->max_bssid
2669 && intr[ht_info->vdevid].plink_status_req) {
2670 if (ht_info->tx_nss || ht_info->rx_nss)
2671 link_status = LINK_STATUS_MIMO;
2672
2673 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2674 (ht_info->rx_preamble == LINK_RATE_VHT))
2675 link_status |= LINK_STATUS_VHT;
2676
2677 if (intr[ht_info->vdevid].nss == 2)
2678 link_status |= LINK_SUPPORT_MIMO;
2679
2680 if (intr[ht_info->vdevid].rate_flags &
2681 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
2682 eHAL_TX_RATE_VHT80))
2683 link_status |= LINK_SUPPORT_VHT;
2684
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002685 wma_post_link_status(
2686 intr[ht_info->vdevid].plink_status_req,
2687 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 intr[ht_info->vdevid].plink_status_req = NULL;
2689 link_status = LINK_STATUS_LEGACY;
2690 }
2691
2692 ht_info++;
2693 }
2694
2695 return 0;
2696}
2697
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302698int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2699{
2700 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002701 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302702 QDF_STATUS qdf_status;
2703
2704 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2705 if (!rso_status) {
2706 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2707 return -ENOMEM;
2708 }
2709
2710 rso_status->vdev_id = wmi_event->vdev_id;
2711 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2712 rso_status->status = true;
2713 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2714 rso_status->status = false;
2715 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2716 sme_msg.bodyptr = rso_status;
2717 sme_msg.bodyval = 0;
2718 WMA_LOGI("%s: Post RSO cmd status to SME", __func__);
2719
2720 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2721 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2722 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2723 qdf_mem_free(rso_status);
2724 }
2725 return 0;
2726}
2727
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728/**
Will Huanga9814592017-05-24 15:47:58 +08002729 * wma_handle_sta_peer_info() - handle peer information in
2730 * peer stats
2731 * @num_peer_stats: peer number
2732 * @peer_stats: peer stats received from firmware
2733 * @peer_macaddr: the specified mac address
2734 * @sapaddr: sap mac address
2735 *
2736 * This function will send eWNI_SME_GET_PEER_INFO_IND
2737 * to sme with stations' information
2738 *
2739 */
2740static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2741 wmi_peer_stats *peer_stats,
2742 struct qdf_mac_addr peer_macaddr,
2743 uint8_t *sapaddr)
2744{
2745 QDF_STATUS qdf_status;
2746 wmi_mac_addr temp_addr;
2747 struct sir_peer_info_resp *peer_info;
2748 struct scheduler_msg sme_msg = {0};
2749 uint32_t i;
2750 uint32_t j = 0;
2751
2752 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2753 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2754 for (i = 0; i < num_peer_stats; i++) {
2755 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2756 ((peer_stats->peer_macaddr.mac_addr47to32) &
2757 0x0000ffff))
2758 && (temp_addr.mac_addr31to0 ==
2759 peer_stats->peer_macaddr.mac_addr31to0)) {
2760
2761 break;
2762 }
2763 peer_stats = peer_stats + 1;
2764 }
2765 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2766 sizeof(peer_info->info[0]));
2767 if (NULL == peer_info) {
2768 WMA_LOGE("%s: Memory allocation failed.", __func__);
2769 return;
2770 }
2771 if (i < num_peer_stats) {
2772 peer_info->count = 1;
2773 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2774 peer_info->info[0].peer_macaddr.bytes);
2775 peer_info->info[0].rssi = peer_stats->peer_rssi;
2776 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2777 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2778 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2779 __func__,
2780 peer_info->info[0].peer_macaddr.bytes,
2781 peer_stats->peer_rssi,
2782 peer_stats->peer_tx_rate,
2783 peer_stats->peer_rx_rate);
2784 } else {
2785 WMA_LOGE("%s: no match mac address", __func__);
2786 peer_info->count = 0;
2787 }
2788 } else {
2789 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2790 num_peer_stats * sizeof(peer_info->info[0]));
2791 if (NULL == peer_info) {
2792 WMA_LOGE("%s: Memory allocation failed.", __func__);
2793 return;
2794 }
2795 peer_info->count = num_peer_stats;
2796
2797 for (i = 0; i < num_peer_stats; i++) {
2798 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2799 peer_info->info[j].peer_macaddr.bytes);
2800 peer_info->info[j].rssi = peer_stats->peer_rssi;
2801 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2802 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2803 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2804 __func__,
2805 peer_info->info[j].peer_macaddr.bytes,
2806 peer_stats->peer_rssi,
2807 peer_stats->peer_tx_rate,
2808 peer_stats->peer_rx_rate);
2809 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2810 sapaddr, QDF_MAC_ADDR_SIZE)) {
2811 peer_info->count = peer_info->count - 1;
2812 } else {
2813 j++;
2814 }
2815 peer_stats = peer_stats + 1;
2816 }
2817 WMA_LOGD("WDA send peer num %d", peer_info->count);
2818 }
2819
2820 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
2821 sme_msg.bodyptr = peer_info;
2822 sme_msg.bodyval = 0;
2823
2824 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2825 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2826 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
2827 qdf_mem_free(peer_info);
2828 }
2829
2830 return;
2831}
2832
2833/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 * wma_stats_event_handler() - stats event handler
2835 * @handle: wma handle
2836 * @cmd_param_info: data from event
2837 * @len: length
2838 *
2839 * Return: 0 for success or error code
2840 */
2841int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
2842 uint32_t len)
2843{
2844 tp_wma_handle wma = (tp_wma_handle) handle;
2845 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
2846 wmi_stats_event_fixed_param *event;
2847 wmi_pdev_stats *pdev_stats;
2848 wmi_vdev_stats *vdev_stats;
2849 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302850 wmi_rssi_stats *rssi_stats;
2851 wmi_per_chain_rssi_stats *rssi_event;
2852 struct wma_txrx_node *node;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002853 uint8_t i, *temp;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05302854 wmi_congestion_stats *congestion_stats;
2855 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2858 if (!param_buf) {
2859 WMA_LOGA("%s: Invalid stats event", __func__);
2860 return -EINVAL;
2861 }
2862 event = param_buf->fixed_param;
2863 temp = (uint8_t *) param_buf->data;
2864
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865 if (event->num_pdev_stats > 0) {
2866 for (i = 0; i < event->num_pdev_stats; i++) {
2867 pdev_stats = (wmi_pdev_stats *) temp;
2868 wma_update_pdev_stats(wma, pdev_stats);
2869 temp += sizeof(wmi_pdev_stats);
2870 }
2871 }
2872
2873 if (event->num_vdev_stats > 0) {
2874 for (i = 0; i < event->num_vdev_stats; i++) {
2875 vdev_stats = (wmi_vdev_stats *) temp;
2876 wma_update_vdev_stats(wma, vdev_stats);
2877 temp += sizeof(wmi_vdev_stats);
2878 }
2879 }
2880
2881 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08002882 if (wma->get_sta_peer_info == true) {
2883 wma_handle_sta_peer_info(event->num_peer_stats,
2884 (wmi_peer_stats *)temp,
2885 wma->peer_macaddr,
2886 wma->myaddr);
2887 } else {
2888 for (i = 0; i < event->num_peer_stats; i++) {
2889 peer_stats = (wmi_peer_stats *) temp;
2890 wma_update_peer_stats(wma, peer_stats);
2891 temp += sizeof(wmi_peer_stats);
2892 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 }
2894 }
2895
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302896 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
2897 if (rssi_event) {
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05302898 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
2899 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
2900 ((rssi_event->tlv_header & 0x0000FFFF) ==
2901 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302902 if (rssi_event->num_per_chain_rssi_stats > 0) {
2903 temp = (uint8_t *) rssi_event;
2904 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08002905
2906 /* skip past struct array tlv header */
2907 temp += WMI_TLV_HDR_SIZE;
2908
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302909 for (i = 0;
2910 i < rssi_event->num_per_chain_rssi_stats;
2911 i++) {
2912 rssi_stats = (wmi_rssi_stats *)temp;
2913 wma_update_rssi_stats(wma, rssi_stats);
2914 temp += sizeof(wmi_rssi_stats);
2915 }
2916 }
2917 }
2918 }
2919
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05302920 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
2921 if (congestion_stats) {
2922 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
2923 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
2924 ((congestion_stats->tlv_header & 0x0000FFFF) ==
2925 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
2926 mac = cds_get_context(QDF_MODULE_ID_PE);
2927 if (!mac) {
2928 WMA_LOGE("%s: Invalid mac", __func__);
2929 return -EINVAL;
2930 }
2931 if (!mac->sme.congestion_cb) {
2932 WMA_LOGE("%s: Callback not registered",
2933 __func__);
2934 return -EINVAL;
2935 }
2936 WMA_LOGI("%s: congestion %d", __func__,
2937 congestion_stats->congestion);
2938 mac->sme.congestion_cb(mac->hHdd,
2939 congestion_stats->congestion,
2940 congestion_stats->vdev_id);
2941 }
2942 }
2943
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302944 for (i = 0; i < wma->max_bssid; i++) {
2945 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002946 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302947 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302948 }
2949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 return 0;
2951}
2952
2953/**
Will Huanga9814592017-05-24 15:47:58 +08002954 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
2955 * @wma: wma interface
2956 * @stats_info: WMI peer info pointer
2957 * @peer_info: SIR peer info pointer
2958 *
2959 * This function will fill SIR peer info from WMI peer info struct
2960 *
2961 * Return: None
2962 */
2963static void wma_fill_peer_info(tp_wma_handle wma,
2964 wmi_peer_stats_info *stats_info,
2965 struct sir_peer_info_ext *peer_info)
2966{
2967 peer_info->tx_packets = stats_info->tx_packets.low_32;
2968 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
2969 peer_info->tx_bytes <<= 32;
2970 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
2971 peer_info->rx_packets = stats_info->rx_packets.low_32;
2972 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
2973 peer_info->rx_bytes <<= 32;
2974 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
2975 peer_info->tx_retries = stats_info->tx_retries;
2976 peer_info->tx_failed = stats_info->tx_failed;
2977 peer_info->rssi = stats_info->peer_rssi;
2978 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
2979 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
2980 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
2981 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
2982}
2983
2984/**
2985 * wma_peer_info_ext_rsp() - process peer ext info ext
2986 * @handle: wma interface
2987 * @buf: wmi event buf pointer
2988 *
2989 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
2990 *
2991 * Return: 0 on success, error code otherwise
2992 */
2993static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
2994{
2995 wmi_peer_stats_info_event_fixed_param *event;
2996 wmi_peer_stats_info *stats_info;
2997 struct sir_peer_info_ext_resp *resp;
2998 struct sir_peer_info_ext *peer_info;
2999 struct scheduler_msg sme_msg = {0};
3000 int i, j = 0;
3001 QDF_STATUS qdf_status;
3002
3003 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3004 stats_info = (wmi_peer_stats_info *)(buf +
3005 sizeof(wmi_peer_stats_info_event_fixed_param));
3006
3007 if (wma->get_one_peer_info) {
3008 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3009 sizeof(resp->info[0]));
3010 if (!resp) {
3011 WMA_LOGE(FL("resp allocation failed."));
3012 return QDF_STATUS_E_NOMEM;
3013 }
3014 resp->count = 0;
3015 peer_info = &resp->info[0];
3016 for (i = 0; i < event->num_peers; i++) {
3017 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3018 peer_info->peer_macaddr.bytes);
3019
3020 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3021 wma->peer_macaddr.bytes,
3022 QDF_MAC_ADDR_SIZE)) {
3023 wma_fill_peer_info(wma, stats_info, peer_info);
3024 resp->count++;
3025 break;
3026 }
3027
3028 stats_info = stats_info + 1;
3029 }
3030 } else {
3031 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3032 event->num_peers * sizeof(resp->info[0]));
3033 if (!resp) {
3034 WMA_LOGE(FL("resp allocation failed."));
3035 return QDF_STATUS_E_NOMEM;
3036 }
3037 resp->count = event->num_peers;
3038 for (i = 0; i < event->num_peers; i++) {
3039 peer_info = &resp->info[j];
3040 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3041 peer_info->peer_macaddr.bytes);
3042
3043 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3044 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3045 resp->count = resp->count - 1;
3046 } else {
3047 wma_fill_peer_info(wma, stats_info, peer_info);
3048 j++;
3049 }
3050 stats_info = stats_info + 1;
3051 }
3052 }
3053
3054 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3055 sme_msg.bodyptr = resp;
3056 sme_msg.bodyval = 0;
3057
3058 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3059 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3060 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3061 qdf_mem_free(resp);
3062 }
3063
3064 return qdf_status;
3065}
3066
3067/**
3068 * dump_peer_stats_info() - dump wmi peer info struct
3069 * @event: wmi peer info fixed param pointer
3070 * @peer_stats: wmi peer stats info pointer
3071 *
3072 * This function will dump wmi peer info struct
3073 *
3074 * Return: None
3075 */
3076static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3077 wmi_peer_stats_info *peer_stats)
3078{
3079 int i;
3080 wmi_peer_stats_info *stats = peer_stats;
3081 u_int8_t mac[6];
3082
3083 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3084 __func__, event->vdev_id,
3085 event->num_peers, event->more_data);
3086
3087 for (i = 0; i < event->num_peers; i++) {
3088 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3089 WMA_LOGI("%s mac %pM", __func__, mac);
3090 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3091 __func__,
3092 stats->tx_bytes.low_32,
3093 stats->tx_bytes.high_32,
3094 stats->tx_packets.low_32,
3095 stats->tx_packets.high_32);
3096 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3097 __func__,
3098 stats->rx_bytes.low_32,
3099 stats->rx_bytes.high_32,
3100 stats->rx_packets.low_32,
3101 stats->rx_packets.high_32);
3102 WMA_LOGI("%s tx_retries %d tx_failed %d",
3103 __func__, stats->tx_retries, stats->tx_failed);
3104 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3105 __func__,
3106 stats->last_tx_rate_code,
3107 stats->last_rx_rate_code);
3108 WMA_LOGI("%s tx_rate %x rx_rate %x",
3109 __func__,
3110 stats->last_tx_bitrate_kbps,
3111 stats->last_rx_bitrate_kbps);
3112 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3113 stats++;
3114 }
3115}
3116
3117int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3118 u_int32_t len)
3119{
3120 tp_wma_handle wma = (tp_wma_handle) handle;
3121 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3122 wmi_peer_stats_info_event_fixed_param *event;
3123 u_int32_t buf_size;
3124 u_int8_t *buf;
3125
3126 param_buf =
3127 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3128 if (!param_buf) {
3129 WMA_LOGA("%s: Invalid stats event", __func__);
3130 return -EINVAL;
3131 }
3132
3133 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3134 event = param_buf->fixed_param;
3135 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3136 sizeof(wmi_peer_stats_info) * event->num_peers;
3137 buf = qdf_mem_malloc(buf_size);
3138 if (!buf) {
3139 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3140 return -ENOMEM;
3141 }
3142
3143 qdf_mem_copy(buf, param_buf->fixed_param,
3144 sizeof(wmi_peer_stats_info_event_fixed_param));
3145 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3146 param_buf->peer_stats_info,
3147 sizeof(wmi_peer_stats_info) * event->num_peers);
3148 WMA_LOGI("%s dump peer stats info", __func__);
3149 dump_peer_stats_info(event, param_buf->peer_stats_info);
3150
3151 wma_peer_info_ext_rsp(wma, buf);
3152 qdf_mem_free(buf);
3153
3154 return 0;
3155}
3156
3157/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 * wma_send_link_speed() - send link speed to SME
3159 * @link_speed: link speed
3160 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303161 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303166 tpAniSirGlobal mac_ctx;
3167 tSirLinkSpeedInfo *ls_ind;
3168
3169 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3170 if (!mac_ctx) {
3171 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3172 return QDF_STATUS_E_INVAL;
3173 }
3174
3175 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 if (!ls_ind) {
3177 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303178 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 } else {
3180 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303181 if (mac_ctx->sme.pLinkSpeedIndCb)
3182 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3183 mac_ctx->sme.pLinkSpeedCbContext);
3184 else
3185 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3186 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303189 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190}
3191
3192/**
3193 * wma_link_speed_event_handler() - link speed event handler
3194 * @handle: wma handle
3195 * @cmd_param_info: event data
3196 * @len: length
3197 *
3198 * Return: 0 for success or error code
3199 */
3200int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3201 uint32_t len)
3202{
3203 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3204 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303205 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003207 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3208 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 if (!param_buf) {
3210 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3211 return -EINVAL;
3212 }
3213 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303214 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003215 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 return 0;
3218}
3219
3220/**
3221 * wma_wni_cfg_dnld() - cfg download request
3222 * @handle: wma handle
3223 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303226QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303229 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230
3231 WMA_LOGD("%s: Enter", __func__);
3232
3233 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003234 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303235 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 }
3238
3239 process_cfg_download_req(mac);
3240
3241 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303242 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243}
3244
3245/**
3246 * wma_unified_debug_print_event_handler() - debug print event handler
3247 * @handle: wma handle
3248 * @datap: data pointer
3249 * @len: length
3250 *
3251 * Return: 0 for success or error code
3252 */
3253int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3254 uint32_t len)
3255{
3256 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3257 uint8_t *data;
3258 uint32_t datalen;
3259
3260 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
3261 if (!param_buf) {
3262 WMA_LOGE("Get NULL point message from FW");
3263 return -ENOMEM;
3264 }
3265 data = param_buf->data;
3266 datalen = param_buf->num_data;
3267
3268#ifdef BIG_ENDIAN_HOST
3269 {
3270 char dbgbuf[500] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 memcpy(dbgbuf, data, datalen);
3273 SWAPME(dbgbuf, datalen);
3274 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3275 return 0;
3276 }
3277#else
3278 WMA_LOGD("FIRMWARE:%s", data);
3279 return 0;
3280#endif /* BIG_ENDIAN_HOST */
3281}
3282
3283/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 * wma_is_sap_active() - check sap is active or not
3285 * @handle: wma handle
3286 *
3287 * Return: true/false
3288 */
3289bool wma_is_sap_active(tp_wma_handle wma_handle)
3290{
3291 int i;
3292
3293 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303294 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 continue;
3296 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3297 wma_handle->interfaces[i].sub_type == 0)
3298 return true;
3299 }
3300 return false;
3301}
3302
3303/**
3304 * wma_is_p2p_go_active() - check p2p go is active or not
3305 * @handle: wma handle
3306 *
3307 * Return: true/false
3308 */
3309bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3310{
3311 int i;
3312
3313 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303314 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003315 continue;
3316 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3317 wma_handle->interfaces[i].sub_type ==
3318 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3319 return true;
3320 }
3321 return false;
3322}
3323
3324/**
3325 * wma_is_p2p_cli_active() - check p2p cli is active or not
3326 * @handle: wma handle
3327 *
3328 * Return: true/false
3329 */
3330bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3331{
3332 int i;
3333
3334 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303335 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336 continue;
3337 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3338 wma_handle->interfaces[i].sub_type ==
3339 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3340 return true;
3341 }
3342 return false;
3343}
3344
3345/**
3346 * wma_is_sta_active() - check sta is active or not
3347 * @handle: wma handle
3348 *
3349 * Return: true/false
3350 */
3351bool wma_is_sta_active(tp_wma_handle wma_handle)
3352{
3353 int i;
3354
3355 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303356 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 continue;
3358 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3359 wma_handle->interfaces[i].sub_type == 0)
3360 return true;
3361 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3362 return true;
3363 }
3364 return false;
3365}
3366
3367/**
3368 * wma_peer_phymode() - get phymode
3369 * @nw_type: nw type
3370 * @sta_type: sta type
3371 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003372 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003374 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375 *
3376 * Return: WLAN_PHY_MODE
3377 */
3378WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3379 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003380 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381{
3382 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3383
3384 switch (nw_type) {
3385 case eSIR_11B_NW_TYPE:
3386 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003387 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 WMA_LOGE("HT/VHT is enabled with 11B NW type");
3389 break;
3390 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003391 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392 phymode = MODE_11G;
3393 break;
3394 }
3395 if (CH_WIDTH_40MHZ < ch_width)
3396 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3397 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003398 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3399 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003401 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3402 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403 break;
3404 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003405 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406 phymode = MODE_11A;
3407 break;
3408 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003409 if (is_he) {
3410 if (ch_width == CH_WIDTH_160MHZ)
3411 phymode = MODE_11AX_HE160;
3412 else if (ch_width == CH_WIDTH_80P80MHZ)
3413 phymode = MODE_11AX_HE80_80;
3414 else if (ch_width == CH_WIDTH_80MHZ)
3415 phymode = MODE_11AX_HE80;
3416 else
3417 phymode = (ch_width) ?
3418 MODE_11AX_HE40 : MODE_11AX_HE20;
3419 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 if (ch_width == CH_WIDTH_160MHZ)
3421 phymode = MODE_11AC_VHT160;
3422 else if (ch_width == CH_WIDTH_80P80MHZ)
3423 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003424 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 phymode = MODE_11AC_VHT80;
3426 else
3427 phymode = (ch_width) ?
3428 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3429 } else
3430 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3431 break;
3432 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003433 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 break;
3435 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003436 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3437 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438
3439 return phymode;
3440}
3441
3442/**
3443 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3444 * @wma_handle: wma handle
3445 * @vdev_id: vdev id
3446 * @value: value
3447 *
3448 * Return: 0 for success or return error
3449 */
3450int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3451 uint8_t vdev_id, uint32_t value)
3452{
3453 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003454 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303455 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3456
3457 if (!soc) {
3458 WMA_LOGE("%s:SOC context is NULL", __func__);
3459 return -EINVAL;
3460 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461
3462 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3463 if (!vdev) {
3464 WMA_LOGE("%s:Invalid vdev handle", __func__);
3465 return -EINVAL;
3466 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303467 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003469 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470
3471 return 0;
3472}
3473
3474#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003475#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 ((_mask) = 1 << (_rate_info ## _V2))
3477#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003478#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 ((_mask) = 1 << (_rate_info))
3480#endif
3481
Nirav Shah93e789e2016-04-14 19:47:43 +05303482#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003483static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303484{
3485 if (value > (HTT_DBG_NUM_STATS + 1) ||
3486 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3487 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3488 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3489 WMA_LOGE("%s: Not supported", __func__);
3490 return false;
3491 }
3492 return true;
3493}
3494#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003495static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303496{
3497 if (value > (HTT_DBG_NUM_STATS + 1) ||
3498 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3499 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3500 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3501 WMA_LOGE("%s: Not supported", __func__);
3502 return false;
3503 }
3504 return true;
3505}
3506#endif
3507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508/**
3509 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3510 * @wma_handle: wma handle
3511 * @vdev_id: vdev id
3512 * @value: value
3513 *
3514 * Return: 0 for success or return error
3515 */
3516int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3517 uint8_t vdev_id, uint32_t value)
3518{
3519 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003520 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003521 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303522 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3523
3524 if (!soc) {
3525 WMA_LOGE("%s:SOC context is NULL", __func__);
3526 return -EINVAL;
3527 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528
3529 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3530 if (!vdev) {
3531 WMA_LOGE("%s:Invalid vdev handle", __func__);
3532 return -EINVAL;
3533 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303534
3535 if (wma_is_valid_fw_stats_cmd(value) == false)
3536 return -EINVAL;
3537
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303538 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 req.print.verbose = 1;
3540
Nirav Shah93e789e2016-04-14 19:47:43 +05303541 /* TODO: Need to check how to avoid mem leak*/
3542 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 req.stats_type_upload_mask = l_up_mask;
3544
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003545 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546
3547 return 0;
3548}
3549
3550/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 * wma_get_stats_rsp_buf() - fill get stats response buffer
3552 * @get_stats_param: get stats parameters
3553 *
3554 * Return: stats response buffer
3555 */
3556static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3557 (tAniGetPEStatsReq *get_stats_param)
3558{
3559 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003560 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
3562 len = sizeof(tAniGetPEStatsRsp);
3563 temp_mask = get_stats_param->statsMask;
3564
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003565 if (temp_mask & (1 << eCsrSummaryStats))
3566 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003568 if (temp_mask & (1 << eCsrGlobalClassAStats))
3569 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003571 if (temp_mask & (1 << eCsrGlobalClassDStats))
3572 len += sizeof(tCsrGlobalClassDStatsInfo);
3573
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003574 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3575 len += sizeof(struct csr_per_chain_rssi_stats_info);
3576
3577 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 if (!stats_rsp_params) {
3579 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303580 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581 return NULL;
3582 }
3583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 stats_rsp_params->staId = get_stats_param->staId;
3585 stats_rsp_params->statsMask = get_stats_param->statsMask;
3586 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3587 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303588 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 return stats_rsp_params;
3590}
3591
3592/**
3593 * wma_get_stats_req() - get stats request
3594 * @handle: wma handle
3595 * @get_stats_param: stats params
3596 *
3597 * Return: none
3598 */
3599void wma_get_stats_req(WMA_HANDLE handle,
3600 tAniGetPEStatsReq *get_stats_param)
3601{
3602 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3603 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05303604 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607
3608 WMA_LOGD("%s: Enter", __func__);
3609 node = &wma_handle->interfaces[get_stats_param->sessionId];
3610 if (node->stats_rsp) {
3611 pGetPEStatsRspParams = node->stats_rsp;
3612 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3613 pGetPEStatsRspParams->statsMask ==
3614 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003615 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 get_stats_param->staId,
3617 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303618 pGetPEStatsRspParams =
3619 wma_get_stats_rsp_buf(get_stats_param);
3620 if (!pGetPEStatsRspParams) {
3621 WMA_LOGE("failed to allocate memory for stats response");
3622 goto end;
3623 }
3624 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303626 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 node->stats_rsp = NULL;
3628 node->fw_stats_set = 0;
3629 }
3630 }
3631
3632 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3633 if (!pGetPEStatsRspParams)
3634 goto end;
3635
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003637 if (node->stats_rsp) {
3638 WMA_LOGD(FL("stats_rsp is not null, prev_value: %p"),
3639 node->stats_rsp);
3640 qdf_mem_free(node->stats_rsp);
3641 node->stats_rsp = NULL;
3642 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003644 wma_handle->get_sta_peer_info = false;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003645 WMA_LOGD("stats_rsp allocated: %p, sta_id: %d, mask: %d, vdev_id: %d",
3646 node->stats_rsp, node->stats_rsp->staId,
3647 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303648
3649 cmd.session_id = get_stats_param->sessionId;
Dustin Brown12a96022017-07-12 10:34:50 -07003650 cmd.stats_mask = get_stats_param->statsMask;
Govind Singh4863da42016-03-08 11:45:00 +05303651 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
3652 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653
3654 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3655 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 goto failed;
3657 }
3658
3659 goto end;
3660failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303661 node->stats_rsp = NULL;
3662req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303663 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 /* send response to UMAC */
3665 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3666 0);
3667end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303668 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670}
3671
3672/**
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303673 * wma_get_cca_stats() - send request to fw to get CCA
3674 * @wma_handle: wma handle
3675 * @vdev_id: vdev id
3676 *
3677 * Return: QDF status
3678 */
3679QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3680 uint8_t vdev_id)
3681{
3682 if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3683 vdev_id)) {
3684 WMA_LOGE("Failed to congestion request to fw");
3685 return QDF_STATUS_E_FAILURE;
3686 }
3687 return QDF_STATUS_SUCCESS;
3688}
3689
3690/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3692 * @vdev_id: vdev id
3693 * @buffer_size: size of buffer
3694 *
3695 * Return: none
3696 */
3697void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3698{
3699 tp_wma_handle wma;
3700 struct beacon_info *beacon;
3701 uint8_t *buf;
3702 uint32_t buf_size;
3703
Anurag Chouhan6d760662016-02-20 16:05:43 +05303704 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 if (!wma) {
3706 WMA_LOGE("%s: Invalid WMA handle", __func__);
3707 return NULL;
3708 }
3709
3710 if (vdev_id >= wma->max_bssid) {
3711 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3712 return NULL;
3713 }
3714
3715 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
3716 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
3717 return NULL;
3718 }
3719
3720 beacon = wma->interfaces[vdev_id].beacon;
3721
3722 if (!beacon) {
3723 WMA_LOGE("%s: beacon invalid", __func__);
3724 return NULL;
3725 }
3726
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303727 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003728
Nirav Shahcbc6d722016-03-01 16:24:53 +05303729 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303730 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731
3732 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303733 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
3735 return NULL;
3736 }
3737
Nirav Shahcbc6d722016-03-01 16:24:53 +05303738 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303740 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741
3742 if (buffer_size)
3743 *buffer_size = buf_size;
3744
3745 return buf;
3746}
3747
3748/**
3749 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
3750 * @vdev_id: vdev id
3751 *
3752 * Return: mac address
3753 */
3754uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
3755{
3756 tp_wma_handle wma;
3757
Anurag Chouhan6d760662016-02-20 16:05:43 +05303758 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759 if (!wma) {
3760 WMA_LOGE("%s: Invalid WMA handle", __func__);
3761 return NULL;
3762 }
3763
3764 if (vdev_id >= wma->max_bssid) {
3765 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3766 return NULL;
3767 }
3768
3769 return wma->interfaces[vdev_id].addr;
3770}
3771
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003772QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
3773 struct policy_mgr_vdev_entry_info *conn_table_entry)
3774{
3775 struct wma_txrx_node *wma_conn_table_entry;
3776
3777 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
3778 if (NULL == wma_conn_table_entry) {
3779 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
3780 return QDF_STATUS_E_FAILURE;
3781 }
3782 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
3783 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
3784 conn_table_entry->mhz = wma_conn_table_entry->mhz;
3785 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
3786 conn_table_entry->type = wma_conn_table_entry->type;
3787
3788 return QDF_STATUS_SUCCESS;
3789}
3790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791/**
3792 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
3793 * @vdev_id: vdev id
3794 *
3795 * Return: entry from vdev table
3796 */
3797struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
3798{
3799 tp_wma_handle wma;
3800
Anurag Chouhan6d760662016-02-20 16:05:43 +05303801 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003802 if (!wma) {
3803 WMA_LOGE("%s: Invalid WMA handle", __func__);
3804 return NULL;
3805 }
3806
3807 if (vdev_id >= wma->max_bssid) {
3808 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3809 return NULL;
3810 }
3811
3812 return &wma->interfaces[vdev_id];
3813}
3814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815#if defined(QCA_WIFI_FTM)
3816/**
3817 * wma_utf_rsp() - utf response
3818 * @wma_handle: wma handle
3819 * @payload: payload
3820 * @len: length of payload
3821 *
3822 * Return: 0 for success or error code
3823 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003824static int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload,
3825 uint32_t *len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826{
3827 int ret = -1;
3828 uint32_t payload_len;
3829
3830 payload_len = wma_handle->utf_event_info.length;
3831 if (payload_len) {
3832 ret = 0;
3833
3834 /*
3835 * The first 4 bytes holds the payload size
3836 * and the actual payload sits next to it
3837 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303838 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 + sizeof(A_UINT32));
3840 *(A_UINT32 *) &(*payload[0]) =
3841 wma_handle->utf_event_info.length;
3842 memcpy(*payload + sizeof(A_UINT32),
3843 wma_handle->utf_event_info.data, payload_len);
3844 wma_handle->utf_event_info.length = 0;
3845 *len = payload_len;
3846 }
3847
3848 return ret;
3849}
3850
3851/**
3852 * wma_post_ftm_response() - post ftm response to upper layer
3853 * @wma_handle: wma handle
3854 *
3855 * Return: none
3856 */
3857static void wma_post_ftm_response(tp_wma_handle wma_handle)
3858{
3859 int ret;
3860 uint8_t *payload;
3861 uint32_t data_len;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08003862 struct scheduler_msg msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303863 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864
3865 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
3866
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003867 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869
3870 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
3871 msg.bodyptr = payload;
3872 msg.bodyval = 0;
3873
Rajeev Kumarb60abe42017-01-21 15:39:31 -08003874 status = scheduler_post_msg(QDF_MODULE_ID_SYS, &msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303876 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303878 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 }
3880}
3881
3882/**
3883 * wma_process_utf_event() - process utf event
3884 * @handle: wma handle
3885 * @datap: data buffer
3886 * @dataplen: data length
3887 *
3888 * Return: 0 for success or error code
3889 */
3890static int
3891wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
3892{
3893 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05303894 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 uint8_t totalNumOfSegments, currentSeq;
3896 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
3897 uint8_t *data;
3898 uint32_t datalen;
3899
3900 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
3901 if (!param_buf) {
3902 WMA_LOGE("Get NULL point message from FW");
3903 return -EINVAL;
3904 }
3905 data = param_buf->data;
3906 datalen = param_buf->num_data;
3907
Govind Singhd76a5b02016-03-08 15:12:14 +05303908 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909
3910 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
3911
3912 currentSeq = (segHdrInfo.segmentInfo & 0xF);
3913 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
3914
3915 datalen = datalen - sizeof(segHdrInfo);
3916
3917 if (currentSeq == 0) {
3918 wma_handle->utf_event_info.expectedSeq = 0;
3919 wma_handle->utf_event_info.offset = 0;
3920 } else {
3921 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003922 WMA_LOGE("Mismatch in expecting seq expected Seq %d got seq %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923 wma_handle->utf_event_info.expectedSeq,
3924 currentSeq);
3925 }
3926
3927 memcpy(&wma_handle->utf_event_info.
3928 data[wma_handle->utf_event_info.offset],
3929 &data[sizeof(segHdrInfo)], datalen);
3930 wma_handle->utf_event_info.offset =
3931 wma_handle->utf_event_info.offset + datalen;
3932 wma_handle->utf_event_info.expectedSeq++;
3933
3934 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
3935 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003936 WMA_LOGE("All segs received total len mismatch.. len %zu total len %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003937 wma_handle->utf_event_info.offset,
3938 segHdrInfo.len);
3939
3940 wma_handle->utf_event_info.length =
3941 wma_handle->utf_event_info.offset;
3942 }
3943
3944 wma_post_ftm_response(wma_handle);
3945
3946 return 0;
3947}
3948
3949/**
3950 * wma_utf_detach() - utf detach
3951 * @wma_handle: wma handle
3952 *
3953 * Return: none
3954 */
3955void wma_utf_detach(tp_wma_handle wma_handle)
3956{
3957 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303958 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003959 wma_handle->utf_event_info.data = NULL;
3960 wma_handle->utf_event_info.length = 0;
3961 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
3962 WMI_PDEV_UTF_EVENTID);
3963 }
3964}
3965
3966/**
3967 * wma_utf_attach() - utf attach
3968 * @wma_handle: wma handle
3969 *
3970 * Return: none
3971 */
3972void wma_utf_attach(tp_wma_handle wma_handle)
3973{
3974 int ret;
3975
3976 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303977 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 wma_handle->utf_event_info.length = 0;
3979
3980 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
3981 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05303982 wma_process_utf_event,
3983 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984
3985 if (ret)
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003986 WMA_LOGE("%s: Failed to register UTF event callback", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987}
3988
3989/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 * wma_utf_cmd() - utf command
3991 * @wma_handle: wma handle
3992 * @data: data
3993 * @len: length
3994 *
Govind Singhd76a5b02016-03-08 15:12:14 +05303995 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003996 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003997static QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data,
3998 uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999{
Govind Singhd76a5b02016-03-08 15:12:14 +05304000 struct pdev_utf_params param = {0};
4001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05304003 param.utf_payload = data;
4004 param.len = len;
4005
4006 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
4007 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008}
4009
4010/**
4011 * wma_process_ftm_command() - process ftm command
4012 * @wma_handle: wma handle
4013 * @msg_buffer: message buffer
4014 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304015 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304017QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018wma_process_ftm_command(tp_wma_handle wma_handle,
4019 struct ar6k_testmode_cmd_data *msg_buffer)
4020{
4021 uint8_t *data = NULL;
4022 uint16_t len = 0;
4023 int ret;
4024
4025 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304026 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027
Anurag Chouhan6d760662016-02-20 16:05:43 +05304028 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304030 qdf_mem_free(msg_buffer->data);
4031 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 }
4034
4035 data = msg_buffer->data;
4036 len = msg_buffer->len;
4037
4038 ret = wma_utf_cmd(wma_handle, data, len);
4039
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304040 qdf_mem_free(msg_buffer->data);
4041 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042
4043 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304044 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304046 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047}
4048#endif /* QCA_WIFI_FTM */
4049
4050/**
4051 * wma_get_wcnss_software_version() - get wcnss software version
4052 * @p_cds_gctx: cds context
4053 * @pVersion: version pointer
4054 * @versionBufferSize: buffer size
4055 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304056 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304058QDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004059 uint8_t *pVersion,
4060 uint32_t versionBufferSize)
4061{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004062 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063
4064 if (NULL == wma_handle) {
4065 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304066 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 }
4068
4069 snprintf(pVersion, versionBufferSize, "%x",
4070 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304071 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072}
4073
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004074/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
4076 * @vdev_id: VDEV whose MAC ID is required
4077 *
4078 * Get MAC id corresponding to a vdev id from the WMA structure
4079 *
4080 * Return: Negative value on failure and MAC id on success
4081 */
4082int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
4083{
4084 tp_wma_handle wma;
4085
Anurag Chouhan6d760662016-02-20 16:05:43 +05304086 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004087 if (!wma) {
4088 WMA_LOGE("%s: Invalid WMA handle", __func__);
4089 return -EINVAL;
4090 }
4091
4092 if (wma->interfaces)
4093 return wma->interfaces[vdev_id].mac_id;
4094
4095 return -EINVAL;
4096}
4097
4098/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 * wma_update_intf_hw_mode_params() - Update WMA params
4100 * @vdev_id: VDEV id whose params needs to be updated
4101 * @mac_id: MAC id to be updated
4102 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
4103 *
4104 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
4105 *
4106 * Return: None
4107 */
4108void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
4109 uint32_t cfgd_hw_mode_index)
4110{
4111 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004112 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113
Anurag Chouhan6d760662016-02-20 16:05:43 +05304114 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 if (!wma) {
4116 WMA_LOGE("%s: Invalid WMA handle", __func__);
4117 return;
4118 }
4119
4120 if (!wma->interfaces) {
4121 WMA_LOGE("%s: Interface is NULL", __func__);
4122 return;
4123 }
4124
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004125 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
4126 WMA_LOGE("%s: Invalid index", __func__);
4127 return;
4128 }
4129
4130 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004131 wma->interfaces[vdev_id].mac_id = mac_id;
4132 if (mac_id == 0) {
4133 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304134 WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304136 WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 } else {
4138 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304139 WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304141 WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 }
4143}
4144
4145/**
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004146 * wma_get_vht_ch_width - return vht channel width
4147 *
4148 * Return: return vht channel width
4149 */
4150uint32_t wma_get_vht_ch_width(void)
4151{
4152 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304153 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004154
4155 if (NULL == wm_hdl)
4156 return fw_ch_wd;
4157
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004158 if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004159 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004160 else if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
4161 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004162
4163 return fw_ch_wd;
4164}
Govind Singhd76a5b02016-03-08 15:12:14 +05304165
4166/**
Krunal Soniaa664da2016-06-15 23:46:40 -07004167 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
4168 * @mask: given bitmask
4169 *
4170 * This helper function should return number of setbits from bitmask
4171 *
4172 * Return: number of setbits from bitmask
4173 */
4174uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
4175{
4176 uint32_t num_of_setbits = 0;
4177
4178 while (mask) {
4179 mask &= (mask - 1);
4180 num_of_setbits++;
4181 }
4182 return num_of_setbits;
4183}
4184
4185/**
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004186 * wma_is_csa_offload_enabled - checks fw CSA offload capability
4187 *
4188 * Return: true or false
4189 */
4190
4191bool wma_is_csa_offload_enabled(void)
4192{
4193 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4194
4195 if (!wma)
4196 return false;
4197
4198 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4199 WMI_SERVICE_CSA_OFFLOAD);
4200}
4201/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304202 * wma_config_debug_module_cmd - set debug log config
4203 * @wmi_handle: wmi layer handle
4204 * @param: debug log parameter
4205 * @val: debug log value
4206 * @module_id_bitmap: debug module id bitmap
4207 * @bitmap_len: debug module bitmap length
4208 *
4209 * Return: QDF_STATUS_SUCCESS for success or error code
4210 */
4211QDF_STATUS
4212wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4213 A_UINT32 val, A_UINT32 *module_id_bitmap,
4214 A_UINT32 bitmap_len)
4215{
4216 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004217
Govind Singhd76a5b02016-03-08 15:12:14 +05304218 dbg_param.param = param;
4219 dbg_param.val = val;
4220 dbg_param.module_id_bitmap = module_id_bitmap;
4221 dbg_param.bitmap_len = bitmap_len;
4222
4223 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4224}
Peng Xu8fdaa492016-06-22 10:20:47 -07004225
4226/**
4227 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4228 *
4229 * This function checks if driver is capable of p2p listen offload
4230 * true: capable of p2p offload
4231 * false: not capable
4232 *
4233 * Return: true - capable, false - not capable
4234 */
4235bool wma_is_p2p_lo_capable(void)
4236{
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004237 return wma_is_service_enabled(WMI_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT);
Peng Xu8fdaa492016-06-22 10:20:47 -07004238}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004239
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004240bool wma_capability_enhanced_mcast_filter(void)
4241{
4242 return wma_is_service_enabled(WMI_SERVICE_ENHANCED_MCAST_FILTER);
4243}
4244
4245
Mukul Sharmaf9047232017-03-02 16:58:56 +05304246bool wma_is_vdev_up(uint8_t vdev_id)
4247{
4248 struct wlan_objmgr_vdev *vdev;
4249 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4250 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4251
4252 if (!wma) {
4253 WMA_LOGE("%s: WMA context is invald!", __func__);
4254 return false;
4255 }
4256
4257 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4258 WLAN_LEGACY_WMA_ID);
4259 if (vdev) {
4260 wlan_vdev_obj_lock(vdev);
4261 state = wlan_vdev_mlme_get_state(vdev);
4262 wlan_vdev_obj_unlock(vdev);
4263 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4264 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304265 return (state == WLAN_VDEV_S_RUN) ? true : false;
4266}
4267
Dustin Brownec2c92e2017-07-26 11:13:49 -07004268void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004269{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004270 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4271
4272 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4273 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004274 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004275}
4276
Dustin Brownec2c92e2017-07-26 11:13:49 -07004277void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004278{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004279 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4280
4281 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004282 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004283}
4284
Dustin Brownd5f12942017-03-10 11:06:25 -08004285QDF_STATUS
4286wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4287{
4288 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004289 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004290
Dustin Brownec2c92e2017-07-26 11:13:49 -07004291 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4292 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004293 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4294 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004295 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004296
4297 return status;
4298}
4299
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004300QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4301{
4302 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004303 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004304
Dustin Brownec2c92e2017-07-26 11:13:49 -07004305 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4306 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004307 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4308 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004309 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004310
4311 return status;
4312}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004313
4314bool wma_is_service_enabled(WMI_SERVICE service_type)
4315{
4316 tp_wma_handle wma;
4317 wma = cds_get_context(QDF_MODULE_ID_WMA);
4318 if (!wma) {
4319 WMA_LOGE("%s: Invalid WMA handle", __func__);
4320 return false;
4321 }
4322
4323 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, service_type);
4324}
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004325
Dustin Brownec2c92e2017-07-26 11:13:49 -07004326QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4327 struct vdev_up_params *params,
4328 uint8_t bssid[IEEE80211_ADDR_LEN])
4329{
4330 QDF_STATUS status;
4331 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4332
4333 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4334 wma_release_wakelock(&vdev->vdev_start_wakelock);
4335
4336 return status;
4337}
4338
4339QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4340{
4341 QDF_STATUS status;
4342 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4343
4344 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4345 wma_release_wakelock(&vdev->vdev_start_wakelock);
4346
4347 return status;
4348}
4349
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004350tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4351{
4352 switch (type) {
4353 case WMI_PEER_TYPE_DEFAULT:
4354 return WIFI_PEER_STA;
4355 case WMI_PEER_TYPE_BSS:
4356 return WIFI_PEER_AP;
4357 case WMI_PEER_TYPE_TDLS:
4358 return WIFI_PEER_TDLS;
4359 case WMI_PEER_TYPE_NAN_DATA:
4360 return WIFI_PEER_NAN;
4361 default:
4362 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4363 return WIFI_PEER_INVALID;
4364 }
4365}
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304366
4367int wma_chip_power_save_failure_detected_handler(void *handle,
4368 uint8_t *cmd_param_info,
4369 uint32_t len)
4370{
4371 tp_wma_handle wma = (tp_wma_handle)handle;
4372 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4373 wmi_chip_power_save_failure_detected_fixed_param *event;
4374 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4375 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4376 QDF_MODULE_ID_PE);
4377 if (wma == NULL) {
4378 WMA_LOGE("%s: wma_handle is NULL", __func__);
4379 return -EINVAL;
4380 }
4381 if (!mac) {
4382 WMA_LOGE("%s: Invalid mac context", __func__);
4383 return -EINVAL;
4384 }
4385 if (!mac->sme.chip_power_save_fail_cb) {
4386 WMA_LOGE("%s: Callback not registered", __func__);
4387 return -EINVAL;
4388 }
4389
4390 param_buf =
4391 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4392 cmd_param_info;
4393 if (!param_buf) {
4394 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4395 __func__);
4396 return -EINVAL;
4397 }
4398 event = param_buf->fixed_param;
4399 pwr_save_fail_params.failure_reason_code =
4400 event->power_save_failure_reason_code;
4401 pwr_save_fail_params.wake_lock_bitmap[0] =
4402 event->protocol_wake_lock_bitmap[0];
4403 pwr_save_fail_params.wake_lock_bitmap[1] =
4404 event->protocol_wake_lock_bitmap[1];
4405 pwr_save_fail_params.wake_lock_bitmap[2] =
4406 event->protocol_wake_lock_bitmap[2];
4407 pwr_save_fail_params.wake_lock_bitmap[3] =
4408 event->protocol_wake_lock_bitmap[3];
4409 mac->sme.chip_power_save_fail_cb(mac->hHdd,
4410 &pwr_save_fail_params);
4411
4412 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4413 return 0;
4414}