blob: cebd5c40a86baebbc08d940f50a64efafb8aeea4 [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
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -0700456 if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE -
457 sizeof(*stats_ext_info))) {
458 WMA_LOGE("Excess data_len:%d", stats_ext_info->data_len);
459 QDF_ASSERT(0);
460 return -EINVAL;
461 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530462 stats_ext_event = (tSirStatsExtEvent *) qdf_mem_malloc(alloc_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 if (NULL == stats_ext_event) {
464 WMA_LOGE("%s: Memory allocation failure", __func__);
465 return -ENOMEM;
466 }
467
468 buf_ptr += sizeof(wmi_stats_ext_event_fixed_param) + WMI_TLV_HDR_SIZE;
469
470 stats_ext_event->vdev_id = stats_ext_info->vdev_id;
471 stats_ext_event->event_data_len = stats_ext_info->data_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530472 qdf_mem_copy(stats_ext_event->event_data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 buf_ptr, stats_ext_event->event_data_len);
474
475 cds_msg.type = eWNI_SME_STATS_EXT_EVENT;
476 cds_msg.bodyptr = (void *)stats_ext_event;
477 cds_msg.bodyval = 0;
478
Rajeev Kumarb60abe42017-01-21 15:39:31 -0800479 status = scheduler_post_msg(QDF_MODULE_ID_SME, &cds_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530480 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 WMA_LOGE("%s: Failed to post stats ext event to SME", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530482 qdf_mem_free(stats_ext_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 return -EFAULT;
484 }
485
486 WMA_LOGD("%s: stats ext event Posted to SME", __func__);
487 return 0;
488}
489#endif /* WLAN_FEATURE_STATS_EXT */
490
Nirav Shah93e789e2016-04-14 19:47:43 +0530491
Govind Singha471e5e2015-10-12 17:11:14 +0530492/**
493 * wma_profile_data_report_event_handler() - fw profiling handler
494 * @handle: wma handle
495 * @event_buf: event buffer received from fw
496 * @len: length of data
497 *
498 * Return: 0 for success or error code
499 */
500int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
501 uint32_t len)
502{
503 WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf;
504 wmi_wlan_profile_ctx_t *profile_ctx;
505 wmi_wlan_profile_t *profile_data;
506 uint32_t i = 0;
507 uint32_t entries;
508 uint8_t *buf_ptr;
Nirav Shah93e789e2016-04-14 19:47:43 +0530509 char temp_str[150];
Govind Singha471e5e2015-10-12 17:11:14 +0530510
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -0700511 param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf;
Govind Singha471e5e2015-10-12 17:11:14 +0530512 if (!param_buf) {
513 WMA_LOGE("%s: Invalid profile data event buf", __func__);
514 return -EINVAL;
515 }
516 profile_ctx = param_buf->profile_ctx;
517 buf_ptr = (uint8_t *)profile_ctx;
518 buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE;
519 profile_data = (wmi_wlan_profile_t *) buf_ptr;
520 entries = profile_ctx->bin_count;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530521 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530522 "Profile data stats\n");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530523 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Govind Singha471e5e2015-10-12 17:11:14 +0530524 "TOT: %d\n"
525 "tx_msdu_cnt: %d\n"
526 "tx_mpdu_cnt: %d\n"
527 "tx_ppdu_cnt: %d\n"
528 "rx_msdu_cnt: %d\n"
529 "rx_mpdu_cnt: %d\n"
530 "bin_count: %d\n",
531 profile_ctx->tot,
532 profile_ctx->tx_msdu_cnt,
533 profile_ctx->tx_mpdu_cnt,
534 profile_ctx->tx_ppdu_cnt,
535 profile_ctx->rx_msdu_cnt,
536 profile_ctx->rx_mpdu_cnt,
537 profile_ctx->bin_count);
538
Nirav Shah93e789e2016-04-14 19:47:43 +0530539 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
540 "Profile ID: Count: TOT: Min: Max: hist_intvl: hist[0]: hist[1]:hist[2]");
541
Govind Singha471e5e2015-10-12 17:11:14 +0530542 for (i = 0; i < entries; i++) {
543 if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT)
544 break;
Nirav Shah93e789e2016-04-14 19:47:43 +0530545 snprintf(temp_str, sizeof(temp_str),
546 " %d : %d : %d : %d : %d : %d : %d : %d : %d",
Govind Singha471e5e2015-10-12 17:11:14 +0530547 profile_data[i].id,
548 profile_data[i].cnt,
549 profile_data[i].tot,
550 profile_data[i].min,
551 profile_data[i].max,
552 profile_data[i].hist_intvl,
553 profile_data[i].hist[0],
554 profile_data[i].hist[1],
555 profile_data[i].hist[2]);
Nirav Shah93e789e2016-04-14 19:47:43 +0530556 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
557 "%s", temp_str);
Govind Singha471e5e2015-10-12 17:11:14 +0530558 }
559
560 return 0;
561}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562
563#ifdef WLAN_FEATURE_LINK_LAYER_STATS
564
Zhang Qian73c348a2017-03-13 16:15:55 +0800565#define WMA_FILL_TX_STATS(eve, msg) do {\
566 (msg)->msdus = (eve)->tx_msdu_cnt;\
567 (msg)->mpdus = (eve)->tx_mpdu_cnt;\
568 (msg)->ppdus = (eve)->tx_ppdu_cnt;\
569 (msg)->bytes = (eve)->tx_bytes;\
570 (msg)->drops = (eve)->tx_msdu_drop_cnt;\
571 (msg)->drop_bytes = (eve)->tx_drop_bytes;\
572 (msg)->retries = (eve)->tx_mpdu_retry_cnt;\
573 (msg)->failed = (eve)->tx_mpdu_fail_cnt;\
574} while (0)
575
576#define WMA_FILL_RX_STATS(eve, msg) do {\
577 (msg)->mpdus = (eve)->mac_rx_mpdu_cnt;\
578 (msg)->bytes = (eve)->mac_rx_bytes;\
579 (msg)->ppdus = (eve)->phy_rx_ppdu_cnt;\
580 (msg)->ppdu_bytes = (eve)->phy_rx_bytes;\
581 (msg)->mpdu_retry = (eve)->rx_mpdu_retry_cnt;\
582 (msg)->mpdu_dup = (eve)->rx_mpdu_dup_cnt;\
583 (msg)->mpdu_discard = (eve)->rx_mpdu_discard_cnt;\
584} while (0)
585
586/**
587 * wma_get_ll_stats_ext_buf() - alloc result buffer for MAC counters
588 * @len: buffer length output
589 * @peer_num: peer number
590 * @fixed_param: fixed parameters in WMI event
591 *
592 * Structure of the stats message
593 * LL_EXT_STATS
594 * |
595 * |--Channel stats[1~n]
596 * |--Peer[1~n]
597 * |
598 * +---Signal
599 * +---TX
600 * | +---BE
601 * | +---BK
602 * | +---VI
603 * | +---VO
604 * |
605 * +---RX
606 * +---BE
607 * +---BK
608 * +---VI
609 * +---VO
610 * For each Access Category, the arregation and mcs
611 * stats are as this:
612 * TX
613 * +-BE/BK/VI/VO
614 * +----tx_mpdu_aggr_array
615 * +----tx_succ_mcs_array
616 * +----tx_fail_mcs_array
617 * +----tx_delay_array
618 * RX
619 * +-BE/BK/VI/VO
620 * +----rx_mpdu_aggr_array
621 * +----rx_mcs_array
622 *
623 * return: Address for result buffer.
624 */
625static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
626 uint32_t peer_num,
627 wmi_report_stats_event_fixed_param *fixed_param)
628{
629 tSirLLStatsResults *buf;
630 uint32_t buf_len;
631
632 if (!len || !fixed_param) {
633 WMA_LOGE(FL("Invalid input parameters."));
634 return NULL;
635 }
636
637 /*
638 * Result buffer has a structure like this:
639 * ---------------------------------
640 * | trigger_cond_i |
641 * +-------------------------------+
642 * | cca_chgd_bitmap |
643 * +-------------------------------+
644 * | sig_chgd_bitmap |
645 * +-------------------------------+
646 * | tx_chgd_bitmap |
647 * +-------------------------------+
648 * | rx_chgd_bitmap |
649 * +-------------------------------+
650 * | peer_num |
651 * +-------------------------------+
652 * | channel_num |
653 * +-------------------------------+
654 * | tx_mpdu_aggr_array_len |
655 * +-------------------------------+
656 * | tx_succ_mcs_array_len |
657 * +-------------------------------+
658 * | tx_fail_mcs_array_len |
659 * +-------------------------------+
660 * | tx_delay_array_len |
661 * +-------------------------------+
662 * | rx_mpdu_aggr_array_len |
663 * +-------------------------------+
664 * | rx_mcs_array_len |
665 * +-------------------------------+
666 * | pointer to CCA stats |
667 * +-------------------------------+
668 * | CCA stats |
669 * +-------------------------------+
670 * | peer_stats |----+
671 * +-------------------------------+ |
672 * | TX aggr/mcs parameters array | |
673 * | Length of this buffer is | |
674 * | not fixed. |<-+ |
675 * +-------------------------------+ | |
676 * | per peer tx stats |--+ |
677 * | BE | <--+
678 * | BK | |
679 * | VI | |
680 * | VO | |
681 * +-------------------------------+ |
682 * | TX aggr/mcs parameters array | |
683 * | Length of this buffer is | |
684 * | not fixed. |<-+ |
685 * +-------------------------------+ | |
686 * | peer peer rx stats |--+ |
687 * | BE | <--+
688 * | BK |
689 * | VI |
690 * | VO |
691 * ---------------------------------
692 */
693 buf_len = sizeof(tSirLLStatsResults) +
694 sizeof(struct sir_wifi_ll_ext_stats) +
695 fixed_param->num_chan_cca_stats *
696 sizeof(struct sir_wifi_chan_cca_stats) +
697 peer_num *
698 (sizeof(struct sir_wifi_ll_ext_peer_stats) +
699 WLAN_MAX_AC *
700 (sizeof(struct sir_wifi_tx) +
701 sizeof(struct sir_wifi_rx)) +
702 sizeof(uint32_t) * WLAN_MAX_AC *
703 (fixed_param->tx_mpdu_aggr_array_len +
704 fixed_param->tx_succ_mcs_array_len +
705 fixed_param->tx_fail_mcs_array_len +
706 fixed_param->tx_ppdu_delay_array_len +
707 fixed_param->rx_mpdu_aggr_array_len +
708 fixed_param->rx_mcs_array_len));
709
710 buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
711 if (buf == NULL) {
712 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
713 buf_len = 0;
714 return NULL;
715 }
716
717 *len = buf_len;
718 return buf;
719}
720
721/**
722 * wma_fill_tx_stats() - Fix TX stats into result buffer
723 * @ll_stats: LL stats buffer
724 * @fix_param: parameters with fixed length in WMI event
725 * @param_buf: parameters without fixed length in WMI event
726 * @buf: buffer for TLV parameters
727 *
728 * Return: None
729 */
730static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
731 wmi_report_stats_event_fixed_param *fix_param,
732 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
733 uint8_t **buf, uint32_t *buf_length)
734{
735 uint8_t *result;
736 uint32_t i, j, k;
737 wmi_peer_ac_tx_stats *wmi_peer_tx;
738 wmi_tx_stats *wmi_tx;
739 struct sir_wifi_tx *tx_stats;
740 struct sir_wifi_ll_ext_peer_stats *peer_stats;
741 uint32_t *tx_mpdu_aggr, *tx_succ_mcs, *tx_fail_mcs, *tx_delay;
742 uint32_t len, dst_len, tx_mpdu_aggr_array_len, tx_succ_mcs_array_len,
743 tx_fail_mcs_array_len, tx_delay_array_len;
744
745 result = *buf;
746 dst_len = *buf_length;
747 tx_mpdu_aggr_array_len = fix_param->tx_mpdu_aggr_array_len;
748 ll_stats->tx_mpdu_aggr_array_len = tx_mpdu_aggr_array_len;
749 tx_succ_mcs_array_len = fix_param->tx_succ_mcs_array_len;
750 ll_stats->tx_succ_mcs_array_len = tx_succ_mcs_array_len;
751 tx_fail_mcs_array_len = fix_param->tx_fail_mcs_array_len;
752 ll_stats->tx_fail_mcs_array_len = tx_fail_mcs_array_len;
753 tx_delay_array_len = fix_param->tx_ppdu_delay_array_len;
754 ll_stats->tx_delay_array_len = tx_delay_array_len;
755 wmi_peer_tx = param_buf->peer_ac_tx_stats;
756 wmi_tx = param_buf->tx_stats;
757
758 len = fix_param->num_peer_ac_tx_stats *
759 WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t);
760 if (len <= dst_len) {
761 tx_mpdu_aggr = (uint32_t *)result;
762 qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len);
763 result += len;
764 dst_len -= len;
765 } else {
766 WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong."));
767 tx_mpdu_aggr = NULL;
768 }
769
770 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
771 tx_succ_mcs_array_len * sizeof(uint32_t);
772 if (len <= dst_len) {
773 tx_succ_mcs = (uint32_t *)result;
774 qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len);
775 result += len;
776 dst_len -= len;
777 } else {
778 WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong."));
779 tx_succ_mcs = NULL;
780 }
781
782 len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC *
783 tx_fail_mcs_array_len * sizeof(uint32_t);
784 if (len <= dst_len) {
785 tx_fail_mcs = (uint32_t *)result;
786 qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len);
787 result += len;
788 dst_len -= len;
789 } else {
790 WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong."));
791 tx_fail_mcs = NULL;
792 }
793
794 len = fix_param->num_peer_ac_tx_stats *
795 WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t);
796 if (len <= dst_len) {
797 tx_delay = (uint32_t *)result;
798 qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len);
799 result += len;
800 dst_len -= len;
801 } else {
802 WMA_LOGE(FL("TX_DELAY buffer length is wrong."));
803 tx_delay = NULL;
804 }
805
806 /* per peer tx stats */
807 peer_stats = ll_stats->peer_stats;
808
809 for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) {
810 uint32_t peer_id = wmi_peer_tx[i].peer_id;
811 struct sir_wifi_tx *ac;
812 wmi_tx_stats *wmi_tx_stats;
813
814 for (j = 0; j < ll_stats->peer_num; j++) {
815 peer_stats += j;
816 if (peer_stats->peer_id == WIFI_INVALID_PEER_ID ||
817 peer_stats->peer_id == peer_id)
818 break;
819 }
820
821 if (j < ll_stats->peer_num) {
822 peer_stats->peer_id = wmi_peer_tx[i].peer_id;
823 peer_stats->vdev_id = wmi_peer_tx[i].vdev_id;
824 tx_stats = (struct sir_wifi_tx *)result;
825 for (k = 0; k < WLAN_MAX_AC; k++) {
826 wmi_tx_stats = &wmi_tx[i * WLAN_MAX_AC + k];
827 ac = &tx_stats[k];
828 WMA_FILL_TX_STATS(wmi_tx_stats, ac);
829 ac->mpdu_aggr_size = tx_mpdu_aggr;
830 ac->aggr_len = tx_mpdu_aggr_array_len *
831 sizeof(uint32_t);
832 ac->success_mcs_len = tx_succ_mcs_array_len *
833 sizeof(uint32_t);
834 ac->success_mcs = tx_succ_mcs;
835 ac->fail_mcs = tx_fail_mcs;
836 ac->fail_mcs_len = tx_fail_mcs_array_len *
837 sizeof(uint32_t);
838 ac->delay = tx_delay;
839 ac->delay_len = tx_delay_array_len *
840 sizeof(uint32_t);
841 peer_stats->ac_stats[k].tx_stats = ac;
842 peer_stats->ac_stats[k].type = k;
843 tx_mpdu_aggr += tx_mpdu_aggr_array_len;
844 tx_succ_mcs += tx_succ_mcs_array_len;
845 tx_fail_mcs += tx_fail_mcs_array_len;
846 tx_delay += tx_delay_array_len;
847 }
848 result += WLAN_MAX_AC * sizeof(struct sir_wifi_tx);
849 } else {
850 /*
851 * Buffer for Peer TX counter overflow.
852 * There is peer ID mismatch between TX, RX,
853 * signal counters.
854 */
855 WMA_LOGE(FL("One peer TX info is dropped."));
856
857 tx_mpdu_aggr += tx_mpdu_aggr_array_len * WLAN_MAX_AC;
858 tx_succ_mcs += tx_succ_mcs_array_len * WLAN_MAX_AC;
859 tx_fail_mcs += tx_fail_mcs_array_len * WLAN_MAX_AC;
860 tx_delay += tx_delay_array_len * WLAN_MAX_AC;
861 }
862 }
863 *buf = result;
864 *buf_length = dst_len;
865}
866
867/**
868 * wma_fill_rx_stats() - Fix RX stats into result buffer
869 * @ll_stats: LL stats buffer
870 * @fix_param: parameters with fixed length in WMI event
871 * @param_buf: parameters without fixed length in WMI event
872 * @buf: buffer for TLV parameters
873 *
874 * Return: None
875 */
876static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats,
877 wmi_report_stats_event_fixed_param *fix_param,
878 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf,
879 uint8_t **buf, uint32_t *buf_length)
880{
881 uint8_t *result;
882 uint32_t i, j, k;
883 uint32_t *rx_mpdu_aggr, *rx_mcs;
884 wmi_rx_stats *wmi_rx;
885 wmi_peer_ac_rx_stats *wmi_peer_rx;
886 struct sir_wifi_rx *rx_stats;
887 struct sir_wifi_ll_ext_peer_stats *peer_stats;
888 uint32_t len, dst_len, rx_mpdu_aggr_array_len, rx_mcs_array_len;
889
890 rx_mpdu_aggr_array_len = fix_param->rx_mpdu_aggr_array_len;
891 ll_stats->rx_mpdu_aggr_array_len = rx_mpdu_aggr_array_len;
892 rx_mcs_array_len = fix_param->rx_mcs_array_len;
893 ll_stats->rx_mcs_array_len = rx_mcs_array_len;
894 wmi_peer_rx = param_buf->peer_ac_rx_stats;
895 wmi_rx = param_buf->rx_stats;
896
897 result = *buf;
898 dst_len = *buf_length;
899 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
900 WLAN_MAX_AC * rx_mpdu_aggr_array_len);
901 if (len <= dst_len) {
902 rx_mpdu_aggr = (uint32_t *)result;
903 qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len);
904 result += len;
905 dst_len -= len;
906 } else {
907 WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong."));
908 rx_mpdu_aggr = NULL;
909 }
910
911 len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats *
912 WLAN_MAX_AC * rx_mcs_array_len);
913 if (len <= dst_len) {
914 rx_mcs = (uint32_t *)result;
915 qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len);
916 result += len;
917 dst_len -= len;
918 } else {
919 WMA_LOGE(FL("RX_MCS array length is wrong."));
920 rx_mcs = NULL;
921 }
922
923 /* per peer rx stats */
924 peer_stats = ll_stats->peer_stats;
925 for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) {
926 uint32_t peer_id = wmi_peer_rx[i].peer_id;
927 struct sir_wifi_rx *ac;
928 wmi_rx_stats *wmi_rx_stats;
929
930 for (j = 0; j < ll_stats->peer_num; j++) {
931 peer_stats += j;
932 if ((peer_stats->peer_id == WIFI_INVALID_PEER_ID) ||
933 (peer_stats->peer_id == peer_id))
934 break;
935 }
936
937 if (j < ll_stats->peer_num) {
938 peer_stats->peer_id = wmi_peer_rx[i].peer_id;
939 peer_stats->vdev_id = wmi_peer_rx[i].vdev_id;
940 peer_stats->sta_ps_inds = wmi_peer_rx[i].sta_ps_inds;
941 peer_stats->sta_ps_durs = wmi_peer_rx[i].sta_ps_durs;
942 peer_stats->rx_probe_reqs =
943 wmi_peer_rx[i].rx_probe_reqs;
944 peer_stats->rx_oth_mgmts = wmi_peer_rx[i].rx_oth_mgmts;
945 rx_stats = (struct sir_wifi_rx *)result;
946
947 for (k = 0; k < WLAN_MAX_AC; k++) {
948 wmi_rx_stats = &wmi_rx[i * WLAN_MAX_AC + k];
949 ac = &rx_stats[k];
950 WMA_FILL_RX_STATS(wmi_rx_stats, ac);
951 ac->mpdu_aggr = rx_mpdu_aggr;
952 ac->aggr_len = rx_mpdu_aggr_array_len *
953 sizeof(uint32_t);
954 ac->mcs = rx_mcs;
955 ac->mcs_len = rx_mcs_array_len *
956 sizeof(uint32_t);
957 peer_stats->ac_stats[k].rx_stats = ac;
958 peer_stats->ac_stats[k].type = k;
959 rx_mpdu_aggr += rx_mpdu_aggr_array_len;
960 rx_mcs += rx_mcs_array_len;
961 }
962 result += WLAN_MAX_AC * sizeof(struct sir_wifi_rx);
963 } else {
964 /*
965 * Buffer for Peer RX counter overflow.
966 * There is peer ID mismatch between TX, RX,
967 * signal counters.
968 */
969 WMA_LOGE(FL("One peer RX info is dropped."));
970 rx_mpdu_aggr += rx_mpdu_aggr_array_len * WLAN_MAX_AC;
971 rx_mcs += rx_mcs_array_len * WLAN_MAX_AC;
972 }
973 }
974 *buf = result;
975 *buf_length = dst_len;
976}
977
978/**
979 * wma_ll_stats_evt_handler() - handler for MAC layer counters.
980 * @handle - wma handle
981 * @event - FW event
982 * @len - length of FW event
983 *
984 * return: 0 success.
985 */
986static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event,
987 u_int32_t len)
988{
989 WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf;
990 wmi_report_stats_event_fixed_param *fixed_param;
991 tSirLLStatsResults *link_stats_results;
992 wmi_chan_cca_stats *wmi_cca_stats;
993 wmi_peer_signal_stats *wmi_peer_signal;
994 wmi_peer_ac_rx_stats *wmi_peer_rx;
995 struct sir_wifi_ll_ext_stats *ll_stats;
996 struct sir_wifi_ll_ext_peer_stats *peer_stats;
997 struct sir_wifi_chan_cca_stats *cca_stats;
998 struct sir_wifi_peer_signal_stats *peer_signal;
999 uint8_t *result;
1000 uint32_t i, peer_num, result_size, dst_len;
1001 tpAniSirGlobal mac;
1002 struct scheduler_msg sme_msg = { 0 };
1003 QDF_STATUS qdf_status;
1004
1005 mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
1006 if (!mac) {
1007 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1008 return -EINVAL;
1009 }
1010
1011 if (!mac->sme.link_layer_stats_ext_cb) {
1012 WMA_LOGD("%s: HDD callback is null", __func__);
1013 return -EINVAL;
1014 }
1015
1016 WMA_LOGD("%s: Posting MAC counters event to HDD", __func__);
1017
1018 param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event;
1019 fixed_param = param_buf->fixed_param;
1020 wmi_cca_stats = param_buf->chan_cca_stats;
1021 wmi_peer_signal = param_buf->peer_signal_stats;
1022 wmi_peer_rx = param_buf->peer_ac_rx_stats;
1023
1024 /* Get the MAX of three peer numbers */
1025 peer_num = fixed_param->num_peer_signal_stats >
1026 fixed_param->num_peer_ac_tx_stats ?
1027 fixed_param->num_peer_signal_stats :
1028 fixed_param->num_peer_ac_tx_stats;
1029 peer_num = peer_num > fixed_param->num_peer_ac_rx_stats ?
1030 peer_num : fixed_param->num_peer_ac_rx_stats;
1031
1032 if (peer_num == 0)
1033 return -EINVAL;
1034
1035 link_stats_results = wma_get_ll_stats_ext_buf(&result_size,
1036 peer_num,
1037 fixed_param);
1038 if (!link_stats_results) {
1039 WMA_LOGE("%s: Fail to allocate stats buffer", __func__);
1040 return -EINVAL;
1041 }
1042 link_stats_results->paramId = WMI_LL_STATS_EXT_MAC_COUNTER;
1043 link_stats_results->num_peers = peer_num;
1044 link_stats_results->peer_event_number = 1;
1045 link_stats_results->moreResultToFollow = 0;
1046
1047 ll_stats = (struct sir_wifi_ll_ext_stats *)link_stats_results->results;
1048 ll_stats->trigger_cond_id = fixed_param->trigger_cond_id;
1049 ll_stats->cca_chgd_bitmap = fixed_param->cca_chgd_bitmap;
1050 ll_stats->sig_chgd_bitmap = fixed_param->sig_chgd_bitmap;
1051 ll_stats->tx_chgd_bitmap = fixed_param->tx_chgd_bitmap;
1052 ll_stats->rx_chgd_bitmap = fixed_param->rx_chgd_bitmap;
1053 ll_stats->channel_num = fixed_param->num_chan_cca_stats;
1054 ll_stats->peer_num = peer_num;
1055
1056 result = (uint8_t *)ll_stats->stats;
1057 peer_stats = (struct sir_wifi_ll_ext_peer_stats *)result;
1058 ll_stats->peer_stats = peer_stats;
1059
1060 for (i = 0; i < peer_num; i++) {
1061 peer_stats[i].peer_id = WIFI_INVALID_PEER_ID;
1062 peer_stats[i].vdev_id = WIFI_INVALID_VDEV_ID;
1063 }
1064
1065 /* Per peer signal */
1066 result_size -= sizeof(struct sir_wifi_ll_ext_stats);
1067 dst_len = sizeof(struct sir_wifi_peer_signal_stats);
1068 for (i = 0; i < fixed_param->num_peer_signal_stats; i++) {
1069 peer_stats[i].peer_id = wmi_peer_signal->peer_id;
1070 peer_stats[i].vdev_id = wmi_peer_signal->vdev_id;
1071 peer_signal = &peer_stats[i].peer_signal_stats;
1072
Zhang Qian303ebe92017-05-18 13:59:07 +08001073 WMA_LOGD("%d antennas for peer %d",
1074 wmi_peer_signal->num_chains_valid,
1075 wmi_peer_signal->peer_id);
Zhang Qian73c348a2017-03-13 16:15:55 +08001076 if (dst_len <= result_size) {
Zhang Qian303ebe92017-05-18 13:59:07 +08001077 peer_signal->vdev_id = wmi_peer_signal->vdev_id;
1078 peer_signal->peer_id = wmi_peer_signal->peer_id;
1079 peer_signal->num_chain =
1080 wmi_peer_signal->num_chains_valid;
1081 qdf_mem_copy(peer_signal->per_ant_snr,
1082 wmi_peer_signal->per_chain_snr,
1083 sizeof(peer_signal->per_ant_snr));
1084 qdf_mem_copy(peer_signal->nf,
1085 wmi_peer_signal->per_chain_nf,
1086 sizeof(peer_signal->nf));
1087 qdf_mem_copy(peer_signal->per_ant_rx_mpdus,
1088 wmi_peer_signal->per_antenna_rx_mpdus,
1089 sizeof(peer_signal->per_ant_rx_mpdus));
1090 qdf_mem_copy(peer_signal->per_ant_tx_mpdus,
1091 wmi_peer_signal->per_antenna_tx_mpdus,
1092 sizeof(peer_signal->per_ant_tx_mpdus));
Zhang Qian73c348a2017-03-13 16:15:55 +08001093 result_size -= dst_len;
1094 } else {
1095 WMA_LOGE(FL("Invalid length of PEER signal."));
1096 }
1097 wmi_peer_signal++;
1098 }
1099
1100 result += peer_num * sizeof(struct sir_wifi_ll_ext_peer_stats);
1101 cca_stats = (struct sir_wifi_chan_cca_stats *)result;
1102 ll_stats->cca = cca_stats;
1103 dst_len = sizeof(struct sir_wifi_chan_cca_stats);
1104 for (i = 0; i < ll_stats->channel_num; i++) {
1105 if (dst_len <= result_size) {
1106 qdf_mem_copy(&cca_stats[i], &wmi_cca_stats->vdev_id,
1107 dst_len);
1108 result_size -= dst_len;
1109 } else {
1110 WMA_LOGE(FL("Invalid length of CCA."));
1111 }
1112 }
1113
1114 result += i * sizeof(struct sir_wifi_chan_cca_stats);
1115 wma_fill_tx_stats(ll_stats, fixed_param, param_buf,
1116 &result, &result_size);
1117 wma_fill_rx_stats(ll_stats, fixed_param, param_buf,
1118 &result, &result_size);
1119 sme_msg.type = eWMI_SME_LL_STATS_IND;
1120 sme_msg.bodyptr = (void *)link_stats_results;
1121 sme_msg.bodyval = 0;
1122 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1123 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1124 WMA_LOGP(FL("Failed to post peer stat change msg!"));
1125 qdf_mem_free(link_stats_results);
1126 return -EINVAL;
1127 }
1128
1129 return 0;
1130}
1131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132/**
1133 * wma_unified_link_peer_stats_event_handler() - peer stats event handler
1134 * @handle: wma handle
1135 * @cmd_param_info: data received with event from fw
1136 * @len: length of data
1137 *
1138 * Return: 0 for success or error code
1139 */
1140static int wma_unified_link_peer_stats_event_handler(void *handle,
1141 uint8_t *cmd_param_info,
1142 uint32_t len)
1143{
1144 WMI_PEER_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1145 wmi_peer_stats_event_fixed_param *fixed_param;
1146 wmi_peer_link_stats *peer_stats, *temp_peer_stats;
1147 wmi_rate_stats *rate_stats;
1148 tSirLLStatsResults *link_stats_results;
1149 uint8_t *results, *t_peer_stats, *t_rate_stats;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301150 uint32_t count, num_rates = 0, rate_cnt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 uint32_t next_res_offset, next_peer_offset, next_rate_offset;
1152 size_t peer_info_size, peer_stats_size, rate_stats_size;
1153 size_t link_stats_results_size;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001154 bool excess_data = false;
1155 uint32_t buf_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156
Anurag Chouhan6d760662016-02-20 16:05:43 +05301157 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158
1159 if (!pMac) {
1160 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1161 return -EINVAL;
1162 }
1163
1164 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1165 WMA_LOGD("%s: HDD callback is null", __func__);
1166 return -EINVAL;
1167 }
1168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001169 param_tlvs = (WMI_PEER_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1170 if (!param_tlvs) {
1171 WMA_LOGA("%s: Invalid stats event", __func__);
1172 return -EINVAL;
1173 }
1174 /*
1175 * cmd_param_info contains
1176 * wmi_peer_stats_event_fixed_param fixed_param;
1177 * num_peers * size of(struct wmi_peer_link_stats)
1178 * num_rates * size of(struct wmi_rate_stats)
1179 * num_rates is the sum of the rates of all the peers.
1180 */
1181 fixed_param = param_tlvs->fixed_param;
1182 peer_stats = param_tlvs->peer_stats;
1183 rate_stats = param_tlvs->peer_rate_stats;
1184
1185 if (!fixed_param || !peer_stats ||
1186 (peer_stats->num_rates && !rate_stats)) {
1187 WMA_LOGA("%s: Invalid param_tlvs for Peer Stats", __func__);
1188 return -EINVAL;
1189 }
1190
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001191 do {
1192 if (peer_stats->num_rates >
1193 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_rate_stats)) {
1194 excess_data = true;
1195 break;
1196 } else {
1197 buf_len =
1198 peer_stats->num_rates * sizeof(wmi_rate_stats);
1199 }
1200 if (fixed_param->num_peers >
1201 WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats)) {
1202 excess_data = true;
1203 break;
1204 } else {
1205 buf_len += fixed_param->num_peers *
1206 sizeof(wmi_peer_link_stats);
1207 }
1208 } while (0);
1209
1210 if (excess_data ||
1211 (sizeof(*fixed_param) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
1212 WMA_LOGE("excess wmi buffer: rates:%d, peers:%d",
1213 peer_stats->num_rates, fixed_param->num_peers);
1214 QDF_ASSERT(0);
1215 return -EINVAL;
1216 }
1217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 /*
1219 * num_rates - sum of the rates of all the peers
1220 */
1221 temp_peer_stats = (wmi_peer_link_stats *) peer_stats;
1222 for (count = 0; count < fixed_param->num_peers; count++) {
1223 num_rates += temp_peer_stats->num_rates;
1224 temp_peer_stats++;
1225 }
1226
1227 peer_stats_size = sizeof(tSirWifiPeerStat);
1228 peer_info_size = sizeof(tSirWifiPeerInfo);
1229 rate_stats_size = sizeof(tSirWifiRateStat);
1230 link_stats_results_size =
1231 sizeof(*link_stats_results) + peer_stats_size +
1232 (fixed_param->num_peers * peer_info_size) +
1233 (num_rates * rate_stats_size);
1234
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301235 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 if (NULL == link_stats_results) {
1237 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1238 __func__, link_stats_results_size);
1239 return -ENOMEM;
1240 }
1241
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301242 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243
1244 link_stats_results->paramId = WMI_LINK_STATS_ALL_PEER;
1245 link_stats_results->rspId = fixed_param->request_id;
1246 link_stats_results->ifaceId = 0;
1247 link_stats_results->num_peers = fixed_param->num_peers;
1248 link_stats_results->peer_event_number = fixed_param->peer_event_number;
1249 link_stats_results->moreResultToFollow = fixed_param->more_data;
1250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(link_stats_results->results,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 &fixed_param->num_peers, peer_stats_size);
1253
1254 results = (uint8_t *) link_stats_results->results;
1255 t_peer_stats = (uint8_t *) peer_stats;
1256 t_rate_stats = (uint8_t *) rate_stats;
1257 next_res_offset = peer_stats_size;
1258 next_peer_offset = WMI_TLV_HDR_SIZE;
1259 next_rate_offset = WMI_TLV_HDR_SIZE;
Kondabattini, Ganesh32be0832016-08-09 15:19:50 +05301260 for (rate_cnt = 0; rate_cnt < fixed_param->num_peers; rate_cnt++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301261 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262 t_peer_stats + next_peer_offset, peer_info_size);
1263 next_res_offset += peer_info_size;
1264
1265 /* Copy rate stats associated with this peer */
1266 for (count = 0; count < peer_stats->num_rates; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 rate_stats++;
1268
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301269 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270 t_rate_stats + next_rate_offset,
1271 rate_stats_size);
1272 next_res_offset += rate_stats_size;
1273 next_rate_offset += sizeof(*rate_stats);
1274 }
1275 next_peer_offset += sizeof(*peer_stats);
1276 peer_stats++;
1277 }
1278
1279 /* call hdd callback with Link Layer Statistics
1280 * vdev_id/ifacId in link_stats_results will be
1281 * used to retrieve the correct HDD context
1282 */
1283 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1284 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1285 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301286 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287
1288 return 0;
1289}
1290
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001291/**
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001292 * wma_unified_radio_tx_mem_free() - Free radio tx power stats memory
1293 * @handle: WMI handle
1294 *
1295 * Return: 0 on success, error number otherwise.
1296 */
yeshwanth sriram guntuka584c2332017-07-29 12:50:25 +05301297int wma_unified_radio_tx_mem_free(void *handle)
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001298{
1299 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1300 tSirWifiRadioStat *rs_results;
1301 uint32_t i = 0;
1302
1303 if (!wma_handle->link_stats_results)
1304 return 0;
1305
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001306 rs_results = (tSirWifiRadioStat *)
1307 &wma_handle->link_stats_results->results[0];
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001308 for (i = 0; i < wma_handle->link_stats_results->num_radio; i++) {
1309 rs_results += i;
1310 if (rs_results->tx_time_per_power_level) {
1311 qdf_mem_free(rs_results->tx_time_per_power_level);
1312 rs_results->tx_time_per_power_level = NULL;
1313 }
1314
1315 if (rs_results->channels) {
1316 qdf_mem_free(rs_results->channels);
1317 rs_results->channels = NULL;
1318 }
1319 }
1320
1321 qdf_mem_free(wma_handle->link_stats_results);
1322 wma_handle->link_stats_results = NULL;
1323
1324 return 0;
1325}
1326
1327/**
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001328 * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
1329 * @handle: WMI handle
1330 * @cmd_param_info: command param info
1331 * @len: Length of @cmd_param_info
1332 *
1333 * This is the WMI event handler function to receive radio stats tx
1334 * power level stats.
1335 *
1336 * Return: 0 on success, error number otherwise.
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001337 */
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001338static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
1339 u_int8_t *cmd_param_info, u_int32_t len)
1340{
1341 tp_wma_handle wma_handle = (tp_wma_handle) handle;
1342 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
1343 wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
1344 uint8_t *tx_power_level_values;
1345 tSirLLStatsResults *link_stats_results;
1346 tSirWifiRadioStat *rs_results;
1347
1348 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1349
1350 if (!mac) {
1351 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1352 return -EINVAL;
1353 }
1354
1355 if (!mac->sme.pLinkLayerStatsIndCallback) {
1356 WMA_LOGD("%s: HDD callback is null", __func__);
1357 return -EINVAL;
1358 }
1359
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001360 param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)
1361 cmd_param_info;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001362 if (!param_tlvs) {
1363 WMA_LOGA("%s: Invalid tx power level stats event", __func__);
1364 return -EINVAL;
1365 }
1366
1367 fixed_param = param_tlvs->fixed_param;
1368 if (!fixed_param) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001369 WMA_LOGA("%s:Invalid param_tlvs for Radio tx_power level Stats",
1370 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001371 return -EINVAL;
1372 }
1373
1374 link_stats_results = wma_handle->link_stats_results;
Srinivas Girigowda52cbce42016-10-25 14:11:58 -07001375 if (!link_stats_results) {
1376 WMA_LOGA("%s: link_stats_results is NULL", __func__);
1377 return -EINVAL;
1378 }
1379
Wu Gao478282a2017-09-19 15:45:29 +08001380 if (fixed_param->radio_id >= link_stats_results->num_radio) {
1381 WMA_LOGE("%s, invalid radio id:%d, num radio:%d",
1382 __func__, fixed_param->radio_id,
1383 link_stats_results->num_radio);
1384 return -EINVAL;
1385 }
1386
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001387 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 -07001388 __func__, fixed_param->total_num_tx_power_levels,
1389 fixed_param->num_tx_power_levels,
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001390 fixed_param->power_level_offset,
1391 fixed_param->radio_id);
1392
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07001393 if (fixed_param->num_tx_power_levels > ((WMI_SVC_MSG_MAX_SIZE -
1394 sizeof(*fixed_param)) / sizeof(uint32_t))) {
1395 WMA_LOGE("%s: excess tx_power buffers:%d", __func__,
1396 fixed_param->num_tx_power_levels);
1397 QDF_ASSERT(0);
1398 return -EINVAL;
1399 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001400 rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] +
1401 fixed_param->radio_id;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001402 tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001403
1404 rs_results->total_num_tx_power_levels =
1405 fixed_param->total_num_tx_power_levels;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001406 if (!rs_results->total_num_tx_power_levels) {
1407 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001408 goto post_stats;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001409 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001410
1411 if (!rs_results->tx_time_per_power_level) {
1412 rs_results->tx_time_per_power_level = qdf_mem_malloc(
1413 sizeof(uint32_t) *
1414 rs_results->total_num_tx_power_levels);
1415 if (!rs_results->tx_time_per_power_level) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001416 WMA_LOGA("%s: Mem alloc fail for tx power level stats",
1417 __func__);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001418 /* In error case, atleast send the radio stats without
1419 * tx_power_level stats */
1420 rs_results->total_num_tx_power_levels = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001421 link_stats_results->nr_received++;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001422 goto post_stats;
1423 }
1424 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001425 qdf_mem_copy(&rs_results->tx_time_per_power_level[
1426 fixed_param->power_level_offset],
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001427 tx_power_level_values,
1428 sizeof(uint32_t) * fixed_param->num_tx_power_levels);
1429 if (rs_results->total_num_tx_power_levels ==
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001430 (fixed_param->num_tx_power_levels +
1431 fixed_param->power_level_offset)) {
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001432 link_stats_results->moreResultToFollow = 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001433 link_stats_results->nr_received++;
1434 }
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001435
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001436 WMA_LOGD("%s: moreResultToFollow: %u nr: %u nr_received: %u",
1437 __func__, link_stats_results->moreResultToFollow,
1438 link_stats_results->num_radio,
1439 link_stats_results->nr_received);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001440
1441 /* If still data to receive, return from here */
1442 if (link_stats_results->moreResultToFollow)
1443 return 0;
1444
1445post_stats:
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001446 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1447 /* Not received all radio stats yet, don't post yet */
1448 return 0;
1449 }
1450
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001451 /* call hdd callback with Link Layer Statistics
1452 * vdev_id/ifacId in link_stats_results will be
1453 * used to retrieve the correct HDD context
1454 */
1455 mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
1456 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1457 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001458 wma_unified_radio_tx_mem_free(handle);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001459
1460 return 0;
1461}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462
1463/**
1464 * wma_unified_link_radio_stats_event_handler() - radio link stats event handler
1465 * @handle: wma handle
1466 * @cmd_param_info: data received with event from fw
1467 * @len: length of data
1468 *
1469 * Return: 0 for success or error code
1470 */
1471static int wma_unified_link_radio_stats_event_handler(void *handle,
1472 uint8_t *cmd_param_info,
1473 uint32_t len)
1474{
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001475 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1477 wmi_radio_link_stats_event_fixed_param *fixed_param;
1478 wmi_radio_link_stats *radio_stats;
1479 wmi_channel_stats *channel_stats;
1480 tSirLLStatsResults *link_stats_results;
1481 uint8_t *results, *t_radio_stats, *t_channel_stats;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001482 uint32_t next_chan_offset, count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 size_t radio_stats_size, chan_stats_size;
1484 size_t link_stats_results_size;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001485 tSirWifiRadioStat *rs_results;
1486 tSirWifiChannelStats *chn_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001487
Anurag Chouhan6d760662016-02-20 16:05:43 +05301488 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489
1490 if (!pMac) {
1491 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1492 return -EINVAL;
1493 }
1494
1495 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1496 WMA_LOGD("%s: HDD callback is null", __func__);
1497 return -EINVAL;
1498 }
1499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 param_tlvs = (WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1501 if (!param_tlvs) {
1502 WMA_LOGA("%s: Invalid stats event", __func__);
1503 return -EINVAL;
1504 }
1505
1506 /*
1507 * cmd_param_info contains
1508 * wmi_radio_link_stats_event_fixed_param fixed_param;
1509 * size of(struct wmi_radio_link_stats);
1510 * num_channels * size of(struct wmi_channel_stats)
1511 */
1512 fixed_param = param_tlvs->fixed_param;
1513 radio_stats = param_tlvs->radio_stats;
1514 channel_stats = param_tlvs->channel_stats;
1515
1516 if (!fixed_param || !radio_stats ||
1517 (radio_stats->num_channels && !channel_stats)) {
1518 WMA_LOGA("%s: Invalid param_tlvs for Radio Stats", __func__);
1519 return -EINVAL;
1520 }
1521
1522 radio_stats_size = sizeof(tSirWifiRadioStat);
1523 chan_stats_size = sizeof(tSirWifiChannelStats);
1524 link_stats_results_size = sizeof(*link_stats_results) +
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001525 fixed_param->num_radio * radio_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001526
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001527 if (!wma_handle->link_stats_results) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001528 wma_handle->link_stats_results = qdf_mem_malloc(
1529 link_stats_results_size);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001530 if (NULL == wma_handle->link_stats_results) {
1531 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
1532 __func__, link_stats_results_size);
1533 return -ENOMEM;
1534 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 }
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001536 link_stats_results = wma_handle->link_stats_results;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001538 WMA_LOGD("Radio stats Fixed Param:");
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001539 WMA_LOGD("req_id: %u num_radio: %u more_radio_events: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 fixed_param->request_id, fixed_param->num_radio,
1541 fixed_param->more_radio_events);
1542
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001543 WMA_LOGD("Radio Info: radio_id: %u on_time: %u tx_time: %u rx_time: %u on_time_scan: %u",
1544 radio_stats->radio_id, radio_stats->on_time,
1545 radio_stats->tx_time, radio_stats->rx_time,
1546 radio_stats->on_time_scan);
1547 WMA_LOGD("on_time_nbd: %u on_time_gscan: %u on_time_roam_scan: %u",
1548 radio_stats->on_time_nbd,
1549 radio_stats->on_time_gscan, radio_stats->on_time_roam_scan);
1550 WMA_LOGD("on_time_pno_scan: %u on_time_hs20: %u num_channels: %u",
1551 radio_stats->on_time_pno_scan, radio_stats->on_time_hs20,
1552 radio_stats->num_channels);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001553 WMA_LOGD("on_time_host_scan: %u, on_time_lpi_scan: %u",
1554 radio_stats->on_time_host_scan, radio_stats->on_time_lpi_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 link_stats_results->paramId = WMI_LINK_STATS_RADIO;
1557 link_stats_results->rspId = fixed_param->request_id;
1558 link_stats_results->ifaceId = 0;
1559 link_stats_results->num_radio = fixed_param->num_radio;
1560 link_stats_results->peer_event_number = 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001561
1562 /*
1563 * Backward compatibility:
1564 * There are firmware(s) which will send Radio stats only with
1565 * more_radio_events set to 0 and firmware which sends Radio stats
1566 * followed by tx_power level stats with more_radio_events set to 1.
1567 * if more_radio_events is set to 1, buffer the radio stats and
1568 * wait for tx_power_level stats.
1569 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001570 link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
1571
1572 results = (uint8_t *) link_stats_results->results;
1573 t_radio_stats = (uint8_t *) radio_stats;
1574 t_channel_stats = (uint8_t *) channel_stats;
1575
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001576 rs_results = (tSirWifiRadioStat *) &results[0] + radio_stats->radio_id;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001577 rs_results->radio = radio_stats->radio_id;
1578 rs_results->onTime = radio_stats->on_time;
1579 rs_results->txTime = radio_stats->tx_time;
1580 rs_results->rxTime = radio_stats->rx_time;
1581 rs_results->onTimeScan = radio_stats->on_time_scan;
1582 rs_results->onTimeNbd = radio_stats->on_time_nbd;
1583 rs_results->onTimeGscan = radio_stats->on_time_gscan;
1584 rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
1585 rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
1586 rs_results->onTimeHs20 = radio_stats->on_time_hs20;
1587 rs_results->total_num_tx_power_levels = 0;
1588 rs_results->tx_time_per_power_level = NULL;
1589 rs_results->numChannels = radio_stats->num_channels;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001590 rs_results->on_time_host_scan = radio_stats->on_time_host_scan;
1591 rs_results->on_time_lpi_scan = radio_stats->on_time_lpi_scan;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001592 rs_results->channels = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001594 if (rs_results->numChannels) {
1595 rs_results->channels = (tSirWifiChannelStats *) qdf_mem_malloc(
1596 radio_stats->num_channels *
1597 chan_stats_size);
1598 if (rs_results->channels == NULL) {
1599 WMA_LOGD("%s: could not allocate mem for channel stats (size=%zu)",
1600 __func__, radio_stats->num_channels * chan_stats_size);
1601 wma_unified_radio_tx_mem_free(handle);
1602 return -ENOMEM;
1603 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001605 chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
1606 next_chan_offset = WMI_TLV_HDR_SIZE;
1607 WMA_LOGD("Channel Stats Info");
1608 for (count = 0; count < radio_stats->num_channels; count++) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001609 WMA_LOGD("channel_width %u center_freq %u center_freq0 %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001610 channel_stats->channel_width,
1611 channel_stats->center_freq,
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001612 channel_stats->center_freq0);
1613 WMA_LOGD("center_freq1 %u radio_awake_time %u cca_busy_time %u",
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001614 channel_stats->center_freq1,
1615 channel_stats->radio_awake_time,
1616 channel_stats->cca_busy_time);
1617 channel_stats++;
1618
1619 qdf_mem_copy(chn_results,
1620 t_channel_stats + next_chan_offset,
1621 chan_stats_size);
1622 chn_results++;
1623 next_chan_offset += sizeof(*channel_stats);
1624 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 }
1626
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001627 if (link_stats_results->moreResultToFollow) {
1628 /* More results coming, don't post yet */
1629 return 0;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001630 }
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001631 link_stats_results->nr_received++;
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001632
1633 if (link_stats_results->num_radio != link_stats_results->nr_received) {
1634 /* Not received all radio stats yet, don't post yet */
1635 return 0;
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001636 }
1637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
1639 WMA_LINK_LAYER_STATS_RESULTS_RSP,
1640 link_stats_results);
Srinivas Girigowda57b450e2016-10-27 21:00:46 -07001641 wma_unified_radio_tx_mem_free(handle);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001642
1643 return 0;
1644}
1645
Zhang Qiana6e9c102016-12-22 16:47:24 +08001646#ifdef WLAN_PEER_PS_NOTIFICATION
1647/**
1648 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1649 * @handle: wma handle
1650 * @event: FW event
1651 * @len: length of FW event
1652 *
1653 * Once peer STA power state changes, an event will be indicated by
1654 * FW. This function send a link layer state change msg to HDD. HDD
1655 * link layer callback will converts the event to NL msg.
1656 *
1657 * Return: 0 Success. Others fail.
1658 */
1659static int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1660 u_int32_t len)
1661{
1662 WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *param_buf;
1663 wmi_peer_sta_ps_statechange_event_fixed_param *fixed_param;
1664 tSirWifiPeerStat *peer_stat;
1665 tSirWifiPeerInfo *peer_info;
1666 tSirLLStatsResults *link_stats_results;
1667 tSirMacAddr mac_address;
1668 uint32_t result_len;
1669 cds_msg_t sme_msg = { 0 };
1670 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1671
1672 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1673
1674 if (!mac) {
1675 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1676 return -EINVAL;
1677 }
1678
1679 if (!mac->sme.link_layer_stats_ext_cb) {
1680 WMA_LOGD("%s: HDD callback is null", __func__);
1681 return -EINVAL;
1682 }
1683
1684 WMA_LOGD("%s: Posting Peer Stats PS event to HDD", __func__);
1685
1686 param_buf = (WMI_PEER_STA_PS_STATECHG_EVENTID_param_tlvs *)event;
1687 fixed_param = param_buf->fixed_param;
1688
1689 result_len = sizeof(tSirLLStatsResults) +
1690 sizeof(tSirWifiPeerStat) +
1691 sizeof(tSirWifiPeerInfo);
1692 link_stats_results = qdf_mem_malloc(result_len);
1693 if (link_stats_results == NULL) {
1694 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1695 return -EINVAL;
1696 }
1697
1698 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->peer_macaddr, &mac_address[0]);
1699 WMA_LOGD("Peer power state change event from FW");
1700 WMA_LOGD("Fixed Param:");
1701 WMA_LOGD("MAC address: %2x:%2x:%2x:%2x:%2x:%2x, Power state: %d",
1702 mac_address[0], mac_address[1], mac_address[2],
1703 mac_address[3], mac_address[4], mac_address[5],
1704 fixed_param->peer_ps_state);
1705
1706 link_stats_results->paramId = WMI_LL_STATS_EXT_PS_CHG;
1707 link_stats_results->num_peers = 1;
1708 link_stats_results->peer_event_number = 1;
1709 link_stats_results->moreResultToFollow = 0;
1710
1711 peer_stat = (tSirWifiPeerStat *)link_stats_results->results;
1712 peer_stat->numPeers = 1;
1713 peer_info = (tSirWifiPeerInfo *)peer_stat->peerInfo;
1714 qdf_mem_copy(&peer_info->peerMacAddress,
1715 &mac_address,
1716 sizeof(tSirMacAddr));
1717 peer_info->power_saving = fixed_param->peer_ps_state;
1718
1719 sme_msg.type = eWMI_SME_LL_STATS_IND;
1720 sme_msg.bodyptr = link_stats_results;
1721 sme_msg.bodyval = 0;
1722
Zhang Qian73c348a2017-03-13 16:15:55 +08001723 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001724 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1725 WMA_LOGE("%s: Fail to post ps change ind msg", __func__);
1726 qdf_mem_free(link_stats_results);
1727 }
1728
1729 return 0;
1730}
1731#else
1732/**
1733 * wma_peer_ps_evt_handler() - handler for PEER power state change.
1734 * @handle: wma handle
1735 * @event: FW event
1736 * @len: length of FW event
1737 *
1738 * Once peer STA power state changes, an event will be indicated by
1739 * FW. This function send a link layer state change msg to HDD. HDD
1740 * link layer callback will converts the event to NL msg.
1741 *
1742 * Return: 0 Success. Others fail.
1743 */
1744static inline int wma_peer_ps_evt_handler(void *handle, u_int8_t *event,
1745 u_int32_t len)
1746{
1747 return 0;
1748}
1749#endif
1750
1751/**
1752 * wma_tx_failure_cb() - TX failure callback
1753 * @ctx: txrx context
1754 * @num_msdu: number of msdu with the same status
1755 * @tid: TID number
1756 * @status: failure status
1757 */
1758void wma_tx_failure_cb(void *ctx, uint32_t num_msdu,
1759 uint8_t tid, enum htt_tx_status status)
1760{
1761 tSirLLStatsResults *results;
1762 struct sir_wifi_iface_tx_fail *tx_fail;
1763 struct scheduler_msg sme_msg = { 0 };
1764 QDF_STATUS qdf_status;
1765 tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
1766
1767 if (!mac) {
1768 WMA_LOGD("%s: NULL mac ptr. Exiting", __func__);
1769 return;
1770 }
1771
1772 if (!mac->sme.link_layer_stats_ext_cb) {
1773 WMA_LOGD("%s: HDD callback is null", __func__);
1774 return;
1775 }
1776
1777 results = qdf_mem_malloc(sizeof(tSirLLStatsResults) +
1778 sizeof(struct sir_wifi_iface_tx_fail));
1779 if (results == NULL) {
1780 WMA_LOGE("%s: Cannot allocate link layer stats.", __func__);
1781 return;
1782 }
1783
1784 results->paramId = WMI_LL_STATS_EXT_TX_FAIL;
1785 results->num_peers = 1;
1786 results->peer_event_number = 1;
1787 results->moreResultToFollow = 0;
1788
1789 tx_fail = (struct sir_wifi_iface_tx_fail *)results->results;
1790 tx_fail->tid = tid;
1791 tx_fail->msdu_num = num_msdu;
1792 tx_fail->status = status;
1793
1794 sme_msg.type = eWMI_SME_LL_STATS_IND;
1795 sme_msg.bodyptr = results;
1796 sme_msg.bodyval = 0;
1797
1798 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
1799 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1800 WMA_LOGE("%s: Fail to post TX failure ind msg", __func__);
1801 qdf_mem_free(results);
1802 }
1803}
1804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805/**
1806 * wma_register_ll_stats_event_handler() - register link layer stats related
1807 * event handler
1808 * @wma_handle: wma handle
1809 *
1810 * Return: none
1811 */
1812void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
1813{
1814 if (NULL == wma_handle) {
1815 WMA_LOGE("%s: wma_handle is NULL", __func__);
1816 return;
1817 }
1818
1819 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301820 WMI_IFACE_LINK_STATS_EVENTID,
1821 wma_unified_link_iface_stats_event_handler,
1822 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301824 WMI_PEER_LINK_STATS_EVENTID,
1825 wma_unified_link_peer_stats_event_handler,
1826 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001827 wmi_unified_register_event_handler(wma_handle->wmi_handle,
Govind Singhd76a5b02016-03-08 15:12:14 +05301828 WMI_RADIO_LINK_STATS_EVENTID,
1829 wma_unified_link_radio_stats_event_handler,
1830 WMA_RX_SERIALIZER_CTX);
Srinivas Girigowdaad874a82016-10-25 14:08:00 -07001831 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1832 WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID,
1833 wma_unified_radio_tx_power_level_stats_event_handler,
1834 WMA_RX_SERIALIZER_CTX);
Zhang Qiana6e9c102016-12-22 16:47:24 +08001835 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1836 WMI_PEER_STA_PS_STATECHG_EVENTID,
1837 wma_peer_ps_evt_handler,
1838 WMA_RX_SERIALIZER_CTX);
Zhang Qian73c348a2017-03-13 16:15:55 +08001839 wmi_unified_register_event_handler(wma_handle->wmi_handle,
1840 WMI_REPORT_STATS_EVENTID,
1841 wma_ll_stats_evt_handler,
1842 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844}
1845
1846
1847/**
1848 * wma_process_ll_stats_clear_req() - clear link layer stats
1849 * @wma: wma handle
1850 * @clearReq: ll stats clear request command params
1851 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301852 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001854QDF_STATUS wma_process_ll_stats_clear_req(tp_wma_handle wma,
1855 const tpSirLLStatsClearReq clearReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856{
Govind Singh4863da42016-03-08 11:45:00 +05301857 struct ll_stats_clear_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 int ret;
1859
1860 if (!clearReq || !wma) {
1861 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301862 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001863 }
1864
Deepak Dhamdhere6adc08e2017-07-27 09:33:22 -07001865 if (!wma->interfaces[clearReq->staId].handle) {
1866 WMA_LOGE("%s: vdev_id %d handle is NULL",
1867 __func__, clearReq->staId);
1868 return QDF_STATUS_E_FAILURE;
1869 }
1870
Govind Singh4863da42016-03-08 11:45:00 +05301871 cmd.stop_req = clearReq->stopReq;
1872 cmd.sta_id = clearReq->staId;
1873 cmd.stats_clear_mask = clearReq->statsClearReqMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874
Govind Singh4863da42016-03-08 11:45:00 +05301875 ret = wmi_unified_process_ll_stats_clear_cmd(wma->wmi_handle, &cmd,
1876 wma->interfaces[clearReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 if (ret) {
1878 WMA_LOGE("%s: Failed to send clear link stats req", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301879 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 }
1881
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301882 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883}
1884
1885/**
1886 * wma_process_ll_stats_set_req() - link layer stats set request
1887 * @wma: wma handle
1888 * @setReq: ll stats set request command params
1889 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301890 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001892QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma,
1893 const tpSirLLStatsSetReq setReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894{
Govind Singh4863da42016-03-08 11:45:00 +05301895 struct ll_stats_set_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 int ret;
1897
1898 if (!setReq || !wma) {
1899 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301900 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 }
1902
Govind Singh4863da42016-03-08 11:45:00 +05301903 cmd.mpdu_size_threshold = setReq->mpduSizeThreshold;
1904 cmd.aggressive_statistics_gathering =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 setReq->aggressiveStatisticsGathering;
1906
Govind Singh4863da42016-03-08 11:45:00 +05301907 ret = wmi_unified_process_ll_stats_set_cmd(wma->wmi_handle,
1908 &cmd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 if (ret) {
1910 WMA_LOGE("%s: Failed to send set link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301911 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 }
1913
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301914 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915}
1916
1917/**
1918 * wma_process_ll_stats_get_req() - link layer stats get request
1919 * @wma:wma handle
1920 * @getReq:ll stats get request command params
1921 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301922 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 */
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07001924QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
1925 const tpSirLLStatsGetReq getReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926{
Govind Singh4863da42016-03-08 11:45:00 +05301927 struct ll_stats_get_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 int ret;
1929
1930 if (!getReq || !wma) {
1931 WMA_LOGE("%s: input pointer is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301932 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933 }
1934
Selvaraj, Sridhar171e2252016-06-22 22:33:26 +05301935 if (!wma->interfaces[getReq->staId].vdev_active) {
1936 WMA_LOGE("%s: vdev not created yet", __func__);
1937 return QDF_STATUS_E_FAILURE;
1938 }
1939
Govind Singh4863da42016-03-08 11:45:00 +05301940 cmd.req_id = getReq->reqId;
1941 cmd.param_id_mask = getReq->paramIdMask;
1942 cmd.sta_id = getReq->staId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943
Govind Singh4863da42016-03-08 11:45:00 +05301944 ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd,
1945 wma->interfaces[getReq->staId].addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 if (ret) {
1947 WMA_LOGE("%s: Failed to send get link stats request", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301948 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 }
1950
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301951 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952}
1953
1954/**
1955 * wma_unified_link_iface_stats_event_handler() - link iface stats event handler
1956 * @wma:wma handle
1957 * @cmd_param_info: data from event
1958 * @len: length
1959 *
1960 * Return: 0 for success or error code
1961 */
1962int wma_unified_link_iface_stats_event_handler(void *handle,
1963 uint8_t *cmd_param_info,
1964 uint32_t len)
1965{
1966 WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
1967 wmi_iface_link_stats_event_fixed_param *fixed_param;
1968 wmi_iface_link_stats *link_stats;
1969 wmi_wmm_ac_stats *ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001970 wmi_iface_offload_stats *offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 tSirLLStatsResults *link_stats_results;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001972 uint8_t *results, *t_link_stats, *t_ac_stats, *t_offload_stats;
1973 uint32_t next_res_offset, next_ac_offset, next_offload_offset, count;
1974 uint32_t roaming_offset, size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 size_t link_stats_size, ac_stats_size, iface_info_size;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08001976 size_t link_stats_results_size, offload_stats_size;
1977 size_t total_ac_size, total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978
Anurag Chouhan6d760662016-02-20 16:05:43 +05301979 tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980
1981 if (!pMac) {
1982 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
1983 return -EINVAL;
1984 }
1985
1986 if (!pMac->sme.pLinkLayerStatsIndCallback) {
1987 WMA_LOGD("%s: HDD callback is null", __func__);
1988 return -EINVAL;
1989 }
1990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 param_tlvs = (WMI_IFACE_LINK_STATS_EVENTID_param_tlvs *) cmd_param_info;
1992 if (!param_tlvs) {
1993 WMA_LOGA("%s: Invalid stats event", __func__);
1994 return -EINVAL;
1995 }
1996
1997 /*
1998 * cmd_param_info contains
1999 * wmi_iface_link_stats_event_fixed_param fixed_param;
2000 * wmi_iface_link_stats iface_link_stats;
2001 * iface_link_stats->num_ac * size of(struct wmi_wmm_ac_stats)
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002002 * fixed_param->num_offload_stats * size of(wmi_iface_offload_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 */
2004 fixed_param = param_tlvs->fixed_param;
2005 link_stats = param_tlvs->iface_link_stats;
2006 ac_stats = param_tlvs->ac;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002007 offload_stats = param_tlvs->iface_offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002009 if (!fixed_param || !link_stats || (link_stats->num_ac && !ac_stats) ||
2010 (fixed_param->num_offload_stats && !offload_stats)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 WMA_LOGA("%s: Invalid param_tlvs for Iface Stats", __func__);
2012 return -EINVAL;
2013 }
2014
2015 link_stats_size = sizeof(tSirWifiIfaceStat);
2016 iface_info_size = sizeof(tSirWifiInterfaceInfo);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 ac_stats_size = sizeof(tSirWifiWmmAcStat);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002019 offload_stats_size = sizeof(struct wifi_iface_offload_stat);
2020
2021 total_ac_size = ac_stats_size * WIFI_AC_MAX;
2022 total_offload_size = offload_stats_size * WMI_OFFLOAD_STATS_TYPE_MAX +
2023 member_size(tSirWifiIfaceStat, num_offload_stats);
2024
2025 link_stats_results_size = sizeof(*link_stats_results) + link_stats_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302027 link_stats_results = qdf_mem_malloc(link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 if (!link_stats_results) {
2029 WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
2030 __func__, link_stats_results_size);
2031 return -ENOMEM;
2032 }
2033
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302034 qdf_mem_zero(link_stats_results, link_stats_results_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035
2036 link_stats_results->paramId = WMI_LINK_STATS_IFACE;
2037 link_stats_results->rspId = fixed_param->request_id;
2038 link_stats_results->ifaceId = fixed_param->vdev_id;
2039 link_stats_results->num_peers = link_stats->num_peers;
2040 link_stats_results->peer_event_number = 0;
2041 link_stats_results->moreResultToFollow = 0;
2042
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002043 /* results is copied to tSirWifiIfaceStat in upper layer
2044 * tSirWifiIfaceStat
2045 * - tSirWifiInterfaceInfo (all fields except roaming is
2046 * filled by host in the upper layer)
2047 * - various members of tSirWifiIfaceStat (from wmi_iface_link_stats)
2048 * - ACs information (from wmi_wmm_ac_stats)
2049 * - num_offload_stats (from fixed param)
2050 * - offload stats (from wmi_iface_offload_stats)
2051 */
2052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 results = (uint8_t *) link_stats_results->results;
2054 t_link_stats = (uint8_t *) link_stats;
2055 t_ac_stats = (uint8_t *) ac_stats;
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002056 t_offload_stats = (uint8_t *) offload_stats;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057
2058 /* Copy roaming state */
2059 roaming_offset = offsetof(tSirWifiInterfaceInfo, roaming);
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002060 size = member_size(tSirWifiInterfaceInfo, roaming);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002062 qdf_mem_copy(results + roaming_offset, &link_stats->roam_state, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002064 next_res_offset = iface_info_size;
2065 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 t_link_stats + WMI_TLV_HDR_SIZE,
2067 link_stats_size - iface_info_size -
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002068 total_ac_size - total_offload_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002070 next_res_offset = link_stats_size - total_ac_size - total_offload_size;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 next_ac_offset = WMI_TLV_HDR_SIZE;
2072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002073 for (count = 0; count < link_stats->num_ac; count++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002074 ac_stats++;
2075
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302076 qdf_mem_copy(results + next_res_offset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 t_ac_stats + next_ac_offset, ac_stats_size);
2078 next_res_offset += ac_stats_size;
2079 next_ac_offset += sizeof(*ac_stats);
2080 }
2081
Krishna Kumaar Natarajan7bff29b2017-03-08 16:05:05 -08002082 next_res_offset = link_stats_size - total_offload_size;
2083 /* copy num_offload_stats into result */
2084 size = member_size(tSirWifiIfaceStat, num_offload_stats);
2085 qdf_mem_copy(results + next_res_offset, &fixed_param->num_offload_stats,
2086 size);
2087
2088 next_res_offset += size;
2089 next_offload_offset = WMI_TLV_HDR_SIZE;
2090
2091 for (count = 0; count < fixed_param->num_offload_stats; count++) {
2092 qdf_mem_copy(results + next_res_offset,
2093 t_offload_stats + next_offload_offset,
2094 offload_stats_size);
2095 next_res_offset += offload_stats_size;
2096 next_offload_offset += sizeof(*offload_stats);
2097 }
2098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099 /* call hdd callback with Link Layer Statistics
2100 * vdev_id/ifacId in link_stats_results will be
2101 * used to retrieve the correct HDD context
2102 */
2103 pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
2104 WMA_LINK_LAYER_STATS_RESULTS_RSP,
2105 link_stats_results);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302106 qdf_mem_free(link_stats_results);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107
2108 return 0;
2109}
2110
Zhang Qian73c348a2017-03-13 16:15:55 +08002111/**
2112 * wma_config_stats_ext_threshold - set threthold for MAC counters
2113 * @wma: wma handler
2114 * @threshold: threhold for MAC counters
2115 *
2116 * For each MAC layer counter, FW holds two copies. One is the current value.
2117 * The other is the last report. Once a current counter's increment is larger
2118 * than the threshold, FW will indicate that counter to host even if the
2119 * monitoring timer does not expire.
2120 *
2121 * Return: None
2122 */
2123void wma_config_stats_ext_threshold(tp_wma_handle wma,
2124 struct sir_ll_ext_stats_threshold *thresh)
2125{
2126 uint32_t len, tag, hdr_len;
2127 uint8_t *buf_ptr;
2128 wmi_buf_t buf;
2129 wmi_pdev_set_stats_threshold_cmd_fixed_param *cmd;
2130 wmi_chan_cca_stats_thresh *cca;
2131 wmi_peer_signal_stats_thresh *signal;
2132 wmi_tx_stats_thresh *tx;
2133 wmi_rx_stats_thresh *rx;
2134
2135 if (!thresh) {
2136 WMA_LOGE(FL("Invalid threshold input."));
2137 return;
2138 }
2139
2140 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param) +
2141 sizeof(wmi_chan_cca_stats_thresh) +
2142 sizeof(wmi_peer_signal_stats_thresh) +
2143 sizeof(wmi_tx_stats_thresh) +
2144 sizeof(wmi_rx_stats_thresh) +
2145 5 * WMI_TLV_HDR_SIZE;
2146 buf = wmi_buf_alloc(wma->wmi_handle, len);
2147 if (!buf) {
2148 WMA_LOGP("%s: wmi_buf_alloc failed", __func__);
2149 return;
2150 }
2151
2152 buf_ptr = (u_int8_t *)wmi_buf_data(buf);
2153 tag = WMITLV_TAG_STRUC_wmi_pdev_set_stats_threshold_cmd_fixed_param;
2154 hdr_len = WMITLV_GET_STRUCT_TLVLEN(
2155 wmi_pdev_set_stats_threshold_cmd_fixed_param);
2156 WMA_LOGD(FL("Setting fixed parameters. tag=%d, len=%d"), tag, hdr_len);
2157 cmd = (wmi_pdev_set_stats_threshold_cmd_fixed_param *)buf_ptr;
2158 WMITLV_SET_HDR(&cmd->tlv_header, tag, hdr_len);
2159 cmd->enable_thresh = thresh->enable;
2160 cmd->use_thresh_bitmap = thresh->enable_bitmap;
2161 cmd->gbl_thresh = thresh->global_threshold;
2162 cmd->cca_thresh_enable_bitmap = thresh->cca_bitmap;
2163 cmd->signal_thresh_enable_bitmap = thresh->signal_bitmap;
2164 cmd->tx_thresh_enable_bitmap = thresh->tx_bitmap;
2165 cmd->rx_thresh_enable_bitmap = thresh->rx_bitmap;
2166 len = sizeof(wmi_pdev_set_stats_threshold_cmd_fixed_param);
2167
2168 tag = WMITLV_TAG_STRUC_wmi_chan_cca_stats_thresh,
2169 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_chan_cca_stats_thresh);
2170 cca = (wmi_chan_cca_stats_thresh *)(buf_ptr + len);
2171 WMITLV_SET_HDR(&cca->tlv_header, tag, hdr_len);
2172 WMA_LOGD(FL("Setting cca parameters. tag=%d, len=%d"), tag, hdr_len);
2173 cca->idle_time = thresh->cca.idle_time;
2174 cca->tx_time = thresh->cca.tx_time;
2175 cca->rx_in_bss_time = thresh->cca.rx_in_bss_time;
2176 cca->rx_out_bss_time = thresh->cca.rx_out_bss_time;
2177 cca->rx_busy_time = thresh->cca.rx_busy_time;
2178 cca->rx_in_bad_cond_time = thresh->cca.rx_in_bad_cond_time;
2179 cca->tx_in_bad_cond_time = thresh->cca.tx_in_bad_cond_time;
2180 cca->wlan_not_avail_time = thresh->cca.wlan_not_avail_time;
2181 WMA_LOGD(FL("idle time=%d, tx_time=%d, in_bss=%d, out_bss=%d"),
2182 cca->idle_time, cca->tx_time,
2183 cca->rx_in_bss_time, cca->rx_out_bss_time);
2184 WMA_LOGD(FL("rx_busy=%d, rx_bad=%d, tx_bad=%d, not_avail=%d"),
2185 cca->rx_busy_time, cca->rx_in_bad_cond_time,
2186 cca->tx_in_bad_cond_time, cca->wlan_not_avail_time);
2187 len += sizeof(wmi_chan_cca_stats_thresh);
2188
2189 signal = (wmi_peer_signal_stats_thresh *)(buf_ptr + len);
2190 tag = WMITLV_TAG_STRUC_wmi_peer_signal_stats_thresh;
2191 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_peer_signal_stats_thresh);
2192 WMA_LOGD(FL("Setting signal parameters. tag=%d, len=%d"), tag, hdr_len);
2193 WMITLV_SET_HDR(&signal->tlv_header, tag, hdr_len);
2194 signal->per_chain_snr = thresh->signal.snr;
2195 signal->per_chain_nf = thresh->signal.nf;
2196 WMA_LOGD(FL("snr=%d, nf=%d"), signal->per_chain_snr,
2197 signal->per_chain_nf);
2198 len += sizeof(wmi_peer_signal_stats_thresh);
2199
2200 tx = (wmi_tx_stats_thresh *)(buf_ptr + len);
2201 tag = WMITLV_TAG_STRUC_wmi_tx_stats_thresh;
2202 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_tx_stats_thresh);
2203 WMA_LOGD(FL("Setting TX parameters. tag=%d, len=%d"), tag, len);
2204 WMITLV_SET_HDR(&tx->tlv_header, tag, hdr_len);
2205 tx->tx_msdu_cnt = thresh->tx.msdu;
2206 tx->tx_mpdu_cnt = thresh->tx.mpdu;
2207 tx->tx_ppdu_cnt = thresh->tx.ppdu;
2208 tx->tx_bytes = thresh->tx.bytes;
2209 tx->tx_msdu_drop_cnt = thresh->tx.msdu_drop;
2210 tx->tx_drop_bytes = thresh->tx.byte_drop;
2211 tx->tx_mpdu_retry_cnt = thresh->tx.mpdu_retry;
2212 tx->tx_mpdu_fail_cnt = thresh->tx.mpdu_fail;
2213 tx->tx_ppdu_fail_cnt = thresh->tx.ppdu_fail;
2214 tx->tx_mpdu_aggr = thresh->tx.aggregation;
2215 tx->tx_succ_mcs = thresh->tx.succ_mcs;
2216 tx->tx_fail_mcs = thresh->tx.fail_mcs;
2217 tx->tx_ppdu_delay = thresh->tx.delay;
2218 WMA_LOGD(FL("msdu=%d, mpdu=%d, ppdu=%d, bytes=%d, msdu_drop=%d"),
2219 tx->tx_msdu_cnt, tx->tx_mpdu_cnt, tx->tx_ppdu_cnt,
2220 tx->tx_bytes, tx->tx_msdu_drop_cnt);
2221 WMA_LOGD(FL("byte_drop=%d, mpdu_retry=%d, mpdu_fail=%d, ppdu_fail=%d"),
2222 tx->tx_drop_bytes, tx->tx_mpdu_retry_cnt,
2223 tx->tx_mpdu_fail_cnt, tx->tx_ppdu_fail_cnt);
2224 WMA_LOGD(FL("aggr=%d, succ_mcs=%d, fail_mcs=%d, delay=%d"),
2225 tx->tx_mpdu_aggr, tx->tx_succ_mcs, tx->tx_fail_mcs,
2226 tx->tx_ppdu_delay);
2227 len += sizeof(wmi_tx_stats_thresh);
2228
2229 rx = (wmi_rx_stats_thresh *)(buf_ptr + len);
2230 tag = WMITLV_TAG_STRUC_wmi_rx_stats_thresh,
2231 hdr_len = WMITLV_GET_STRUCT_TLVLEN(wmi_rx_stats_thresh);
2232 WMITLV_SET_HDR(&rx->tlv_header, tag, hdr_len);
2233 WMA_LOGD(FL("Setting RX parameters. tag=%d, len=%d"), tag, hdr_len);
2234 rx->mac_rx_mpdu_cnt = thresh->rx.mpdu;
2235 rx->mac_rx_bytes = thresh->rx.bytes;
2236 rx->phy_rx_ppdu_cnt = thresh->rx.ppdu;
2237 rx->phy_rx_bytes = thresh->rx.ppdu_bytes;
2238 rx->rx_disorder_cnt = thresh->rx.disorder;
2239 rx->rx_mpdu_retry_cnt = thresh->rx.mpdu_retry;
2240 rx->rx_mpdu_dup_cnt = thresh->rx.mpdu_dup;
2241 rx->rx_mpdu_discard_cnt = thresh->rx.mpdu_discard;
2242 rx->rx_mpdu_aggr = thresh->rx.aggregation;
2243 rx->rx_mcs = thresh->rx.mcs;
2244 rx->sta_ps_inds = thresh->rx.ps_inds;
2245 rx->sta_ps_durs = thresh->rx.ps_durs;
2246 rx->rx_probe_reqs = thresh->rx.probe_reqs;
2247 rx->rx_oth_mgmts = thresh->rx.other_mgmt;
2248 WMA_LOGD(FL("rx_mpdu=%d, rx_bytes=%d, rx_ppdu=%d, rx_pbytes=%d"),
2249 rx->mac_rx_mpdu_cnt, rx->mac_rx_bytes,
2250 rx->phy_rx_ppdu_cnt, rx->phy_rx_bytes);
2251 WMA_LOGD(FL("disorder=%d, rx_dup=%d, rx_aggr=%d, rx_mcs=%d"),
2252 rx->rx_disorder_cnt, rx->rx_mpdu_dup_cnt,
2253 rx->rx_mpdu_aggr, rx->rx_mcs);
2254 WMA_LOGD(FL("rx_ind=%d, rx_dur=%d, rx_probe=%d, rx_mgmt=%d"),
2255 rx->sta_ps_inds, rx->sta_ps_durs,
2256 rx->rx_probe_reqs, rx->rx_oth_mgmts);
2257 len += sizeof(wmi_rx_stats_thresh);
2258
2259 WMA_LOGA("WMA --> WMI_PDEV_SET_STATS_THRESHOLD_CMDID(0x%x), length=%d",
2260 WMI_PDEV_SET_STATS_THRESHOLD_CMDID, len);
2261 if (EOK != wmi_unified_cmd_send(wma->wmi_handle,
2262 buf, len,
2263 WMI_PDEV_SET_STATS_THRESHOLD_CMDID)) {
2264 WMA_LOGE("Failed to send WMI_PDEV_SET_STATS_THRESHOLD_CMDID");
2265 wmi_buf_free(buf);
2266 }
2267}
2268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2270
2271/**
2272 * wma_update_pdev_stats() - update pdev stats
2273 * @wma: wma handle
2274 * @pdev_stats: pdev stats
2275 *
2276 * Return: none
2277 */
2278static void wma_update_pdev_stats(tp_wma_handle wma,
2279 wmi_pdev_stats *pdev_stats)
2280{
2281 tAniGetPEStatsRsp *stats_rsp_params;
2282 uint32_t temp_mask;
2283 uint8_t *stats_buf;
2284 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2285 struct wma_txrx_node *node;
2286 uint8_t i;
2287
2288 for (i = 0; i < wma->max_bssid; i++) {
2289 node = &wma->interfaces[i];
2290 stats_rsp_params = node->stats_rsp;
2291 if (stats_rsp_params) {
2292 node->fw_stats_set |= FW_PDEV_STATS_SET;
2293 WMA_LOGD("<---FW PDEV STATS received for vdevId:%d", i);
2294 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2295 temp_mask = stats_rsp_params->statsMask;
2296 if (temp_mask & (1 << eCsrSummaryStats))
2297 stats_buf += sizeof(tCsrSummaryStatsInfo);
2298
2299 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2300 classa_stats =
2301 (tCsrGlobalClassAStatsInfo *) stats_buf;
2302 classa_stats->max_pwr = pdev_stats->chan_tx_pwr;
2303 }
2304 }
2305 }
2306}
2307
2308/**
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302309 * wma_vdev_stats_lost_link_helper() - helper function to extract
2310 * lost link information from vdev statistics event while deleting BSS.
2311 * @wma: WMA handle
2312 * @vdev_stats: statistics information from firmware
2313 *
2314 * This is for informing HDD to collect lost link information while
2315 * disconnection. Following conditions to check
2316 * 1. vdev is up
2317 * 2. bssid is zero. When handling DELETE_BSS request message, it sets bssid to
2318 * zero, hence add the check here to indicate the event comes during deleting
2319 * BSS
2320 * 3. DELETE_BSS is the request message queued. Put this condition check on the
2321 * last one as it consumes more resource searching entries in the list
2322 *
2323 * Return: none
2324 */
2325static void wma_vdev_stats_lost_link_helper(tp_wma_handle wma,
2326 wmi_vdev_stats *vdev_stats)
2327{
2328 struct wma_txrx_node *node;
2329 int32_t rssi;
2330 struct wma_target_req *req_msg;
2331 static const uint8_t zero_mac[QDF_MAC_ADDR_SIZE] = {0};
Naveen Rawatf440a132017-05-05 12:27:39 -07002332 int32_t bcn_snr, dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302333
2334 node = &wma->interfaces[vdev_stats->vdev_id];
Mukul Sharmaf9047232017-03-02 16:58:56 +05302335 if (wma_is_vdev_up(vdev_stats->vdev_id) &&
Hanumanth Reddy Pothulaaef3c7f2017-05-18 12:19:23 +05302336 !qdf_mem_cmp(node->bssid, zero_mac, QDF_MAC_ADDR_SIZE)) {
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302337 req_msg = wma_peek_vdev_req(wma, vdev_stats->vdev_id,
2338 WMA_TARGET_REQ_TYPE_VDEV_STOP);
2339 if ((NULL == req_msg) ||
2340 (WMA_DELETE_BSS_REQ != req_msg->msg_type)) {
2341 WMA_LOGD(FL("cannot find DELETE_BSS request message"));
2342 return;
2343 }
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002344 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2345 dat_snr = vdev_stats->vdev_snr.dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302346 WMA_LOGD(FL("get vdev id %d, beancon snr %d, data snr %d"),
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002347 vdev_stats->vdev_id, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302348
2349 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002350 rssi = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302351 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002352 rssi = dat_snr;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302353 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302354 rssi = WMA_TGT_INVALID_SNR;
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302355
2356 /* Get the absolute rssi value from the current rssi value */
2357 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2358 wma_lost_link_info_handler(wma, vdev_stats->vdev_id, rssi);
2359 }
2360}
2361
2362/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363 * wma_update_vdev_stats() - update vdev stats
2364 * @wma: wma handle
2365 * @vdev_stats: vdev stats
2366 *
2367 * Return: none
2368 */
2369static void wma_update_vdev_stats(tp_wma_handle wma,
2370 wmi_vdev_stats *vdev_stats)
2371{
2372 tAniGetPEStatsRsp *stats_rsp_params;
2373 tCsrSummaryStatsInfo *summary_stats = NULL;
2374 uint8_t *stats_buf;
2375 struct wma_txrx_node *node;
2376 uint8_t i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002377 int32_t rssi = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302378 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq *) wma->pGetRssiReq;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002380 struct scheduler_msg sme_msg = { 0 };
Naveen Rawatf440a132017-05-05 12:27:39 -07002381 int32_t bcn_snr, dat_snr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002383 bcn_snr = vdev_stats->vdev_snr.bcn_snr;
2384 dat_snr = vdev_stats->vdev_snr.dat_snr;
2385 WMA_LOGD("vdev id %d beancon snr %d data snr %d",
2386 vdev_stats->vdev_id, bcn_snr, dat_snr);
2387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 node = &wma->interfaces[vdev_stats->vdev_id];
2389 stats_rsp_params = node->stats_rsp;
2390 if (stats_rsp_params) {
2391 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2392 node->fw_stats_set |= FW_VDEV_STATS_SET;
2393 WMA_LOGD("<---FW VDEV STATS received for vdevId:%d",
2394 vdev_stats->vdev_id);
2395 if (stats_rsp_params->statsMask & (1 << eCsrSummaryStats)) {
2396 summary_stats = (tCsrSummaryStatsInfo *) stats_buf;
2397 for (i = 0; i < 4; i++) {
2398 summary_stats->tx_frm_cnt[i] =
2399 vdev_stats->tx_frm_cnt[i];
2400 summary_stats->fail_cnt[i] =
2401 vdev_stats->fail_cnt[i];
2402 summary_stats->multiple_retry_cnt[i] =
2403 vdev_stats->multiple_retry_cnt[i];
2404 }
2405
2406 summary_stats->rx_frm_cnt = vdev_stats->rx_frm_cnt;
2407 summary_stats->rx_error_cnt = vdev_stats->rx_err_cnt;
2408 summary_stats->rx_discard_cnt =
2409 vdev_stats->rx_discard_cnt;
2410 summary_stats->ack_fail_cnt = vdev_stats->ack_fail_cnt;
2411 summary_stats->rts_succ_cnt = vdev_stats->rts_succ_cnt;
2412 summary_stats->rts_fail_cnt = vdev_stats->rts_fail_cnt;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002413 /* Update SNR and RSSI in SummaryStats */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302414 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002415 summary_stats->snr = bcn_snr;
2416 summary_stats->rssi =
2417 bcn_snr + WMA_TGT_NOISE_FLOOR_DBM;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302418 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002419 summary_stats->snr = dat_snr;
2420 summary_stats->rssi =
Naveen Rawatf440a132017-05-05 12:27:39 -07002421 dat_snr + WMA_TGT_NOISE_FLOOR_DBM;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002422 } else {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302423 summary_stats->snr = WMA_TGT_INVALID_SNR;
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002424 summary_stats->rssi = 0;
2425 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 }
2427 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428
2429 if (pGetRssiReq && pGetRssiReq->sessionId == vdev_stats->vdev_id) {
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302430 if (WMA_TGT_IS_VALID_SNR(bcn_snr)) {
2431 rssi = bcn_snr;
2432 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2433 } else if (WMA_TGT_IS_VALID_SNR(dat_snr)) {
2434 rssi = dat_snr;
2435 rssi = rssi + WMA_TGT_NOISE_FLOOR_DBM;
2436 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 /*
2438 * Firmware sends invalid snr till it sees
2439 * Beacon/Data after connection since after
2440 * vdev up fw resets the snr to invalid.
2441 * In this duartion Host will return the last know
2442 * rssi during connection.
2443 */
2444 WMA_LOGE("Invalid SNR from firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 }
2446
2447 WMA_LOGD("Average Rssi = %d, vdev id= %d", rssi,
2448 pGetRssiReq->sessionId);
2449
2450 /* update the average rssi value to UMAC layer */
2451 if (NULL != pGetRssiReq->rssiCallback) {
2452 ((tCsrRssiCallback) (pGetRssiReq->rssiCallback))(rssi,
2453 pGetRssiReq->staId,
2454 pGetRssiReq->pDevContext);
2455 }
2456
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302457 qdf_mem_free(pGetRssiReq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 wma->pGetRssiReq = NULL;
2459 }
2460
2461 if (node->psnr_req) {
2462 tAniGetSnrReq *p_snr_req = node->psnr_req;
2463
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302464 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Varun Reddy Yeturu83ccb9b2016-06-29 11:55:41 -07002465 p_snr_req->snr = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302466 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
Naveen Rawat2cb788d2016-10-11 17:44:44 -07002467 p_snr_req->snr = dat_snr;
Varun Reddy Yeturue5476a92017-02-18 12:16:43 -08002468 else
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302469 p_snr_req->snr = WMA_TGT_INVALID_SNR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470
2471 sme_msg.type = eWNI_SME_SNR_IND;
2472 sme_msg.bodyptr = p_snr_req;
2473 sme_msg.bodyval = 0;
2474
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002475 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302476 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 WMA_LOGE("%s: Fail to post snr ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302478 qdf_mem_free(p_snr_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 }
2480
2481 node->psnr_req = NULL;
2482 }
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05302483 wma_vdev_stats_lost_link_helper(wma, vdev_stats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484}
2485
2486/**
2487 * wma_post_stats() - update stats to PE
2488 * @wma: wma handle
2489 * @node: txrx node
2490 *
2491 * Return: none
2492 */
2493static void wma_post_stats(tp_wma_handle wma, struct wma_txrx_node *node)
2494{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 /* send response to UMAC */
Naveen Rawat3c49d192017-03-02 18:43:16 -08002496 wma_send_msg(wma, WMA_GET_STATISTICS_RSP, node->stats_rsp, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 node->stats_rsp = NULL;
2498 node->fw_stats_set = 0;
2499}
2500
2501/**
2502 * wma_update_peer_stats() - update peer stats
2503 * @wma: wma handle
2504 * @peer_stats: peer stats
2505 *
2506 * Return: none
2507 */
2508static void wma_update_peer_stats(tp_wma_handle wma,
2509 wmi_peer_stats *peer_stats)
2510{
2511 tAniGetPEStatsRsp *stats_rsp_params;
2512 tCsrGlobalClassAStatsInfo *classa_stats = NULL;
2513 struct wma_txrx_node *node;
2514 uint8_t *stats_buf, vdev_id, macaddr[IEEE80211_ADDR_LEN], mcsRateFlags;
2515 uint32_t temp_mask;
2516
2517 WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, &macaddr[0]);
2518 if (!wma_find_vdev_by_bssid(wma, macaddr, &vdev_id))
2519 return;
2520
2521 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002522 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2523 if (stats_rsp_params) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 node->fw_stats_set |= FW_PEER_STATS_SET;
2525 WMA_LOGD("<-- FW PEER STATS received for vdevId:%d", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2527 temp_mask = stats_rsp_params->statsMask;
2528 if (temp_mask & (1 << eCsrSummaryStats))
2529 stats_buf += sizeof(tCsrSummaryStatsInfo);
2530
2531 if (temp_mask & (1 << eCsrGlobalClassAStats)) {
2532 classa_stats = (tCsrGlobalClassAStatsInfo *) stats_buf;
2533 WMA_LOGD("peer tx rate:%d", peer_stats->peer_tx_rate);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002534 /* The linkspeed returned by fw is in kbps so convert
2535 * it in to units of 500kbps which is expected by UMAC
2536 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 if (peer_stats->peer_tx_rate) {
2538 classa_stats->tx_rate =
2539 peer_stats->peer_tx_rate / 500;
2540 }
2541
2542 classa_stats->tx_rate_flags = node->rate_flags;
2543 if (!(node->rate_flags & eHAL_TX_RATE_LEGACY)) {
2544 classa_stats->mcs_index =
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002545 wma_get_mcs_idx(
2546 (peer_stats->peer_tx_rate /
2547 100), node->rate_flags,
2548 node->nss, &mcsRateFlags);
Jeff Johnsonad0b2c62017-03-16 14:37:38 -07002549 classa_stats->nss = node->nss;
2550 classa_stats->mcs_rate_flags = mcsRateFlags;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 }
2552 /* FW returns tx power in intervals of 0.5 dBm
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002553 * Convert it back to intervals of 1 dBm
2554 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 classa_stats->max_pwr =
2556 roundup(classa_stats->max_pwr, 2) >> 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 }
2559}
2560
2561/**
2562 * wma_post_link_status() - post link status to SME
2563 * @pGetLinkStatus: SME Link status
2564 * @link_status: Link status
2565 *
2566 * Return: none
2567 */
2568void wma_post_link_status(tAniGetLinkStatus *pGetLinkStatus,
2569 uint8_t link_status)
2570{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302571 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002572 struct scheduler_msg sme_msg = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573
2574 pGetLinkStatus->linkStatus = link_status;
2575 sme_msg.type = eWNI_SME_LINK_STATUS_IND;
2576 sme_msg.bodyptr = pGetLinkStatus;
2577 sme_msg.bodyval = 0;
2578
Rajeev Kumarb60abe42017-01-21 15:39:31 -08002579 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 WMA_LOGE("%s: Fail to post link status ind msg", __func__);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302582 qdf_mem_free(pGetLinkStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 }
2584}
2585
2586/**
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302587 * wma_update_per_chain_rssi_stats() - to store per chain rssi stats
2588 * @wma: wma handle
2589 * @rssi_stats: rssi stats
2590 * @rssi_per_chain_stats: buffer where rssi stats to be stored
2591 *
2592 * This function stores per chain rssi stats received from fw for all vdevs for
2593 * which the stats were requested into a csr stats structure.
2594 *
2595 * Return: void
2596 */
2597static void wma_update_per_chain_rssi_stats(tp_wma_handle wma,
2598 wmi_rssi_stats *rssi_stats,
2599 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats)
2600{
2601 int i;
Naveen Rawatf440a132017-05-05 12:27:39 -07002602 int32_t bcn_snr, dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302603
2604 for (i = 0; i < NUM_CHAINS_MAX; i++) {
2605 bcn_snr = rssi_stats->rssi_avg_beacon[i];
2606 dat_snr = rssi_stats->rssi_avg_data[i];
2607 WMA_LOGD("chain %d beacon snr %d data snr %d",
2608 i, bcn_snr, dat_snr);
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302609 if (WMA_TGT_IS_VALID_SNR(bcn_snr))
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302610 rssi_per_chain_stats->rssi[i] = bcn_snr;
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302611 else if (WMA_TGT_IS_VALID_SNR(dat_snr))
2612 rssi_per_chain_stats->rssi[i] = dat_snr;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302613 else
2614 /*
2615 * Firmware sends invalid snr till it sees
2616 * Beacon/Data after connection since after
2617 * vdev up fw resets the snr to invalid.
2618 * In this duartion Host will return an invalid rssi
2619 * value.
2620 */
Hanumanth Reddy Pothula90051782017-05-04 22:14:43 +05302621 rssi_per_chain_stats->rssi[i] = WMA_TGT_INVALID_SNR;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302622
2623 /*
2624 * Get the absolute rssi value from the current rssi value the
2625 * sinr value is hardcoded into 0 in the qcacld-new/CORE stack
2626 */
2627 rssi_per_chain_stats->rssi[i] += WMA_TGT_NOISE_FLOOR_DBM;
2628 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(rssi_stats->peer_macaddr),
2629 rssi_per_chain_stats->peer_mac_addr);
2630 }
2631}
2632
2633/**
2634 * wma_update_rssi_stats() - to update rssi stats for all vdevs
2635 * for which the stats were requested.
2636 * @wma: wma handle
2637 * @rssi_stats: rssi stats
2638 *
2639 * This function updates the rssi stats for all vdevs for which
2640 * the stats were requested.
2641 *
2642 * Return: void
2643 */
2644static void wma_update_rssi_stats(tp_wma_handle wma,
2645 wmi_rssi_stats *rssi_stats)
2646{
2647 tAniGetPEStatsRsp *stats_rsp_params;
2648 struct csr_per_chain_rssi_stats_info *rssi_per_chain_stats = NULL;
2649 struct wma_txrx_node *node;
2650 uint8_t *stats_buf;
2651 uint32_t temp_mask;
2652 uint8_t vdev_id;
2653
2654 vdev_id = rssi_stats->vdev_id;
2655 node = &wma->interfaces[vdev_id];
Naveen Rawat3c49d192017-03-02 18:43:16 -08002656 stats_rsp_params = (tAniGetPEStatsRsp *) node->stats_rsp;
2657 if (stats_rsp_params) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302658 node->fw_stats_set |= FW_RSSI_PER_CHAIN_STATS_SET;
2659 WMA_LOGD("<-- FW RSSI PER CHAIN STATS received for vdevId:%d",
2660 vdev_id);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302661 stats_buf = (uint8_t *) (stats_rsp_params + 1);
2662 temp_mask = stats_rsp_params->statsMask;
2663
2664 if (temp_mask & (1 << eCsrSummaryStats))
2665 stats_buf += sizeof(tCsrSummaryStatsInfo);
2666 if (temp_mask & (1 << eCsrGlobalClassAStats))
2667 stats_buf += sizeof(tCsrGlobalClassAStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302668 if (temp_mask & (1 << eCsrGlobalClassDStats))
2669 stats_buf += sizeof(tCsrGlobalClassDStatsInfo);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302670
2671 if (temp_mask & (1 << csr_per_chain_rssi_stats)) {
2672 rssi_per_chain_stats =
2673 (struct csr_per_chain_rssi_stats_info *)stats_buf;
2674 wma_update_per_chain_rssi_stats(wma, rssi_stats,
2675 rssi_per_chain_stats);
2676 }
2677 }
2678}
2679
2680
2681/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 * wma_link_status_event_handler() - link status event handler
2683 * @handle: wma handle
2684 * @cmd_param_info: data from event
2685 * @len: length
2686 *
2687 * Return: 0 for success or error code
2688 */
2689int wma_link_status_event_handler(void *handle, uint8_t *cmd_param_info,
2690 uint32_t len)
2691{
2692 tp_wma_handle wma = (tp_wma_handle) handle;
2693 WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *param_buf;
2694 wmi_vdev_rate_stats_event_fixed_param *event;
2695 wmi_vdev_rate_ht_info *ht_info;
2696 struct wma_txrx_node *intr = wma->interfaces;
2697 uint8_t link_status = LINK_STATUS_LEGACY;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002698 uint32_t i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699
2700 param_buf =
2701 (WMI_UPDATE_VDEV_RATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2702 if (!param_buf) {
2703 WMA_LOGA("%s: Invalid stats event", __func__);
2704 return -EINVAL;
2705 }
2706
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002707 event = (wmi_vdev_rate_stats_event_fixed_param *)
2708 param_buf->fixed_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 ht_info = (wmi_vdev_rate_ht_info *) param_buf->ht_info;
2710
2711 WMA_LOGD("num_vdev_stats: %d", event->num_vdev_stats);
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002712
2713 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2714 sizeof(*event)) / sizeof(*ht_info))) {
2715 WMA_LOGE("%s: excess vdev_stats buffers:%d", __func__,
2716 event->num_vdev_stats);
2717 QDF_ASSERT(0);
2718 return -EINVAL;
2719 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 for (i = 0; (i < event->num_vdev_stats) && ht_info; i++) {
2721 WMA_LOGD("%s vdevId:%d tx_nss:%d rx_nss:%d tx_preamble:%d rx_preamble:%d",
2722 __func__, ht_info->vdevid, ht_info->tx_nss,
2723 ht_info->rx_nss, ht_info->tx_preamble,
2724 ht_info->rx_preamble);
2725 if (ht_info->vdevid < wma->max_bssid
2726 && intr[ht_info->vdevid].plink_status_req) {
2727 if (ht_info->tx_nss || ht_info->rx_nss)
2728 link_status = LINK_STATUS_MIMO;
2729
2730 if ((ht_info->tx_preamble == LINK_RATE_VHT) ||
2731 (ht_info->rx_preamble == LINK_RATE_VHT))
2732 link_status |= LINK_STATUS_VHT;
2733
2734 if (intr[ht_info->vdevid].nss == 2)
2735 link_status |= LINK_SUPPORT_MIMO;
2736
2737 if (intr[ht_info->vdevid].rate_flags &
2738 (eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 |
2739 eHAL_TX_RATE_VHT80))
2740 link_status |= LINK_SUPPORT_VHT;
2741
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07002742 wma_post_link_status(
2743 intr[ht_info->vdevid].plink_status_req,
2744 link_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745 intr[ht_info->vdevid].plink_status_req = NULL;
2746 link_status = LINK_STATUS_LEGACY;
2747 }
2748
2749 ht_info++;
2750 }
2751
2752 return 0;
2753}
2754
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302755int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
2756{
2757 struct rso_cmd_status *rso_status;
Rajeev Kumarcf7bd802017-04-18 11:11:42 -07002758 struct scheduler_msg sme_msg = {0};
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302759 QDF_STATUS qdf_status;
2760
2761 rso_status = qdf_mem_malloc(sizeof(*rso_status));
2762 if (!rso_status) {
2763 WMA_LOGE("%s: malloc fails for rso cmd status", __func__);
2764 return -ENOMEM;
2765 }
2766
2767 rso_status->vdev_id = wmi_event->vdev_id;
2768 if (WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS == wmi_event->notif)
2769 rso_status->status = true;
2770 else if (WMI_ROAM_NOTIF_SCAN_MODE_FAIL == wmi_event->notif)
2771 rso_status->status = false;
2772 sme_msg.type = eWNI_SME_RSO_CMD_STATUS_IND;
2773 sme_msg.bodyptr = rso_status;
2774 sme_msg.bodyval = 0;
2775 WMA_LOGI("%s: Post RSO cmd status to SME", __func__);
2776
2777 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2778 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2779 WMA_LOGE("%s: fail to post RSO cmd status to SME", __func__);
2780 qdf_mem_free(rso_status);
2781 }
2782 return 0;
2783}
2784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785/**
Will Huanga9814592017-05-24 15:47:58 +08002786 * wma_handle_sta_peer_info() - handle peer information in
2787 * peer stats
2788 * @num_peer_stats: peer number
2789 * @peer_stats: peer stats received from firmware
2790 * @peer_macaddr: the specified mac address
2791 * @sapaddr: sap mac address
2792 *
2793 * This function will send eWNI_SME_GET_PEER_INFO_IND
2794 * to sme with stations' information
2795 *
2796 */
2797static void wma_handle_sta_peer_info(uint32_t num_peer_stats,
2798 wmi_peer_stats *peer_stats,
2799 struct qdf_mac_addr peer_macaddr,
2800 uint8_t *sapaddr)
2801{
2802 QDF_STATUS qdf_status;
2803 wmi_mac_addr temp_addr;
2804 struct sir_peer_info_resp *peer_info;
2805 struct scheduler_msg sme_msg = {0};
2806 uint32_t i;
2807 uint32_t j = 0;
2808
2809 if (!qdf_is_macaddr_broadcast(&peer_macaddr)) {
2810 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_macaddr.bytes, &temp_addr);
2811 for (i = 0; i < num_peer_stats; i++) {
2812 if ((((temp_addr.mac_addr47to32) & 0x0000ffff) ==
2813 ((peer_stats->peer_macaddr.mac_addr47to32) &
2814 0x0000ffff))
2815 && (temp_addr.mac_addr31to0 ==
2816 peer_stats->peer_macaddr.mac_addr31to0)) {
2817
2818 break;
2819 }
2820 peer_stats = peer_stats + 1;
2821 }
2822 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2823 sizeof(peer_info->info[0]));
2824 if (NULL == peer_info) {
2825 WMA_LOGE("%s: Memory allocation failed.", __func__);
2826 return;
2827 }
2828 if (i < num_peer_stats) {
2829 peer_info->count = 1;
2830 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2831 peer_info->info[0].peer_macaddr.bytes);
2832 peer_info->info[0].rssi = peer_stats->peer_rssi;
2833 peer_info->info[0].tx_rate = peer_stats->peer_tx_rate;
2834 peer_info->info[0].rx_rate = peer_stats->peer_rx_rate;
2835 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2836 __func__,
2837 peer_info->info[0].peer_macaddr.bytes,
2838 peer_stats->peer_rssi,
2839 peer_stats->peer_tx_rate,
2840 peer_stats->peer_rx_rate);
2841 } else {
2842 WMA_LOGE("%s: no match mac address", __func__);
2843 peer_info->count = 0;
2844 }
2845 } else {
2846 peer_info = qdf_mem_malloc(sizeof(*peer_info) +
2847 num_peer_stats * sizeof(peer_info->info[0]));
2848 if (NULL == peer_info) {
2849 WMA_LOGE("%s: Memory allocation failed.", __func__);
2850 return;
2851 }
2852 peer_info->count = num_peer_stats;
2853
2854 for (i = 0; i < num_peer_stats; i++) {
2855 WMI_MAC_ADDR_TO_CHAR_ARRAY(&(peer_stats->peer_macaddr),
2856 peer_info->info[j].peer_macaddr.bytes);
2857 peer_info->info[j].rssi = peer_stats->peer_rssi;
2858 peer_info->info[j].tx_rate = peer_stats->peer_tx_rate;
2859 peer_info->info[j].rx_rate = peer_stats->peer_rx_rate;
2860 WMA_LOGD("%s peer %pM rssi %d tx_rate %d rx_rate %d",
2861 __func__,
2862 peer_info->info[j].peer_macaddr.bytes,
2863 peer_stats->peer_rssi,
2864 peer_stats->peer_tx_rate,
2865 peer_stats->peer_rx_rate);
2866 if (!qdf_mem_cmp(peer_info->info[j].peer_macaddr.bytes,
2867 sapaddr, QDF_MAC_ADDR_SIZE)) {
2868 peer_info->count = peer_info->count - 1;
2869 } else {
2870 j++;
2871 }
2872 peer_stats = peer_stats + 1;
2873 }
2874 WMA_LOGD("WDA send peer num %d", peer_info->count);
2875 }
2876
2877 sme_msg.type = eWNI_SME_GET_PEER_INFO_IND;
2878 sme_msg.bodyptr = peer_info;
2879 sme_msg.bodyval = 0;
2880
2881 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
2882 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2883 WMA_LOGE("%s: Fail to post get rssi msg", __func__);
2884 qdf_mem_free(peer_info);
2885 }
2886
2887 return;
2888}
2889
2890/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 * wma_stats_event_handler() - stats event handler
2892 * @handle: wma handle
2893 * @cmd_param_info: data from event
2894 * @len: length
2895 *
2896 * Return: 0 for success or error code
2897 */
2898int wma_stats_event_handler(void *handle, uint8_t *cmd_param_info,
2899 uint32_t len)
2900{
2901 tp_wma_handle wma = (tp_wma_handle) handle;
2902 WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
2903 wmi_stats_event_fixed_param *event;
2904 wmi_pdev_stats *pdev_stats;
2905 wmi_vdev_stats *vdev_stats;
2906 wmi_peer_stats *peer_stats;
Himanshu Agarwal37e42412016-07-21 14:35:09 +05302907 wmi_rssi_stats *rssi_stats;
2908 wmi_per_chain_rssi_stats *rssi_event;
2909 struct wma_txrx_node *node;
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002910 uint8_t *temp;
2911 uint32_t i;
2912 uint32_t buf_len = 0;
2913 bool excess_data = false;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05302914 wmi_congestion_stats *congestion_stats;
2915 tpAniSirGlobal mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) cmd_param_info;
2918 if (!param_buf) {
2919 WMA_LOGA("%s: Invalid stats event", __func__);
2920 return -EINVAL;
2921 }
2922 event = param_buf->fixed_param;
2923 temp = (uint8_t *) param_buf->data;
2924
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002925 do {
2926 if (event->num_pdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2927 sizeof(*event)) / sizeof(*pdev_stats))) {
2928 excess_data = true;
2929 break;
2930 } else {
2931 buf_len += event->num_pdev_stats * sizeof(*pdev_stats);
2932 }
2933
2934 if (event->num_vdev_stats > ((WMI_SVC_MSG_MAX_SIZE -
2935 sizeof(*event)) / sizeof(*vdev_stats))) {
2936 excess_data = true;
2937 break;
2938 } else {
2939 buf_len += event->num_vdev_stats * sizeof(*vdev_stats);
2940 }
2941
2942 if (event->num_peer_stats > ((WMI_SVC_MSG_MAX_SIZE -
2943 sizeof(*event)) / sizeof(*peer_stats))) {
2944 excess_data = true;
2945 break;
2946 } else {
2947 buf_len += event->num_peer_stats * sizeof(*peer_stats);
2948 }
2949
2950 rssi_event =
2951 (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
bingsf9047652017-08-31 08:05:54 +08002952 if (rssi_event) {
2953 if (rssi_event->num_per_chain_rssi_stats >
2954 ((WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) /
2955 sizeof(*rssi_event))) {
2956 excess_data = true;
2957 break;
2958 } else {
2959 buf_len += sizeof(*rssi_event) *
2960 rssi_event->num_per_chain_rssi_stats;
2961 }
Varun Reddy Yeturu46ba20c2017-08-17 15:03:27 -07002962 }
2963 } while (0);
2964
2965 if (excess_data ||
2966 (sizeof(*event) > WMI_SVC_MSG_MAX_SIZE - buf_len)) {
2967 WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d",
2968 event->num_pdev_stats, event->num_vdev_stats,
2969 event->num_peer_stats);
2970 QDF_ASSERT(0);
2971 return -EINVAL;
2972 }
2973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 if (event->num_pdev_stats > 0) {
2975 for (i = 0; i < event->num_pdev_stats; i++) {
2976 pdev_stats = (wmi_pdev_stats *) temp;
2977 wma_update_pdev_stats(wma, pdev_stats);
2978 temp += sizeof(wmi_pdev_stats);
2979 }
2980 }
2981
2982 if (event->num_vdev_stats > 0) {
2983 for (i = 0; i < event->num_vdev_stats; i++) {
2984 vdev_stats = (wmi_vdev_stats *) temp;
2985 wma_update_vdev_stats(wma, vdev_stats);
2986 temp += sizeof(wmi_vdev_stats);
2987 }
2988 }
2989
2990 if (event->num_peer_stats > 0) {
Will Huanga9814592017-05-24 15:47:58 +08002991 if (wma->get_sta_peer_info == true) {
2992 wma_handle_sta_peer_info(event->num_peer_stats,
2993 (wmi_peer_stats *)temp,
2994 wma->peer_macaddr,
2995 wma->myaddr);
2996 } else {
2997 for (i = 0; i < event->num_peer_stats; i++) {
2998 peer_stats = (wmi_peer_stats *) temp;
2999 wma_update_peer_stats(wma, peer_stats);
3000 temp += sizeof(wmi_peer_stats);
3001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 }
3003 }
3004
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303005 rssi_event = (wmi_per_chain_rssi_stats *) param_buf->chain_stats;
3006 if (rssi_event) {
Himanshu Agarwalcd8a84a2016-07-21 14:59:50 +05303007 if (((rssi_event->tlv_header & 0xFFFF0000) >> 16 ==
3008 WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats) &&
3009 ((rssi_event->tlv_header & 0x0000FFFF) ==
3010 WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats))) {
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303011 if (rssi_event->num_per_chain_rssi_stats > 0) {
3012 temp = (uint8_t *) rssi_event;
3013 temp += sizeof(*rssi_event);
Dustin Brownc4a5ba22016-11-10 17:21:18 -08003014
3015 /* skip past struct array tlv header */
3016 temp += WMI_TLV_HDR_SIZE;
3017
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303018 for (i = 0;
3019 i < rssi_event->num_per_chain_rssi_stats;
3020 i++) {
3021 rssi_stats = (wmi_rssi_stats *)temp;
3022 wma_update_rssi_stats(wma, rssi_stats);
3023 temp += sizeof(wmi_rssi_stats);
3024 }
3025 }
3026 }
3027 }
3028
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303029 congestion_stats = (wmi_congestion_stats *) param_buf->congestion_stats;
3030 if (congestion_stats) {
3031 if (((congestion_stats->tlv_header & 0xFFFF0000) >> 16 ==
3032 WMITLV_TAG_STRUC_wmi_congestion_stats) &&
3033 ((congestion_stats->tlv_header & 0x0000FFFF) ==
3034 WMITLV_GET_STRUCT_TLVLEN(wmi_congestion_stats))) {
3035 mac = cds_get_context(QDF_MODULE_ID_PE);
3036 if (!mac) {
3037 WMA_LOGE("%s: Invalid mac", __func__);
3038 return -EINVAL;
3039 }
3040 if (!mac->sme.congestion_cb) {
3041 WMA_LOGE("%s: Callback not registered",
3042 __func__);
3043 return -EINVAL;
3044 }
3045 WMA_LOGI("%s: congestion %d", __func__,
3046 congestion_stats->congestion);
3047 mac->sme.congestion_cb(mac->hHdd,
3048 congestion_stats->congestion,
3049 congestion_stats->vdev_id);
3050 }
3051 }
3052
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303053 for (i = 0; i < wma->max_bssid; i++) {
3054 node = &wma->interfaces[i];
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003055 if (node->fw_stats_set & FW_PEER_STATS_SET)
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303056 wma_post_stats(wma, node);
Himanshu Agarwal37e42412016-07-21 14:35:09 +05303057 }
3058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 return 0;
3060}
3061
3062/**
Will Huanga9814592017-05-24 15:47:58 +08003063 * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
3064 * @wma: wma interface
3065 * @stats_info: WMI peer info pointer
3066 * @peer_info: SIR peer info pointer
3067 *
3068 * This function will fill SIR peer info from WMI peer info struct
3069 *
3070 * Return: None
3071 */
3072static void wma_fill_peer_info(tp_wma_handle wma,
3073 wmi_peer_stats_info *stats_info,
3074 struct sir_peer_info_ext *peer_info)
3075{
3076 peer_info->tx_packets = stats_info->tx_packets.low_32;
3077 peer_info->tx_bytes = stats_info->tx_bytes.high_32;
3078 peer_info->tx_bytes <<= 32;
3079 peer_info->tx_bytes += stats_info->tx_bytes.low_32;
3080 peer_info->rx_packets = stats_info->rx_packets.low_32;
3081 peer_info->rx_bytes = stats_info->rx_bytes.high_32;
3082 peer_info->rx_bytes <<= 32;
3083 peer_info->rx_bytes += stats_info->rx_bytes.low_32;
3084 peer_info->tx_retries = stats_info->tx_retries;
3085 peer_info->tx_failed = stats_info->tx_failed;
3086 peer_info->rssi = stats_info->peer_rssi;
3087 peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
3088 peer_info->tx_rate_code = stats_info->last_tx_rate_code;
3089 peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
3090 peer_info->rx_rate_code = stats_info->last_rx_rate_code;
3091}
3092
3093/**
3094 * wma_peer_info_ext_rsp() - process peer ext info ext
3095 * @handle: wma interface
3096 * @buf: wmi event buf pointer
3097 *
3098 * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
3099 *
3100 * Return: 0 on success, error code otherwise
3101 */
3102static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
3103{
3104 wmi_peer_stats_info_event_fixed_param *event;
3105 wmi_peer_stats_info *stats_info;
3106 struct sir_peer_info_ext_resp *resp;
3107 struct sir_peer_info_ext *peer_info;
3108 struct scheduler_msg sme_msg = {0};
3109 int i, j = 0;
3110 QDF_STATUS qdf_status;
3111
3112 event = (wmi_peer_stats_info_event_fixed_param *)buf;
3113 stats_info = (wmi_peer_stats_info *)(buf +
3114 sizeof(wmi_peer_stats_info_event_fixed_param));
3115
3116 if (wma->get_one_peer_info) {
3117 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3118 sizeof(resp->info[0]));
3119 if (!resp) {
3120 WMA_LOGE(FL("resp allocation failed."));
3121 return QDF_STATUS_E_NOMEM;
3122 }
3123 resp->count = 0;
3124 peer_info = &resp->info[0];
3125 for (i = 0; i < event->num_peers; i++) {
3126 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3127 peer_info->peer_macaddr.bytes);
3128
3129 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3130 wma->peer_macaddr.bytes,
3131 QDF_MAC_ADDR_SIZE)) {
3132 wma_fill_peer_info(wma, stats_info, peer_info);
3133 resp->count++;
3134 break;
3135 }
3136
3137 stats_info = stats_info + 1;
3138 }
3139 } else {
3140 resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
3141 event->num_peers * sizeof(resp->info[0]));
3142 if (!resp) {
3143 WMA_LOGE(FL("resp allocation failed."));
3144 return QDF_STATUS_E_NOMEM;
3145 }
3146 resp->count = event->num_peers;
3147 for (i = 0; i < event->num_peers; i++) {
3148 peer_info = &resp->info[j];
3149 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
3150 peer_info->peer_macaddr.bytes);
3151
3152 if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
3153 wma->myaddr, QDF_MAC_ADDR_SIZE)) {
3154 resp->count = resp->count - 1;
3155 } else {
3156 wma_fill_peer_info(wma, stats_info, peer_info);
3157 j++;
3158 }
3159 stats_info = stats_info + 1;
3160 }
3161 }
3162
3163 sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
3164 sme_msg.bodyptr = resp;
3165 sme_msg.bodyval = 0;
3166
3167 qdf_status = scheduler_post_msg(QDF_MODULE_ID_SME, &sme_msg);
3168 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
3169 WMA_LOGE("%s: Fail to post get peer info msg", __func__);
3170 qdf_mem_free(resp);
3171 }
3172
3173 return qdf_status;
3174}
3175
3176/**
3177 * dump_peer_stats_info() - dump wmi peer info struct
3178 * @event: wmi peer info fixed param pointer
3179 * @peer_stats: wmi peer stats info pointer
3180 *
3181 * This function will dump wmi peer info struct
3182 *
3183 * Return: None
3184 */
3185static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
3186 wmi_peer_stats_info *peer_stats)
3187{
3188 int i;
3189 wmi_peer_stats_info *stats = peer_stats;
3190 u_int8_t mac[6];
3191
3192 WMA_LOGI("%s vdev_id %d, num_peers %d more_data %d",
3193 __func__, event->vdev_id,
3194 event->num_peers, event->more_data);
3195
3196 for (i = 0; i < event->num_peers; i++) {
3197 WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
3198 WMA_LOGI("%s mac %pM", __func__, mac);
3199 WMA_LOGI("%s tx_bytes %d %d tx_packets %d %d",
3200 __func__,
3201 stats->tx_bytes.low_32,
3202 stats->tx_bytes.high_32,
3203 stats->tx_packets.low_32,
3204 stats->tx_packets.high_32);
3205 WMA_LOGI("%s rx_bytes %d %d rx_packets %d %d",
3206 __func__,
3207 stats->rx_bytes.low_32,
3208 stats->rx_bytes.high_32,
3209 stats->rx_packets.low_32,
3210 stats->rx_packets.high_32);
3211 WMA_LOGI("%s tx_retries %d tx_failed %d",
3212 __func__, stats->tx_retries, stats->tx_failed);
3213 WMA_LOGI("%s tx_rate_code %x rx_rate_code %x",
3214 __func__,
3215 stats->last_tx_rate_code,
3216 stats->last_rx_rate_code);
3217 WMA_LOGI("%s tx_rate %x rx_rate %x",
3218 __func__,
3219 stats->last_tx_bitrate_kbps,
3220 stats->last_rx_bitrate_kbps);
3221 WMA_LOGI("%s peer_rssi %d", __func__, stats->peer_rssi);
3222 stats++;
3223 }
3224}
3225
3226int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
3227 u_int32_t len)
3228{
3229 tp_wma_handle wma = (tp_wma_handle) handle;
3230 WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
3231 wmi_peer_stats_info_event_fixed_param *event;
3232 u_int32_t buf_size;
3233 u_int8_t *buf;
3234
3235 param_buf =
3236 (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
3237 if (!param_buf) {
3238 WMA_LOGA("%s: Invalid stats event", __func__);
3239 return -EINVAL;
3240 }
3241
3242 WMA_LOGI("%s Recv WMI_PEER_STATS_INFO_EVENTID", __func__);
3243 event = param_buf->fixed_param;
Varun Reddy Yeturue4e2f292017-09-26 15:51:07 -07003244 if (event->num_peers >
3245 ((WMI_SVC_MSG_MAX_SIZE -
3246 sizeof(wmi_peer_stats_info_event_fixed_param))/
3247 sizeof(wmi_peer_stats_info))) {
3248 WMA_LOGE("Excess num of peers from fw %d", event->num_peers);
3249 return -EINVAL;
3250 }
Will Huanga9814592017-05-24 15:47:58 +08003251 buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
3252 sizeof(wmi_peer_stats_info) * event->num_peers;
3253 buf = qdf_mem_malloc(buf_size);
3254 if (!buf) {
3255 WMA_LOGE("%s: Failed alloc memory for buf", __func__);
3256 return -ENOMEM;
3257 }
3258
3259 qdf_mem_copy(buf, param_buf->fixed_param,
3260 sizeof(wmi_peer_stats_info_event_fixed_param));
3261 qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
3262 param_buf->peer_stats_info,
3263 sizeof(wmi_peer_stats_info) * event->num_peers);
3264 WMA_LOGI("%s dump peer stats info", __func__);
3265 dump_peer_stats_info(event, param_buf->peer_stats_info);
3266
3267 wma_peer_info_ext_rsp(wma, buf);
3268 qdf_mem_free(buf);
3269
3270 return 0;
3271}
3272
3273/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 * wma_send_link_speed() - send link speed to SME
3275 * @link_speed: link speed
3276 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303279QDF_STATUS wma_send_link_speed(uint32_t link_speed)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303281 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303282 tpAniSirGlobal mac_ctx;
3283 tSirLinkSpeedInfo *ls_ind;
3284
3285 mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
3286 if (!mac_ctx) {
3287 WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
3288 return QDF_STATUS_E_INVAL;
3289 }
3290
3291 ls_ind = (tSirLinkSpeedInfo *)qdf_mem_malloc(sizeof(tSirLinkSpeedInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 if (!ls_ind) {
3293 WMA_LOGE("%s: Memory allocation failed.", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303294 qdf_status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 } else {
3296 ls_ind->estLinkSpeed = link_speed;
Mukul Sharmac3886aa2017-05-04 17:53:22 +05303297 if (mac_ctx->sme.pLinkSpeedIndCb)
3298 mac_ctx->sme.pLinkSpeedIndCb(ls_ind,
3299 mac_ctx->sme.pLinkSpeedCbContext);
3300 else
3301 WMA_LOGD("%s: pLinkSpeedIndCb is null", __func__);
3302 qdf_mem_free(ls_ind);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306}
3307
3308/**
3309 * wma_link_speed_event_handler() - link speed event handler
3310 * @handle: wma handle
3311 * @cmd_param_info: event data
3312 * @len: length
3313 *
3314 * Return: 0 for success or error code
3315 */
3316int wma_link_speed_event_handler(void *handle, uint8_t *cmd_param_info,
3317 uint32_t len)
3318{
3319 WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *param_buf;
3320 wmi_peer_estimated_linkspeed_event_fixed_param *event;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303321 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003323 param_buf = (WMI_PEER_ESTIMATED_LINKSPEED_EVENTID_param_tlvs *)
3324 cmd_param_info;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325 if (!param_buf) {
3326 WMA_LOGE("%s: Invalid linkspeed event", __func__);
3327 return -EINVAL;
3328 }
3329 event = param_buf->fixed_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303330 qdf_status = wma_send_link_speed(event->est_linkspeed_kbps);
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003331 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 return 0;
3334}
3335
3336/**
3337 * wma_wni_cfg_dnld() - cfg download request
3338 * @handle: wma handle
3339 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303340 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303342QDF_STATUS wma_wni_cfg_dnld(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303344 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303345 void *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346
3347 WMA_LOGD("%s: Enter", __func__);
3348
3349 if (NULL == mac) {
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003350 WMA_LOGE("%s: Invalid context", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303351 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 }
3354
3355 process_cfg_download_req(mac);
3356
3357 WMA_LOGD("%s: Exit", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359}
3360
3361/**
3362 * wma_unified_debug_print_event_handler() - debug print event handler
3363 * @handle: wma handle
3364 * @datap: data pointer
3365 * @len: length
3366 *
3367 * Return: 0 for success or error code
3368 */
3369int wma_unified_debug_print_event_handler(void *handle, uint8_t *datap,
3370 uint32_t len)
3371{
3372 WMI_DEBUG_PRINT_EVENTID_param_tlvs *param_buf;
3373 uint8_t *data;
3374 uint32_t datalen;
3375
3376 param_buf = (WMI_DEBUG_PRINT_EVENTID_param_tlvs *) datap;
3377 if (!param_buf) {
3378 WMA_LOGE("Get NULL point message from FW");
3379 return -ENOMEM;
3380 }
3381 data = param_buf->data;
3382 datalen = param_buf->num_data;
3383
3384#ifdef BIG_ENDIAN_HOST
3385 {
3386 char dbgbuf[500] = { 0 };
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 memcpy(dbgbuf, data, datalen);
3389 SWAPME(dbgbuf, datalen);
3390 WMA_LOGD("FIRMWARE:%s", dbgbuf);
3391 return 0;
3392 }
3393#else
3394 WMA_LOGD("FIRMWARE:%s", data);
3395 return 0;
3396#endif /* BIG_ENDIAN_HOST */
3397}
3398
3399/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 * wma_is_sap_active() - check sap is active or not
3401 * @handle: wma handle
3402 *
3403 * Return: true/false
3404 */
3405bool wma_is_sap_active(tp_wma_handle wma_handle)
3406{
3407 int i;
3408
3409 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303410 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411 continue;
3412 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3413 wma_handle->interfaces[i].sub_type == 0)
3414 return true;
3415 }
3416 return false;
3417}
3418
3419/**
3420 * wma_is_p2p_go_active() - check p2p go is active or not
3421 * @handle: wma handle
3422 *
3423 * Return: true/false
3424 */
3425bool wma_is_p2p_go_active(tp_wma_handle wma_handle)
3426{
3427 int i;
3428
3429 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303430 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431 continue;
3432 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_AP &&
3433 wma_handle->interfaces[i].sub_type ==
3434 WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO)
3435 return true;
3436 }
3437 return false;
3438}
3439
3440/**
3441 * wma_is_p2p_cli_active() - check p2p cli is active or not
3442 * @handle: wma handle
3443 *
3444 * Return: true/false
3445 */
3446bool wma_is_p2p_cli_active(tp_wma_handle wma_handle)
3447{
3448 int i;
3449
3450 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303451 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452 continue;
3453 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3454 wma_handle->interfaces[i].sub_type ==
3455 WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT)
3456 return true;
3457 }
3458 return false;
3459}
3460
3461/**
3462 * wma_is_sta_active() - check sta is active or not
3463 * @handle: wma handle
3464 *
3465 * Return: true/false
3466 */
3467bool wma_is_sta_active(tp_wma_handle wma_handle)
3468{
3469 int i;
3470
3471 for (i = 0; i < wma_handle->max_bssid; i++) {
Mukul Sharmaf9047232017-03-02 16:58:56 +05303472 if (!wma_is_vdev_up(i))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 continue;
3474 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_STA &&
3475 wma_handle->interfaces[i].sub_type == 0)
3476 return true;
3477 if (wma_handle->interfaces[i].type == WMI_VDEV_TYPE_IBSS)
3478 return true;
3479 }
3480 return false;
3481}
3482
3483/**
3484 * wma_peer_phymode() - get phymode
3485 * @nw_type: nw type
3486 * @sta_type: sta type
3487 * @is_ht: is ht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003488 * @ch_width: supported channel width
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 * @is_vht: is vht supported
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003490 * @is_he: is HE supported
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 *
3492 * Return: WLAN_PHY_MODE
3493 */
3494WLAN_PHY_MODE wma_peer_phymode(tSirNwType nw_type, uint8_t sta_type,
3495 uint8_t is_ht, uint8_t ch_width,
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003496 uint8_t is_vht, bool is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497{
3498 WLAN_PHY_MODE phymode = MODE_UNKNOWN;
3499
3500 switch (nw_type) {
3501 case eSIR_11B_NW_TYPE:
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003502#ifdef FEATURE_WLAN_TDLS
3503 if (STA_ENTRY_TDLS_PEER == sta_type) {
3504 if (is_vht) {
3505 if (CH_WIDTH_80MHZ == ch_width)
3506 phymode = MODE_11AC_VHT80;
3507 else
3508 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3509 MODE_11AC_VHT40 :
3510 MODE_11AC_VHT20;
3511 } else if (is_ht) {
3512 phymode = (CH_WIDTH_40MHZ == ch_width) ?
3513 MODE_11NG_HT40 : MODE_11NG_HT20;
3514 } else
3515 phymode = MODE_11B;
3516 } else
3517#endif /* FEATURE_WLAN_TDLS */
3518 {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 phymode = MODE_11B;
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003520 if (is_ht || is_vht || is_he)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003521 WMA_LOGE("HT/VHT is enabled with 11B NW type");
Kabilan Kannanedff06d2017-08-23 16:55:13 -07003522 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523 break;
3524 case eSIR_11G_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003525 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526 phymode = MODE_11G;
3527 break;
3528 }
3529 if (CH_WIDTH_40MHZ < ch_width)
3530 WMA_LOGE("80/160 MHz BW sent in 11G, configured 40MHz");
3531 if (ch_width)
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003532 phymode = (is_he) ? MODE_11AX_HE40_2G : (is_vht) ?
3533 MODE_11AC_VHT40_2G : MODE_11NG_HT40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 else
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003535 phymode = (is_he) ? MODE_11AX_HE20_2G : (is_vht) ?
3536 MODE_11AC_VHT20_2G : MODE_11NG_HT20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 break;
3538 case eSIR_11A_NW_TYPE:
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003539 if (!(is_ht || is_vht || is_he)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 phymode = MODE_11A;
3541 break;
3542 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003543 if (is_he) {
3544 if (ch_width == CH_WIDTH_160MHZ)
3545 phymode = MODE_11AX_HE160;
3546 else if (ch_width == CH_WIDTH_80P80MHZ)
3547 phymode = MODE_11AX_HE80_80;
3548 else if (ch_width == CH_WIDTH_80MHZ)
3549 phymode = MODE_11AX_HE80;
3550 else
3551 phymode = (ch_width) ?
3552 MODE_11AX_HE40 : MODE_11AX_HE20;
3553 } else if (is_vht) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 if (ch_width == CH_WIDTH_160MHZ)
3555 phymode = MODE_11AC_VHT160;
3556 else if (ch_width == CH_WIDTH_80P80MHZ)
3557 phymode = MODE_11AC_VHT80_80;
Amar Singhal046eb8a2016-05-05 12:50:15 -07003558 else if (ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559 phymode = MODE_11AC_VHT80;
3560 else
3561 phymode = (ch_width) ?
3562 MODE_11AC_VHT40 : MODE_11AC_VHT20;
3563 } else
3564 phymode = (ch_width) ? MODE_11NA_HT40 : MODE_11NA_HT20;
3565 break;
3566 default:
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08003567 WMA_LOGE("%s: Invalid nw type %d", __func__, nw_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003568 break;
3569 }
Krishna Kumaar Natarajan0103ef82017-02-17 18:15:56 -08003570 WMA_LOGD(FL("nw_type %d is_ht %d ch_width %d is_vht %d is_he %d phymode %d"),
3571 nw_type, is_ht, ch_width, is_vht, is_he, phymode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572
3573 return phymode;
3574}
3575
3576/**
3577 * wma_txrx_fw_stats_reset() - reset txrx fw statistics
3578 * @wma_handle: wma handle
3579 * @vdev_id: vdev id
3580 * @value: value
3581 *
3582 * Return: 0 for success or return error
3583 */
3584int32_t wma_txrx_fw_stats_reset(tp_wma_handle wma_handle,
3585 uint8_t vdev_id, uint32_t value)
3586{
3587 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003588 struct cdp_vdev *vdev;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303589 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3590
3591 if (!soc) {
3592 WMA_LOGE("%s:SOC context is NULL", __func__);
3593 return -EINVAL;
3594 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595
3596 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3597 if (!vdev) {
3598 WMA_LOGE("%s:Invalid vdev handle", __func__);
3599 return -EINVAL;
3600 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303601 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 req.stats_type_reset_mask = value;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003603 cdp_fw_stats_get(soc, vdev, &req, false, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604
3605 return 0;
3606}
3607
3608#ifdef HELIUMPLUS
Jeff Johnson560dc562017-03-17 15:19:31 -07003609#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 ((_mask) = 1 << (_rate_info ## _V2))
3611#else /* !HELIUMPLUS */
Jeff Johnson560dc562017-03-17 15:19:31 -07003612#define SET_UPLOAD_MASK(_mask, _rate_info) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 ((_mask) = 1 << (_rate_info))
3614#endif
3615
Nirav Shah93e789e2016-04-14 19:47:43 +05303616#ifdef HELIUMPLUS
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003617static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303618{
3619 if (value > (HTT_DBG_NUM_STATS + 1) ||
3620 value == (HTT_DBG_STATS_RX_RATE_INFO + 1) ||
3621 value == (HTT_DBG_STATS_TX_RATE_INFO + 1) ||
3622 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3623 WMA_LOGE("%s: Not supported", __func__);
3624 return false;
3625 }
3626 return true;
3627}
3628#else
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003629static bool wma_is_valid_fw_stats_cmd(uint32_t value)
Nirav Shah93e789e2016-04-14 19:47:43 +05303630{
3631 if (value > (HTT_DBG_NUM_STATS + 1) ||
3632 value == (HTT_DBG_STATS_RX_RATE_INFO_V2 + 1) ||
3633 value == (HTT_DBG_STATS_TX_RATE_INFO_V2 + 1) ||
3634 value == (HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT + 1)) {
3635 WMA_LOGE("%s: Not supported", __func__);
3636 return false;
3637 }
3638 return true;
3639}
3640#endif
3641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642/**
3643 * wma_set_txrx_fw_stats_level() - set txrx fw stats level
3644 * @wma_handle: wma handle
3645 * @vdev_id: vdev id
3646 * @value: value
3647 *
3648 * Return: 0 for success or return error
3649 */
3650int32_t wma_set_txrx_fw_stats_level(tp_wma_handle wma_handle,
3651 uint8_t vdev_id, uint32_t value)
3652{
3653 struct ol_txrx_stats_req req;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003654 struct cdp_vdev *vdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655 uint32_t l_up_mask;
Nishank Aggarwala13b61d2016-12-01 12:53:58 +05303656 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3657
3658 if (!soc) {
3659 WMA_LOGE("%s:SOC context is NULL", __func__);
3660 return -EINVAL;
3661 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662
3663 vdev = wma_find_vdev_by_id(wma_handle, vdev_id);
3664 if (!vdev) {
3665 WMA_LOGE("%s:Invalid vdev handle", __func__);
3666 return -EINVAL;
3667 }
Nirav Shah93e789e2016-04-14 19:47:43 +05303668
3669 if (wma_is_valid_fw_stats_cmd(value) == false)
3670 return -EINVAL;
3671
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303672 qdf_mem_zero(&req, sizeof(req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 req.print.verbose = 1;
3674
Nirav Shah93e789e2016-04-14 19:47:43 +05303675 /* TODO: Need to check how to avoid mem leak*/
3676 l_up_mask = 1 << (value - 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677 req.stats_type_upload_mask = l_up_mask;
3678
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003679 cdp_fw_stats_get(soc, vdev, &req, false, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680
3681 return 0;
3682}
3683
3684/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685 * wma_get_stats_rsp_buf() - fill get stats response buffer
3686 * @get_stats_param: get stats parameters
3687 *
3688 * Return: stats response buffer
3689 */
3690static tAniGetPEStatsRsp *wma_get_stats_rsp_buf
3691 (tAniGetPEStatsReq *get_stats_param)
3692{
3693 tAniGetPEStatsRsp *stats_rsp_params;
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003694 uint32_t len, temp_mask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695
3696 len = sizeof(tAniGetPEStatsRsp);
3697 temp_mask = get_stats_param->statsMask;
3698
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003699 if (temp_mask & (1 << eCsrSummaryStats))
3700 len += sizeof(tCsrSummaryStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003702 if (temp_mask & (1 << eCsrGlobalClassAStats))
3703 len += sizeof(tCsrGlobalClassAStatsInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003705 if (temp_mask & (1 << eCsrGlobalClassDStats))
3706 len += sizeof(tCsrGlobalClassDStatsInfo);
3707
Jeff Johnsondfd360e2017-03-10 16:23:07 -08003708 if (temp_mask & (1 << csr_per_chain_rssi_stats))
3709 len += sizeof(struct csr_per_chain_rssi_stats_info);
3710
3711 stats_rsp_params = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003712 if (!stats_rsp_params) {
3713 WMA_LOGE("memory allocation failed for tAniGetPEStatsRsp");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303714 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 return NULL;
3716 }
3717
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718 stats_rsp_params->staId = get_stats_param->staId;
3719 stats_rsp_params->statsMask = get_stats_param->statsMask;
3720 stats_rsp_params->msgType = WMA_GET_STATISTICS_RSP;
3721 stats_rsp_params->msgLen = len - sizeof(tAniGetPEStatsRsp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303722 stats_rsp_params->rc = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 return stats_rsp_params;
3724}
3725
3726/**
3727 * wma_get_stats_req() - get stats request
3728 * @handle: wma handle
3729 * @get_stats_param: stats params
3730 *
3731 * Return: none
3732 */
3733void wma_get_stats_req(WMA_HANDLE handle,
3734 tAniGetPEStatsReq *get_stats_param)
3735{
3736 tp_wma_handle wma_handle = (tp_wma_handle) handle;
3737 struct wma_txrx_node *node;
Govind Singh4863da42016-03-08 11:45:00 +05303738 struct pe_stats_req cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 tAniGetPEStatsRsp *pGetPEStatsRspParams;
Govind Singh4863da42016-03-08 11:45:00 +05303740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741
3742 WMA_LOGD("%s: Enter", __func__);
3743 node = &wma_handle->interfaces[get_stats_param->sessionId];
3744 if (node->stats_rsp) {
3745 pGetPEStatsRspParams = node->stats_rsp;
3746 if (pGetPEStatsRspParams->staId == get_stats_param->staId &&
3747 pGetPEStatsRspParams->statsMask ==
3748 get_stats_param->statsMask) {
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07003749 WMA_LOGD("Stats for staId %d with stats mask %d is pending.. ignore new request",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 get_stats_param->staId,
3751 get_stats_param->statsMask);
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303752 pGetPEStatsRspParams =
3753 wma_get_stats_rsp_buf(get_stats_param);
3754 if (!pGetPEStatsRspParams) {
3755 WMA_LOGE("failed to allocate memory for stats response");
3756 goto end;
3757 }
3758 goto req_pending;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303760 qdf_mem_free(node->stats_rsp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761 node->stats_rsp = NULL;
3762 node->fw_stats_set = 0;
3763 }
3764 }
3765
3766 pGetPEStatsRspParams = wma_get_stats_rsp_buf(get_stats_param);
3767 if (!pGetPEStatsRspParams)
3768 goto end;
3769
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 node->fw_stats_set = 0;
Naveen Rawat3c49d192017-03-02 18:43:16 -08003771 if (node->stats_rsp) {
Jeff Johnsonadba3962017-09-18 08:12:35 -07003772 WMA_LOGD(FL("stats_rsp is not null, prev_value: %pK"),
Naveen Rawat3c49d192017-03-02 18:43:16 -08003773 node->stats_rsp);
3774 qdf_mem_free(node->stats_rsp);
3775 node->stats_rsp = NULL;
3776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 node->stats_rsp = pGetPEStatsRspParams;
Will Huanga9814592017-05-24 15:47:58 +08003778 wma_handle->get_sta_peer_info = false;
Jeff Johnsonadba3962017-09-18 08:12:35 -07003779 WMA_LOGD("stats_rsp allocated: %pK, sta_id: %d, mask: %d, vdev_id: %d",
Naveen Rawat3c49d192017-03-02 18:43:16 -08003780 node->stats_rsp, node->stats_rsp->staId,
3781 node->stats_rsp->statsMask, get_stats_param->sessionId);
Govind Singh4863da42016-03-08 11:45:00 +05303782
3783 cmd.session_id = get_stats_param->sessionId;
Dustin Brown12a96022017-07-12 10:34:50 -07003784 cmd.stats_mask = get_stats_param->statsMask;
Govind Singh4863da42016-03-08 11:45:00 +05303785 if (wmi_unified_get_stats_cmd(wma_handle->wmi_handle, &cmd,
3786 node->bssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787
3788 WMA_LOGE("%s: Failed to send WMI_REQUEST_STATS_CMDID",
3789 __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 goto failed;
3791 }
3792
3793 goto end;
3794failed:
Ganesh Kondabattini5bcc3e72017-05-17 15:20:31 +05303795 node->stats_rsp = NULL;
3796req_pending:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303797 pGetPEStatsRspParams->rc = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 /* send response to UMAC */
3799 wma_send_msg(wma_handle, WMA_GET_STATISTICS_RSP, pGetPEStatsRspParams,
3800 0);
3801end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303802 qdf_mem_free(get_stats_param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 WMA_LOGD("%s: Exit", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804}
3805
3806/**
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303807 * wma_get_cca_stats() - send request to fw to get CCA
3808 * @wma_handle: wma handle
3809 * @vdev_id: vdev id
3810 *
3811 * Return: QDF status
3812 */
3813QDF_STATUS wma_get_cca_stats(tp_wma_handle wma_handle,
3814 uint8_t vdev_id)
3815{
3816 if (wmi_unified_congestion_request_cmd(wma_handle->wmi_handle,
3817 vdev_id)) {
3818 WMA_LOGE("Failed to congestion request to fw");
3819 return QDF_STATUS_E_FAILURE;
3820 }
3821 return QDF_STATUS_SUCCESS;
3822}
3823
3824/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 * wma_get_beacon_buffer_by_vdev_id() - get the beacon buffer from vdev ID
3826 * @vdev_id: vdev id
3827 * @buffer_size: size of buffer
3828 *
3829 * Return: none
3830 */
3831void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size)
3832{
3833 tp_wma_handle wma;
3834 struct beacon_info *beacon;
3835 uint8_t *buf;
3836 uint32_t buf_size;
3837
Anurag Chouhan6d760662016-02-20 16:05:43 +05303838 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 if (!wma) {
3840 WMA_LOGE("%s: Invalid WMA handle", __func__);
3841 return NULL;
3842 }
3843
3844 if (vdev_id >= wma->max_bssid) {
3845 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3846 return NULL;
3847 }
3848
3849 if (!wma_is_vdev_in_ap_mode(wma, vdev_id)) {
3850 WMA_LOGE("%s: vdevid %d is not in AP mode", __func__, vdev_id);
3851 return NULL;
3852 }
3853
3854 beacon = wma->interfaces[vdev_id].beacon;
3855
3856 if (!beacon) {
3857 WMA_LOGE("%s: beacon invalid", __func__);
3858 return NULL;
3859 }
3860
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303861 qdf_spin_lock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862
Nirav Shahcbc6d722016-03-01 16:24:53 +05303863 buf_size = qdf_nbuf_len(beacon->buf);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303864 buf = qdf_mem_malloc(buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865
3866 if (!buf) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303867 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 WMA_LOGE("%s: alloc failed for beacon buf", __func__);
3869 return NULL;
3870 }
3871
Nirav Shahcbc6d722016-03-01 16:24:53 +05303872 qdf_mem_copy(buf, qdf_nbuf_data(beacon->buf), buf_size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303874 qdf_spin_unlock_bh(&beacon->lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875
3876 if (buffer_size)
3877 *buffer_size = buf_size;
3878
3879 return buf;
3880}
3881
3882/**
3883 * wma_get_vdev_address_by_vdev_id() - lookup MAC address from vdev ID
3884 * @vdev_id: vdev id
3885 *
3886 * Return: mac address
3887 */
3888uint8_t *wma_get_vdev_address_by_vdev_id(uint8_t vdev_id)
3889{
3890 tp_wma_handle wma;
3891
Anurag Chouhan6d760662016-02-20 16:05:43 +05303892 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 if (!wma) {
3894 WMA_LOGE("%s: Invalid WMA handle", __func__);
3895 return NULL;
3896 }
3897
3898 if (vdev_id >= wma->max_bssid) {
3899 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3900 return NULL;
3901 }
3902
3903 return wma->interfaces[vdev_id].addr;
3904}
3905
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003906QDF_STATUS wma_get_connection_info(uint8_t vdev_id,
3907 struct policy_mgr_vdev_entry_info *conn_table_entry)
3908{
3909 struct wma_txrx_node *wma_conn_table_entry;
3910
3911 wma_conn_table_entry = wma_get_interface_by_vdev_id(vdev_id);
3912 if (NULL == wma_conn_table_entry) {
3913 WMA_LOGE("%s: can't find vdev_id %d in WMA table", __func__, vdev_id);
3914 return QDF_STATUS_E_FAILURE;
3915 }
3916 conn_table_entry->chan_width = wma_conn_table_entry->chan_width;
3917 conn_table_entry->mac_id = wma_conn_table_entry->mac_id;
3918 conn_table_entry->mhz = wma_conn_table_entry->mhz;
3919 conn_table_entry->sub_type = wma_conn_table_entry->sub_type;
3920 conn_table_entry->type = wma_conn_table_entry->type;
3921
3922 return QDF_STATUS_SUCCESS;
3923}
3924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925/**
3926 * wma_get_interface_by_vdev_id() - lookup interface entry using vdev ID
3927 * @vdev_id: vdev id
3928 *
3929 * Return: entry from vdev table
3930 */
3931struct wma_txrx_node *wma_get_interface_by_vdev_id(uint8_t vdev_id)
3932{
3933 tp_wma_handle wma;
3934
Anurag Chouhan6d760662016-02-20 16:05:43 +05303935 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936 if (!wma) {
3937 WMA_LOGE("%s: Invalid WMA handle", __func__);
3938 return NULL;
3939 }
3940
3941 if (vdev_id >= wma->max_bssid) {
3942 WMA_LOGE("%s: Invalid vdev_id %u", __func__, vdev_id);
3943 return NULL;
3944 }
3945
3946 return &wma->interfaces[vdev_id];
3947}
3948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949#if defined(QCA_WIFI_FTM)
3950/**
3951 * wma_utf_rsp() - utf response
3952 * @wma_handle: wma handle
3953 * @payload: payload
3954 * @len: length of payload
3955 *
3956 * Return: 0 for success or error code
3957 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07003958static int wma_utf_rsp(tp_wma_handle wma_handle, uint8_t **payload,
3959 uint32_t *len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960{
3961 int ret = -1;
3962 uint32_t payload_len;
3963
3964 payload_len = wma_handle->utf_event_info.length;
3965 if (payload_len) {
3966 ret = 0;
3967
3968 /*
3969 * The first 4 bytes holds the payload size
3970 * and the actual payload sits next to it
3971 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303972 *payload = (uint8_t *) qdf_mem_malloc((uint32_t) payload_len
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 + sizeof(A_UINT32));
3974 *(A_UINT32 *) &(*payload[0]) =
3975 wma_handle->utf_event_info.length;
3976 memcpy(*payload + sizeof(A_UINT32),
3977 wma_handle->utf_event_info.data, payload_len);
3978 wma_handle->utf_event_info.length = 0;
3979 *len = payload_len;
3980 }
3981
3982 return ret;
3983}
3984
3985/**
3986 * wma_post_ftm_response() - post ftm response to upper layer
3987 * @wma_handle: wma handle
3988 *
3989 * Return: none
3990 */
3991static void wma_post_ftm_response(tp_wma_handle wma_handle)
3992{
3993 int ret;
3994 uint8_t *payload;
3995 uint32_t data_len;
Rajeev Kumarb60abe42017-01-21 15:39:31 -08003996 struct scheduler_msg msg = { 0 };
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303997 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998
3999 ret = wma_utf_rsp(wma_handle, &payload, &data_len);
4000
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004001 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003
4004 sys_build_message_header(SYS_MSG_ID_FTM_RSP, &msg);
4005 msg.bodyptr = payload;
4006 msg.bodyval = 0;
4007
Rajeev Kumarb60abe42017-01-21 15:39:31 -08004008 status = scheduler_post_msg(QDF_MODULE_ID_SYS, &msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304010 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 WMA_LOGE("failed to post ftm response to SYS");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304012 qdf_mem_free(payload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 }
4014}
4015
4016/**
4017 * wma_process_utf_event() - process utf event
4018 * @handle: wma handle
4019 * @datap: data buffer
4020 * @dataplen: data length
4021 *
4022 * Return: 0 for success or error code
4023 */
4024static int
4025wma_process_utf_event(WMA_HANDLE handle, uint8_t *datap, uint32_t dataplen)
4026{
4027 tp_wma_handle wma_handle = (tp_wma_handle) handle;
Govind Singhd76a5b02016-03-08 15:12:14 +05304028 struct seg_hdr_info segHdrInfo;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 uint8_t totalNumOfSegments, currentSeq;
4030 WMI_PDEV_UTF_EVENTID_param_tlvs *param_buf;
4031 uint8_t *data;
4032 uint32_t datalen;
4033
4034 param_buf = (WMI_PDEV_UTF_EVENTID_param_tlvs *) datap;
4035 if (!param_buf) {
4036 WMA_LOGE("Get NULL point message from FW");
4037 return -EINVAL;
4038 }
4039 data = param_buf->data;
4040 datalen = param_buf->num_data;
4041
Govind Singhd76a5b02016-03-08 15:12:14 +05304042 segHdrInfo = *(struct seg_hdr_info *) &(data[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043
4044 wma_handle->utf_event_info.currentSeq = (segHdrInfo.segmentInfo & 0xF);
4045
4046 currentSeq = (segHdrInfo.segmentInfo & 0xF);
4047 totalNumOfSegments = (segHdrInfo.segmentInfo >> 4) & 0xF;
4048
4049 datalen = datalen - sizeof(segHdrInfo);
4050
4051 if (currentSeq == 0) {
4052 wma_handle->utf_event_info.expectedSeq = 0;
4053 wma_handle->utf_event_info.offset = 0;
4054 } else {
4055 if (wma_handle->utf_event_info.expectedSeq != currentSeq)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004056 WMA_LOGE("Mismatch in expecting seq expected Seq %d got seq %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 wma_handle->utf_event_info.expectedSeq,
4058 currentSeq);
4059 }
4060
Varun Reddy Yeturud4c523d2017-09-26 15:28:42 -07004061 if ((datalen > MAX_UTF_EVENT_LENGTH) ||
4062 (wma_handle->utf_event_info.offset >
4063 (MAX_UTF_EVENT_LENGTH - datalen))) {
4064 WMA_LOGE("Excess data from firmware, offset:%zu, len:%d",
4065 wma_handle->utf_event_info.offset, datalen);
4066 return -EINVAL;
4067 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 memcpy(&wma_handle->utf_event_info.
4069 data[wma_handle->utf_event_info.offset],
4070 &data[sizeof(segHdrInfo)], datalen);
4071 wma_handle->utf_event_info.offset =
4072 wma_handle->utf_event_info.offset + datalen;
4073 wma_handle->utf_event_info.expectedSeq++;
4074
4075 if (wma_handle->utf_event_info.expectedSeq == totalNumOfSegments) {
4076 if (wma_handle->utf_event_info.offset != segHdrInfo.len)
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004077 WMA_LOGE("All segs received total len mismatch.. len %zu total len %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 wma_handle->utf_event_info.offset,
4079 segHdrInfo.len);
4080
4081 wma_handle->utf_event_info.length =
4082 wma_handle->utf_event_info.offset;
4083 }
4084
4085 wma_post_ftm_response(wma_handle);
4086
4087 return 0;
4088}
4089
4090/**
4091 * wma_utf_detach() - utf detach
4092 * @wma_handle: wma handle
4093 *
4094 * Return: none
4095 */
4096void wma_utf_detach(tp_wma_handle wma_handle)
4097{
4098 if (wma_handle->utf_event_info.data) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304099 qdf_mem_free(wma_handle->utf_event_info.data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 wma_handle->utf_event_info.data = NULL;
4101 wma_handle->utf_event_info.length = 0;
4102 wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
4103 WMI_PDEV_UTF_EVENTID);
4104 }
4105}
4106
4107/**
4108 * wma_utf_attach() - utf attach
4109 * @wma_handle: wma handle
4110 *
4111 * Return: none
4112 */
4113void wma_utf_attach(tp_wma_handle wma_handle)
4114{
4115 int ret;
4116
4117 wma_handle->utf_event_info.data = (unsigned char *)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304118 qdf_mem_malloc(MAX_UTF_EVENT_LENGTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 wma_handle->utf_event_info.length = 0;
4120
4121 ret = wmi_unified_register_event_handler(wma_handle->wmi_handle,
4122 WMI_PDEV_UTF_EVENTID,
Govind Singhd76a5b02016-03-08 15:12:14 +05304123 wma_process_utf_event,
4124 WMA_RX_SERIALIZER_CTX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125
4126 if (ret)
Srinivas Girigowdad1a07a52017-03-06 22:48:16 -08004127 WMA_LOGE("%s: Failed to register UTF event callback", __func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128}
4129
4130/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004131 * wma_utf_cmd() - utf command
4132 * @wma_handle: wma handle
4133 * @data: data
4134 * @len: length
4135 *
Govind Singhd76a5b02016-03-08 15:12:14 +05304136 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 */
Jeff Johnsonc4b47a92016-10-07 12:34:41 -07004138static QDF_STATUS wma_utf_cmd(tp_wma_handle wma_handle, uint8_t *data,
4139 uint16_t len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140{
Govind Singhd76a5b02016-03-08 15:12:14 +05304141 struct pdev_utf_params param = {0};
4142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143 wma_handle->utf_event_info.length = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05304144 param.utf_payload = data;
4145 param.len = len;
4146
4147 return wmi_unified_pdev_utf_cmd_send(wma_handle->wmi_handle, &param,
4148 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004149}
4150
4151/**
4152 * wma_process_ftm_command() - process ftm command
4153 * @wma_handle: wma handle
4154 * @msg_buffer: message buffer
4155 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304156 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304158QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159wma_process_ftm_command(tp_wma_handle wma_handle,
4160 struct ar6k_testmode_cmd_data *msg_buffer)
4161{
4162 uint8_t *data = NULL;
4163 uint16_t len = 0;
4164 int ret;
4165
4166 if (!msg_buffer)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304167 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168
Anurag Chouhan6d760662016-02-20 16:05:43 +05304169 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 WMA_LOGE("FTM command issued in non-FTM mode");
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304171 qdf_mem_free(msg_buffer->data);
4172 qdf_mem_free(msg_buffer);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304173 return QDF_STATUS_E_NOSUPPORT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 }
4175
4176 data = msg_buffer->data;
4177 len = msg_buffer->len;
4178
4179 ret = wma_utf_cmd(wma_handle, data, len);
4180
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304181 qdf_mem_free(msg_buffer->data);
4182 qdf_mem_free(msg_buffer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183
4184 if (ret)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304185 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304187 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188}
4189#endif /* QCA_WIFI_FTM */
4190
Jeff Johnsonabb74042017-08-31 11:44:55 -07004191QDF_STATUS wma_get_wcnss_software_version(uint8_t *version,
4192 uint32_t version_buffer_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004193{
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004194 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195
4196 if (NULL == wma_handle) {
4197 WMA_LOGE("%s: Failed to get wma", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304198 return QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199 }
4200
Jeff Johnsonabb74042017-08-31 11:44:55 -07004201 snprintf(version, version_buffer_size, "%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 (unsigned int)wma_handle->target_fw_version);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204}
4205
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004206/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 * wma_get_mac_id_of_vdev() - Get MAC id corresponding to a vdev
4208 * @vdev_id: VDEV whose MAC ID is required
4209 *
4210 * Get MAC id corresponding to a vdev id from the WMA structure
4211 *
4212 * Return: Negative value on failure and MAC id on success
4213 */
4214int8_t wma_get_mac_id_of_vdev(uint32_t vdev_id)
4215{
4216 tp_wma_handle wma;
4217
Anurag Chouhan6d760662016-02-20 16:05:43 +05304218 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 if (!wma) {
4220 WMA_LOGE("%s: Invalid WMA handle", __func__);
4221 return -EINVAL;
4222 }
4223
4224 if (wma->interfaces)
4225 return wma->interfaces[vdev_id].mac_id;
4226
4227 return -EINVAL;
4228}
4229
4230/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 * wma_update_intf_hw_mode_params() - Update WMA params
4232 * @vdev_id: VDEV id whose params needs to be updated
4233 * @mac_id: MAC id to be updated
4234 * @cfgd_hw_mode_index: HW mode index from which Tx and Rx SS will be updated
4235 *
4236 * Updates the MAC id, tx spatial stream, rx spatial stream in WMA
4237 *
4238 * Return: None
4239 */
4240void wma_update_intf_hw_mode_params(uint32_t vdev_id, uint32_t mac_id,
4241 uint32_t cfgd_hw_mode_index)
4242{
4243 tp_wma_handle wma;
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004244 uint32_t param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245
Anurag Chouhan6d760662016-02-20 16:05:43 +05304246 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 if (!wma) {
4248 WMA_LOGE("%s: Invalid WMA handle", __func__);
4249 return;
4250 }
4251
4252 if (!wma->interfaces) {
4253 WMA_LOGE("%s: Interface is NULL", __func__);
4254 return;
4255 }
4256
Tushnim Bhattacharyya206bcac2015-11-10 15:20:06 -08004257 if (cfgd_hw_mode_index > wma->num_dbs_hw_modes) {
4258 WMA_LOGE("%s: Invalid index", __func__);
4259 return;
4260 }
4261
4262 param = wma->hw_mode.hw_mode_list[cfgd_hw_mode_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 wma->interfaces[vdev_id].mac_id = mac_id;
4264 if (mac_id == 0) {
4265 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304266 WMA_HW_MODE_MAC0_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304268 WMA_HW_MODE_MAC0_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 } else {
4270 wma->interfaces[vdev_id].tx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304271 WMA_HW_MODE_MAC1_TX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 wma->interfaces[vdev_id].rx_streams =
Nitesh Shah5b7bae02016-09-28 18:58:33 +05304273 WMA_HW_MODE_MAC1_RX_STREAMS_GET(param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 }
4275}
4276
4277/**
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004278 * wma_get_vht_ch_width - return vht channel width
4279 *
4280 * Return: return vht channel width
4281 */
4282uint32_t wma_get_vht_ch_width(void)
4283{
4284 uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304285 tp_wma_handle wm_hdl = cds_get_context(QDF_MODULE_ID_WMA);
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004286
4287 if (NULL == wm_hdl)
4288 return fw_ch_wd;
4289
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004290 if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004291 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
Kiran Kumar Lokere02b9aa42016-05-26 14:54:49 -07004292 else if (wm_hdl->vht_cap_info & WMI_VHT_CAP_CH_WIDTH_160MHZ)
4293 fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
Naveen Rawatc0c91cd2015-11-05 14:27:37 -08004294
4295 return fw_ch_wd;
4296}
Govind Singhd76a5b02016-03-08 15:12:14 +05304297
4298/**
Krunal Soniaa664da2016-06-15 23:46:40 -07004299 * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
4300 * @mask: given bitmask
4301 *
4302 * This helper function should return number of setbits from bitmask
4303 *
4304 * Return: number of setbits from bitmask
4305 */
4306uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
4307{
4308 uint32_t num_of_setbits = 0;
4309
4310 while (mask) {
4311 mask &= (mask - 1);
4312 num_of_setbits++;
4313 }
4314 return num_of_setbits;
4315}
4316
4317/**
Kiran Kumar Lokered0fad462017-06-13 18:23:48 -07004318 * wma_is_csa_offload_enabled - checks fw CSA offload capability
4319 *
4320 * Return: true or false
4321 */
4322
4323bool wma_is_csa_offload_enabled(void)
4324{
4325 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
4326
4327 if (!wma)
4328 return false;
4329
4330 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
4331 WMI_SERVICE_CSA_OFFLOAD);
4332}
4333/**
Govind Singhd76a5b02016-03-08 15:12:14 +05304334 * wma_config_debug_module_cmd - set debug log config
4335 * @wmi_handle: wmi layer handle
4336 * @param: debug log parameter
4337 * @val: debug log value
4338 * @module_id_bitmap: debug module id bitmap
4339 * @bitmap_len: debug module bitmap length
4340 *
4341 * Return: QDF_STATUS_SUCCESS for success or error code
4342 */
4343QDF_STATUS
4344wma_config_debug_module_cmd(wmi_unified_t wmi_handle, A_UINT32 param,
4345 A_UINT32 val, A_UINT32 *module_id_bitmap,
4346 A_UINT32 bitmap_len)
4347{
4348 struct dbglog_params dbg_param;
Manikandan Mohan1dd8b5d2017-04-18 15:54:09 -07004349
Govind Singhd76a5b02016-03-08 15:12:14 +05304350 dbg_param.param = param;
4351 dbg_param.val = val;
4352 dbg_param.module_id_bitmap = module_id_bitmap;
4353 dbg_param.bitmap_len = bitmap_len;
4354
4355 return wmi_unified_dbglog_cmd_send(wmi_handle, &dbg_param);
4356}
Peng Xu8fdaa492016-06-22 10:20:47 -07004357
4358/**
4359 * wma_is_p2p_lo_capable() - if driver is capable of p2p listen offload
4360 *
4361 * This function checks if driver is capable of p2p listen offload
4362 * true: capable of p2p offload
4363 * false: not capable
4364 *
4365 * Return: true - capable, false - not capable
4366 */
4367bool wma_is_p2p_lo_capable(void)
4368{
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004369 return wma_is_service_enabled(WMI_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT);
Peng Xu8fdaa492016-06-22 10:20:47 -07004370}
Aravind Narasimhan5b7c2cd2016-12-08 21:04:26 -08004371
Dustin Brown8d8d9fe2017-07-18 16:01:25 -07004372bool wma_capability_enhanced_mcast_filter(void)
4373{
4374 return wma_is_service_enabled(WMI_SERVICE_ENHANCED_MCAST_FILTER);
4375}
4376
4377
Mukul Sharmaf9047232017-03-02 16:58:56 +05304378bool wma_is_vdev_up(uint8_t vdev_id)
4379{
4380 struct wlan_objmgr_vdev *vdev;
4381 tp_wma_handle wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
4382 enum wlan_vdev_state state = WLAN_VDEV_S_INIT;
4383
4384 if (!wma) {
4385 WMA_LOGE("%s: WMA context is invald!", __func__);
4386 return false;
4387 }
4388
4389 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
4390 WLAN_LEGACY_WMA_ID);
4391 if (vdev) {
4392 wlan_vdev_obj_lock(vdev);
4393 state = wlan_vdev_mlme_get_state(vdev);
4394 wlan_vdev_obj_unlock(vdev);
4395 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
4396 }
Mukul Sharmaf9047232017-03-02 16:58:56 +05304397 return (state == WLAN_VDEV_S_RUN) ? true : false;
4398}
4399
Dustin Brownec2c92e2017-07-26 11:13:49 -07004400void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004401{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004402 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4403
4404 cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
4405 qdf_wake_lock_timeout_acquire(wl, msec);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004406 qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004407}
4408
Dustin Brownec2c92e2017-07-26 11:13:49 -07004409void wma_release_wakelock(qdf_wake_lock_t *wl)
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004410{
Dustin Brownec2c92e2017-07-26 11:13:49 -07004411 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
4412
4413 qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
Prashanth Bhatta87b6dc02017-01-19 15:17:58 -08004414 qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004415}
4416
Dustin Brownd5f12942017-03-10 11:06:25 -08004417QDF_STATUS
4418wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
4419{
4420 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004421 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
Dustin Brownd5f12942017-03-10 11:06:25 -08004422
Dustin Brownec2c92e2017-07-26 11:13:49 -07004423 wma_acquire_wakelock(&vdev->vdev_start_wakelock,
4424 WMA_VDEV_START_REQUEST_TIMEOUT);
Dustin Brownd5f12942017-03-10 11:06:25 -08004425 status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
4426 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004427 wma_release_wakelock(&vdev->vdev_start_wakelock);
Dustin Brownd5f12942017-03-10 11:06:25 -08004428
4429 return status;
4430}
4431
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004432QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4433{
4434 QDF_STATUS status;
Dustin Brownec2c92e2017-07-26 11:13:49 -07004435 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004436
Dustin Brownec2c92e2017-07-26 11:13:49 -07004437 wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
4438 WMA_VDEV_STOP_REQUEST_TIMEOUT);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004439 status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id);
4440 if (QDF_IS_STATUS_ERROR(status))
Dustin Brownec2c92e2017-07-26 11:13:49 -07004441 wma_release_wakelock(&vdev->vdev_stop_wakelock);
Dustin Brownbf6d16b2017-03-03 11:41:05 -08004442
4443 return status;
4444}
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08004445
4446bool wma_is_service_enabled(WMI_SERVICE service_type)
4447{
4448 tp_wma_handle wma;
4449 wma = cds_get_context(QDF_MODULE_ID_WMA);
4450 if (!wma) {
4451 WMA_LOGE("%s: Invalid WMA handle", __func__);
4452 return false;
4453 }
4454
4455 return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, service_type);
4456}
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004457
Dustin Brownec2c92e2017-07-26 11:13:49 -07004458QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
4459 struct vdev_up_params *params,
4460 uint8_t bssid[IEEE80211_ADDR_LEN])
4461{
4462 QDF_STATUS status;
4463 struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
4464
4465 status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
4466 wma_release_wakelock(&vdev->vdev_start_wakelock);
4467
4468 return status;
4469}
4470
4471QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
4472{
4473 QDF_STATUS status;
4474 struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
4475
4476 status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
4477 wma_release_wakelock(&vdev->vdev_start_wakelock);
4478
4479 return status;
4480}
4481
Krishna Kumaar Natarajanc7e2bb72017-03-10 10:38:46 -08004482tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
4483{
4484 switch (type) {
4485 case WMI_PEER_TYPE_DEFAULT:
4486 return WIFI_PEER_STA;
4487 case WMI_PEER_TYPE_BSS:
4488 return WIFI_PEER_AP;
4489 case WMI_PEER_TYPE_TDLS:
4490 return WIFI_PEER_TDLS;
4491 case WMI_PEER_TYPE_NAN_DATA:
4492 return WIFI_PEER_NAN;
4493 default:
4494 WMA_LOGE("Cannot map wmi_peer_type %d to HAL peer type", type);
4495 return WIFI_PEER_INVALID;
4496 }
4497}
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304498
4499int wma_chip_power_save_failure_detected_handler(void *handle,
4500 uint8_t *cmd_param_info,
4501 uint32_t len)
4502{
4503 tp_wma_handle wma = (tp_wma_handle)handle;
4504 WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *param_buf;
4505 wmi_chip_power_save_failure_detected_fixed_param *event;
4506 struct chip_pwr_save_fail_detected_params pwr_save_fail_params;
4507 tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(
4508 QDF_MODULE_ID_PE);
4509 if (wma == NULL) {
4510 WMA_LOGE("%s: wma_handle is NULL", __func__);
4511 return -EINVAL;
4512 }
4513 if (!mac) {
4514 WMA_LOGE("%s: Invalid mac context", __func__);
4515 return -EINVAL;
4516 }
4517 if (!mac->sme.chip_power_save_fail_cb) {
4518 WMA_LOGE("%s: Callback not registered", __func__);
4519 return -EINVAL;
4520 }
4521
4522 param_buf =
4523 (WMI_PDEV_CHIP_POWER_SAVE_FAILURE_DETECTED_EVENTID_param_tlvs *)
4524 cmd_param_info;
4525 if (!param_buf) {
4526 WMA_LOGE("%s: Invalid pwr_save_fail_params breached event",
4527 __func__);
4528 return -EINVAL;
4529 }
4530 event = param_buf->fixed_param;
4531 pwr_save_fail_params.failure_reason_code =
4532 event->power_save_failure_reason_code;
4533 pwr_save_fail_params.wake_lock_bitmap[0] =
4534 event->protocol_wake_lock_bitmap[0];
4535 pwr_save_fail_params.wake_lock_bitmap[1] =
4536 event->protocol_wake_lock_bitmap[1];
4537 pwr_save_fail_params.wake_lock_bitmap[2] =
4538 event->protocol_wake_lock_bitmap[2];
4539 pwr_save_fail_params.wake_lock_bitmap[3] =
4540 event->protocol_wake_lock_bitmap[3];
4541 mac->sme.chip_power_save_fail_cb(mac->hHdd,
4542 &pwr_save_fail_params);
4543
4544 WMA_LOGD("%s: Invoke HDD pwr_save_fail callback", __func__);
4545 return 0;
4546}